next up previous contents
Next: Handling Arrays: The Horizon Up: The Horizon Metadata Model Previous: Handle Updateable Metadata Values

Protecting Metadata Via Defaults

 

The Metadata class shares another important feature of the Properties class in its the support for default values; that is, Metadata objects can store two sets of data within themselves: primary data and default data. Calls to getMetadatum(String) will return requested data from the primary set; if it does not exist there, the data in the default list is searched for a value. (One can prevent the search of the default set by calling getMetadatum(String, null).)

The default data are stored as a protected Metadata
[1] field within the primary Metadata class and can only be set during construction. The Metadata class interface never gives out a reference to the defaults list, preventing client objects from adding, removing, or replacing any of its contents. Many Horizon classes exploit this feature as a way of keeping exclusive control of the metadata that they manage but still allow read-only access to the metadata. For example, the CoordinateSystem class can share its metadata with other objects via its getMetadata method; however, it probably does not want to allow other objects to alter the metadata list. So, it has two choices: it can either clone the Metadata list and return the new copy:

protected Metadata mdata;
...
public Metadata getMetadata() {
    return mdata.clone();
}
or it can use a ``protection'' technique by creating a new Metadata list with CoordinateSystem's own Metadata as the default:
protected Metadata mdata;
...
public Metadata getMetadata() {
    return new Metadata(mdata);
}

Why wouldn't the CoordinateSystem object want to return a clone? That depends in part on how clone is implemented. The deepest possible clone implementation would clone both the primary and default hashtables plus each object in the hashtables. This could potentially be an expensive operation if the tables contain a lot of data, and it could be inefficient if much of the data is of a non-updatable type (e.g. Double). A less deep clone would clone only the primary hashtable and the default Metadata list; however, this also could get expensive if the default list has a default list of its own which also has a default list and so on. By contrast, the ``protection'' implementation for getMetadata does not clone any hashtables; the biggest overhead incurred is in the creation of a single empty hashtable.

In actuality, the Metadata's clone method only clones the primary hastable which may or may not be an expensive operation. Nevertheless, there are some advantages the ``protection'' technique provides to client objects. Suppose object aClient calls a CoordinateSystem's getMetadata method which returns a Metadata object using the ``protection'' technique. aClient is free to update its Metadata list without affecting the copy help the CoordinateSystem; replacement operations really only hide the original values. Thus, aClient can return to the default value later, if necessary, by removing any data its added. If, by contrast, aClient had gotten a clone, updates would have removed the original values of the primary hashtable. Another feature relates to the fact that the CoordinateSystem still has a reference to the list being used as the defaults of aClient's list; in this case, we say that aClient's Metadata object is ``attached'' to the CoordinateSystem. The consequence of this is that whenever aClient calls the getMetadatum method, it is guaranteed to get the most up-to-date value for the metadatum in use by the CoordinateSystem.

Client objects may not want their Metadata objects to have such close connections with the Metadata's originator. Therefore, the Metadata class provides a variety of methods offering different levels of cloning and ``attachment'':

For instance, aClient could remove the defaults list in its Metadata object by calling setDefaults(null). A less severe and usually more useful alternative would be to call detach() which replaces the defaults list with a clone.gif As a result, any changes the CoordinateSystem makes to its metadata list will not affect the list held by aClient.

Of course, protecting metadata in a defaults list does not protect against updates to data internal to the objects contained within the list. Following our above example, suppose aClient gets a double[] array from the Metadata object it got from CoordinateSystem. It can now change the value of one of the elements of that array. The next time the CoordinateSystem accesses the array, it would see the update. The moral here is that if you want client objects to only have complete, deep read-only access to a Metadata list, do not use updateable objects as values in that list. The exceptions to this rule, however, are Metavector objects and other Metadata objects.

The Metadata class takes special care when a metadatum value is of type Metadata. If the getMetadatum method must resort to getting a value from the default list and if that value is itself of type Metadata, then it will not return a direct reference to the sub-Metadata; instead it will set it as the default list in a new Metadata instance which is then returned, thus protecting it from updates by the client.

Arrays are often too useful to avoid using to hold metadata; therefore, the Horizon package also provides the Metavector class (described in §2.4) for this purpose. A Metavector is much like a Metadata object, including its support for default data; the difference is that instead of using a hashtable for storing its data, it uses an array. The Metadata class will also watch out for Metavector objects extracted from the defaults list, protecting them when necessary.

In summary, the defaults Metadata list can provide a read-only access to metadata, limited by whether or not the stored values are of an updateable type. Full read-only access can be achieved if the only updateable classes used are Metadata and Metavector. This should be sufficient for most cases, because the Metadata class can be considered a kind of structure (as in C programming)--a class with only fields but no methods. In place of the methods, a metadata list is governed by the schema definition for handling the data. Of course, a Metadata object is not as powerful as a full-featured class; however, one of the main purposes of the Metadata class is to provide a container for transporting this information, particularly from persistant storage like a data file of a specific format. Once carried to the part of the code that will process the data, the data can be converted into a fully intelligent class. In fact, this is what is done with the Horizon coordinate classes, the topic of section §3.


next up previous contents
Next: Handling Arrays: The Horizon Up: The Horizon Metadata Model Previous: Handle Updateable Metadata Values

Ray Plante
Mon Aug 25 15:16:12 CDT 1997