Blame DDS.h

Packit a4aae4
// -*- mode: c++; c-basic-offset:4 -*-
Packit a4aae4
Packit a4aae4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
Packit a4aae4
// Access Protocol.
Packit a4aae4
Packit a4aae4
// Copyright (c) 2002,2003 OPeNDAP, Inc.
Packit a4aae4
// Author: James Gallagher <jgallagher@opendap.org>
Packit a4aae4
//
Packit a4aae4
// This library is free software; you can redistribute it and/or
Packit a4aae4
// modify it under the terms of the GNU Lesser General Public
Packit a4aae4
// License as published by the Free Software Foundation; either
Packit a4aae4
// version 2.1 of the License, or (at your option) any later version.
Packit a4aae4
//
Packit a4aae4
// This library is distributed in the hope that it will be useful,
Packit a4aae4
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4aae4
// Lesser General Public License for more details.
Packit a4aae4
//
Packit a4aae4
// You should have received a copy of the GNU Lesser General Public
Packit a4aae4
// License along with this library; if not, write to the Free Software
Packit a4aae4
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit a4aae4
//
Packit a4aae4
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
Packit a4aae4
Packit a4aae4
// (c) COPYRIGHT URI/MIT 1994-1999
Packit a4aae4
// Please read the full copyright statement in the file COPYRIGHT_URI.
Packit a4aae4
//
Packit a4aae4
// Authors:
Packit a4aae4
//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
Packit a4aae4
Packit a4aae4
// Provide access to the DDS. This class is used to parse DDS text files, to
Packit a4aae4
// produce a printed representation of the in-memory variable table, and to
Packit a4aae4
// update the table on a per-variable basis.
Packit a4aae4
//
Packit a4aae4
// jhrg 9/8/94
Packit a4aae4
Packit a4aae4
#ifndef _dds_h
Packit a4aae4
#define _dds_h 1
Packit a4aae4
Packit a4aae4
#include <cstdio>
Packit a4aae4
#include <iostream>
Packit a4aae4
#include <string>
Packit a4aae4
#include <vector>
Packit a4aae4
Packit a4aae4
#ifndef _basetype_h
Packit a4aae4
#include "BaseType.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef _constructor_h
Packit a4aae4
#include "Constructor.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef base_type_factory_h
Packit a4aae4
#include "BaseTypeFactory.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef _das_h
Packit a4aae4
#include "DAS.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef A_DapObj_h
Packit a4aae4
#include "DapObj.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef KEYWORDS_H_
Packit a4aae4
#include "Keywords2.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef XMLWRITER_H_
Packit a4aae4
#include "XMLWriter.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
using std::cout;
Packit a4aae4
Packit a4aae4
namespace libdap
Packit a4aae4
{
Packit a4aae4
Packit a4aae4
/** The DAP2 Data Descriptor Object (DDS) is a data structure used by
Packit a4aae4
    the DAP2 software to describe datasets and subsets of those
Packit a4aae4
    datasets.  The DDS may be thought of as the declarations for the
Packit a4aae4
    data structures that will hold data requested by some DAP2 client.
Packit a4aae4
    Part of the job of a DAP2 server is to build a suitable DDS for a
Packit a4aae4
    specific dataset and to send it to the client.  Depending on the
Packit a4aae4
    data access API in use, this may involve reading part of the
Packit a4aae4
    dataset and inferring the DDS.  Other APIs may require the server
Packit a4aae4
    simply to read some ancillary data file with the DDS in it.
Packit a4aae4
Packit a4aae4
    On the server side, in addition to the data declarations, the DDS
Packit a4aae4
    holds the clauses of any constraint expression that may have
Packit a4aae4
    accompanied the data request from the DAP2 client.  The DDS object
Packit a4aae4
    includes methods for modifying the DDS according to the given
Packit a4aae4
    constraint expression.  It also has methods for directly modifying
Packit a4aae4
    a DDS, and for transmitting it from a server to a client.
Packit a4aae4
Packit a4aae4
    For the client, the DDS object includes methods for reading the
Packit a4aae4
    persistent form of the object sent from a server. This includes parsing
Packit a4aae4
    the ASCII representation of the object and, possibly, reading data
Packit a4aae4
    received from a server into a data object.
Packit a4aae4
Packit a4aae4
    Note that the class DDS is used to instantiate both DDS and DataDDS
Packit a4aae4
    objects. A DDS that is empty (contains no actual data) is used by servers
Packit a4aae4
    to send structural information to the client. The same DDS can becomes a
Packit a4aae4
    DataDDS when data values are bound to the variables it defines.
Packit a4aae4
Packit a4aae4
    For a complete description of the DDS layout and protocol, please
Packit a4aae4
    refer to The OPeNDAP User Guide.
Packit a4aae4
Packit a4aae4
    The DDS has an ASCII representation, which is what is transmitted
Packit a4aae4
    from a DAP2 server to a client.  Here is the DDS representation of
Packit a4aae4
    an entire dataset containing a time series of worldwide grids of
Packit a4aae4
    sea surface temperatures:
Packit a4aae4
Packit a4aae4
    
Packit a4aae4
    Dataset {
Packit a4aae4
        Float64 lat[lat = 180];
Packit a4aae4
        Float64 lon[lon = 360];
Packit a4aae4
        Float64 time[time = 404];
Packit a4aae4
        Grid {
Packit a4aae4
         ARRAY:
Packit a4aae4
            Int32 sst[time = 404][lat = 180][lon = 360];
Packit a4aae4
         MAPS:
Packit a4aae4
            Float64 time[time = 404];
Packit a4aae4
            Float64 lat[lat = 180];
Packit a4aae4
            Float64 lon[lon = 360];
Packit a4aae4
        } sst;
Packit a4aae4
    } weekly;
Packit a4aae4
    
Packit a4aae4
Packit a4aae4
    If the data request to this dataset includes a constraint
Packit a4aae4
    expression, the corresponding DDS might be different.  For
Packit a4aae4
    example, if the request was only for northern hemisphere data
Packit a4aae4
    at a specific time, the above DDS might be modified to appear like
Packit a4aae4
    this:
Packit a4aae4
Packit a4aae4
    
Packit a4aae4
    Dataset {
Packit a4aae4
        Grid {
Packit a4aae4
         ARRAY:
Packit a4aae4
            Int32 sst[time = 1][lat = 90][lon = 360];
Packit a4aae4
         MAPS:
Packit a4aae4
            Float64 time[time = 1];
Packit a4aae4
            Float64 lat[lat = 90];
Packit a4aae4
            Float64 lon[lon = 360];
Packit a4aae4
        } sst;
Packit a4aae4
    } weekly;
Packit a4aae4
    
Packit a4aae4
Packit a4aae4
    Since the constraint has narrowed the area of interest, the range
Packit a4aae4
    of latitude values has been halved, and there is only one time
Packit a4aae4
    value in the returned array.  Note that the simple arrays (<tt>lat</tt>,
Packit a4aae4
    <tt>lon</tt>, and <tt>time</tt>) described in the dataset are also
Packit a4aae4
    part of the <tt>sst</tt> Grid object.  They can be requested by
Packit a4aae4
    themselves or as part of that larger object.
Packit a4aae4
Packit a4aae4
    See the The OPeNDAP User Guide, or the documentation of the
Packit a4aae4
    BaseType class for descriptions of the DAP2 data types.
Packit a4aae4
Packit a4aae4
    @note Make sure to pass a valid pointer to the DDS constructor or use
Packit a4aae4
    the set_factory() method before actually using the DDS. Also make sure
Packit a4aae4
    that the Factory's lifetime thereafter is the same as the DDS's. Never
Packit a4aae4
    delete the factory until you're done using the DDS.
Packit a4aae4
Packit a4aae4
    @note Update: I removed the DEFAULT_BASETYPE_FACTORY switch because it
Packit a4aae4
    caused more confusion than it avoided. See Trac #130. jhrg
Packit a4aae4
Packit a4aae4
    @note The compile-time symbol DEFAULT_BASETYPE_FACTORY controls whether
Packit a4aae4
    the old (3.4 and earlier) DDS and DataDDS constructors are supported.
Packit a4aae4
    These constructors now use a default factory class (BaseTypeFactory,
Packit a4aae4
    implemented by this library) to instantiate Byte, ..., Grid variables. To
Packit a4aae4
    use the default ctor in your code you must also define this symbol. If
Packit a4aae4
    you \e do choose to define this and fail to provide a specialization of
Packit a4aae4
    BaseTypeFactory when your software needs one, you code may not link or
Packit a4aae4
    may fail at run time. In addition to the older ctors for DDS and DataDDS,
Packit a4aae4
    defining the symbol also makes some of the older methods in Connect
Packit a4aae4
    available (because those methods require the older DDS and DataDDS ctors.
Packit a4aae4
Packit a4aae4
    @see BaseType
Packit a4aae4
    @see DAS */
Packit a4aae4
Packit a4aae4
class DDS : public DapObj
Packit a4aae4
{
Packit a4aae4
private:
Packit a4aae4
    BaseTypeFactory *d_factory;
Packit a4aae4
Packit a4aae4
    string d_name;                // The dataset d_name
Packit a4aae4
    string d_filename;		    // File d_name (or other OS identifier) for
Packit a4aae4
    string d_container_name;	// d_name of container structure
Packit a4aae4
    Structure *d_container; 	// current container for container d_name
Packit a4aae4
				                // dataset or part of dataset.
Packit a4aae4
Packit a4aae4
    int d_dap_major;       	    // The protocol major version number
Packit a4aae4
    int d_dap_minor;       	    // ... and minor version number
Packit a4aae4
    string d_dap_version; 	    // String version of the protocol
Packit a4aae4
    string d_request_xml_base;
Packit a4aae4
    string d_namespace;
Packit a4aae4
Packit a4aae4
    AttrTable d_attr;           // Global attributes.
Packit a4aae4
Packit a4aae4
    vector<BaseType *> vars;    // Variables at the top level
Packit a4aae4
Packit a4aae4
    int d_timeout;              // alarm time in seconds. If greater than
Packit a4aae4
                                // zero, raise the alarm signal if more than
Packit a4aae4
                                // d_timeout seconds are spent reading data.
Packit a4aae4
    Keywords d_keywords;	    // Holds keywords parsed from the CE
Packit a4aae4
Packit a4aae4
    long d_max_response_size;   // In bytes...
Packit a4aae4
Packit a4aae4
    friend class DDSTest;
Packit a4aae4
Packit a4aae4
protected:
Packit a4aae4
    void duplicate(const DDS &dds;;
Packit a4aae4
    BaseType *leaf_match(const string &name, BaseType::btp_stack *s = 0);
Packit a4aae4
    BaseType *exact_match(const string &name, BaseType::btp_stack *s = 0);
Packit a4aae4
Packit a4aae4
public:
Packit a4aae4
    typedef std::vector<BaseType *>::const_iterator Vars_citer ;
Packit a4aae4
    typedef std::vector<BaseType *>::iterator Vars_iter ;
Packit a4aae4
    typedef std::vector<BaseType *>::reverse_iterator Vars_riter ;
Packit a4aae4
Packit a4aae4
    DDS(BaseTypeFactory *factory, const string &name = "");
Packit a4aae4
    DDS(BaseTypeFactory *factory, const string &name, const string &version);
Packit a4aae4
    DDS(const DDS &dds;;
Packit a4aae4
Packit a4aae4
    virtual ~DDS();
Packit a4aae4
Packit a4aae4
    DDS & operator=(const DDS &rhs;;
Packit a4aae4
Packit a4aae4
    virtual void transfer_attributes(DAS *das);
Packit a4aae4
Packit a4aae4
    string get_dataset_name() const;
Packit a4aae4
    void set_dataset_name(const string &n);
Packit a4aae4
Packit a4aae4
    /** Return the factory which makes instances of the Byte, ..., Grid
Packit a4aae4
        type classes. Specialize BaseTypeFactory so that a DDS will be
Packit a4aae4
        populated with your client or server's specialized types.
Packit a4aae4
        @return An instance of BaseTypeFactory. */
Packit a4aae4
    BaseTypeFactory *get_factory() const
Packit a4aae4
    {
Packit a4aae4
        return d_factory;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    /** Set the factory class used to instantiate variables during the
Packit a4aae4
        parse of a DDS.
Packit a4aae4
        @param factory The factory this DDS should use. Caller must free
Packit a4aae4
        factory when done with this DDS.
Packit a4aae4
        @return The old factory.
Packit a4aae4
        @see BaseTypeFactory */
Packit a4aae4
    BaseTypeFactory *set_factory(BaseTypeFactory *factory)
Packit a4aae4
    {
Packit a4aae4
        BaseTypeFactory *t = d_factory;
Packit a4aae4
        d_factory = factory;
Packit a4aae4
        return t;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    virtual AttrTable &get_attr_table();
Packit a4aae4
Packit a4aae4
    string filename() const;
Packit a4aae4
    void filename(const string &fn);
Packit a4aae4
Packit a4aae4
    /// Get the DAP major version as sent by the client
Packit a4aae4
    int get_dap_major() const { return d_dap_major; }
Packit a4aae4
    /// Get the DAP minor version as sent by the client
Packit a4aae4
    int get_dap_minor() const { return d_dap_minor; }
Packit a4aae4
Packit a4aae4
    void set_dap_version(const string &version_string = "2.0");
Packit a4aae4
    string get_dap_version() const { return d_dap_version; }
Packit a4aae4
    string get_dmr_version() const { return "1.0"; }
Packit a4aae4
Packit a4aae4
    /// @deprecated
Packit a4aae4
    void set_dap_major(int p);
Packit a4aae4
    /// @deprecated
Packit a4aae4
    void set_dap_minor(int p);
Packit a4aae4
    /// @deprecated
Packit a4aae4
    void set_dap_version(double d);
Packit a4aae4
Packit a4aae4
    Keywords &get_keywords() { return d_keywords; }
Packit a4aae4
Packit a4aae4
    /// Get the URL that will return this DDS/DDX/DataThing
Packit a4aae4
    string get_request_xml_base() const { return d_request_xml_base; }
Packit a4aae4
Packit a4aae4
    /// @see get_request_xml_base
Packit a4aae4
    void set_request_xml_base(const string &xb) { d_request_xml_base = xb; }
Packit a4aae4
Packit a4aae4
    /// Get the namespace associated with the DDS - likely set only by DDX responses
Packit a4aae4
    string get_namespace() const { return d_namespace; }
Packit a4aae4
Packit a4aae4
    /// Set the namespace for this DDS/DDX object/response
Packit a4aae4
    void set_namespace(const string &ns) { d_namespace = ns; }
Packit a4aae4
Packit a4aae4
    /// Get the maximum response size, in KB. Zero indicates no limit.
Packit a4aae4
    long get_response_limit() { return d_max_response_size; }
Packit a4aae4
Packit a4aae4
    /** Set the maximum response size. Zero is the default value. The size
Packit a4aae4
        is given in kilobytes.
Packit a4aae4
        @param size The maximum size of the response in kilobytes. */
Packit a4aae4
    void set_response_limit(long size) { d_max_response_size = size * 1024; }
Packit a4aae4
Packit a4aae4
    /// Get the estimated response size.
Packit a4aae4
    int get_request_size(bool constrained);
Packit a4aae4
Packit a4aae4
    string container_name() ;
Packit a4aae4
    void container_name( const string &cn ) ;
Packit a4aae4
    Structure *container() ;
Packit a4aae4
Packit a4aae4
    void add_var(BaseType *bt);
Packit a4aae4
    void add_var_nocopy(BaseType *bt);
Packit a4aae4
Packit a4aae4
    /// Removes a variable from the DDS.
Packit a4aae4
    void del_var(const string &n);
Packit a4aae4
Packit a4aae4
    BaseType *var(const string &n, BaseType::btp_stack &s);
Packit a4aae4
    BaseType *var(const string &n, BaseType::btp_stack *s = 0);
Packit a4aae4
    int num_var();
Packit a4aae4
Packit a4aae4
    /// Return an iterator to the first variable
Packit a4aae4
    Vars_iter var_begin();
Packit a4aae4
#if 0
Packit a4aae4
    /// Return a const iterator.
Packit a4aae4
    Vars_citer var_cbegin() const { return vars.cbegin(); }
Packit a4aae4
#endif
Packit a4aae4
    /// Return a reverse iterator
Packit a4aae4
    Vars_riter var_rbegin();
Packit a4aae4
    /// Return an iterator
Packit a4aae4
    Vars_iter var_end();
Packit a4aae4
#if 0
Packit a4aae4
    /// Return a const iterator
Packit a4aae4
    Vars_citer var_cend() const { return vars.cend(); }
Packit a4aae4
#endif
Packit a4aae4
    /// Return a reverse iterator
Packit a4aae4
    Vars_riter var_rend();
Packit a4aae4
    /// Get an iterator
Packit a4aae4
    Vars_iter get_vars_iter(int i);
Packit a4aae4
    /// Get a variable
Packit a4aae4
    BaseType *get_var_index(int i);
Packit a4aae4
    /// Insert a variable before the referenced element
Packit a4aae4
    void insert_var(Vars_iter i, BaseType *ptr);
Packit a4aae4
    void insert_var_nocopy(Vars_iter i, BaseType *ptr);
Packit a4aae4
    /// Removes a variable from the DDS.
Packit a4aae4
    void del_var(Vars_iter i);
Packit a4aae4
    /// Removes a range of variables from the DDS.
Packit a4aae4
    void del_var(Vars_iter i1, Vars_iter i2);
Packit a4aae4
Packit a4aae4
    /** @name DDS_timeout
Packit a4aae4
     *  Old deprecated DDS timeout code
Packit a4aae4
     *  @deprecated
Packit a4aae4
     */
Packit a4aae4
    ///@{
Packit a4aae4
    void timeout_on();
Packit a4aae4
    void timeout_off();
Packit a4aae4
    void set_timeout(int t);
Packit a4aae4
    int get_timeout();
Packit a4aae4
    //@}
Packit a4aae4
Packit a4aae4
    // These parse the DAP2 curly-brace document and make a C++ object.
Packit a4aae4
    void parse(string fname);
Packit a4aae4
    void parse(int fd);
Packit a4aae4
    void parse(FILE *in = stdin);
Packit a4aae4
Packit a4aae4
    // These print the Binary object in either the curly-brace or XML reps
Packit a4aae4
    void print(FILE *out);
Packit a4aae4
    void print_constrained(FILE *out);
Packit a4aae4
    void print_xml(FILE *out, bool constrained, const string &blob = "");
Packit a4aae4
Packit a4aae4
    // Same as above, but using C++ i/o streams
Packit a4aae4
    void print(ostream &out;;
Packit a4aae4
    void print_constrained(ostream &out;;
Packit a4aae4
    void print_xml(ostream &out, bool constrained, const string &blob = "");
Packit a4aae4
Packit a4aae4
    // Print the XML using libxml2; the other print_xml methods use this impl.
Packit a4aae4
    void print_xml_writer(ostream &out, bool constrained, const string &blob = "");
Packit a4aae4
Packit a4aae4
    // Print the DAP4 DMR 'object'
Packit a4aae4
    void print_dmr(ostream &out, bool constrained);
Packit a4aae4
Packit a4aae4
    void print_das(ostream &out;;
Packit a4aae4
Packit a4aae4
    void mark_all(bool state);
Packit a4aae4
    bool mark(const string &name, bool state);
Packit a4aae4
    bool check_semantics(bool all = false);
Packit a4aae4
Packit a4aae4
    void tag_nested_sequences();
Packit a4aae4
Packit a4aae4
    virtual void dump(ostream &strm) const ;
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
} // namespace libdap
Packit a4aae4
Packit a4aae4
#endif // _dds_h