/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1998, California Institute of Technology.
// ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged.
//
// Please read the full copyright notice in the file COPYRIGHT
// in this directory.
//
// Author: Jake Hamby, NASA/Jet Propulsion Laboratory
// Jake.Hamby@jpl.nasa.gov
/////////////////////////////////////////////////////////////////////////////
package dods.dap;
import java.util.Enumeration;
import dods.util.SortedTable;
import dods.dap.parser.DASParser;
import dods.dap.parser.ParseException;
import java.io.*;
/**
* The Data Attribute Structure is a set of name-value pairs used to
* describe the data in a particular dataset. The name-value pairs
* are called the "attributes." The values may be of any of the
* DODS simple data types (DByte, DInt32, DUInt32, DFloat64, DString and
* DURL), and may be scalar or vector. (Note that all values are
* actually stored as string data.)
* <p>
* A value may also consist of a set of other name-value pairs. This
* makes it possible to nest collections of attributes, giving rise
* to a hierarchy of attributes. DODS uses this structure to provide
* information about variables in a dataset.
* <p>
* In the following example of a DAS, several of the attribute
* collections have names corresponding to the names of variables in
* a hypothetical dataset. The attributes in that collection are said to
* belong to that variable. For example, the <code>lat</code> variable has an
* attribute <code>units</code> of <code>degrees_north</code>.
*
* <blockquote><pre>
* Attributes {
* GLOBAL {
* String title "Reynolds Optimum Interpolation (OI) SST";
* }
* lat {
* String units "degrees_north";
* String long_name "Latitude";
* Float64 actual_range 89.5, -89.5;
* }
* lon {
* String units "degrees_east";
* String long_name "Longitude";
* Float64 actual_range 0.5, 359.5;
* }
* time {
* String units "days since 1-1-1 00:00:00";
* String long_name "Time";
* Float64 actual_range 726468., 729289.;
* String delta_t "0000-00-07 00:00:00";
* }
* sst {
* String long_name "Weekly Means of Sea Surface Temperature";
* Float64 actual_range -1.8, 35.09;
* String units "degC";
* Float64 add_offset 0.;
* Float64 scale_factor 0.0099999998;
* Int32 missing_value 32767;
* }
* }
* </pre></blockquote>
*
* Attributes may have arbitrary names, although in most datasets it
* is important to choose these names so a reader will know what they
* describe. In the above example, the <code>GLOBAL</code> attribute provides
* information about the entire dataset.
* <p>
* Data attribute information is an important part of the the data
* provided to a DODS client by a server, and the DAS is how this
* data is packaged for sending (and how it is received).
*
* @version $Revision: 1.2 $
* @author jehamby
* @see DDS
* @see AttributeTable
* @see Attribute
*/
public class DAS implements Cloneable {
/** A table containing AttributeTables with their names as a key */
private SortedTable attr;
/** Create a new empty <code>DAS</code>. */
public DAS() {
attr = new SortedTable();
}
/**
* Returns a clone of this <code>DAS</code>. A deep copy is performed on
* all <code>AttributeTable</code>s inside the <code>DAS</code>.
*
* @return a clone of this <code>DAS</code>.
*/
public Object clone() {
try {
DAS d = (DAS)super.clone();
d.attr = new SortedTable();
for(int i=0; i<attr.size(); i++) {
String key = (String)attr.getKey(i);
AttributeTable element = (AttributeTable)attr.elementAt(i);
// clone element (don't clone key because it's a read-only String)
d.attr.put(key, element.clone());
}
return d;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* Returns an <code>Enumeration</code> of the attribute names in this
* <code>DAS</code>.
* Use the <code>getAttributeTable</code> method to get the
* <code>AttributeTable</code> for a given name.
*
* @return an <code>Enumeration</code> of <code>String</code>.
* @see DAS#getAttributeTable(String)
*/
public final Enumeration getNames() {
return attr.keys();
}
/**
* Returns the <code>AttributeTable</code> with the given name.
*
* @param name the name of the <code>AttributeTable</code> to return.
* @return the <code>AttributeTable</code> with the specified name, or null
* if there is no matching <code>AttributeTable</code>.
* @see AttributeTable
*/
public final AttributeTable getAttributeTable(String name) {
return (AttributeTable)attr.get(name);
}
/**
* Adds an <code>AttributeTable</code> to the DAS.
*
* @param name the name of the <code>AttributeTable</code> to add.
* @param a the <code>AttributeTable</code> to add.
* @see AttributeTable
*/
public void addAttributeTable(String name, AttributeTable a) {
attr.put(name, a);
}
/**
* Reads a <code>DAS</code> from the named <code>InputStream</code>. This
* method calls a generated parser to interpret an ASCII representation of a
* <code>DAS</code>, and regenerate that <code>DAS</code> in memory.
*
* @param is the <code>InputStream</code> containing the <code>DAS</code> to
* parse.
* @exception ParseException error in parser.
* @exception DASException error in constructing <code>DAS</code>.
* @exception dods.dap.parser.TokenMgrError error in token manager
* (unterminated quote).
* @see dods.dap.parser.DASParser
*/
public void parse(InputStream is) throws ParseException, DASException {
DASParser dp = new DASParser(is);
dp.Attributes(this);
}
/**
* Print the <code>DAS</code> on the given <code>PrintWriter</code>.
*
* @param os the <code>PrintWriter</code> to use for output.
*/
public void print(PrintWriter os) {
os.println("Attributes {");
for (Enumeration e = getNames(); e.hasMoreElements() ;) {
String name = (String)e.nextElement();
os.println(" " + name + " {");
getAttributeTable(name).print(os, " ");
os.println(" }");
}
os.println("}");
os.flush();
}
/**
* Print the <code>DAS</code> on the given <code>OutputStream</code>.
*
* @param os the <code>OutputStream</code> to use for output.
* @see DAS#print(PrintWriter)
*/
public final void print(OutputStream os) {
print(new PrintWriter(new BufferedWriter(new OutputStreamWriter(os))));
}
}