Next: Reserved Metadatum Names: schema Up: The Horizon Metadata Model Previous: What are Metadata?

## The Horizon `Metadata` Class

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.

- Reserved Metadatum Names: schema and schemaVersion
- Possible Pitfalls and Safety Nets
  - Use only `String` objects as keys.
  - Use Consistant Value Types When Reading and Writing Metadata.
  - Handle Updateable Metadata Values With Care.

Next: Reserved Metadatum Names: schema Up: The Horizon Metadata Model Previous: What are Metadata?