<<O>>  Difference Topic WritingClient (r1.5 - 13 Mar 2007 - YuanHo)

-- YuanHo - 10 Mar 2007
Deleted:
<
<

Preface

This tutorial describes the steps required to enable your client

Line: 137 to 136

Changed:
<
<
DatasetName DatasetURL DASType DDSType
COADS Climatology http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.dds
NASA Scatterometer Data http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.ascii?Wind_Speed http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.dds
Catalog of AVHRR Files http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.dds
AHVRR Image http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.ascii?dsp_band_1" http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.dds
>
>
DatasetURL DASType DDSType
COADS Climatology DAS DDS
NASA Scatterometer Data DAS DDS
Catalog of AVHRR Files DAS DDS
AHVRR Image DAS DDS

Line: 161 to 160

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: 188 to 187

DataseProvider DatasetASCIIURL: HTML: INFO:
Changed:
<
<
COADS Climatology http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.asc?SST http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.info
NASA Scatterometer Data http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.ascii?Wind_Speed http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.dds
Catalog of AVHRR Files http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.ascii?year,day_num,DODS_URL&day_num http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.info
AHVRR Image http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.ascii?dsp_band_1" http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.info
>
>
COADS Climatology SST HTML INFO
NASA Scatterometer Data WindSpeed HTML INFO
Catalog of AVHRR Files DATE HTML INFO
AHVRR Image DSP Band HTML INFO


 <<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 [] and []
>
>
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:
<
<
DatasetName DatasetURL DASType DDSType
>
>
DatasetName DatasetURL DASType DDSType

COADS Climatology http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.dds
NASA Scatterometer Data http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.ascii?Wind_Speed http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.dds
Catalog of AVHRR Files http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.dds
Line: 145 to 146

The DAP models all datasets as collections of

Changed:
<
<
[]. The []
>
>
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}
>
>

Object: Response
ASCII Data can be requested in CSV form.
HTML Each server can return an HTML form that facilitates building URLs.
INFO] Each server can combine the DDS and DAS and present that as HTML.
VERSION Each server must be able to respond to a request for it's version and the version of the DAP it implements.
HELP Each server must be able to provide a rudimentary help response.


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} \[] & [] & [] & [] \[] & [] \Catalog of AVHRR Files & [] & [] \[] & [] \\end{tabular}

The VERSION and HELP responses can be see by appending

{help} or
{version} to the end of the server's base URL. For example:
\begin{tabular}[c]{l} \[]\[]\\end{tabular}
>
>

DataseProvider DatasetASCIIURL: HTML: INFO:
COADS Climatology http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.asc?SST http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.info
NASA Scatterometer Data http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.ascii?Wind_Speed http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.dds
Catalog of AVHRR Files http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.ascii?year,day_num,DODS_URL&day_num http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.info
AHVRR Image http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.ascii?dsp_band_1" http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.info


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}>] and
[<
{geturl.cc}>] sources as examples of command-line
>
>
remote server using the {Connect} class, and then issues requests to the remote server through the {Connect} class methods. Please refer to the Geturl.java and geturl.cc sources as examples of command-line

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 ui = null; if (gui) ui = new StatusWindow(nextURL);
Changed:
<
<
DataDDS dds = url.getData(expr, ui);
>
>
DataDDS dds = url.getData(expr, ui);

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 {getData} forms the data

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
{StatusWindow} object to provide
>
>
the initial {DConnect} to the remote site. The parameter, {ui}, provides an optional {StatusWindow} object to provide

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
{request_data} forms the data request

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 {InternalErr}. All of the exceptions are either instances of {Error} or are specializations of it, so catching just {Error} will get everything.

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(const string &n)
Line: 413 to 418

throw InternalErr(FILE, LINE, "Called unimplemented read method"); }
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

{request_dds} is called, passing a

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 
{BaseType} objects held by the DDS. See
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::print_attr_table(AttrTable &at, ostream &os)
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 classes themselves provide methods that
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 {DDS} which

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
{BaseType::buf2val()}

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 {DDS}, {BaseType} and their iterators

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 
{request_data()} method accepts a constraint
>
>
Use {Connect} to ask a remote server for a {DataDDS}. The {Connect} provides
{Connect::request_data()} to get the
{DataDDS}. The 
{request_data()} method accepts a constraint

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 
{BaseType::buf2val} method is used.
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::print_one_row(ostream &os, int row, string space,
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 
{ var_value(row,col)} method to
access the individual elements of the \class{Sequence}. The
{var_value()} method returns a \class{BaseType} pointer to the row,
column element of the \class{Sequence}. To access the binary data value
stored in that element, the \class{BaseType} method 
{buf2val()} can be
>
>
rows in the {Sequence} and calls the
{print_one_row()} for each
of the rows in the {Sequence}. The C++ DAP implementation of the
{Sequence} data type provides the 
{ var_value(row,col)} method to
access the individual elements of the {Sequence}. The
{var_value()} method returns a {BaseType} pointer to the row,
column element of the {Sequence}. To access the binary data value
stored in that element, the {BaseType} method 
{buf2val()} can be

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::print_val(ostream &os, string, bool print_decl_p)
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:
<
<
Dataset DASType DDSType
| |
| |
| |
| |
>
>

Added:
>
>
DatasetName DatasetURL DASType DDSType
COADS Climatology http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/nc/coads_climatology.nc.dds
NASA Scatterometer Data http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.ascii?Wind_Speed http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/hdf/S2000415.HDF.dds
Catalog of AVHRR Files http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.html http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/ff/1998-6-avhrr.dat.dds
AHVRR Image http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.ascii?dsp_band_1" http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.das http://dodsdev.gso.uri.edu/dods-3.4/nph-dods/data/dsp/east.coast.pvu.dds

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} \[] & [] & [] \[] & [] \Catalog of AVHRR Files & [] & [] \[] & [] \\end{tabular}
>
>
Dataset DASType DDSType
| |
| |
| |
| |

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:
<
<
[] & [] &
>
>
[] & [] &

[] & [] \[<ref="http://localhost/dods-3.4/nph-dods/data/hdf/S2000415.HDF.ascii?Wind_Speed

 <<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>] and [<\OPDjavaUrl>] implementations of the DAP. Each library includes classes that implement the various objects which comprise the DAP software for building clients. Each also includes some extra software which simplifies building clients by managing virtual connections, handling data caching, et cetera. To choose one of the toolkits, several factors should be weighed. With which of the two programming languages are you most comfortable? What type of computer will the client run on? For client development, both Java and C++ are supported on win32 and Unix architectures. Java is more likely to be supported on other architectures, such as Mac. The DAP library is middle-ware. You can use it to build a completely new client or to add network data access to an existing program (making it a client). If you're interested in writing a client from scratch, simply choose the toolkit/language you feel most comfortable. If you're going to take an existing program and transform it into a client there are several additional factors beyond programming language you should consider. If the program you want to DAP-enable can read netCDF files, by far the easiest way to achieve your goal is to use our DAP-enable netCDF ''client library'' (CL). This piece of software works like the standard netCDF CL but has been modified to recognize DAP URLs when they are presented in place of local file names. The OPeNDAP netCDF CL has exactly the same functional interface as the standard netCDF library available from Unidata. That makes it a very powerful tool because it is possible to tap into a large number of existing programs and build OPeNDAP clients. Ferret, GRrADS and IDV are complex programs which have been OPeNDAP-enabled using the netCDF CL. Using the netCDF CL is not without its caveats. First netCDF does not do a good job of representing the entire OPeNDAP data model (That's not a dig at netCDF, it's a reflection of different design goals for two pieces of software). It's very hard to access point data using the netCDF CL, although we're working on this problem. Second, the C++ DAP library is used to build the C version of the netCDF CL\footnote{Unidata bundles OPeNDAP access with their standard release of the Java version of netCDF.} which means that the application programs ''must'' be linked use a C++ compiler. Finally, it can be tricky to build a shared object (aka DLL) using the C++ DAP library.\footnote{As the C++ ABI becomes more widely supported, this situation should change.} If you're going to do that, please contact us through user support or the technical discussion list. However, while the previous points are true, the principle distinction between using the netCDF CL and one of the DAP class libraries is that with the netcDF CL you often do not have to write any new software at all! If you choose to use one of the DAP libraries, you're going to have to write some code. If you plan to OPeNDAP-enable an existing application using the Java toolkit, the application typically must provide a Java Virtual Machine (VM). You may be able to side-step this if you feel you can rely on the host OS to provide a JVM and/or your target program already has a JVM embedded in it. Still you must be sure there is a way to communicate data values between the DAP library and the application. To use the C++ toolkit you should insure that your client application can be built with, or link with libraries constructed using C++ compilers.\footnote{As of winter 2004 we're using gcc 2.95.x, 3.2, 3.3 and MS Visual C++.} Check the current list of supported architectures on the web-site, or contact the DODS technical support (\OPDsupport), or write to the \OPDtechList\ mailing list for information and/or help. This tutorial will focus on using the C++ toolkit. In Section~2 the main programmatic differences between the two class libraries is listed. Both toolkits are essentially the same, with only minor differences between them.

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 ([], []). 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 because the DAP uses headers in both the [] and [] 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 handle these tasks for you (look at the [] 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.

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 []. 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 subclass of the DDS object that adds the capacity to store values with each variable.

\begin{tabular}[c]{lll} \[] & [] & [] \[] & [] \Catalog of AVHRR Files & [] & [] \[] & [] \\end{tabular}

The DAP models all datasets as collections of []. The [] 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

\begin \"Implementing the DDS object" in ''Writing an OPeNDAP Server'' .\\end \ \begin \[<../ws-html/server-implementing-dds.html>] \in ''Writing an OPeNDAP Server'' . \end \ 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} \[] & [] & [] & [] \[] & [] \Catalog of AVHRR Files & [] & [] \[] & [] \\end{tabular}

The VERSION and HELP responses can be see by appending

{help} or
{version} to the end of the server's base URL. For example:
\begin{tabular}[c]{l} \[]\[]\\end{tabular}

==Connecting to the server==

  
To manage the connection between the client application and the remote
server, the DAP uses two objects.  The \class{Connect} class manages
one connection to either a remote data server, or a local access.  The
\class{Connections} class is used to manage a set of instances to the
class \class{Connect}.  For each data source that the client
opens, there must be exactly one instance of the \class{Connect}
class.  The \OPDapi\ provides a description for the C++ toolkit's
usage.

=Getting ready to write your client=

  
An OPeNDAP-enabled client application creates a connection to the
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}>] and
[<
{geturl.cc}>] sources as examples of command-line
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.

DConnect url = null; try { url = new DConnect(nextURL, accept_deflate); }
This code snippet instantiates a new instance of the \class{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.
if (get_data) { if ((cexpr==false) && (nextURL.indexOf('?') == -1)) { System.err.println("Must supply a constraint expression with -D."); continue; } for (int j=0; j
This compound statement block initiaties a data request to the remote server. The \class{DConnect} method
{getData} forms the data
request to the remote server by appending the string, {expr},
containing the constraint-expression, onto the URL used in creating
the initial \class{DConnect} to the remote site.  The parameter,
{ui}, provides an optional 
{StatusWindow} object to provide
the status of the current request to the client.

catch (DODSException e) { System.err.println(e); System.exit(1); } catch (java.io.FileNotFoundException e) { System.err.println(e); System.exit(1); } catch (Exception e) { System.err.println(e); e.printStackTrace(); System.exit(1); }
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 though the parameters to the individual \class{Connect} methods may vary. The C++ client application [] uses the similar C++ toolkit classes as the Java toolkit to implement the Geturl client application:
string name = argv[i]; Connect url(name, trace, accept_deflate);
This code fragment declares an instance of the \class{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.
else if (get_data) { if (expr.empty() && name.find('?') == string::npos) expr = ""; for (int j = 0; j < times; ++j) { DataDDS dds; try { DBG(cerr << "URL: " << url->URL(false) << endl); DBG(cerr << "CE: " << expr << endl); url->request_data(dds, expr