| <<O>> Difference Topic WritingClient (r1.5 - 13 Mar 2007 - YuanHo) |
| <<O>> Difference Topic WritingClient (r1.4 - 12 Mar 2007 - YuanHo) |
| -- YuanHo - 10 Mar 2007 | |||||||||||||||||||||
| Line: 104 to 104 | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
The DAP uses HTTP which in turn uses MIME
Clients use HTTP when they make requests of DAP servers. HTTP is a fairly
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
straightforward protocol ([ | ||||||||||||||||||||
| > > |
straightforward protocol (for general information on HTTP see www.w3.org/Protocols/, and for the HTTP/1.1 specification, see www.w3.org/Protocols/rfc2616/rfc2616.html). | ||||||||||||||||||||
| It uses pseudo-MIME documents to encapsulate both the request sent from client to server and the response sent back. This is important for the DAP | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
because the DAP uses headers in both the [ | ||||||||||||||||||||
| > > |
because the DAP uses headers in both the request and response | ||||||||||||||||||||
| documents to transfer information. However, for a programmer who intends to write a DAP server, exactly what gets written into those headers and how it gets written is not important. Both the C++ and Java class libraries will | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
handle these tasks for you (look at the [ | ||||||||||||||||||||
| > > |
handle these tasks for you (look at the DODSFilterclass | ||||||||||||||||||||
| to see how). It's important to know about, however, because if you decide not to use the libraries, or the parts that automate generating the correct MIME documents, then your server will have to generate the correct headers itself. | |||||||||||||||||||||
| Line: 127 to 127 | |||||||||||||||||||||
| Descriptor Structure (DDS), Dataset Attribute Structure (DAS), and Data object (DataDDS). These are described in considerable detail in other documentation. The Programmer's Guide contains a description of the | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
[ | ||||||||||||||||||||
| > > |
DDS and DAS objects (see http://www.unidata.ucar.edu/packages/dods/api/pguide-html/)]]. | ||||||||||||||||||||
| These objects contain the name and types of the variables in a dataset, along with any attributes (name-value pairs) bound to the variables. The DataDDS contains data values. We have implemented the SDKs so that the DataDDS is a | |||||||||||||||||||||
| Line: 137 to 137 | |||||||||||||||||||||
|
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
| ||||||||||||||||||||
| > > |
| ||||||||||||||||||||
| |||||||||||||||||||||
| Line: 145 to 146 | |||||||||||||||||||||
| The DAP models all datasets as collections of | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
[ | ||||||||||||||||||||
| > > |
variables. The DDS andDataDDS | ||||||||||||||||||||
| objects are containers for those variables. How you represent your dataset using the three objects and the DAP's data type hierarchy is covered in | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\begin \"Implementing the DDS object" in ''Writing an OPeNDAP Server'' .\\end \
\begin \[<../ws-html/server-implementing-dds.html> | ||||||||||||||||||||
| > > |
Implementing the DDS object | ||||||||||||||||||||
| in ''Writing an OPeNDAP Server'' . | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\end \ | ||||||||||||||||||||
| > > |
|||||||||||||||||||||
The DAP also defines services
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
Information of the DAP services is presented here for completeness and | ||||||||||||||||||||
| > > |
_Information of the DAP services is presented here for completeness and | ||||||||||||||||||||
| because using these can help speed and simplify development of you client. For example, you can use the HTML and ASCII services to look at a data source using only a web browser. Similarly, the INFO response can be used | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
to look at the attributes and variables in a given data source. | ||||||||||||||||||||
| > > |
to look at the attributes and variables in a given data source._ | ||||||||||||||||||||
| In the previous section we said that the DAP defined three objects and | |||||||||||||||||||||
| Line: 174 to 169 | |||||||||||||||||||||
| the DAP also defines other responses. They are: | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\begin{description} \item[ASCII] Data can be requested in CSV form. \item[HTML] Each server can return an HTML form that facilitates building URLs. \item[INFO] Each server can combine the DDS and DAS and present that as HTML. \item[VERSION] Each server must be able to respond to a request for it's version and the version of the DAP it implements. \item[HELP] Each server must be able to provide a rudimentary help response. \end{description} | ||||||||||||||||||||
| > > |
| ||||||||||||||||||||
| In each case the server's response to these requests is built using one or more of the basic three objects. Here are some links to various datasets' ASCII, HTML and INFO responses: | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\begin{tabular}[c]{llll} \[{help} or
| ||||||||||||||||||||
| > > |
| ||||||||||||||||||||
Connecting to the server
| |||||||||||||||||||||
| Line: 229 to 212 | |||||||||||||||||||||
| An OPeNDAP-enabled client application creates a connection to the | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
remote server using the \class{Connect} class, and then issues
requests to the remote server through the \class{Connect} class
methods. Please refer to the [{Geturl.java}>{geturl.cc}> | ||||||||||||||||||||
| > > |
remote server using the {Connect} class, and then issues
requests to the remote server through the | ||||||||||||||||||||
| based DAP client applications written in Java and C++, respectively. Most of the software is boilerplate. Following are sections of the Geturl.java client application, later a description of the same example in C++ will be provided. Again, please refer to the complete source listings referenced above. | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
| ||||||||||||||||||||
| > > |
| ||||||||||||||||||||
| DConnect url = null; try { url = new DConnect(nextURL, accept_deflate); } | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
This code snippet instantiates a new instance of the \class{DConnect} | ||||||||||||||||||||
| > > |
This code snippet instantiates a new instance of the {DConnect}
| ||||||||||||||||||||
| class, passing the URL referencing the remote data server, and a boolean flag indicating that the client can accept responses from the server which are compressed. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
if (get_data) {
if ((cexpr==false) && (nextURL.indexOf('?') == -1)) {
| |||||||||||||||||||||
| Line: 259 to 246 | |||||||||||||||||||||
|
StatusUI | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
DataDDS dds = url.getData(expr, ui); | ||||||||||||||||||||
| > > |
DataDDS | ||||||||||||||||||||
| processData(url, dds, verbose, dump_data, accept_deflate); } catch (DODSException e) { | |||||||||||||||||||||
| Line: 277 to 264 | |||||||||||||||||||||
| } } } | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
| ||||||||||||||||||||
| > > |
|||||||||||||||||||||
| This compound statement block initiaties a data request to the remote | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
server. The \class{DConnect} method {getData} forms the data
| ||||||||||||||||||||
| > > |
server. The {DConnect} method | ||||||||||||||||||||
request to the remote server by appending the string, {expr},
containing the constraint-expression, onto the URL used in creating
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
the initial \class{DConnect} to the remote site. The parameter,
{ui}, provides an optional | ||||||||||||||||||||
| > > |
the initial {DConnect} to the remote site. The parameter,
| ||||||||||||||||||||
| the status of the current request to the client. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
catch (DODSException e) {
System.err.println(e);
| |||||||||||||||||||||
| Line: 300 to 291 | |||||||||||||||||||||
|
System.exit(1);
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| Completing the try block is a series of catch blocks that catch exceptions thrown by the DAP library code, and Java input/output and general exceptions. The C++ toolkit provides similar functionality as the Java toolkit | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
though the parameters to the individual \class{Connect} methods may vary.
The C++ client application [ | ||||||||||||||||||||
| > > |
though the parameters to the individual {Connect} methods may vary.
The C++ client application geturl.cc | ||||||||||||||||||||
| uses the similar C++ toolkit classes as the Java toolkit to implement the Geturl client application: | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
string name = argv[i];
Connect url(name, trace, accept_deflate);
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
This code fragment declares an instance of the \class{Connect} class, | ||||||||||||||||||||
| > > |
This code fragment declares an instance of the {Connect} class,
| ||||||||||||||||||||
| passing the URL referencing the remote data server, and a boolean flag indicating that the client can accept responses from the server that are compressed. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
else if (get_data) {
if (expr.empty() && name.find('?') == string::npos)
| |||||||||||||||||||||
| Line: 339 to 337 | |||||||||||||||||||||
|
}
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| This compound statement block initiaties a data request from the remote | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
server. The \class{Connect} method {request_data} forms the data request
| ||||||||||||||||||||
| > > |
server. The {Connect} method | ||||||||||||||||||||
to the remote server by appending the string, {expr}, containing the
constraint-expression, onto the URL used in creating the initial
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\class{Connect} to the remote site. | ||||||||||||||||||||
| > > |
{Connect} to the remote site.
| ||||||||||||||||||||
catch (Error &e) {
e.display_message();
continue
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| Completing the try block is a catch block that picks up exceptions thrown by the DAP library code. The DAP C++ library throws several types of exceptions, | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
the most common of which are \class{Error} and \class{InternalErr}. All of the exceptions are either instances of \class{Error} or are specializations of it, so catching just \class{Error} will get everything. | ||||||||||||||||||||
| > > |
the most common of which are {Error} and | ||||||||||||||||||||
Subclassing the data types
| |||||||||||||||||||||
| Line: 383 to 386 | |||||||||||||||||||||
georeferenced array data (e.g., a projected satellite image). The DAP does
not have a pointer data type, but in some cases the {Url} data type can
be used as a pointer to variables between files. More information about the
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
[ | ||||||||||||||||||||
| > > |
DAP's data typehierarchy | ||||||||||||||||||||
is given in the Programmer's Guide.
Creating the subclasses
| |||||||||||||||||||||
| Line: 396 to 399 | |||||||||||||||||||||
| the C++ Matlab client. The class is the Byte class. In the case of the matlab client, this class doesn't do anything beyond the bare minimum, so it's a good starting point: | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
Byte *
NewByte | |||||||||||||||||||||
| Line: 413 to 418 | |||||||||||||||||||||
|
throw InternalErr | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
To create a child of any of the data type leaf classes, you must define three
methods and one function. Let's talk about the function first. The function
{NewByte} is what Meyers[[meyers:ecpp]] calls a \emph{virtual
| |||||||||||||||||||||
| Line: 475 to 482 | |||||||||||||||||||||
| a DODS server to a client. Here is the DDS representation of an entire dataset containing a time series of worldwide grids of sea surface temperatures: | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
Dataset {
Grid {
| |||||||||||||||||||||
| Line: 487 to 496 | |||||||||||||||||||||
|
} sst;
} weekly;
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| 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: | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
Dataset {
Grid {
| |||||||||||||||||||||
| Line: 504 to 516 | |||||||||||||||||||||
|
} sst;
} weekly;
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| 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 | |||||||||||||||||||||
| Line: 518 to 531 | |||||||||||||||||||||
| facilitate access to the wide variety of data accessible through OPeNDAP servers. In practice, once you know how to map variables from the DAP into your client application, writing code to build the DDS instance is easy. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
else if (get_dds) {
for (int j = 0; j < times; ++j) {
| |||||||||||||||||||||
| Line: 539 to 554 | |||||||||||||||||||||
|
}
}
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
Above, the \class{Connect} method {request_dds} is called, passing a
| ||||||||||||||||||||
| > > |
Above, the {Connect} method | ||||||||||||||||||||
reference to a DDS object. Following is an example from the C++ Matlab client
illustrates a simple traversal of the DDS object returned from the
{connect::request_data} method.
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
static void
process_data(Connect &url, DDS &dds)
| |||||||||||||||||||||
| Line: 557 to 575 | |||||||||||||||||||||
|
}
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
In the C++ DAP classes STL iterators are used to iterate over the members
(i.e., variables) in the DDS object. The iterator {i} references pointers
to the top-level | |||||||||||||||||||||
| Line: 617 to 638 | |||||||||||||||||||||
|
}
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| 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 GLOBAL attribute provides | |||||||||||||||||||||
| Line: 626 to 649 | |||||||||||||||||||||
packaged for sending (and how it is received).
An example of Attribute handling in a client application is provided in
the {www-int} C++ source:
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
void
LoaddodsProcessing | |||||||||||||||||||||
| Line: 661 to 686 | |||||||||||||||||||||
|
}
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| As with the DDS, the DAS object is a container and STL iterators are used to access its members (the attributes). There are several differences, however, between the two containers. The DDS holds complete objects, each of which is | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
an instance of the class \class{BaseType}. A DAS, however, holds a collection | ||||||||||||||||||||
| > > |
an instance of the class {BaseType}. A DAS, however, holds a collection
| ||||||||||||||||||||
|
of attributes. Unless the attribute is itself a container for other attribute
type-name-value tuples, there is no contained object to access with methods
to run. Instead the DAS and AttrTable | |||||||||||||||||||||
| Line: 682 to 709 | |||||||||||||||||||||
| Up till now we have talked about access to a data source's meta data. The DDS provides access to the syntactic meta data and the DAS provides semantic meta data. Use the DataDDS to access data values held by the data source. | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
The \class{DataDDS} class is an extension of class \class{DDS} which | ||||||||||||||||||||
| > > |
The {DataDDS} class is an extension of class | ||||||||||||||||||||
| contains the binary data values returned by the remote server. It supports | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
the same methods as the class \class{DDS}, but the {BaseType::buf2val()}
| ||||||||||||||||||||
| > > |
the same methods as the class {DDS}, but the | ||||||||||||||||||||
| methods can be used to extract data held in the variable instances of | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\class{BaseType}. Use the \class{DDS}, \class{BaseType} and their iterators | ||||||||||||||||||||
| > > |
{BaseType}. Use the | ||||||||||||||||||||
| to access the variables. | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
Use \class{Connect} to ask a remote server for a \class{DataDDS}. The
\class{Connect} provides {Connect::request_data()} to get the
\class{DataDDS}. The | ||||||||||||||||||||
| > > |
Use {Connect} to ask a remote server for a | ||||||||||||||||||||
| expression which can be used to restrict the data returned by the remote server. See \OPDuser\ for more information about constraint expression syntax.\footnote{The details of the constraint expression syntax are covered in The \xlink{DODS User Guide[constraint]} {\OPDuserUrl/constraint.html}.} | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
Use iterators to traverse the \class{DataDDS} and access the individual DAP | ||||||||||||||||||||
| > > |
Use iterators to traverse the {DataDDS} and access the individual DAP
| ||||||||||||||||||||
| data variable objects. The following example prints the DAP data objects declaration, to access the binary data returned by the server the DAP provides access methods to retrieve the data object's buffer contents. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
static void
process_data(Connect &url, DDS *dds)
| |||||||||||||||||||||
| Line: 712 to 741 | |||||||||||||||||||||
| smart_newline(cout, v->type()); } } | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
|
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
The binary data returned by the server is stored in the {_buf} member of
each of the DAP's atomic data types. To retrieve the atomic data type's
buffer contents the | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
n_bytes = dds->var(q)->buf2val((void **) &localVar);
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
|||||||||||||||||||||
| > > |
|||||||||||||||||||||
| The following C++ example is from the C++ Matlab client application and illustrates the use of the C++ DAP classes and methods to access elements from a \class{Sequence} data type. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
void
ClientSequence | |||||||||||||||||||||
| Line: 748 to 784 | |||||||||||||||||||||
|
}
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
| The C++ client uses rows and columns to access the individual elements of the | |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
\class{Sequence}. The C++ Matlab client uses two methods to accomplish the | ||||||||||||||||||||
| > > |
{Sequence}. The C++ Matlab client uses two methods to accomplish the
| ||||||||||||||||||||
extraction, the first, {print_val_by_row()} determines the number of
| |||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
rows in the \class{Sequence} and calls the {print_one_row()} for each
of the rows in the \class{Sequence}. The C++ DAP implementation of the
\class{Sequence} data type provides the | ||||||||||||||||||||
| > > |
rows in the {Sequence} and calls the | ||||||||||||||||||||
| used. The preceding example simply prints the contents of the element, most client applications would assign the contents to a local variable in the workspace. | |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
void
ClientArray | |||||||||||||||||||||
| Line: 779 to 818 | |||||||||||||||||||||
|
var(i)->print_val(os, "", false);
}
| |||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
|||||||||||||||||||||
Notes
| |||||||||||||||||||||
| <<O>> Difference Topic WritingClient (r1.3 - 12 Mar 2007 - YuanHo) |
| -- YuanHo - 10 Mar 2007 | |||||||||||||||||||||
| Line: 134 to 134 | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| subclass of the DDS object that adds the capacity to store values with each variable. | |||||||||||||||||||||
| Deleted: | |||||||||||||||||||||
| < < |
| ||||||||||||||||||||
| Changed: | |||||||||||||||||||||
| < < |
| ||||||||||||||||||||
| > > |
| ||||||||||||||||||||
| Added: | |||||||||||||||||||||
| > > |
| ||||||||||||||||||||
| The DAP models all datasets as collections of | |||||||||||||||||||||
| <<O>> Difference Topic WritingClient (r1.2 - 12 Mar 2007 - YuanHo) |
| Deleted: | ||||||||
| < < |
||||||||
| -- YuanHo - 10 Mar 2007 | ||||||||
| Line: 136 to 134 | ||||||||
|---|---|---|---|---|---|---|---|---|
| subclass of the DDS object that adds the capacity to store values with each variable. | ||||||||
| Added: | ||||||||
| > > |
| |||||||
| Changed: | ||||||||
| < < |
\begin{tabular}[c]{lll} \[ | |||||||
| > > |
| |||||||
| Added: | ||||||||
| > > |
||||||||
|
The DAP models all datasets as collections of
[ | ||||||||
| Line: 197 to 196 | ||||||||
| one or more of the basic three objects. Here are some links to various datasets' ASCII, HTML and INFO responses: \begin{tabular}[c]{llll} \ | ||||||||
| Changed: | ||||||||
| < < |
[ | |||||||
| > > |
[ | |||||||
|
[ | ||||||||
| <<O>> Difference Topic WritingClient (r1.1 - 10 Mar 2007 - YuanHo) |
| Line: 1 to 1 | ||||||||
|---|---|---|---|---|---|---|---|---|
| Added: | ||||||||
| > > |
-- YuanHo - 10 Mar 2007
Preface
This tutorial describes the steps required to enable your client
application to interact with the OPeNDAP Data Access Protocol by using
the Java or C++ classes provided in the OPeNDAP class libraries. It also
describes the trade offs between using these toolkits and a client-library
interface such as netCDF.
The C++ and Java toolkis are class libraries which provide for direct
interaction with a remote OPeNDAP server. You'll need to write some code.
If your client application currently uses one of the netCDF, GDAL or OGR
APIs, then you only need to relink your application with the OPeNDAP-enabled
version of the API library, allowing you to skip this tutorial entirely.
Writing your own OPeNDAP client
Choose a language
The OPeNDAP project provides both [<\OPDapiUrl>Client Architecture
In essence, an OPeNDAP-enabled client uses overloaded URLs to form the
requests to a remote data server. Through the URL, the client connects to
the remote server and issues one of several requests. In response to
each request, the server will return a well-defined response that the client
can use to intern the structure and content of the remote data into local
data structures, as well as retrieve any attributes associated with the
remote data.
The C++ and Java toolkits share the same characteristics, though the
names of the objects and their methods may be slightly different. If
you understand how the clients are built, it will be easy to see how
your own client application can be OPeNDAP-enabled with minimal
effort. The \OPDapi\ provides a complete description of the C++
Toolkit and the \OPDjavaUrl\ provides a complete description of the
Java toolkit.
The DAP Architecture
The DAP can be thought of as a layered protocol composed of MIME, HTTP, basic
objects, and complex, presentation-style, responses.
The DAP uses HTTP which in turn uses MIME
Clients use HTTP when they make requests of DAP servers. HTTP is a fairly
straightforward protocol ([The DAP defines three objects
To transfer information from servers to clients, the DAP uses three objects.
Whenever a client asks a server for information, it does so by requesting one
of these three objects (note: this is not strictly true, but the whole truth
will be told in just a bit. For now, assume it's true). These are the Dataset
Descriptor Structure (DDS), Dataset Attribute Structure (DAS), and Data
object (DataDDS). These are described in considerable detail in other
documentation. The Programmer's Guide contains a description of the
[The DAP also defines services
Information of the DAP services is presented here for completeness and
because using these can help speed and simplify development of you client.
For example, you can use the HTML and ASCII services to look at a data
source using only a web browser. Similarly, the INFO response can be used
to look at the attributes and variables in a given data source.
In the previous section we said that the DAP defined three objects and
all interaction with the server involved those three objects. In fact,
the DAP also defines other responses. They are:
\begin{description}
\item[ASCII] Data can be requested in CSV form.
\item[HTML] Each server can return an HTML form that facilitates building
URLs.
\item[INFO] Each server can combine the DDS and DAS and present that as
HTML.
\item[VERSION] Each server must be able to respond to a request for it's
version and the version of the DAP it implements.
\item[HELP] Each server must be able to provide a rudimentary help response.
\end{description}
In each case the server's response to these requests is built using
one or more of the basic three objects. Here are some links to
various datasets' ASCII, HTML and INFO responses:
\begin{tabular}[c]{llll} \[{help} or
| |||||||