The Horizon package encapsulates the concept of metadata into a class called ncsa.horizon.util.Metadata. This class is very similar to the java.util.Properties class, sharing much of its interface as well as implementation. Like Properties, Metadata is a subclass of java.util.Hashtable which provides the storage and lookup functions of the container. For example, one can use the Hashtable method put to load data into the Metadata object:
Metadata mdata = new Metadata();
mdata.put("instrument", "Wide-field Camera");
mdata.put("altitude", new Double(4036.2));
Metadata's main difference with Properties is that the value of a key-value pair is not restricted to be a String object. Given a Metadata object, one can extract the value of an individual metadatum it contains:
Metadata mdata;
...
String instr = (String) mdata.getMetadatum("instrument");
Double alt = (Double) mdata.getMetadatum("altitude");
Metadata cmdata = (Metadata) mdata.getMetadatum("coordinateSystem");
If a requested metadatum is not found in the metadata list,
getMetadatum will return null.
There are a few things to note in the above example. First is that
since the
[4] getMetadatum(String) method returns the
type Object, one must cast it to its specific type. This, of
course, requires that we know what the type should be, reflecting the
inescapable assumption about the meaning of each of metadatum name.
It is possible that the data might have been loaded into the Metadata
container with the wrong type; thus, one or more of the statements
could throw a ClassCastException. If this is a concern that
you want to catch, you might handle the error explicitly:
String instr;
Double alt;
Metadata cmdata;
try {
instr = (String) mdata.getMetadatum("instrument");
alt = (Double) mdata.getMetadatum("altitude");
cmdata = (Metadata) mdata.getMetadatum("coordinateSystem");
}
catch (ClassCastException ex) {
throw new
MetadataTypeException("Encountered metadatum of incorrect type");
// Note that MetadataTypeException is a RuntimeException; users of this
// method are not required to catch the exception.
}
Another thing to note about this example is that a Metadata
[3] object can contain other Metadata objects. In our
example, the ``CoordinateSystem'' metadatum is actually a Metadata
object containing all the metadata describing the coordinate system.
Thus metadata can be stored hierarchically. What if I was interested
in a particular metadatum within the ``CoordinateSystem'' metadata
list, say the value of ``naxes''? In this example, ``naxes'' is
considered sub-metadatum of ``CoordinateSystem''. The
Metadata class provides a short-cut accessing such sub-metadata:
Integer naxes = (Integer) mdata.getMetadatum("CoordinateSystem.naxes");
This is equivalent to
Integer naxes =
(Integer) mdata.getMetadatum("CoordinateSystem").getMetadatum("naxes");
except that the latter version might throw a
NullPointerException if the ``CoordinateSystem'' datum does not
exist. In the former case, getMetadatum will return
null if either ``CoordinateSystem'' does not exist or ``naxes''
does not exist in the ``CoordinateSystem'' list. (It will also return
null if the ``CoordinateSystem'' metadatum is not of type
Metadata.) Note that one cannot use the sub-metadata syntax
to update hierarchical metadata.