Package opendap.dap
Class DDS
-
- All Implemented Interfaces:
Serializable,Cloneable,ClientIO
- Direct Known Subclasses:
DataDDS
public class DDS extends DStructure
The OPeNDAP Data Descriptor Object (DDS) is a data structure used by the OPeNDAP software to describe datasets and subsets of those datasets. The DDS may be thought of as the declarations for the data structures that will hold data requested by some OPeNDAP client. Part of the job of a OPeNDAP server is to build a suitable DDS for a specific dataset and to send it to the client. Depending on the data access API in use, this may involve reading part of the dataset and inferring the DDS. Other APIs may require the server simply to read some ancillary data file with the DDS in it. On the server side, in addition to the data declarations, the DDS holds the clauses of any constraint expression that may have accompanied the data request from the OPeNDAP client. The DDS object includes methods for modifying the DDS according to the given constraint expression. It also has methods for directly modifying a DDS, and for transmitting it from a server to a client. For the client, the DDS object includes methods for reading the persistent form of the object sent from a server. This includes parsing the ASCII representation of the object and, possibly, reading data received from a server into a data object. Note that the class DDS is used to instantiate both DDS and DataDDS objects. A DDS that is empty (contains no actual data) is used by servers to send structural information to the client. The same DDS can becomes a DataDDS when data values are bound to the variables it defines. For a complete description of the DDS layout and protocol, please refer to The OPeNDAP User Guide. The DDS has an ASCII representation, which may be transmitted from a OPeNDAP server to a client. Here is the DDS representation of an entire dataset containing a time series of worldwide grids of sea surface temperatures:
If the data request to this dataset includes a constraint expression, the corresponding DDS might be different. For example, if the request was only for northern hemisphere data at a specific time, the above DDS might be modified to appear like this:Dataset { Float64 lat[lat = 180]; Float64 lon[lon = 360]; Float64 time[time = 404]; Grid { ARRAY: Int32 sst[time = 404][lat = 180][lon = 360]; MAPS: Float64 time[time = 404]; Float64 lat[lat = 180]; Float64 lon[lon = 360]; } sst; } weekly;
Since the constraint has narrowed the area of interest, the range of latitude values has been halved, and there is only one time value in the returned array. Note that the simple arrays (lat, lon, and time) described in the dataset are also part of the sst Grid object. They can be requested by themselves or as part of that larger object.Dataset { Grid { ARRAY: Int32 sst[time = 1][lat = 90][lon = 360]; MAPS: Float64 time[time = 1]; Float64 lat[lat = 90]; Float64 lon[lon = 360]; } sst; } weekly;DDX
The DDS also has an XML representation. This is known as a DDX. SinceBaseTypevariables now each have their own set ofAttributesit has become necessary to have a representation of the DDS that captures these relationships. Consider the previous example. A correctly constructed DAS for that DDS might look like:
Combined with the DDS and expressed as a DDX it would look like:Attributes { lat { String fullName "latitude"; String units "degrees North"; } lon { String fullName "longitude"; String units "degrees East"; } time { String units "seconds"; } sst { String fullName "Sea Surface Temperature"; String units "degrees centigrade"; sst { Alias fullName .sst.fullName; Alias units .sst.units; } time { Alias units .time.units; } lat { Alias fullName .lat.fullName; Alias units .lat.units; } lon { Alias fullName .lon.fullName; Alias units .lon.units; } } }
The DDX can also be sent from a server to a client.<?xml version="1.0" encoding="UTF-8"?> <Dataset name="weekly" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xml.opendap.org/ns/DAP2" xsi:schemaLocation="http://xml.opendap.org/ns/DAP2 http://xml.opendap.org/dap/dap2.xsd" > <Array name="lat"> <Attribute name="fullName" type="String"> <value>"latitude"</value> </Attribute> <Attribute name="units" type="String"> <value>"degrees North"</value> </Attribute> <Float64/> <dimension name="lat" size="180"/> </Array> <Array name="lon"> <Attribute name="fullName" type="String"> <value>"longitude"</value> </Attribute> <Attribute name="units" type="String"> <value>"degrees East"</value> </Attribute> <Float64/> <dimension name="lon" size="360"/> </Array> <Array name="time"> <Attribute name="units" type="String"> <value>"seconds"</value> </Attribute> <Float64/> <dimension name="time" size="404"/> </Array> <Grid name="sst"> <Attribute name="fullName" type="String"> <value>"Sea Surface Temperature"</value> </Attribute> <Attribute name="units" type="String"> <value>"degrees centigrade"</value> </Attribute> <Array name="sst"> <Alias name="fullName" Attribute=".sst.fullName"/> <Alias name="units" Attribute=".sst.units"/> <Int32/> <dimension name="time" size="404"/> <dimension name="lat" size="180"/> <dimension name="lon" size="360"/> </Array> <Map name="time"> <Alias name="units" Attribute=".time.units"/> <Float64/> <dimension name="time" size="404"/> </Map> <Map name="lat"> <Alias name="fullName" Attribute=".lat.fullName"/> <Alias name="units" Attribute=".lat.units"/> <Float64/> <dimension name="lat" size="180"/> </Map> <Map name="lon"> <Alias name="fullName" Attribute=".lon.fullName"/> <Alias name="units" Attribute=".lon.units"/> <Float64/> <dimension name="lon" size="360"/> </Map> </Grid> <dataBLOB href="cid:ContentIdOfTheMIMEAttcahmentContainingTheDataBlob"/> </Dataset>
Using the DDS's API to construct a DDS
Many developers choose not to use theDDSParserto buildDDS'sbut to build them using theDDSAPI. This is typical of devlopers writing servers that work with information rich data formats such as NetCDF or HDF. With the addition ofAttributes(andAttributecontainers) to all of the datatypes in the DAP it is now possible to construct aDDSthat contains all of the source meta-data from the original data source. This is an extremly useful thing. However, when building aDDSusing theDDSAPI be sure to call the functionsDDS.checkForAttributeNameConflict()andDDS.resolveAliases()on the new DDS prior to releasing it from the code that builds it. Otherwise the DDS may have functional problems! See The OPeNDAP User Guide, or the documentation of the BaseType class for descriptions of the OPeNDAP data types.
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class opendap.dap.DAPNode
DAPNode.CloneMap
-
-
Field Summary
-
Fields inherited from class opendap.dap.DStructure
vars
-
Fields inherited from class opendap.dap.DAPNode
_nameClear, _nameEncoded, log
-
-
Constructor Summary
Constructors Constructor Description DDS()Creates an emptyDDS.DDS(String clearname)Creates an emptyDDSwith the given dataset name.DDS(String clearname, BaseTypeFactory factory)Creates an emptyDDSwith the given dataset name andBaseTypeFactory.DDS(String clearname, BaseTypeFactory factory, String schema)Creates an emptyDDSwith the given dataset name andBaseTypeFactory.DDS(BaseTypeFactory factory)Creates an emptyDDSwith the givenBaseTypeFactory.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description voidaddVariable(BaseType v, int part)Adds a variable to the container.voidcheckForAttributeNameConflict()Check for name conflicts.voidcheckSemantics(boolean all)Check the semantics of theDDS.DAPNodecloneDAG(DAPNode.CloneMap map)Returns a clone of thisDDS.voiddelVariable(String name)Removes a variable from theDDS.StringgetBlobContentID()Get's the dataBLOB Contnet-ID for this DDS.DASgetDAS()Creates a DAS object from the collection ofBaseTypevariables and their associatedAttributes.StringgetDDSText()This a wrapper method forDDS.print().StringgetDDXText()This a wrapper method forDDS.printXML().BaseTypeFactorygetFactory()Get the Class factory.BaseTypegetVariable(String name)Returns a reference to the named variable.EnumerationgetVariables()Returns anEnumerationof the dataset variables.voidingestDAS(DAS das)Takes the passed parameterdasand attempts to incorporate it's contents into the Attributes of the DDS variables.static Stringnormalize(String field)Thenormalizemethod is used to normalize variable and attribute name strings prior to their comparison with the normalized tokens extracted from the variable and name fields in an Alias declaration.intnumVariables()Returns the number of variables in the dataset.booleanparse(InputStream stream)booleanparse(String text)voidparseXML(InputStream is, boolean validation)Reads a DDX from the namedInputStream.voidparseXML(org.jdom2.Document ddxDoc, boolean validation)Reads a DDX from the namedDocument.voidprint(OutputStream os)Print theDDSon the givenOutputStream.voidprint(PrintWriter os)Print theDDSon the givenPrintWriter.voidprintDAS(OutputStream os)Print a DAS constructed from this DDS and it's BaseType variables.voidprintDAS(PrintWriter pw)Print a DAS constructed from this DDS and it's BaseType variables.voidprintXML(PrintWriter pw)Prints the peristent representation of theDDSas an XML document.voidprintXML(PrintWriter pw, String pad, boolean constrained)Prints the peristent representation of theDDSas an XML document.voidresolveAliases()Before the DDS can be used all of the Aliases in the various AttributeTables must be resolved.Stacksearch(String name, Stack compStack)Look fornamein the DDS.voidsetBlobContentID(String contentID)Set's the dataBLOB reference for this DDS.voidsetFactory(BaseTypeFactory btf)Get the Class factory.voidsetURL(String url)static VectortokenizeAliasField(String field)ThetokenizeAliasFiled()method is used to tokenize the variable and the attribute fields in the alias declaration.-
Methods inherited from class opendap.dap.DStructure
deserialize, elementCount, externalize, getTypeName, getVar, getVarCount, getVariableSet, printDecl, printVal
-
Methods inherited from class opendap.dap.DConstructor
addVariable, someChildHasAttributes
-
Methods inherited from class opendap.dap.BaseType
addAttributeAlias, addAttributeContainer, appendAttribute, appendAttribute, appendAttributeContainer, checkSemantics, delAttribute, delAttribute, elementCount, getAttribute, getAttribute, getAttributeNames, getAttributeTable, getLongName, hasAttributes, newPrimitiveVector, printAttributes, printAttributes, printAttributes, printAttributes, printConstraint, printDecl, printDecl, printDecl, printDecl, printDecl, printDecl, printDecl, printVal, printVal, printVal, printXML, printXML, printXML, setClearName
-
Methods inherited from class opendap.dap.DAPNode
clone, cloneDAG, getClearName, getEncodedName, getParent, isProject, setEncodedName, setParent, setProject, setProject, setProjected
-
-
-
-
Constructor Detail
-
DDS
public DDS()
Creates an emptyDDS.
-
DDS
public DDS(String clearname)
Creates an emptyDDSwith the given dataset name.- Parameters:
clearname- the dataset name
-
DDS
public DDS(BaseTypeFactory factory)
Creates an emptyDDSwith the givenBaseTypeFactory. This will be used for OPeNDAP servers which need to construct subclasses of the variousBaseTypeobjects to hold additional server-side information.- Parameters:
factory- the serverBaseTypeFactoryobject.
-
DDS
public DDS(String clearname, BaseTypeFactory factory)
Creates an emptyDDSwith the given dataset name andBaseTypeFactory. This will be used for OPeNDAP servers which need to construct subclasses of the variousBaseTypeobjects to hold additional server-side information.- Parameters:
clearname- the dataset namefactory- the serverBaseTypeFactoryobject.
-
DDS
public DDS(String clearname, BaseTypeFactory factory, String schema)
Creates an emptyDDSwith the given dataset name andBaseTypeFactory. This will be used for OPeNDAP servers which need to construct subclasses of the variousBaseTypeobjects to hold additional server-side information.- Parameters:
clearname- the dataset namefactory- the serverBaseTypeFactoryobject.schema- the URL where the parser can find an instance of the OPeNDAP namespace schema.
-
-
Method Detail
-
setURL
public void setURL(String url)
-
parse
public boolean parse(InputStream stream) throws ParseException, DAP2Exception
- Throws:
ParseExceptionDAP2Exception
-
parse
public boolean parse(String text) throws ParseException, DAP2Exception
- Throws:
ParseExceptionDAP2Exception
-
getFactory
public final BaseTypeFactory getFactory()
Get the Class factory. This is the machine that builds classes for the internal representation of the data set.- Returns:
- the BaseTypeFactory.
-
setFactory
public final void setFactory(BaseTypeFactory btf)
Get the Class factory. This is the machine that builds classes for the internal representation of the data set.
-
setBlobContentID
public void setBlobContentID(String contentID)
Set's the dataBLOB reference for this DDS. The dataBLOB element has an attribute, href, which is used to reference the MIME part of a the Multipart MIME document in a DAP4 data response that contains the binary encoded data described by the DDX document.- Parameters:
contentID- AStringcontaining the Content-ID of the MIME part that contains the binary encoded data represented by this DDS.
-
getBlobContentID
public String getBlobContentID()
Get's the dataBLOB Contnet-ID for this DDS. The dataBLOB element has an attribute, href, which is used to reference the MIME part of a the Multipart MIME document in a DAP4 data response that contains the binary encoded data described by the DDX document.- Returns:
- A
Stringcontaining the URL of the servers BLOB response for this DDS.
-
getDAS
public DAS getDAS() throws DASException
Creates a DAS object from the collection ofBaseTypevariables and their associatedAttributes. This DAS is correctly formed (vis-a-vis the DAP specification) for this DDS.- Returns:
- A correctly formed
DASobject for this DDS. - Throws:
DASException- See Also:
DAS,BaseType
-
printDAS
public void printDAS(OutputStream os)
Print a DAS constructed from this DDS and it's BaseType variables.- Parameters:
os- TheOutputStreamto print to.
-
printDAS
public void printDAS(PrintWriter pw)
Print a DAS constructed from this DDS and it's BaseType variables.- Parameters:
pw- ThePrintWriterto print to.
-
delVariable
public void delVariable(String name)
Removes a variable from theDDS. Does nothing if the variable can't be found. If there are multiple variables with the same name, only the first will be removed. To detect this, call thecheckSemanticsmethod to verify that each variable has a unique name.- Parameters:
name- the name of the variable to remove.- See Also:
checkSemantics(boolean)
-
getVariable
public BaseType getVariable(String name) throws NoSuchVariableException
Returns a reference to the named variable.- Overrides:
getVariablein classDStructure- Parameters:
name- the name of the variable to return.- Returns:
- the variable named
name. - Throws:
NoSuchVariableException- if the variable isn't found.
-
addVariable
public void addVariable(BaseType v, int part)
Adds a variable to the container. This overrides the getVariable() in DStructure in order to keep the parent value from getting set. Otherwise the name of the DDS (which is typically the name of the Dataset) will appear in calls to BaseType.getLongName().This might be a mistake!!! Watch out for bugs induced by this method.
- Overrides:
addVariablein classDStructure- Parameters:
v- the variable to add.part- ignored forDSequence.
-
search
public Stack search(String name, Stack compStack) throws NoSuchVariableException
Look fornamein the DDS. Start the search using the ctor variable (or array/list of ctors) found on the top of the StackcompStack(for component stack). When the named variable is found, return the stack compStack modified so that it now contains each ctor-type variable that on the path to the named variable. If the variable is not found after exhausting all possibilities, throw NoSuchVariable.
Note: This method takes the stack as a parameter so that it can be used by a parser that is working through a list of identifiers that represents the path to a variable as well as a shorthand notation for the identifier that is the equivalent to the leaf node name alone. In the form case the caller helps build the stack by repeatedly callingsearch, in the latter case this method must build the stack itself. This method is over kill for the first case.- Parameters:
name- Search for the named variable.compStack- The component stack. This holds the BaseType variables that match the each component of a specific variable's name. This method starts its search using the element at the top of the stack and adds to the stack. The order of BaseType variables on the stack is the reverse of the tree-traverse order. That is, the top most element on the stack is the BaseType for the named variable, under that is the named variable's parent and so on.- Returns:
- A stack of BaseType variables which hold the path from the top of the DDS to the named variable.
- Throws:
NoSuchVariableException
-
getVariables
public final Enumeration getVariables()
Returns anEnumerationof the dataset variables.- Overrides:
getVariablesin classDStructure- Returns:
- an
EnumerationofBaseType.
-
numVariables
public final int numVariables()
Returns the number of variables in the dataset.- Returns:
- the number of variables in the dataset.
-
parseXML
public void parseXML(InputStream is, boolean validation) throws DAP2Exception
Reads a DDX from the namedInputStream. This method calls a generated parser to interpret an XML representation of aDDS(aka a DDX), and instantiate thatDDSin memory. This method does the following:- Gets a new
DDSXMLParserusing theBaseTypeFactoryheld in this (theDDS) class. - Uses the
DDSXMLParserto parse the DDX waiting in theInputStreamis. - Calls
DDS.checkForAttributeNameConflict() - Calls
DDS.resolveAliases()
DDSis populated with variables ( by a parser, or through theDDSAPI) and prior to releasing it for use to any calling program.- Parameters:
is- the InputStream containing theDDSto parse.validation- Is a boolean indicating whether or not the parser should validate the XML document using the Schema (typically referenced in the document itself). In general server side applications should always vaidate, while clients shouldn't bother (since they are ostensibly receiving the document from a server that has already done so.)- Throws:
DDSException- thrown on an error constructing theDDS.DAP2Exception- See Also:
DDSXMLParser,checkForAttributeNameConflict(),resolveAliases()
- Gets a new
-
parseXML
public void parseXML(org.jdom2.Document ddxDoc, boolean validation) throws DAP2ExceptionReads a DDX from the namedDocument. This method calls a generated parser to interpret an XML representation of aDDS(aka a DDX), and instantiate thatDDSin memory. This method does the following:- Gets a new
DDSXMLParserusing theBaseTypeFactoryheld in this (theDDS) class. - Uses the
DDSXMLParserto parse the DDX waiting in theInputStreamis. - Calls
DDS.checkForAttributeNameConflict() - Calls
DDS.resolveAliases()
DDSis populated with variables ( by a parser, or through theDDSAPI) and prior to releasing it for use to any calling program.- Parameters:
ddxDoc- A JDOM Document containing theDDSto parse.validation- Is a boolean indicating whether or not the parser should validate the XML document using the Schema (typically referenced in the document itself). In general server side applications should always vaidate, while clients shouldn't bother (since they are ostensibly receiving the document from a server that has already done so.)- Throws:
DDSException- thrown on an error constructing theDDS.DAP2Exception- See Also:
DDSXMLParser,checkForAttributeNameConflict(),resolveAliases()
- Gets a new
-
checkSemantics
public void checkSemantics(boolean all) throws BadSemanticsExceptionCheck the semantics of theDDS. Ifallis true, check not only the semantics of theDDSitself, but also recursively check all variables in the dataset.- Overrides:
checkSemanticsin classDStructure- Parameters:
all- this flag indicates whether to check the semantics of the member variables, too.- Throws:
BadSemanticsException- if semantics are bad- See Also:
BaseType.checkSemantics(boolean)
-
print
public void print(PrintWriter os)
Print theDDSon the givenPrintWriter.- Parameters:
os- thePrintWriterto use for output.
-
print
public final void print(OutputStream os)
Print theDDSon the givenOutputStream.- Parameters:
os- theOutputStreamto use for output.- See Also:
print(PrintWriter)
-
resolveAliases
public void resolveAliases() throws MalformedAliasException, UnresolvedAliasException, NoSuchAttributeExceptionBefore the DDS can be used all of the Aliases in the various AttributeTables must be resolved. This means that it is necessary to verify that each Alias references an Attribute that exists, and is not another Alias. This is accomplished by searching the DDS's variable's attribute holdings for Aliases Everytime an Alias is located, a new search begins to find the Attribute that the Alias is attemoting to reference. This method recursively searchs through the passedBaseTypeparameter bt for Alias members of AttributeTables, and when they are found attempts to resolve them to a specific Attribute. This method should be called ONLY after the entire DDS has been parsed and /or built using the DDS API.This method should/must always be called prior to using a DDS!
This method manipulates the global (private) variablecurrentBT. This method manipulates the global (private) variablecurrentAT.
-
normalize
public static String normalize(String field)
Thenormalizemethod is used to normalize variable and attribute name strings prior to their comparison with the normalized tokens extracted from the variable and name fields in an Alias declaration. The rule for this normalization is as follows:- The " (double quote) and the \ (backslash, aka escape) characters MUST be escaped (using the \ character) in the variable and attribute fields.
- Parameters:
field- The string to be normalized.- Returns:
- The "normalized" string.
-
tokenizeAliasField
public static Vector tokenizeAliasField(String field) throws MalformedAliasException
ThetokenizeAliasFiled()method is used to tokenize the variable and the attribute fields in the alias declaration. It is required that these fields be normalized in the XML instance document. The rules for this normalization are as follows:- The " (double quote) and the \ (backslash, aka escape) characters MUST be escaped (using the \ character) in the variable and attribute fields.
- The variable and attribute fields must be enclosed in double quotes if their values contain the dot (.) character.
- Fully qualified variable and attribute names always begin with the dot (.) character.
- Parameters:
field- The string to be tokenized.- Returns:
- The tokenized string.
- Throws:
MalformedAliasException
-
printXML
public void printXML(PrintWriter pw)
Prints the peristent representation of theDDSas an XML document. This XML document is know as a DDX. The DDX can be parsed using theDDSXMLParser
-
printXML
public void printXML(PrintWriter pw, String pad, boolean constrained)
Prints the peristent representation of theDDSas an XML document. This XML document is know as a DDX. The DDX can be parsed using theDDSXMLParser- Overrides:
printXMLin classDConstructor- Parameters:
pw- ThePrintWriterto print to.pad- AStringto print at the begining of each line. typically this is some white space.constrained- Abooleanthat indcates if the this call should print the constrained version of the DDS. A value of true will cause the only the projected variables of the DDX to be printed .
-
ingestDAS
public void ingestDAS(DAS das)
Takes the passed parameterdasand attempts to incorporate it's contents into the Attributes of the DDS variables. If anAttributein theDAScan't be associated with a variable in a logical manner then it is placed at the top level of the DDS. (Basically it becomes a toplevel attribute in the dataset)- Parameters:
das- TheDASto ingest.
-
checkForAttributeNameConflict
public void checkForAttributeNameConflict() throws BadSemanticsExceptionCheck for name conflicts. In the XML representation of the DDS it is syntactically possible for a variable container (Dconstructor) to possess an Attribute that has the same name as one of the container variable's member variables. That's a NO-NO!. Check for it here and throw a nice fat exception if we find it.- Throws:
BadSemanticsException
-
getDDSText
public String getDDSText()
This a wrapper method forDDS.print().- Returns:
- The output of
DDS.print()asString - See Also:
print(PrintWriter)
-
getDDXText
public String getDDXText()
This a wrapper method forDDS.printXML().- Returns:
- The output of
DDS.printXML()asString - See Also:
printXML(PrintWriter)
-
cloneDAG
public DAPNode cloneDAG(DAPNode.CloneMap map) throws CloneNotSupportedException
Returns a clone of thisDDS. See DAPNode.cloneDag()- Overrides:
cloneDAGin classDStructure- Parameters:
map- track previously cloned nodes- Returns:
- a clone of this DDS.
- Throws:
CloneNotSupportedException
-
-