|
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 |
//
|
|
Packit |
a4aae4 |
// jhrg 9/7/94
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cstdio>
|
|
Packit |
a4aae4 |
#include <cmath>
|
|
Packit |
a4aae4 |
#include <sys/types.h>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
#include <io.h>
|
|
Packit |
a4aae4 |
#include <process.h>
|
|
Packit |
a4aae4 |
#include <fstream>
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
#include <unistd.h> // for alarm and dup
|
|
Packit |
a4aae4 |
#include <sys/wait.h>
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
#include <algorithm>
|
|
Packit |
a4aae4 |
#include <functional>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// #define DODS_DEBUG
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG2
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "GNURegex.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "DAS.h"
|
|
Packit |
a4aae4 |
#include "Clause.h"
|
|
Packit |
a4aae4 |
#include "Error.h"
|
|
Packit |
a4aae4 |
#include "InternalErr.h"
|
|
Packit |
a4aae4 |
#include "Keywords2.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "parser.h"
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Byte.h"
|
|
Packit |
a4aae4 |
#include "Int16.h"
|
|
Packit |
a4aae4 |
#include "UInt16.h"
|
|
Packit |
a4aae4 |
#include "Int32.h"
|
|
Packit |
a4aae4 |
#include "UInt32.h"
|
|
Packit |
a4aae4 |
#include "Float32.h"
|
|
Packit |
a4aae4 |
#include "Float64.h"
|
|
Packit |
a4aae4 |
#include "Str.h"
|
|
Packit |
a4aae4 |
#include "Url.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
#include "Structure.h"
|
|
Packit |
a4aae4 |
#include "Sequence.h"
|
|
Packit |
a4aae4 |
#include "Grid.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* ############################################################################################
|
|
Packit |
a4aae4 |
* ############################################################################################
|
|
Packit |
a4aae4 |
* ############################################################################################
|
|
Packit |
a4aae4 |
* DapXmlNamespaces
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* FIXME Replace all usages of the following variable with calls to DapXmlNamespaces
|
|
Packit |
a4aae4 |
* TODO Replace all usages of the following variable with calls to DapXmlNamespaces
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
const string c_xml_xsi = "http://www.w3.org/2001/XMLSchema-instance";
|
|
Packit |
a4aae4 |
const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string grddl_transformation_dap32 = "http://xml.opendap.org/transforms/ddxToRdfTriples.xsl";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string c_default_dap20_schema_location = "http://xml.opendap.org/dap/dap2.xsd";
|
|
Packit |
a4aae4 |
const string c_default_dap32_schema_location = "http://xml.opendap.org/dap/dap3.2.xsd";
|
|
Packit |
a4aae4 |
const string c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string c_dap20_namespace = "http://xml.opendap.org/ns/DAP2";
|
|
Packit |
a4aae4 |
const string c_dap32_namespace = "http://xml.opendap.org/ns/DAP/3.2#";
|
|
Packit |
a4aae4 |
const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string c_dap_20_n_sl = c_dap20_namespace + " " + c_default_dap20_schema_location;
|
|
Packit |
a4aae4 |
const string c_dap_32_n_sl = c_dap32_namespace + " " + c_default_dap32_schema_location;
|
|
Packit |
a4aae4 |
const string c_dap_40_n_sl = c_dap40_namespace + " " + c_default_dap40_schema_location;
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* DapXmlNamespaces
|
|
Packit |
a4aae4 |
* ############################################################################################
|
|
Packit |
a4aae4 |
* ############################################################################################
|
|
Packit |
a4aae4 |
* ############################################################################################
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace std;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int ddsparse(libdap::parser_arg *arg);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Glue for the DDS parser defined in dds.lex
|
|
Packit |
a4aae4 |
void dds_switch_to_buffer(void *new_buffer);
|
|
Packit |
a4aae4 |
void dds_delete_buffer(void * buffer);
|
|
Packit |
a4aae4 |
void *dds_buffer(FILE *fp);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::duplicate(const DDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering DDS::duplicate... " <
|
|
Packit |
a4aae4 |
#if 0
|
|
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 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_factory = dds.d_factory;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_name = dds.d_name;
|
|
Packit |
a4aae4 |
d_filename = dds.d_filename;
|
|
Packit |
a4aae4 |
d_container_name = dds.d_container_name;
|
|
Packit |
a4aae4 |
d_container = dds.d_container;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_dap_major = dds.d_dap_major;
|
|
Packit |
a4aae4 |
d_dap_minor = dds.d_dap_minor;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_dap_version = dds.d_dap_version; // String version of the protocol
|
|
Packit |
a4aae4 |
d_request_xml_base = dds.d_request_xml_base;
|
|
Packit |
a4aae4 |
d_namespace = dds.d_namespace;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_attr = dds.d_attr;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS &dds_tmp = const_cast<DDS &>(dds);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// copy the things pointed to by the list, not just the pointers
|
|
Packit |
a4aae4 |
for (Vars_iter i = dds_tmp.var_begin(); i != dds_tmp.var_end(); i++) {
|
|
Packit |
a4aae4 |
add_var(*i); // add_var() dups the BaseType.
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_timeout = dds.d_timeout;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_keywords = dds.d_keywords; // value copy; Keywords contains no pointers
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_max_response_size = dds.d_max_response_size;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Make a DDS which uses the given BaseTypeFactory to create variables.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note The default DAP version is 3.2 - this is really DAP2 with a handful
|
|
Packit |
a4aae4 |
* of enhancements that our WCS software relies on.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param factory The BaseTypeFactory to use when creating instances of
|
|
Packit |
a4aae4 |
* DAP variables. The caller must ensure the factory's lifetime is at least
|
|
Packit |
a4aae4 |
* that of the DDS instance.
|
|
Packit |
a4aae4 |
* @param name The name of the DDS - usually derived from the name of the
|
|
Packit |
a4aae4 |
* pathname or table name of the dataset.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DDS::DDS(BaseTypeFactory *factory, const string &name)
|
|
Packit |
a4aae4 |
: d_factory(factory), d_name(name), d_container_name(""), d_container(0),
|
|
Packit |
a4aae4 |
d_request_xml_base(""),
|
|
Packit |
a4aae4 |
d_timeout(0), d_keywords(), d_max_response_size(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Building a DDS for the default version (2.0)" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This method sets a number of values, including those returned by
|
|
Packit |
a4aae4 |
// get_protocol_major(), ..., get_namespace().
|
|
Packit |
a4aae4 |
set_dap_version("2.0");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Make a DDS with the DAP protocol set to a specific value. This method
|
|
Packit |
a4aae4 |
* provides an easy way to build DDS objects for use in a server or client
|
|
Packit |
a4aae4 |
* that will process DAP4, for example. It's roughly equivalent to calling
|
|
Packit |
a4aae4 |
* set_dap_version() after making an instance using
|
|
Packit |
a4aae4 |
* DDS::DDS(BaseTypeFactory *, const string &).
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param factory The BaseTypeFactory to use when creating instances of
|
|
Packit |
a4aae4 |
* DAP variables. The caller must ensure the factory's lifetime is at least
|
|
Packit |
a4aae4 |
* that of the DDS instance.
|
|
Packit |
a4aae4 |
* @param name The name of the DDS - usually derived from the name of the
|
|
Packit |
a4aae4 |
* pathname or table name of the dataset.
|
|
Packit |
a4aae4 |
* @param version The DAP version to support. This sets the DAP version, as
|
|
Packit |
a4aae4 |
* well as a number of other dependent constants.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DDS::DDS(BaseTypeFactory *factory, const string &name, const string &version)
|
|
Packit |
a4aae4 |
: d_factory(factory), d_name(name), d_container_name(""), d_container(0),
|
|
Packit |
a4aae4 |
d_request_xml_base(""),
|
|
Packit |
a4aae4 |
d_timeout(0), d_keywords(), d_max_response_size(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Building a DDS for version: " << version << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This method sets a number of values, including those returned by
|
|
Packit |
a4aae4 |
// get_protocol_major(), ..., get_namespace().
|
|
Packit |
a4aae4 |
set_dap_version(version);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The DDS copy constructor. */
|
|
Packit |
a4aae4 |
DDS::DDS(const DDS &rhs) : DapObj()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering DDS(const DDS &rhs) ..." << endl);
|
|
Packit |
a4aae4 |
duplicate(rhs);
|
|
Packit |
a4aae4 |
DBG(cerr << " bye." << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS::~DDS()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// delete all the variables in this DDS
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
BaseType *btp = *i ;
|
|
Packit |
a4aae4 |
delete btp ; btp = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS &
|
|
Packit |
a4aae4 |
DDS::operator=(const DDS &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering DDS::operator= ..." << endl);
|
|
Packit |
a4aae4 |
if (this == &rhs)
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
duplicate(rhs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << " bye." << endl);
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* This is the main method used to transfer attributes from a DAS object into a
|
|
Packit |
a4aae4 |
* DDS. This uses the BaseType::transfer_attributes() method and the various
|
|
Packit |
a4aae4 |
* implementations found here (in the constructors classes) and in handlers.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* This method uses a deep copy to transfer the attributes, so it is safe to
|
|
Packit |
a4aae4 |
* delete the source DAS object passed to this method once it is done.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note To accommodate oddly built DAS objects produced by various handlers,
|
|
Packit |
a4aae4 |
* specialize the methods there.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param das Transfer (copy) attributes from this DAS object.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void DDS::transfer_attributes(DAS *das)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// If there is a container set in the DDS then check the container from
|
|
Packit |
a4aae4 |
// the DAS. If they are not the same container, then throw an exception
|
|
Packit |
a4aae4 |
// (should be working on the same container). If the container does not
|
|
Packit |
a4aae4 |
// exist in the DAS, then throw an exception
|
|
Packit |
a4aae4 |
if (d_container && das->container_name() != d_container_name)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__,
|
|
Packit |
a4aae4 |
"Error transferring attributes: working on a container in dds, but not das");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Give each variable a chance to claim its attributes.
|
|
Packit |
a4aae4 |
AttrTable *top = das->get_top_level_attributes();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = var_begin(), e = var_end(); i != e; i++) {
|
|
Packit |
a4aae4 |
(*i)->transfer_attributes(top);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
Vars_iter var = var_begin();
|
|
Packit |
a4aae4 |
while (var != var_end()) {
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
DBG(cerr << "Processing the attributes for: " << (*var)->d_name() << " a " << (*var)->type_name() << endl);
|
|
Packit |
a4aae4 |
(*var)->transfer_attributes(top);
|
|
Packit |
a4aae4 |
var++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Got this exception: " << e.get_error_message() << endl);
|
|
Packit |
a4aae4 |
var++;
|
|
Packit |
a4aae4 |
throw e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
// Now we transfer all of the attributes still marked as global to the
|
|
Packit |
a4aae4 |
// global container in the DDS.
|
|
Packit |
a4aae4 |
for (AttrTable::Attr_iter i = top->attr_begin(), e = top->attr_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->type == Attr_container && (*i)->attributes->is_global_attribute()) {
|
|
Packit |
a4aae4 |
// copy the source container so that the DAS passed in can be
|
|
Packit |
a4aae4 |
// deleted after calling this method.
|
|
Packit |
a4aae4 |
AttrTable *at = new AttrTable(*(*i)->attributes);
|
|
Packit |
a4aae4 |
d_attr.append_container(at, at->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter at_cont_p = top_level->attr_begin();
|
|
Packit |
a4aae4 |
while (at_cont_p != top_level->attr_end()) {
|
|
Packit |
a4aae4 |
// In truth, all of the top level attributes should be containers, but
|
|
Packit |
a4aae4 |
// this test handles the abnormal case where somehow someone makes a
|
|
Packit |
a4aae4 |
// top level attribute that is not a container by silently dropping it.
|
|
Packit |
a4aae4 |
if ((*at_cont_p)->type == Attr_container && (*at_cont_p)->attributes->is_global_attribute()) {
|
|
Packit |
a4aae4 |
DBG(cerr << (*at_cont_p)->d_name << " is a global attribute." << endl);
|
|
Packit |
a4aae4 |
// copy the source container so that the DAS passed in can be
|
|
Packit |
a4aae4 |
// deleted after calling this method.
|
|
Packit |
a4aae4 |
AttrTable *at = new AttrTable(*(*at_cont_p)->attributes);
|
|
Packit |
a4aae4 |
d_attr.append_container(at, at->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
at_cont_p++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get and set the dataset's d_name. This is the d_name of the dataset
|
|
Packit |
a4aae4 |
itself, and is not to be confused with the d_name of the file or
|
|
Packit |
a4aae4 |
disk on which it is stored.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@d_name Dataset Name Accessors */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns the dataset's d_name. */
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
DDS::get_dataset_name() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Sets the dataset d_name. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::set_dataset_name(const string &n)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_name = n;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the attribute table for the global attributes. */
|
|
Packit |
a4aae4 |
AttrTable &
|
|
Packit |
a4aae4 |
DDS::get_attr_table()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_attr;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get and set the dataset's filename. This is the physical
|
|
Packit |
a4aae4 |
location on a disk where the dataset exists. The dataset d_name
|
|
Packit |
a4aae4 |
is simply a title.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@d_name File Name Accessor
|
|
Packit |
a4aae4 |
@see Dataset Name Accessors */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
/** Gets the dataset file d_name. */
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
DDS::filename() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_filename;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set the dataset's filename. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::filename(const string &fn)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_filename = fn;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @deprecated
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::set_dap_major(int p)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_dap_major = p;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This works because regardless of the order set_dap_major and set_dap_minor
|
|
Packit |
a4aae4 |
// are called, once they both are called, the value in the string is
|
|
Packit |
a4aae4 |
// correct. I protect against negative numbers because that would be
|
|
Packit |
a4aae4 |
// nonsensical.
|
|
Packit |
a4aae4 |
if (d_dap_minor >= 0) {
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
oss << d_dap_major << "." << d_dap_minor;
|
|
Packit |
a4aae4 |
d_dap_version = oss.str();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @deprecated
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::set_dap_minor(int p)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_dap_minor = p;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_dap_major >= 0) {
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
oss << d_dap_major << "." << d_dap_minor;
|
|
Packit |
a4aae4 |
d_dap_version = oss.str();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Given the DAP protocol version, parse that string and set the DDS fields.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param v The version string.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::set_dap_version(const string &v /* = "2.0" */)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
istringstream iss(v);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int major = -1, minor = -1;
|
|
Packit |
a4aae4 |
char dot;
|
|
Packit |
a4aae4 |
if (!iss.eof() && !iss.fail())
|
|
Packit |
a4aae4 |
iss >> major;
|
|
Packit |
a4aae4 |
if (!iss.eof() && !iss.fail())
|
|
Packit |
a4aae4 |
iss >> dot;
|
|
Packit |
a4aae4 |
if (!iss.eof() && !iss.fail())
|
|
Packit |
a4aae4 |
iss >> minor;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (major == -1 || minor == -1 or dot != '.')
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_dap_version = v;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_dap_major = major;
|
|
Packit |
a4aae4 |
d_dap_minor = minor;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now set the related XML constants. These might be overwritten if
|
|
Packit |
a4aae4 |
// the DDS instance is being built from a document parse, but if it's
|
|
Packit |
a4aae4 |
// being constructed by a server the code to generate the XML document
|
|
Packit |
a4aae4 |
// needs these values to match the DAP version information.
|
|
Packit |
a4aae4 |
switch (d_dap_major) {
|
|
Packit |
a4aae4 |
case 2:
|
|
Packit |
a4aae4 |
d_namespace = c_dap20_namespace;
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
case 3:
|
|
Packit |
a4aae4 |
d_namespace = c_dap32_namespace;
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
case 4:
|
|
Packit |
a4aae4 |
d_namespace = c_dap40_namespace;
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Unknown DAP version.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Old way to set the DAP version.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note Don't use this - two interfaces to set the version number is overkill
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param d The protocol version requested by the client, as a double.
|
|
Packit |
a4aae4 |
* @deprecated
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::set_dap_version(double d)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
int major = floor(d);
|
|
Packit |
a4aae4 |
int minor = (d-major)*10;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Major: " << major << ", Minor: " << minor << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
oss << major << "." << minor;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
set_dap_version(oss.str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get and set the current container. If there are multiple files being
|
|
Packit |
a4aae4 |
used to build this DDS, using a container will set a virtual structure
|
|
Packit |
a4aae4 |
for the current container.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@d_name Container Name Accessor
|
|
Packit |
a4aae4 |
@see Dataset Name Accessors */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
/** Gets the dataset file d_name. */
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
DDS::container_name()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_container_name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set the current container d_name and get or create a structure for that
|
|
Packit |
a4aae4 |
* d_name. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::container_name(const string &cn)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// we want to search the DDS for the top level structure with the given
|
|
Packit |
a4aae4 |
// d_name. Set the container to null so that we don't search some previous
|
|
Packit |
a4aae4 |
// container.
|
|
Packit |
a4aae4 |
d_container = 0 ;
|
|
Packit |
a4aae4 |
if( !cn.empty() )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_container = dynamic_cast<Structure *>( var( cn ) ) ;
|
|
Packit |
a4aae4 |
if( !d_container )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// create a structure for this container. Calling add_var
|
|
Packit |
a4aae4 |
// while_container is null will add the new structure to DDS and
|
|
Packit |
a4aae4 |
// not some sub structure. Adding the new structure makes a copy
|
|
Packit |
a4aae4 |
// of it. So after adding it, go get it and set d_container.
|
|
Packit |
a4aae4 |
Structure *s = new Structure( cn ) ;
|
|
Packit |
a4aae4 |
add_var( s ) ;
|
|
Packit |
a4aae4 |
delete s ;
|
|
Packit |
a4aae4 |
s = 0 ;
|
|
Packit |
a4aae4 |
d_container = dynamic_cast<Structure *>( var( cn ) ) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
d_container_name = cn;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the current container structure. */
|
|
Packit |
a4aae4 |
Structure *
|
|
Packit |
a4aae4 |
DDS::container()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_container ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the size of a response. This method looks at the variables in the DDS
|
|
Packit |
a4aae4 |
* a computes the number of bytes in the response.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note This version of the method does a poor job with Sequences. A better
|
|
Packit |
a4aae4 |
* implementation would look at row-constraint-based limitations and use them
|
|
Packit |
a4aae4 |
* for size computations. If a row-constraint is missing, return an error.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param constrained Should the size of the whole DDS be used or should the
|
|
Packit |
a4aae4 |
* current constraint be taken into account?
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
int
|
|
Packit |
a4aae4 |
DDS::get_request_size(bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
int w = 0;
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
if (constrained) {
|
|
Packit |
a4aae4 |
if ((*i)->send_p())
|
|
Packit |
a4aae4 |
w += (*i)->width(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
w += (*i)->width(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return w;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Adds a copy of the variable to the DDS.
|
|
Packit |
a4aae4 |
Using the ptr_duplicate() method, perform a deep copy on the variable
|
|
Packit |
a4aae4 |
\e bt and adds the result to this DDS.
|
|
Packit |
a4aae4 |
@note The copy will not copy data values.
|
|
Packit |
a4aae4 |
@param bt Source variable. */
|
|
Packit |
a4aae4 |
void DDS::add_var(BaseType *bt) {
|
|
Packit |
a4aae4 |
if (!bt)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
if (bt->is_dap4_only_type())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *btp = bt->ptr_duplicate();
|
|
Packit |
a4aae4 |
DBG2(cerr << "In DDS::add_var(), btp's address is: " << btp << endl);
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
// Mem leak fix [mjohnson nov 2009]
|
|
Packit |
a4aae4 |
// Structure::add_var() creates ANOTHER copy.
|
|
Packit |
a4aae4 |
d_container->add_var(bt);
|
|
Packit |
a4aae4 |
// So we need to delete btp or else it leaks
|
|
Packit |
a4aae4 |
delete btp;
|
|
Packit |
a4aae4 |
btp = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
vars.push_back(btp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Adds the variable to the DDS.
|
|
Packit |
a4aae4 |
@param bt Source variable. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::add_var_nocopy(BaseType *bt)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!bt)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
//FIXME There's no longer a DAP2 and DAP4 DDS
|
|
Packit |
a4aae4 |
if (bt->is_dap4_only_type())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
d_container->add_var_nocopy(bt);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
vars.push_back(bt);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Remove the named variable from the DDS. This method is not smart about
|
|
Packit |
a4aae4 |
looking up names. The variable must exist at the top level of the DDS and
|
|
Packit |
a4aae4 |
must match \e exactly the d_name given.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Invalidates any iterators that reference the contents of the DDS.
|
|
Packit |
a4aae4 |
@param n The d_name of the variable to remove. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::del_var(const string &n)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if( d_container )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_container->del_var( n ) ;
|
|
Packit |
a4aae4 |
return ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->name() == n) {
|
|
Packit |
a4aae4 |
BaseType *bt = *i ;
|
|
Packit |
a4aae4 |
vars.erase(i) ;
|
|
Packit |
a4aae4 |
delete bt ; bt = 0;
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Remove the variable referenced by the iterator and free its storage.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Invalidates any iterators that reference the contents of the DDS.
|
|
Packit |
a4aae4 |
@param i The Vars_iter which refers to the variable. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::del_var(Vars_iter i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (i != vars.end()) {
|
|
Packit |
a4aae4 |
BaseType *bt = *i ;
|
|
Packit |
a4aae4 |
vars.erase(i) ;
|
|
Packit |
a4aae4 |
delete bt ; bt = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Remove the variables referenced by the range of iterators and free their
|
|
Packit |
a4aae4 |
storage.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Invalidates any iterators that reference the contents of the DDS.
|
|
Packit |
a4aae4 |
@param i1 The start of the range.
|
|
Packit |
a4aae4 |
@param i2 The end of the range. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::del_var(Vars_iter i1, Vars_iter i2)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i_tmp = i1; i_tmp != i2; i_tmp++) {
|
|
Packit |
a4aae4 |
BaseType *bt = *i_tmp ;
|
|
Packit |
a4aae4 |
delete bt ; bt = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
vars.erase(i1, i2) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Search for for variable n as above but record all
|
|
Packit |
a4aae4 |
compound type variables which ultimately contain n on
|
|
Packit |
a4aae4 |
s. This stack can then be used to mark the contained
|
|
Packit |
a4aae4 |
compound-type variables as part of the current projection.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return A BaseType pointer to the variable n or 0 if n
|
|
Packit |
a4aae4 |
could not be found. */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
DDS::var(const string &n, BaseType::btp_stack &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return var(n, &s);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
/** @brief Find the variable with the given d_name.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Returns a pointer to the named variable. If the d_name contains one or
|
|
Packit |
a4aae4 |
more field separators then the function looks for a variable whose
|
|
Packit |
a4aae4 |
name matches exactly. If the d_name contains no field separators then
|
|
Packit |
a4aae4 |
the function looks first in the top level and then in all subsequent
|
|
Packit |
a4aae4 |
levels and returns the first occurrence found. In general, this
|
|
Packit |
a4aae4 |
function searches constructor types in the order in which they appear
|
|
Packit |
a4aae4 |
in the DDS, but there is no requirement that it do so.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If a dataset contains two constructor types which have field names
|
|
Packit |
a4aae4 |
that are the same (say point.x and pair.x) you should use fully qualified
|
|
Packit |
a4aae4 |
names to get each of those variables.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n The name of the variable to find.
|
|
Packit |
a4aae4 |
@param s If given, this value-result parameter holds the path to the
|
|
Packit |
a4aae4 |
returned BaseType. Thus, this method can return the FQN for the variable
|
|
Packit |
a4aae4 |
\e n.
|
|
Packit |
a4aae4 |
@return A BaseType pointer to the variable or null if not found. */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
DDS::var(const string &n, BaseType::btp_stack *s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = www2id(n);
|
|
Packit |
a4aae4 |
if( d_container )
|
|
Packit |
a4aae4 |
return d_container->var( name, false, s ) ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *v = exact_match(name, s);
|
|
Packit |
a4aae4 |
if (v)
|
|
Packit |
a4aae4 |
return v;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return leaf_match(name, s);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
DDS::leaf_match(const string &n, BaseType::btp_stack *s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "DDS::leaf_match: Looking for " << n << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
BaseType *btp = *i;
|
|
Packit |
a4aae4 |
DBG(cerr << "DDS::leaf_match: Looking for " << n << " in: " << btp->name() << endl);
|
|
Packit |
a4aae4 |
// Look for the d_name in the dataset's top-level
|
|
Packit |
a4aae4 |
if (btp->name() == n) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
|
|
Packit |
a4aae4 |
return btp;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (btp->is_constructor_type()) {
|
|
Packit |
a4aae4 |
BaseType *found = btp->var(n, false, s);
|
|
Packit |
a4aae4 |
if (found) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
|
|
Packit |
a4aae4 |
return found;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#if STRUCTURE_ARRAY_SYNTAX_OLD
|
|
Packit |
a4aae4 |
if (btp->is_vector_type() && btp->var()->is_constructor_type()) {
|
|
Packit |
a4aae4 |
s->push(btp);
|
|
Packit |
a4aae4 |
BaseType *found = btp->var()->var(n, false, s);
|
|
Packit |
a4aae4 |
if (found) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Found " << n << " in: " << btp->var()->d_name() << endl);
|
|
Packit |
a4aae4 |
return found;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0; // It is not here.
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
DDS::exact_match(const string &name, BaseType::btp_stack *s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
BaseType *btp = *i;
|
|
Packit |
a4aae4 |
DBG2(cerr << "Looking for " << d_name << " in: " << btp << endl);
|
|
Packit |
a4aae4 |
// Look for the d_name in the current ctor type or the top level
|
|
Packit |
a4aae4 |
if (btp->name() == name) {
|
|
Packit |
a4aae4 |
DBG2(cerr << "Found " << d_name << " in: " << btp << endl);
|
|
Packit |
a4aae4 |
return btp;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string::size_type dot_pos = name.find(".");
|
|
Packit |
a4aae4 |
if (dot_pos != string::npos) {
|
|
Packit |
a4aae4 |
string aggregate = name.substr(0, dot_pos);
|
|
Packit |
a4aae4 |
string field = name.substr(dot_pos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *agg_ptr = var(aggregate, s);
|
|
Packit |
a4aae4 |
if (agg_ptr) {
|
|
Packit |
a4aae4 |
DBG2(cerr << "Descending into " << agg_ptr->name() << endl);
|
|
Packit |
a4aae4 |
return agg_ptr->var(field, true, s);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return 0; // qualified names must be *fully* qualified
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0; // It is not here.
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the first variable in the DDS. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS::Vars_iter
|
|
Packit |
a4aae4 |
DDS::var_begin()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return vars.begin();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS::Vars_riter
|
|
Packit |
a4aae4 |
DDS::var_rbegin()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return vars.rbegin();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS::Vars_iter
|
|
Packit |
a4aae4 |
DDS::var_end()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return vars.end() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS::Vars_riter
|
|
Packit |
a4aae4 |
DDS::var_rend()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return vars.rend() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Return the iterator for the \e ith variable.
|
|
Packit |
a4aae4 |
@param i the index
|
|
Packit |
a4aae4 |
@return The corresponding Vars_iter */
|
|
Packit |
a4aae4 |
DDS::Vars_iter
|
|
Packit |
a4aae4 |
DDS::get_vars_iter(int i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return vars.begin() + i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Return the \e ith variable.
|
|
Packit |
a4aae4 |
@param i the index
|
|
Packit |
a4aae4 |
@return The corresponding variable */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
DDS::get_var_index(int i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return *(vars.begin() + i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Insert a copy of the BaseType before the position given.
|
|
Packit |
a4aae4 |
* @param i The iterator that marks the position
|
|
Packit |
a4aae4 |
* @param ptr The BaseType object to copy and insert
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::insert_var(Vars_iter i, BaseType *ptr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
if (ptr->is_dap4_only_type())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vars.insert(i, ptr->ptr_duplicate());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Insert the BaseType before the position given.
|
|
Packit |
a4aae4 |
* @note Does not copy the BaseType object - that caller must not
|
|
Packit |
a4aae4 |
* free the inserted object's pointer. This object will, however,
|
|
Packit |
a4aae4 |
* delete the pointer when it is deleted.
|
|
Packit |
a4aae4 |
* @param i The iterator that marks the position
|
|
Packit |
a4aae4 |
* @param ptr The BaseType object to insert
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::insert_var_nocopy(Vars_iter i, BaseType *ptr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
if (ptr->is_dap4_only_type())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vars.insert(i, ptr);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the number of variables in the DDS. */
|
|
Packit |
a4aae4 |
int
|
|
Packit |
a4aae4 |
DDS::num_var()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return vars.size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::timeout_on()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
#ifndef WIN32
|
|
Packit |
a4aae4 |
alarm(d_timeout);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::timeout_off()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
#ifndef WIN32
|
|
Packit |
a4aae4 |
// Old behavior commented out. I think it is an error to change the value
|
|
Packit |
a4aae4 |
// of d_timeout. The way this will likely be used is to set the timeout
|
|
Packit |
a4aae4 |
// value once and then 'turn on' or turn off' that timeout as the situation
|
|
Packit |
a4aae4 |
// dictates. The initeded use for the DDS timeout is so that timeouts for
|
|
Packit |
a4aae4 |
// data responses will include the CPU resources needed to build the response
|
|
Packit |
a4aae4 |
// but not the time spent transmitting the response. This may change when
|
|
Packit |
a4aae4 |
// more parallelism is added to the server... These methods are called from
|
|
Packit |
a4aae4 |
// BESDapResponseBuilder in bes/dap. jhrg 12/22/15
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// d_timeout = alarm(0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
alarm(0);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::set_timeout(int)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
// Has no effect under win32
|
|
Packit |
a4aae4 |
d_timeout = t;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int
|
|
Packit |
a4aae4 |
DDS::get_timeout()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
// Has to effect under win32
|
|
Packit |
a4aae4 |
return d_timeout;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Traverse DDS, set Sequence leaf nodes. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::tag_nested_sequences()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->type() == dods_sequence_c)
|
|
Packit |
a4aae4 |
dynamic_cast<Sequence&>(**i).set_leaf_sequence();
|
|
Packit |
a4aae4 |
else if ((*i)->type() == dods_structure_c)
|
|
Packit |
a4aae4 |
dynamic_cast<Structure&>(**i).set_leaf_sequence();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Parse a DDS from a file with the given d_name. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::parse(string fname)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
FILE *in = fopen(fname.c_str(), "r");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!in) {
|
|
Packit |
a4aae4 |
throw Error(cannot_read_file, "Could not open: " + fname);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
parse(in);
|
|
Packit |
a4aae4 |
fclose(in);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
fclose(in);
|
|
Packit |
a4aae4 |
throw ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Parse a DDS from a file indicated by the input file descriptor. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::parse(int fd)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
int new_fd = _dup(fd);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
int new_fd = dup(fd);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (new_fd < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not access file.");
|
|
Packit |
a4aae4 |
FILE *in = fdopen(new_fd, "r");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!in) {
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not access file.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
parse(in);
|
|
Packit |
a4aae4 |
fclose(in);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (Error &e) {
|
|
Packit |
a4aae4 |
fclose(in);
|
|
Packit |
a4aae4 |
throw ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Parse a DDS from a file indicated by the input file descriptor.
|
|
Packit |
a4aae4 |
Read the persistent representation of a DDS from the FILE *in, parse it
|
|
Packit |
a4aae4 |
and create a matching binary object.
|
|
Packit |
a4aae4 |
@param in Read the persistent DDS from this FILE*.
|
|
Packit |
a4aae4 |
@exception InternalErr Thrown if \c in is null
|
|
Packit |
a4aae4 |
@exception Error Thrown if the parse fails. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::parse(FILE *in)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!in) {
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Null input stream.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void *buffer = dds_buffer(in);
|
|
Packit |
a4aae4 |
dds_switch_to_buffer(buffer);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
parser_arg arg(this);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool status = ddsparse(&arg) == 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
dds_delete_buffer(buffer);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cout << "Status from parser: " << status << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// STATUS is the result of the parser function; if a recoverable error
|
|
Packit |
a4aae4 |
// was found it will be true but arg.status() will be false.
|
|
Packit |
a4aae4 |
if (!status || !arg.status()) {// Check parse result
|
|
Packit |
a4aae4 |
if (arg.error())
|
|
Packit |
a4aae4 |
throw *arg.error();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Print the entire DDS to the specified file. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print(FILE *out)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
print(oss);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Print the entire DDS to the specified ostream. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print(ostream &out)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
out << "Dataset {\n" ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->print_decl(out) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << "} " << id2www(d_name) << ";\n" ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Print the DAP2 DAS object using attribute information recorded
|
|
Packit |
a4aae4 |
* this DDS object.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note Uses default indenting of four spaces and does not follow
|
|
Packit |
a4aae4 |
* (now deprecated) attribute aliases.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param out Write the DAS here.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
static string four_spaces = " ";
|
|
Packit |
a4aae4 |
void print_var_das(ostream &out, BaseType *bt, string indent=""){
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable attr_table = bt->get_attr_table();
|
|
Packit |
a4aae4 |
out << indent << add_space_encoding(bt->name()) << " {" << endl;
|
|
Packit |
a4aae4 |
attr_table.print(out, indent+four_spaces);
|
|
Packit |
a4aae4 |
Constructor *cnstrctr = dynamic_cast < Constructor * >(bt);
|
|
Packit |
a4aae4 |
if(cnstrctr) {
|
|
Packit |
a4aae4 |
Constructor::Vars_iter i = cnstrctr->var_begin();
|
|
Packit |
a4aae4 |
Constructor::Vars_iter e = cnstrctr->var_end();
|
|
Packit |
a4aae4 |
for (; i!=e; i++) {
|
|
Packit |
a4aae4 |
print_var_das(out,*i,indent+four_spaces);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
out << indent << "}" << endl;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_das(ostream &out)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string indent(" ");
|
|
Packit |
a4aae4 |
out << "Attributes {" << endl ;
|
|
Packit |
a4aae4 |
for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
print_var_das(out, *i, four_spaces);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// Print the global attributes at the end.
|
|
Packit |
a4aae4 |
d_attr.print(out,indent);
|
|
Packit |
a4aae4 |
out << "}" << endl ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Print a constrained DDS to the specified file.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Print those parts (variables) of the DDS structure to OS that
|
|
Packit |
a4aae4 |
are marked to be sent after evaluating the constraint
|
|
Packit |
a4aae4 |
expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This function only works for scalars at the top level.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@returns true.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_constrained(FILE *out)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
print_constrained(oss);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Print a constrained DDS to the specified ostream.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Print those parts (variables) of the DDS structure to OS that
|
|
Packit |
a4aae4 |
are marked to be sent after evaluating the constraint
|
|
Packit |
a4aae4 |
expression.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
\note This function only works for scalars at the top level.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@returns true.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_constrained(ostream &out)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
out << "Dataset {\n" ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
|
|
Packit |
a4aae4 |
// for each variable, indent with four spaces, print a trailing
|
|
Packit |
a4aae4 |
// semicolon, do not print debugging information, print only
|
|
Packit |
a4aae4 |
// variables in the current projection.
|
|
Packit |
a4aae4 |
(*i)->print_decl(out, " ", true, false, true) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << "} " << id2www(d_name) << ";\n" ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Print an XML representation of this DDS. This method is used to generate
|
|
Packit |
a4aae4 |
the part of the DDX response. The \c Dataset tag is \e not written by
|
|
Packit |
a4aae4 |
this code. The caller of this method must handle writing that and
|
|
Packit |
a4aae4 |
including the \c dataBLOB tag.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param out Destination.
|
|
Packit |
a4aae4 |
@param constrained True if the output should be limited to just those
|
|
Packit |
a4aae4 |
variables that are in the projection of the current constraint
|
|
Packit |
a4aae4 |
expression.
|
|
Packit |
a4aae4 |
@param blob The dataBLOB href.
|
|
Packit |
a4aae4 |
@deprecated */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_xml(FILE *out, bool constrained, const string &blob)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
print_xml_writer(oss, constrained, blob);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), 1, oss.str().length(), out);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Print an XML representation of this DDS. This method is used to generate
|
|
Packit |
a4aae4 |
the part of the DDX response. The \c Dataset tag is \e not written by
|
|
Packit |
a4aae4 |
this code. The caller of this method must handle writing that and
|
|
Packit |
a4aae4 |
including the \c dataBLOB tag.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param out Destination ostream.
|
|
Packit |
a4aae4 |
@param constrained True if the output should be limited to just those
|
|
Packit |
a4aae4 |
variables that are in the projection of the current constraint
|
|
Packit |
a4aae4 |
expression.
|
|
Packit |
a4aae4 |
@param blob The dataBLOB href.
|
|
Packit |
a4aae4 |
@deprecated */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_xml(ostream &out, bool constrained, const string &blob)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
print_xml_writer(out, constrained, blob);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
class VariablePrintXMLWriter : public unary_function<BaseType *, void>
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
XMLWriter &d_xml;
|
|
Packit |
a4aae4 |
bool d_constrained;
|
|
Packit |
a4aae4 |
public:
|
|
Packit |
a4aae4 |
VariablePrintXMLWriter(XMLWriter &xml, bool constrained)
|
|
Packit |
a4aae4 |
: d_xml(xml), d_constrained(constrained)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
void operator()(BaseType *bt)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
bt->print_xml_writer(d_xml, d_constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
};
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Print the DDX. This code uses the libxml2 'TextWriter' interface; something
|
|
Packit |
a4aae4 |
* that seems to be a good compromise between doing it by hand (although more
|
|
Packit |
a4aae4 |
* verbose it is also more reliable) and DOM.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note This code handles several different versions of DAP in a fairly
|
|
Packit |
a4aae4 |
* crude way. I've broken it up into three different responses: DAP2, DAP3.2
|
|
Packit |
a4aae4 |
* and DAP4.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param out Write the XML to this output sink
|
|
Packit |
a4aae4 |
* @param constrained True if the only variables to print are those in the
|
|
Packit |
a4aae4 |
* current projection. If true, this will also suppress printing attributes.
|
|
Packit |
a4aae4 |
* @param blob This is an href (DAP2) or a cid (DAP3.4 and 4). The href
|
|
Packit |
a4aae4 |
* points to the binary data; the cid is the M-MIME separator for the binary
|
|
Packit |
a4aae4 |
* data.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_xml_writer(ostream &out, bool constrained, const string &blob)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
XMLWriter xml(" ");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Stamp and repeat for these sections; trying to economize is makes it
|
|
Packit |
a4aae4 |
// even more confusing
|
|
Packit |
a4aae4 |
if (get_dap_major() >= 4) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)get_dap_version().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!get_request_xml_base().empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (!get_namespace().empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)get_namespace().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (get_dap_major() == 3 && get_dap_minor() >= 2) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_32_n_sl.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:grddl", (const xmlChar*)"http://www.w3.org/2003/g/data-view#") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:grddl");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "grddl:transformation", (const xmlChar*)grddl_transformation_dap32.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:transformation");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:dap", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:dap");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)"3.2") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!get_request_xml_base().empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else { // dap2
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap20_namespace.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_20_n_sl.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Print the global attributes
|
|
Packit |
a4aae4 |
d_attr.print_xml_writer(xml);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Print each variable
|
|
Packit |
a4aae4 |
for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
|
|
Packit |
a4aae4 |
// the CID of the MIME part that holds the data. For DAP2 (which includes
|
|
Packit |
a4aae4 |
// 3.0 and 3.1), the blob is an href. For DAP4, only write the CID if it's
|
|
Packit |
a4aae4 |
// given.
|
|
Packit |
a4aae4 |
if (get_dap_major() >= 4) {
|
|
Packit |
a4aae4 |
if (!blob.empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
|
|
Packit |
a4aae4 |
string cid = "cid:" + blob;
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (get_dap_major() == 3 && get_dap_minor() >= 2) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
|
|
Packit |
a4aae4 |
string cid = "cid:" + blob;
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else { // dap2
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "dataBLOB") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write dataBLOB element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) "") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end dataBLOB element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end Dataset element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << xml.get_doc();// << ends;// << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Print the DAP4 DMR object.
|
|
Packit |
a4aae4 |
* This method prints the DMR. If the dap version is not >= 4.0, it's an
|
|
Packit |
a4aae4 |
* error to call this method.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note Calling methods that print the DDS or DDX when get_dap_major()
|
|
Packit |
a4aae4 |
* returns a value >= 4 is undefined. Use this method to get the DAP4
|
|
Packit |
a4aae4 |
* metadata response.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param out Write the XML to this stream
|
|
Packit |
a4aae4 |
* @param constrained Should the DMR be subject to a constraint?
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::print_dmr(ostream &out, bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (get_dap_major() < 4)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Tried to print a DMR with DAP major version less than 4");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
XMLWriter xml(" ");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// DAP4 wraps a dataset in a top-level Group element.
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml",
|
|
Packit |
a4aae4 |
(const xmlChar*) c_xml_namespace.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*) c_xml_xsi.c_str())
|
|
Packit |
a4aae4 |
< 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation",
|
|
Packit |
a4aae4 |
(const xmlChar*) c_dap_40_n_sl.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_namespace().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_dap_version().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*) get_dmr_version().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!get_request_xml_base().empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_request_xml_base().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) d_name.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Print the global attributes
|
|
Packit |
a4aae4 |
d_attr.print_xml_writer(xml);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Print each variable
|
|
Packit |
a4aae4 |
for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
|
|
Packit |
a4aae4 |
// the CID of the MIME part that holds the data. For DAP2 (which includes
|
|
Packit |
a4aae4 |
// 3.0 and 3.1), the blob is an href. For DAP4, only write the CID if it's
|
|
Packit |
a4aae4 |
// given.
|
|
Packit |
a4aae4 |
if (get_dap_major() >= 4) {
|
|
Packit |
a4aae4 |
if (!blob.empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
|
|
Packit |
a4aae4 |
string cid = "cid:" + blob;
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << xml.get_doc();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Used by DDS::send() when returning data from a function call.
|
|
Packit |
a4aae4 |
/** @brief Check the semantics of each of the variables represented in the
|
|
Packit |
a4aae4 |
DDS.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Check the semantics of the DDS describing a complete dataset. If ALL is
|
|
Packit |
a4aae4 |
true, check not only the semantics of THIS->TABLE, but also recursively
|
|
Packit |
a4aae4 |
all ctor types in the THIS->TABLE. By default, ALL is false since parsing
|
|
Packit |
a4aae4 |
a DDS input file runs semantic checks on all variables (but not the
|
|
Packit |
a4aae4 |
dataset itself.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return TRUE if the conventions for the DDS are not violated, FALSE
|
|
Packit |
a4aae4 |
otherwise.
|
|
Packit |
a4aae4 |
@param all If true, recursively check the individual members of
|
|
Packit |
a4aae4 |
compound variables.
|
|
Packit |
a4aae4 |
@see BaseType::check_semantics */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
DDS::check_semantics(bool all)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// The dataset must have a d_name
|
|
Packit |
a4aae4 |
if (d_name == "") {
|
|
Packit |
a4aae4 |
cerr << "A dataset must have a d_name" << endl;
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string msg;
|
|
Packit |
a4aae4 |
if (!unique_names(vars, d_name, "Dataset", msg))
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (all)
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++)
|
|
Packit |
a4aae4 |
if (!(*i)->check_semantics(msg, true))
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Mark the <tt>send_p</tt> flag of the named variable to
|
|
Packit |
a4aae4 |
state.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Mark the named variable by setting its SEND_P flag to STATE (true
|
|
Packit |
a4aae4 |
indicates that it is to be sent). Names must be fully qualified.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note For aggregate types this sets each part to STATE when STATE is
|
|
Packit |
a4aae4 |
True. Thus, if State is True and N is `exp1.test', then both `exp1' and
|
|
Packit |
a4aae4 |
`test' have their SEND_P flag set to True. If STATE is False, then the
|
|
Packit |
a4aae4 |
SEND_P flag of the `test' is set to False, but `exp1' is left
|
|
Packit |
a4aae4 |
unchanged. This means that a single variable can be removed from the
|
|
Packit |
a4aae4 |
current projection without removing all the other children of its
|
|
Packit |
a4aae4 |
parent. See the mfunc set_send_p().
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return True if the named variable was found, false otherwise.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo This should throw an exception on error!!!
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo These methods that use the btp_stack to keep track of the path from
|
|
Packit |
a4aae4 |
the top of a dataset to a particular variable can be rewritten to use the
|
|
Packit |
a4aae4 |
parent field instead.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo All the methods that use names to identify variables should have
|
|
Packit |
a4aae4 |
counterparts that take BaseType pointers.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
DDS::mark(const string &n, bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// TODO use auto_ptr
|
|
Packit |
a4aae4 |
BaseType::btp_stack *s = new BaseType::btp_stack;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cerr << "DDS::mark: Looking for " << n << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *variable = var(n, s);
|
|
Packit |
a4aae4 |
if (!variable) {
|
|
Packit |
a4aae4 |
DBG2(cerr << "Could not find variable " << n << endl);
|
|
Packit |
a4aae4 |
delete s; s = 0;
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
variable->set_send_p(state);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cerr << "DDS::mark: Set variable " << variable->d_name()
|
|
Packit |
a4aae4 |
<< " (a " << variable->type_name() << ")" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now check the btp_stack and run BaseType::set_send_p for every
|
|
Packit |
a4aae4 |
// BaseType pointer on the stack. Using BaseType::set_send_p() will
|
|
Packit |
a4aae4 |
// set the property for a Constructor but not its contained variables
|
|
Packit |
a4aae4 |
// which preserves the semantics of projecting just one field.
|
|
Packit |
a4aae4 |
while (!s->empty()) {
|
|
Packit |
a4aae4 |
s->top()->BaseType::set_send_p(state);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cerr << "DDS::mark: Set variable " << s->top()->d_name()
|
|
Packit |
a4aae4 |
<< " (a " << s->top()->type_name() << ")" << endl);
|
|
Packit |
a4aae4 |
// FIXME get_parent() hosed?
|
|
Packit |
a4aae4 |
#if 1
|
|
Packit |
a4aae4 |
string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
|
|
Packit |
a4aae4 |
string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
|
|
Packit |
a4aae4 |
DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
s->pop();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete s ; s = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Mark the member variable <tt>send_p</tt> flags to
|
|
Packit |
a4aae4 |
state.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return Void
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::mark_all(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = vars.begin(); i != vars.end(); i++)
|
|
Packit |
a4aae4 |
(*i)->set_send_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief dumps information about this object
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Displays the pointer value of this instance and then calls parent dump
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param strm C++ i/o stream to dump the information to
|
|
Packit |
a4aae4 |
* @return void
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DDS::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "DDS::dump - ("
|
|
Packit |
a4aae4 |
<< (void *)this << ")" << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "d_name: " << d_name << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "global attributes:" << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
d_attr.dump(strm) ;
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (vars.size()) {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "vars:" << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
Vars_citer i = vars.begin() ;
|
|
Packit |
a4aae4 |
Vars_citer ie = vars.end() ;
|
|
Packit |
a4aae4 |
for (; i != ie; i++) {
|
|
Packit |
a4aae4 |
(*i)->dump(strm) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "vars: none" << endl ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|