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: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;
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. SinceBaseType
variables now each have their own set ofAttributes
it 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: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; } } }
<?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 theDDSParser
to buildDDS's
but to build them using theDDS
API. This is typical of devlopers writing servers that work with information rich data formats such as NetCDF or HDF. With the addition ofAttributes
(andAttribute
containers) to all of the datatypes in the DAP it is now possible to construct aDDS
that contains all of the source meta-data from the original data source. This is an extremly useful thing. However, when building aDDS
using theDDS
API 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 emptyDDS
with the given dataset name.DDS(String clearname, BaseTypeFactory factory)
Creates an emptyDDS
with the given dataset name andBaseTypeFactory
.DDS(String clearname, BaseTypeFactory factory, String schema)
Creates an emptyDDS
with the given dataset name andBaseTypeFactory
.DDS(BaseTypeFactory factory)
Creates an emptyDDS
with the givenBaseTypeFactory
.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addVariable(BaseType v, int part)
Adds a variable to the container.void
checkForAttributeNameConflict()
Check for name conflicts.void
checkSemantics(boolean all)
Check the semantics of theDDS
.DAPNode
cloneDAG(DAPNode.CloneMap map)
Returns a clone of thisDDS
.void
delVariable(String name)
Removes a variable from theDDS
.String
getBlobContentID()
Get's the dataBLOB Contnet-ID for this DDS.DAS
getDAS()
Creates a DAS object from the collection ofBaseType
variables and their associatedAttributes
.String
getDDSText()
This a wrapper method forDDS.print()
.String
getDDXText()
This a wrapper method forDDS.printXML()
.BaseTypeFactory
getFactory()
Get the Class factory.BaseType
getVariable(String name)
Returns a reference to the named variable.Enumeration
getVariables()
Returns anEnumeration
of the dataset variables.void
ingestDAS(DAS das)
Takes the passed parameterdas
and attempts to incorporate it's contents into the Attributes of the DDS variables.static String
normalize(String field)
Thenormalize
method 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.int
numVariables()
Returns the number of variables in the dataset.boolean
parse(InputStream stream)
boolean
parse(String text)
void
parseXML(InputStream is, boolean validation)
Reads a DDX from the namedInputStream
.void
parseXML(org.jdom2.Document ddxDoc, boolean validation)
Reads a DDX from the namedDocument
.void
print(OutputStream os)
Print theDDS
on the givenOutputStream
.void
print(PrintWriter os)
Print theDDS
on the givenPrintWriter
.void
printDAS(OutputStream os)
Print a DAS constructed from this DDS and it's BaseType variables.void
printDAS(PrintWriter pw)
Print a DAS constructed from this DDS and it's BaseType variables.void
printXML(PrintWriter pw)
Prints the peristent representation of theDDS
as an XML document.void
printXML(PrintWriter pw, String pad, boolean constrained)
Prints the peristent representation of theDDS
as an XML document.void
resolveAliases()
Before the DDS can be used all of the Aliases in the various AttributeTables must be resolved.Stack
search(String name, Stack compStack)
Look forname
in the DDS.void
setBlobContentID(String contentID)
Set's the dataBLOB reference for this DDS.void
setFactory(BaseTypeFactory btf)
Get the Class factory.void
setURL(String url)
static Vector
tokenizeAliasField(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 emptyDDS
with the given dataset name.- Parameters:
clearname
- the dataset name
-
DDS
public DDS(BaseTypeFactory factory)
Creates an emptyDDS
with the givenBaseTypeFactory
. This will be used for OPeNDAP servers which need to construct subclasses of the variousBaseType
objects to hold additional server-side information.- Parameters:
factory
- the serverBaseTypeFactory
object.
-
DDS
public DDS(String clearname, BaseTypeFactory factory)
Creates an emptyDDS
with the given dataset name andBaseTypeFactory
. This will be used for OPeNDAP servers which need to construct subclasses of the variousBaseType
objects to hold additional server-side information.- Parameters:
clearname
- the dataset namefactory
- the serverBaseTypeFactory
object.
-
DDS
public DDS(String clearname, BaseTypeFactory factory, String schema)
Creates an emptyDDS
with the given dataset name andBaseTypeFactory
. This will be used for OPeNDAP servers which need to construct subclasses of the variousBaseType
objects to hold additional server-side information.- Parameters:
clearname
- the dataset namefactory
- the serverBaseTypeFactory
object.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:
ParseException
DAP2Exception
-
parse
public boolean parse(String text) throws ParseException, DAP2Exception
- Throws:
ParseException
DAP2Exception
-
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
- AString
containing 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
String
containing the URL of the servers BLOB response for this DDS.
-
getDAS
public DAS getDAS() throws DASException
Creates a DAS object from the collection ofBaseType
variables and their associatedAttributes
. This DAS is correctly formed (vis-a-vis the DAP specification) for this DDS.- Returns:
- A correctly formed
DAS
object 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
- TheOutputStream
to print to.
-
printDAS
public void printDAS(PrintWriter pw)
Print a DAS constructed from this DDS and it's BaseType variables.- Parameters:
pw
- ThePrintWriter
to 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 thecheckSemantics
method 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:
getVariable
in 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:
addVariable
in classDStructure
- Parameters:
v
- the variable to add.part
- ignored forDSequence
.
-
search
public Stack search(String name, Stack compStack) throws NoSuchVariableException
Look forname
in 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.search
, 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 anEnumeration
of the dataset variables.- Overrides:
getVariables
in classDStructure
- Returns:
- an
Enumeration
ofBaseType
.
-
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 thatDDS
in memory. This method does the following:- Gets a new
DDSXMLParser
using theBaseTypeFactory
held in this (theDDS
) class. - Uses the
DDSXMLParser
to parse the DDX waiting in theInputStream
is. - Calls
DDS.checkForAttributeNameConflict()
- Calls
DDS.resolveAliases()
DDS
is populated with variables ( by a parser, or through theDDS
API) and prior to releasing it for use to any calling program.- Parameters:
is
- the InputStream containing theDDS
to 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 DAP2Exception
Reads a DDX from the namedDocument
. This method calls a generated parser to interpret an XML representation of aDDS
(aka a DDX), and instantiate thatDDS
in memory. This method does the following:- Gets a new
DDSXMLParser
using theBaseTypeFactory
held in this (theDDS
) class. - Uses the
DDSXMLParser
to parse the DDX waiting in theInputStream
is. - Calls
DDS.checkForAttributeNameConflict()
- Calls
DDS.resolveAliases()
DDS
is populated with variables ( by a parser, or through theDDS
API) and prior to releasing it for use to any calling program.- Parameters:
ddxDoc
- A JDOM Document containing theDDS
to 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 BadSemanticsException
Check the semantics of theDDS
. Ifall
is true, check not only the semantics of theDDS
itself, but also recursively check all variables in the dataset.- Overrides:
checkSemantics
in 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 theDDS
on the givenPrintWriter
.- Parameters:
os
- thePrintWriter
to use for output.
-
print
public final void print(OutputStream os)
Print theDDS
on the givenOutputStream
.- Parameters:
os
- theOutputStream
to use for output.- See Also:
print(PrintWriter)
-
resolveAliases
public void resolveAliases() throws MalformedAliasException, UnresolvedAliasException, NoSuchAttributeException
Before 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 passedBaseType
parameter 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)
Thenormalize
method 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 theDDS
as 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 theDDS
as an XML document. This XML document is know as a DDX. The DDX can be parsed using theDDSXMLParser
- Overrides:
printXML
in classDConstructor
- Parameters:
pw
- ThePrintWriter
to print to.pad
- AString
to print at the begining of each line. typically this is some white space.constrained
- Aboolean
that 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 parameterdas
and attempts to incorporate it's contents into the Attributes of the DDS variables. If anAttribute
in theDAS
can'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
- TheDAS
to ingest.
-
checkForAttributeNameConflict
public void checkForAttributeNameConflict() throws BadSemanticsException
Check 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:
cloneDAG
in classDStructure
- Parameters:
map
- track previously cloned nodes- Returns:
- a clone of this DDS.
- Throws:
CloneNotSupportedException
-
-