Class ncsa.horizon.util.Metadata
All Packages  Class Hierarchy  This Package  Previous  Next  Index

Class ncsa.horizon.util.Metadata

java.lang.Object
   |
   +----java.util.Dictionary
           |
           +----java.util.Hashtable
                   |
                   +----ncsa.horizon.util.Metadata

public class Metadata
extends Hashtable
a hashtable where keys are String objects and values are Object objects. Like java.util.Properties, it contains an internal default value list. Data contained within Metadata within Metadata are directly accessible. Also supported is the transparent loading of data into the hashtable only at the point when the user first requests them.

Within the Horizon package, Metadata objects hold data that describe other data. For example, image data sets can have metadata associated with them that can describe things like the number of dimensions it has, the origin of the data, etc; this can information can usually be accessed through Viewable method, getMetadata(). CoordinateSystem objects also have metadata associated with them that provide the parameters that describe the system.

Users of this class should remember that metadata have an assumed type that is implicitly agreed upon by all classes that access it. For example, classes in ncsa.horizon.coordinates package assume that the metadatum named "naxes" to be of type Integer. If a class finds that a metadatum has an unexpected type, the class may throw a MetadataTypeException. (See CoordMetadata for more details about coordinate-related metadata.)

The only pre-defined metadata names are "schema" and "schemaVersion". The "schema" metadatum is a String that identifies the set of metadata names in use by this Metadata object, along with the types and logical meaning of those names. The "schemaVersion" is also a String to identify the version of the schema.

Accessing Hierarchical Metadata

Each piece of Metadata can be accessed through its name (often referred to as its keyword), represented as a String, using the getMetadatum(String) method. A metadatum value is set using the put method (from the super-class, Hashtable).

Special support is provided for hierarchical metadata. For example, a Metadata object can contain another Metadata object. It can also contain one or more Metavector objects, each one containing an array of metadata of the same type. The Metadata class supports this notion by allowing one to request "sub-metadata" directly with the getMetadatum(String key) method. If the key string contains a period ("."), the substring to the left of the period is taken to be the name of a metadatum of type Metadata; the substring to the left of the period is taken to be the name of a metadatum contained within that metadata object. For example, the following code,

    Metadata md;
    ...
    Metadata cmd = (Metadata) md.getMetadatum("coordinates");
    String name = (String) cmd.getMetadatum("name");
is equivalent to:
    String name = (String) md.getMetadatum("coordinates.name")
In fact, the latter is actually safer and more efficient. Similarly, if a Metadata object contains a Metavector object as one of its items, one can access an element of the Metavector by appending "[n]" to the name of the Metavector, where n is an integer specifying the desired array index. For example,
    Object element = md.getMetadatum("Axes[1]");
returns the object at index 1 (the second element) of the Metavector called "Axes".

Use the "sub-metadata" syntax, one can directly access hierarhical metadata of arbitrary depth. For example, the following is the most efficient way (in terms of memory and time) of access the specified sub-metadatum:

    String name = (String) md.getMetadatum("coordinates.Axes[1].name");

Note that one cannot use the "sub-metadata" syntax to update hierarchical metadata.

Default Metadata

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 value in the default searched for a value. (To prevent search of the default set, one should call getMetadatum(String, null).) The default data can only be set during construction. Primary data may be updated via the put and copyMetadata(Metadata) methods. The internally stored default metadata provides a way for managers of metadata to protect their data from updates by other objects. If a metadata manager has a Metadata it wants other objects to read from but not write into, it can create a new Metadata object that has the original as the default. The other users of the new Metadata can then read the elements and even override them without affecting the original Metadata object.

One other feature of the support for default values is that it allows the originator of Metadata (the object that has a reference to the default Metadata) to update the defaults after the Metadata has been created and passed on. Such changes would be seen by those objects that have not overriden the defaults. Client objects that prefer that their copy of the Metadata not be connected the originator in this way can "detach" it via the detach() method. Other methods are provided for obtaining "detached" copies of the data, detachedClone(), and cloneDefaults(). (Note that the standard clone() produces a Metavector whose defaults are "attached" to the same object as the original.)

One should note that the defaults protection only applies to the internal default Metadata container itself, not its elements. That is, the value returned by getMetadatum(String) is the original version of the datum and not a copy. Thus, there may be any number of references to the datum held by other objects. (The datum is protected only if it is of a type that is not internally editable. For example, the value of an Integer or String object cannot be updated; however, if the datum is of type Stack, the data internal to that Stack is not protected from updates.) An exception to this is when the value is obtained from the default list and is of type Metavector or Metadata; in this case, the meta-container is placed as the default list in a new meta-container before being passed on.

Dynamic Metadata Loading

Some metadata may be costly to load into memory, for example, if it needs to be downloaded from the network or it requires an expensive computation. The effort to load the data into a Metadata object may be wasted if the user never requests the data. The Metadata class provides a mechanism for one to store procedures, in the form of Metarunner objects, for obtaining metadata. When a user requests a metadatum object for which there exists a Metarunner object, the Metarunner is executed and the resulting value is returned to the user as well as loaded into the hashtable for future requests.

To make use of this capability, programmers should sub-class the Metarunner class, overridding the getDatum() method. The Metarunner object is then stored in the Metadata object using the name of metadatum appended with the String Metadata.METARUNNER_TAG. When the user later requests a named metadatum, the Metadata object first looks for a static value in its hashtable. If it does not exist, then the Metadata object looks for a Metarunner object that can obtain the value. Failing that, the default list is consulted (which might also engage a Metarunner object). If the Metarunner does exist and successfully returns a value, the value is stored in the primary hastable as a static value.

Support for Metarunner objects is meant by default to be transparent; the user is given some explicit control and access to the objects. To prevent the execution, one can set the public boolean field, executeRunners to false. The getRunnerNames() method returns the names of metadata (without the METARUNNER_TAG appended) that have Metarunners associated with them. In contrast, the MetadatumNames() returns the only the names for which there currently exists static values (including the modified names pointing to Metarunner objects). Since the latter method is expected to be used to step through each metadata value (say to copy it to another container), this behavior prevents the unintended execution of costly Metarunners.


Variable Index

 o defaults
the default Metadata values
 o executeRunners
true if Runnable objects should be executed to obtain values for requested metadata when available.
 o METARUNNER_TAG
the suffix to be appended to a metadatum name to refer to a Metarunnable object that can fetch the value of that metadatum.
 o schema
 o schemaVersion

Constructor Index

 o Metadata()
Creates an empty metadatum list.
 o Metadata(int)
Creates an empty metadatum list with an initial capacity
 o Metadata(int, Metadata)
Creates an empty metadatum list with an initial capacity and specified defaults.
 o Metadata(Metadata)
Creates an empty metadatum list with specified defaults.

Method Index

 o clone()
Clones this metadata object.
 o cloneDefaults()
clone the defaults metadata.
 o copyMetadata(Hashtable)
Copy all the data from a Hashtable whose keys are of type String into the primary data list.
 o copyMetadata(Metadata)
Copy all the data from another Metadata object into the primary data list.
 o deepClone()
create a semi-deep clone.
 o detach()
replace the internal default Metadata with a copy (via deepClone()), detaching control of the defaults from the originator of this Metadata.
 o detachedClone()
Like clone(), except that a copy of the defaults metadata is also made.
 o fetchDatum(String, Metarunner)
Execute a Metarunner that fetches the value of a specifed key and stores the result into this Metadata list
 o fetchMetadatum(String)
execute the runner (if it exists and is accessible) for the specified key, and return its value.
 o getDefaults()
return a new Metadata object with the same default data but with no primary data
 o getMetadatum(String)
Gets a metadatum with the specified key.
 o getMetadatum(String, boolean)
Gets a metadatum with the specified key.
 o getMetadatum(String, Object)
Gets a metadatum with the specified key and default.
 o getMetadatum(String, Object, boolean)
Gets a metadatum with the specified key and default.
 o getRunnerNames()
Enumerate the keys having Metarunner objects associated with them
 o giveDefaults(Metadata)
Copy the default metadata of this Metadata object to the defaults of another Metadata object.
 o metadatumNames()
Enumerates all the keys.
 o removeAllMetadata()
remove the primary key/value pairs from this Metadata object, leaving the defaults.
 o setDefaults(Metadata)
Set the default Metadata of this Metadata object.
 o setSchema(String)
set the name of the schema used by this Metadata object
 o setSchemaVersion(String)
set the version of the schema used by this Metadata object
 o toString()
attempt to convert contents to a multi-line String (useful for debugging

Variables

 o schema
  public final static String schema
 o schemaVersion
  public final static String schemaVersion
 o METARUNNER_TAG
  public final static String METARUNNER_TAG
the suffix to be appended to a metadatum name to refer to a Metarunnable object that can fetch the value of that metadatum.
 o defaults
  protected Metadata defaults
the default Metadata values
 o executeRunners
  public boolean executeRunners
true if Runnable objects should be executed to obtain values for requested metadata when available.

Constructors

 o Metadata
  public Metadata()
Creates an empty metadatum list.
 o Metadata
  public Metadata(Metadata defaults)
Creates an empty metadatum list with specified defaults.
Parameters:
defaults - the defaults
 o Metadata
  public Metadata(int initialCapacity)
Creates an empty metadatum list with an initial capacity
 o Metadata
  public Metadata(int initialCapacity,
                  Metadata defaults)
Creates an empty metadatum list with an initial capacity and specified defaults.

Methods

 o setSchema
  public void setSchema(String in)
set the name of the schema used by this Metadata object
 o setSchemaVersion
  public void setSchemaVersion(String in)
set the version of the schema used by this Metadata object
 o getMetadatum
  public Object getMetadatum(String key)
Gets a metadatum with the specified key. If the key is not found in this metadatum list, it tries the defaults. This method returns null if the metadatum is not found.
Parameters:
key - the metadatum name
 o getMetadatum
  public Object getMetadatum(String key,
                             boolean doRun)
Gets a metadatum with the specified key. If the key is not found in this metadatum list, it tries the defaults. This method returns null if the metadatum is not found.
Parameters:
key - the metadatum name
doRun - if true, a Runnable object should be executed to obtain the requested value when available; overrides the value of executeRunners
 o getMetadatum
  public Object getMetadatum(String key,
                             Object defaultValue)
Gets a metadatum with the specified key and default. This method returns defaultValue if the metadatum is not found.
 o getMetadatum
  public Object getMetadatum(String key,
                             Object defaultValue,
                             boolean doRun)
Gets a metadatum with the specified key and default. This method returns defaultValue if the metadatum is not found.
 o fetchDatum
  protected Object fetchDatum(String key,
                              Metarunner fetcher)
Execute a Metarunner that fetches the value of a specifed key and stores the result into this Metadata list
Parameters:
key - name of metadatum that the Metarunner will fetch.
fetcher - the Metarunner object to execute
 o getRunnerNames
  public synchronized Enumeration getRunnerNames()
Enumerate the keys having Metarunner objects associated with them
 o fetchMetadatum
  public Object fetchMetadatum(String key)
execute the runner (if it exists and is accessible) for the specified key, and return its value. The static value will be updated only if it does not exist or is equal to null. Runners from the default list are inaccessible if a static value or a runner exists in the primary array. If a runner does not exist or is inaccessible, the result is equivalent to getMetadatum();
 o copyMetadata
  public void copyMetadata(Hashtable from)
Copy all the data from a Hashtable whose keys are of type String into the primary data list. Data with non-String keys are ignored.
 o copyMetadata
  public void copyMetadata(Metadata from)
Copy all the data from another Metadata object into the primary data list. (Data with non-String keys are ignored.) Metarunner objects are copied without being executed.
 o setDefaults
  public synchronized void setDefaults(Metadata to)
Set the default Metadata of this Metadata object. The specified defaults replace the one previously in use. This effectively "detaches" this Metadata from its originator and "attaches" it to the caller of this method. If no other object holds a reference to the old defaults, it will get garbage-collected.
 o getDefaults
  public Metadata getDefaults()
return a new Metadata object with the same default data but with no primary data
 o detach
  public final synchronized void detach()
replace the internal default Metadata with a copy (via deepClone()), detaching control of the defaults from the originator of this Metadata. Users should call this method to prevent the originator from updating the defaults later.
 o giveDefaults
  public void giveDefaults(Metadata to)
Copy the default metadata of this Metadata object to the defaults of another Metadata object. Most applications should not need to call this method; in fact, they should avoid it. Because the copy is shallow, it opens the possibility for the data internal to the items held within the default list to become corrupted
Parameters:
to - the other Metadata object to copy defaults to
 o removeAllMetadata
  public void removeAllMetadata()
remove the primary key/value pairs from this Metadata object, leaving the defaults.
 o metadatumNames
  public Enumeration metadatumNames()
Enumerates all the keys.
 o toString
  public String toString()
attempt to convert contents to a multi-line String (useful for debugging
Overrides:
toString in class Hashtable
 o clone
  public Object clone()
Clones this metadata object. The data themselves are not cloned, and the defaults are still in control of this metadata's originator.
Overrides:
clone in class Hashtable
 o detachedClone
  public Metadata detachedClone()
Like clone(), except that a copy of the defaults metadata is also made. This provides a fully metavector object that is fully detached from the originator of this metadata object; that is, the originator can not change the defaults of the new metadata. The elements within both the primary and default arrays are not cloned.
 o cloneDefaults
  public Metadata cloneDefaults()
clone the defaults metadata. The resulting metadata object will not have a defaults list of its own and, therefore, will be detached from the control of other objects. The data held within both the primary and default hashtables are not cloned.
 o deepClone
  public synchronized Metadata deepClone()
create a semi-deep clone. This method is like clone(), except that the Metadata and Metavector objects contained within are replaced with their own clones (using their respecitive deepClone() methods).

All Packages  Class Hierarchy  This Package  Previous  Next  Index