|
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) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.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 <cassert>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG2
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "D4Group.h"
|
|
Packit |
a4aae4 |
#include "BaseType.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
#include "Grid.h"
|
|
Packit |
a4aae4 |
#include "DMR.h"
|
|
Packit |
a4aae4 |
#include "XMLWriter.h"
|
|
Packit |
a4aae4 |
#include "D4BaseTypeFactory.h"
|
|
Packit |
a4aae4 |
#include "D4Attributes.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "DDS.h" // Included so DMRs can be built using a DDS for 'legacy' handlers
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* DapXmlNamespaces
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* TODO Replace all uses of the following variables with calls to DapXmlNamespaces
|
|
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 c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string c_dap_40_n_sl = c_dap40_namespace + " " + c_default_dap40_schema_location;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace std;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DMR::m_duplicate(const DMR &dmr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// This is needed because we use the factory to make a new instance of the root group
|
|
Packit |
a4aae4 |
assert(dmr.OK());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_factory = dmr.d_factory; // Shallow copy here
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_name = dmr.d_name;
|
|
Packit |
a4aae4 |
d_filename = dmr.d_filename;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_dap_major = dmr.d_dap_major;
|
|
Packit |
a4aae4 |
d_dap_minor = dmr.d_dap_minor;
|
|
Packit |
a4aae4 |
d_dap_version = dmr.d_dap_version; // String version of the protocol
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_dmr_version = dmr.d_dmr_version;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_request_xml_base = dmr.d_request_xml_base;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_namespace = dmr.d_namespace;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_max_response_size = dmr.d_max_response_size;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Deep copy, using ptr_duplicate()
|
|
Packit |
a4aae4 |
// d_root can only be a D4Group, so the thing returned by ptr_duplicate() must be a D4Group.
|
|
Packit |
a4aae4 |
d_root = static_cast<D4Group*>(dmr.d_root->ptr_duplicate());
|
|
Packit |
a4aae4 |
DBG(cerr << "dmr.d_root: " << dmr.d_root << endl);
|
|
Packit |
a4aae4 |
DBG(cerr << "d_root (from ptr_dup(): " << d_root << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//d_root = static_cast<D4Group*>(dmr.d_factory->NewVariable(dods_group_c, dmr.d_root->name()));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Make a DMR which uses the given BaseTypeFactory to create variables.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note The default DAP version is 4.0 - use the DDS class to make DAP2
|
|
Packit |
a4aae4 |
* things. The default DMR version is 1.0
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param factory The D4BaseTypeFactory to use when creating instances of
|
|
Packit |
a4aae4 |
* DAP4 variables. The caller must ensure the factory's lifetime is at least
|
|
Packit |
a4aae4 |
* that of the DMR instance.
|
|
Packit |
a4aae4 |
* @param name The name of the DMR - usually derived from the name of the
|
|
Packit |
a4aae4 |
* pathname or table name of the dataset.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DMR::DMR(D4BaseTypeFactory *factory, const string &name)
|
|
Packit |
a4aae4 |
: d_factory(factory), d_name(name), d_filename(""),
|
|
Packit |
a4aae4 |
d_dap_major(4), d_dap_minor(0),
|
|
Packit |
a4aae4 |
d_dmr_version("1.0"), d_request_xml_base(""),
|
|
Packit |
a4aae4 |
d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// sets d_dap_version string and the two integer fields too
|
|
Packit |
a4aae4 |
set_dap_version("4.0");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Build a DMR using a DAP2 DDS.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Given a DDS from code written for DAP2, build a DAP4 DMR object. This
|
|
Packit |
a4aae4 |
* works because DAP4 subsumes DAP2, but there are a few quirks... For
|
|
Packit |
a4aae4 |
* each variable in the DDS, transform it to the equivalent DAP4 variable
|
|
Packit |
a4aae4 |
* type and then copy the variable's attributes. Most types convert easily.
|
|
Packit |
a4aae4 |
* Types that need special treatment are:
|
|
Packit |
a4aae4 |
* Array: DAP2 array dimensions must be morphed to DAP4
|
|
Packit |
a4aae4 |
* Sequence: Make a D4Sequence
|
|
Packit |
a4aae4 |
* Grid: Make a coverage; assume Grids with the same dimension names
|
|
Packit |
a4aae4 |
* have 'shared dimensions' and that maps with the same names are shared too.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note Assume that a DDS has only a root group. This is not actually
|
|
Packit |
a4aae4 |
* true for a DDS from the HDF5 handler, because it has Groups encoded
|
|
Packit |
a4aae4 |
* into the variable names. jhrg 3/18/14
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param factory Factory class used to make new variables
|
|
Packit |
a4aae4 |
* @param dds Get the variables to convert from this DAP2 DDS.
|
|
Packit |
a4aae4 |
* @see BaseType::transform_to_dap4()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DMR::DMR(D4BaseTypeFactory *factory, DDS &dds)
|
|
Packit |
a4aae4 |
: d_factory(factory), d_name(dds.get_dataset_name()),
|
|
Packit |
a4aae4 |
d_filename(dds.filename()), d_dap_major(4), d_dap_minor(0),
|
|
Packit |
a4aae4 |
d_dmr_version("1.0"), d_request_xml_base(""),
|
|
Packit |
a4aae4 |
d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// sets d_dap_version string and the two integer fields too
|
|
Packit |
a4aae4 |
set_dap_version("4.0");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
build_using_dds(dds);
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
BaseType *new_var = (*i)->transform_to_dap4(root() /*group*/, root() /*container*/);
|
|
Packit |
a4aae4 |
// If the variable being transformed is a Grid,
|
|
Packit |
a4aae4 |
// then Grid::transform_to_dap4() will add all the arrays to the
|
|
Packit |
a4aae4 |
// container (root() in this case) and return null, indicating that
|
|
Packit |
a4aae4 |
// this code does not need to do anything to add the transformed variable.
|
|
Packit |
a4aae4 |
if (new_var)
|
|
Packit |
a4aae4 |
root()->add_var_nocopy(new_var);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now copy the global attributes
|
|
Packit |
a4aae4 |
root()->attributes()->transform_to_dap4(dds.get_attr_table());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Make a DMR which uses the given BaseTypeFactory to create variables.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note The default DAP version is 4.0 - use the DDS class to make DAP2
|
|
Packit |
a4aae4 |
* things. The default DMR version is 1.0
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DMR::DMR()
|
|
Packit |
a4aae4 |
: d_factory(0), d_name(""), d_filename(""), d_dap_major(4), d_dap_minor(0),
|
|
Packit |
a4aae4 |
d_dap_version("4.0"), d_dmr_version("1.0"), d_request_xml_base(""),
|
|
Packit |
a4aae4 |
d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// sets d_dap_version string and the two integer fields too
|
|
Packit |
a4aae4 |
set_dap_version("4.0");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The DMR copy constructor. */
|
|
Packit |
a4aae4 |
DMR::DMR(const DMR &rhs) : DapObj()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
m_duplicate(rhs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Delete a DMR. The BaseType factory is not freed, while the contained
|
|
Packit |
a4aae4 |
* group is.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DMR::~DMR()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if 1
|
|
Packit |
a4aae4 |
delete d_root;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DMR &
|
|
Packit |
a4aae4 |
DMR::operator=(const DMR &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (this == &rhs)
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
m_duplicate(rhs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* If we have a DDS that includes Attributes, use it to build the DMR. This
|
|
Packit |
a4aae4 |
* will copy all of the variables in the DDS into the DMR using BaseType::transform_to_dap4(),
|
|
Packit |
a4aae4 |
* so the actual types added can be controlled by code that specializes
|
|
Packit |
a4aae4 |
* the various type classes.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param dds Read variables and Attributes from this DDS
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void DMR::build_using_dds(DDS &dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
set_name(dds.get_dataset_name());
|
|
Packit |
a4aae4 |
set_filename(dds.filename());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *root_grp = root();
|
|
Packit |
a4aae4 |
for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
BaseType *d4_var = root()->var((*i)->name());
|
|
Packit |
a4aae4 |
// Don't add duplicate variables. We have to make this check
|
|
Packit |
a4aae4 |
// because some of the child variables may add arrays
|
|
Packit |
a4aae4 |
// to the root object. For example, this happens in
|
|
Packit |
a4aae4 |
// Grid with the Map Arrays - ndp - 05/08/17
|
|
Packit |
a4aae4 |
if(!d4_var){
|
|
Packit |
a4aae4 |
// no variable of this name is in the root group at this point. Add it.
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Transforming top level variable: " <<
|
|
Packit |
a4aae4 |
" (" << (*i)->type_name() << ":'" << (*i)->name() << "':"<<(void *)(*i) <<
|
|
Packit |
a4aae4 |
") (root:"<< root_grp << ")"<< endl; );
|
|
Packit |
a4aae4 |
(*i)->transform_to_dap4(root_grp, root_grp);
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - top level variable: '" <<
|
|
Packit |
a4aae4 |
(*i)->name() << "' (type:" << (*i)->type_name() << ") Transformed"<< endl; );
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Skipping variable: " <<
|
|
Packit |
a4aae4 |
d4_var->type_name() << " " << d4_var->name() << " because a variable with" <<
|
|
Packit |
a4aae4 |
" this name already exists in the root group." << endl; );
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now copy the global attributes
|
|
Packit |
a4aae4 |
root()->attributes()->transform_to_dap4(dds.get_attr_table());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#if 1
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* If we have a DMR that includes Attributes, use it to build the DDS. This
|
|
Packit |
a4aae4 |
* will copy all of the variables in the DMR into the DDS using
|
|
Packit |
a4aae4 |
* BaseType::transform_to_dap2(), so the actual types added can be
|
|
Packit |
a4aae4 |
* controlled by code that specializes the various type classes.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param dds Read variables and Attributes from this DDS
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
DDS *DMR::getDDS(DMR &dmr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - BEGIN" << endl;);
|
|
Packit |
a4aae4 |
D4Group *root = dmr.root();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseTypeFactory *btf = new BaseTypeFactory();
|
|
Packit |
a4aae4 |
DDS *dds = new DDS(btf,dmr.name());
|
|
Packit |
a4aae4 |
dds->filename(dmr.filename());
|
|
Packit |
a4aae4 |
AttrTable *dds_at = &(dds->get_attr_table());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now copy the global attributes
|
|
Packit |
a4aae4 |
// D4Attributes::load_AttrTable(dds_at,root->attributes());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<BaseType *> *top_vars = root->transform_to_dap2(dds_at,true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<BaseType *>::iterator vIter = top_vars->begin();
|
|
Packit |
a4aae4 |
vector<BaseType *>::iterator vEnd = top_vars->end();
|
|
Packit |
a4aae4 |
for( ; vIter!=vEnd ; vIter++){
|
|
Packit |
a4aae4 |
dds->add_var(*vIter);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
set<string> shared_dim_candidates;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<BaseType *> dropped_vars;
|
|
Packit |
a4aae4 |
for (D4Group::Vars_iter i = root->var_begin(), e = root->var_end(); i != e; ++i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Processing top level variable '"<< (*i)->type_name() << " " << (*i)->name() << "' to DDS." << endl; );
|
|
Packit |
a4aae4 |
vector<BaseType *> *new_vars = (*i)->transform_to_dap2(&(dds->get_attr_table()));
|
|
Packit |
a4aae4 |
if(new_vars!=0){
|
|
Packit |
a4aae4 |
vector<BaseType*>::iterator vIter = new_vars->begin();
|
|
Packit |
a4aae4 |
vector<BaseType*>::iterator end = new_vars->end();
|
|
Packit |
a4aae4 |
for( ; vIter!=end ; vIter++ ){
|
|
Packit |
a4aae4 |
BaseType *new_var = (*vIter);
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Adding variable name: '"<< new_var->name() << "' " <<
|
|
Packit |
a4aae4 |
"type: " << new_var->type() << " " <<
|
|
Packit |
a4aae4 |
"type_name: " << new_var->type_name() << " to DDS." << endl; );
|
|
Packit |
a4aae4 |
dds->add_var_nocopy(new_var);
|
|
Packit |
a4aae4 |
Grid *grid = dynamic_cast <Grid *>(new_var);
|
|
Packit |
a4aae4 |
if(grid){
|
|
Packit |
a4aae4 |
Grid::Map_iter m = grid->map_begin();
|
|
Packit |
a4aae4 |
for( ; m != grid->map_end() ; m++){
|
|
Packit |
a4aae4 |
shared_dim_candidates.insert((*m)->name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
(*vIter) = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete new_vars;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "Adding variable '"<< (*i)->type_name() << " " << (*i)->name() << "' to drop list." << endl; );
|
|
Packit |
a4aae4 |
dropped_vars.push_back((*i));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
AttrTable *dv_table = Constructor::make_dropped_vars_attr_table(&dropped_vars);
|
|
Packit |
a4aae4 |
if(dv_table){
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Adding dropped variable AttrTable." << endl;);
|
|
Packit |
a4aae4 |
dds_at->append_container(dv_table,dv_table->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Get all the child groups.
|
|
Packit |
a4aae4 |
D4Group::groupsIter gIter = root->grp_begin();
|
|
Packit |
a4aae4 |
D4Group::groupsIter gEnd = root->grp_end();
|
|
Packit |
a4aae4 |
for( ; gIter!=gEnd ; gIter++){
|
|
Packit |
a4aae4 |
D4Group *grp = *gIter;
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Processing D4Group " << grp->name() << endl;);
|
|
Packit |
a4aae4 |
vector<BaseType *> *d2_vars = grp->transform_to_dap2(dds_at);
|
|
Packit |
a4aae4 |
if(d2_vars){
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Processing " << grp->name() << " Member Variables." << endl;);
|
|
Packit |
a4aae4 |
vector<BaseType *>::iterator vIter = d2_vars->begin();
|
|
Packit |
a4aae4 |
vector<BaseType *>::iterator vEnd = d2_vars->end();
|
|
Packit |
a4aae4 |
for( ; vIter!=vEnd; vIter++){
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Processing " << grp->name() << " Member Variable: " << (*vIter)->name() << endl;);
|
|
Packit |
a4aae4 |
dds->add_var(*vIter);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - END" << endl;);
|
|
Packit |
a4aae4 |
return dds;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS *DMR::getDDS()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return DMR::getDDS(*this);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *
|
|
Packit |
a4aae4 |
DMR::root()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!d_root) d_root = static_cast<D4Group*>(d_factory->NewVariable(dods_group_c, "/"));
|
|
Packit |
a4aae4 |
return d_root;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Given the DAP protocol version, parse that string and set the DMR fields.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param v The version string.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DMR::set_dap_version(const string &v)
|
|
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 DMR 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 4:
|
|
Packit |
a4aae4 |
d_namespace = c_dap40_namespace;
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
d_namespace = "";
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the size of a response, in kilobytes. This method looks at the
|
|
Packit |
a4aae4 |
* variables in the DMR a computes the number of bytes in the response.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note This version of the method does a poor job with Arrays that
|
|
Packit |
a4aae4 |
* have varying dimensions.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param constrained Should the size of the whole DMR be used or should the
|
|
Packit |
a4aae4 |
* current constraint be taken into account?
|
|
Packit |
a4aae4 |
* @return The size of the request in kilobytes
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
long
|
|
Packit |
a4aae4 |
DMR::request_size(bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_root->request_size(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Print the DAP4 DMR object.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param xml use this XMLWriter to build the XML.
|
|
Packit |
a4aae4 |
* @param constrained Should the DMR be subject to a constraint? Defaults to
|
|
Packit |
a4aae4 |
* False
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DMR::print_dap4(XMLWriter &xml, bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// Reintroduce these if they are really useful. jhrg 4/15/13
|
|
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 |
#endif
|
|
Packit |
a4aae4 |
|
|
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 |
if (!request_xml_base().empty()) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
|
|
Packit |
a4aae4 |
(const xmlChar*)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*) "dapVersion", (const xmlChar*)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*)dmr_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*) "name", (const xmlChar*)name().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
root()->print_dap4(xml, constrained);
|
|
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 |
|
|
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 |
DMR::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "DMR::dump - ("
|
|
Packit |
a4aae4 |
<< (void *)this << ")" << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "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 |
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|