|
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., 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 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
#include <iomanip>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <stdint.h>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "crc.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "BaseType.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "XMLWriter.h"
|
|
Packit |
a4aae4 |
#include "D4Attributes.h"
|
|
Packit |
a4aae4 |
#include "D4Dimensions.h"
|
|
Packit |
a4aae4 |
#include "D4Group.h"
|
|
Packit |
a4aae4 |
#include "D4Enum.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "D4StreamMarshaller.h"
|
|
Packit |
a4aae4 |
#include "D4StreamUnMarshaller.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Define this symbol iff we decide to include information about the
|
|
Packit |
a4aae4 |
* byte order of the response (as sent from the server) so that the
|
|
Packit |
a4aae4 |
* client can determine the correct CRC32 hash code. jhrg 1/4/16
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
#undef INCLUDE_SOURCE_BYTE_ORDER
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void D4Group::m_duplicate(const D4Group &g)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "In D4Group::m_duplicate for " << g.name() << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// dims; deep copy, this is the parent
|
|
Packit |
a4aae4 |
if (g.d_dims) {
|
|
Packit |
a4aae4 |
d_dims = new D4Dimensions(*(g.d_dims));
|
|
Packit |
a4aae4 |
d_dims->set_parent(this);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Update all of the D4Dimension weak pointers in the Array objects.
|
|
Packit |
a4aae4 |
// This is a hack - we know that Constructor::m_duplicate() has been
|
|
Packit |
a4aae4 |
// called at this point and any Array instances have dimension pointers
|
|
Packit |
a4aae4 |
// that reference the 'old' dimensions (g.d_dims) and not the 'new'
|
|
Packit |
a4aae4 |
// dimensions made above. Scan every array and re-wire the weak pointers.
|
|
Packit |
a4aae4 |
// jhrg 8/15/14
|
|
Packit |
a4aae4 |
Vars_citer vi = d_vars.begin();
|
|
Packit |
a4aae4 |
while (vi != d_vars.end()) {
|
|
Packit |
a4aae4 |
if ((*vi)->type() == dods_array_c)
|
|
Packit |
a4aae4 |
static_cast<Array*>(*vi)->update_dimension_pointers(g.d_dims, d_dims);
|
|
Packit |
a4aae4 |
++vi;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// Moved this block up inside the if because g.d_dims might be false. jhrg 9/14/15
|
|
Packit |
a4aae4 |
Vars_citer vi = d_vars.begin();
|
|
Packit |
a4aae4 |
while (vi != d_vars.end()) {
|
|
Packit |
a4aae4 |
if ((*vi)->type() == dods_array_c)
|
|
Packit |
a4aae4 |
static_cast<Array*>(*vi)->update_dimension_pointers(g.d_dims, d_dims);
|
|
Packit |
a4aae4 |
++vi;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// enums; deep copy
|
|
Packit |
a4aae4 |
if (g.d_enum_defs) d_enum_defs = new D4EnumDefs(*g.d_enum_defs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// groups
|
|
Packit |
a4aae4 |
groupsCIter i = g.d_groups.begin();
|
|
Packit |
a4aae4 |
while(i != g.d_groups.end()) {
|
|
Packit |
a4aae4 |
// Only D4Groups are in the d_groups container.
|
|
Packit |
a4aae4 |
D4Group *g = static_cast<D4Group*>((*i++)->ptr_duplicate());
|
|
Packit |
a4aae4 |
add_group_nocopy(g);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Exiting D4Group::m_duplicate" << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The D4Group constructor requires only the name of the variable
|
|
Packit |
a4aae4 |
to be created. The name may be omitted, which will create a
|
|
Packit |
a4aae4 |
nameless variable. This may be adequate for some applications.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This type is available in DAP4 only.
|
|
Packit |
a4aae4 |
See http://docs.opendap.org/index.php/DAP4:_Specification_Volume_1#Groups
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n A string containing the name of the variable.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
D4Group::D4Group(const string &name)
|
|
Packit |
a4aae4 |
: Constructor(name, dods_group_c, /*is_dap4*/true), d_dims(0), d_enum_defs(0)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The D4Group server-side constructor requires the name of the variable
|
|
Packit |
a4aae4 |
to be created and the dataset name from which this variable is being
|
|
Packit |
a4aae4 |
created. Used on server-side handlers.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This type is available in DAP4 only.
|
|
Packit |
a4aae4 |
See http://docs.opendap.org/index.php/DAP4:_Specification_Volume_1#Groups
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n A string containing the name of the variable.
|
|
Packit |
a4aae4 |
@param d A string containing the name of the dataset.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
D4Group::D4Group(const string &name, const string &dataset)
|
|
Packit |
a4aae4 |
: Constructor(name, dataset, dods_group_c, /*is_dap4*/true), d_dims(0), d_enum_defs(0)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The D4Group copy constructor. */
|
|
Packit |
a4aae4 |
D4Group::D4Group(const D4Group &rhs) : Constructor(rhs), d_dims(0), d_enum_defs(0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "In D4Group::copy_ctor for " << rhs.name() << endl);
|
|
Packit |
a4aae4 |
m_duplicate(rhs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group::~D4Group()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
delete d_dims;
|
|
Packit |
a4aae4 |
delete d_enum_defs;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
groupsIter i = d_groups.begin();
|
|
Packit |
a4aae4 |
while(i != d_groups.end())
|
|
Packit |
a4aae4 |
delete *i++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
D4Group *
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// I think this was a mistake. jhrg 11/17/16
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4Group::ptr_duplicate()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return new D4Group(*this);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group &
|
|
Packit |
a4aae4 |
D4Group::operator=(const D4Group &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (this == &rhs)
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
m_duplicate(rhs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Get the Fully Qualified Name for this Group, including the Group. This
|
|
Packit |
a4aae4 |
* uses the name representation described in the DAP4 specification.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @return The FQN in a string
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
D4Group::FQN() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// The root group is named "/" (always)
|
|
Packit |
a4aae4 |
return (name() == "/") ? "/" : static_cast<D4Group*>(get_parent())->FQN() + name() + "/";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Note that in order for this to work the second argument must not be a reference.
|
|
Packit |
a4aae4 |
// jhrg 8/20/13
|
|
Packit |
a4aae4 |
static bool
|
|
Packit |
a4aae4 |
name_eq(D4Group *g, const string name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return g->name() == name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *
|
|
Packit |
a4aae4 |
D4Group::find_child_grp(const string &grp_name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
groupsIter g = find_if(grp_begin(), grp_end(), bind2nd(ptr_fun(name_eq), grp_name));
|
|
Packit |
a4aae4 |
return (g == grp_end()) ? 0: *g;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// TODO Add constraint param? jhrg 11/17/13
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4Group::find_first_var_that_uses_dimension(D4Dimension *dim)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// for each group, starting with the root group
|
|
Packit |
a4aae4 |
// for each variable in the group that is marked to send and is an array
|
|
Packit |
a4aae4 |
// return the btp if it uses the D4Dimension
|
|
Packit |
a4aae4 |
// if it contains child groups, search those
|
|
Packit |
a4aae4 |
// return the btp if it uses the D4Dimension
|
|
Packit |
a4aae4 |
// return null
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// exhaustive breadth-first search for 'dim
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// root group
|
|
Packit |
a4aae4 |
for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->send_p() && (*i)->type() == dods_array_c) {
|
|
Packit |
a4aae4 |
Array *a = static_cast<Array*>(*i);
|
|
Packit |
a4aae4 |
for (Array::Dim_iter di = a->dim_begin(), de = a->dim_end(); di != de; ++di) {
|
|
Packit |
a4aae4 |
if (a->dimension_D4dim(di) == dim)
|
|
Packit |
a4aae4 |
return a;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (groupsIter i = grp_begin(), e = grp_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
BaseType *btp = (*i)->find_first_var_that_uses_dimension(dim);
|
|
Packit |
a4aae4 |
if (btp) return btp;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4Group::find_first_var_that_uses_enumeration(D4EnumDef *enum_def)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// for each group, starting with the root group
|
|
Packit |
a4aae4 |
// for each variable in the group that is marked to send and is an array
|
|
Packit |
a4aae4 |
// return the btp if it uses the D4EnumDef
|
|
Packit |
a4aae4 |
// if it contains child groups, search those
|
|
Packit |
a4aae4 |
// return the btp if it uses the D4EnumDef
|
|
Packit |
a4aae4 |
// return null
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// exhaustive breadth-first search for 'dim
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// root group
|
|
Packit |
a4aae4 |
for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->send_p() && (*i)->type() == dods_enum_c) {
|
|
Packit |
a4aae4 |
D4Enum *e = static_cast<D4Enum*>(*i);
|
|
Packit |
a4aae4 |
if (e->enumeration() == enum_def)
|
|
Packit |
a4aae4 |
return e;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (groupsIter i = grp_begin(), e = grp_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
BaseType *btp = (*i)->find_first_var_that_uses_enumeration(enum_def);
|
|
Packit |
a4aae4 |
if (btp) return btp;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Find the dimension using a path.
|
|
Packit |
a4aae4 |
* Using the DAP4 name syntax, lookup a dimension. The dimension must
|
|
Packit |
a4aae4 |
* be defined before it is used. The \c path argument may be either an
|
|
Packit |
a4aae4 |
* absolute path or a relative path. Note that the name syntax does not
|
|
Packit |
a4aae4 |
* provide for paths to contain an 'up one level' symbol.
|
|
Packit |
a4aae4 |
* @param path The path to the dimension
|
|
Packit |
a4aae4 |
* @return A pointer to the D4Dimension object.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
D4Dimension *
|
|
Packit |
a4aae4 |
D4Group::find_dim(const string &path)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string lpath = path; // get a mutable copy
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// special-case for the root group
|
|
Packit |
a4aae4 |
if (lpath[0] == '/') {
|
|
Packit |
a4aae4 |
if (name() != "/")
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
lpath = lpath.substr(1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string::size_type pos = lpath.find('/');
|
|
Packit |
a4aae4 |
if (pos == string::npos) {
|
|
Packit |
a4aae4 |
// name looks like 'bar'
|
|
Packit |
a4aae4 |
return dims()->find_dim(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// name looks like foo/bar/baz where foo and bar must be groups
|
|
Packit |
a4aae4 |
string grp_name = lpath.substr(0, pos);
|
|
Packit |
a4aae4 |
lpath = lpath.substr(pos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *grp = find_child_grp(grp_name);
|
|
Packit |
a4aae4 |
return (grp == 0) ? 0: grp->find_dim(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Array *
|
|
Packit |
a4aae4 |
D4Group::find_map_source(const string &path)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *map_source = m_find_map_source_helper(path);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// TODO more complete semantic checking jhrg 10/16/13
|
|
Packit |
a4aae4 |
if (map_source && map_source->type() == dods_array_c) return static_cast<Array*>(map_source);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4Group::m_find_map_source_helper(const string &path)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string lpath = path; // get a mutable copy
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// special-case for the root group
|
|
Packit |
a4aae4 |
if (lpath[0] == '/') {
|
|
Packit |
a4aae4 |
if (name() != "/")
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
lpath = lpath.substr(1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string::size_type pos = lpath.find('/');
|
|
Packit |
a4aae4 |
if (pos == string::npos) {
|
|
Packit |
a4aae4 |
// name looks like 'bar'
|
|
Packit |
a4aae4 |
return var(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// name looks like foo/bar/baz where foo an bar must be groups
|
|
Packit |
a4aae4 |
string grp_name = lpath.substr(0, pos);
|
|
Packit |
a4aae4 |
lpath = lpath.substr(pos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *grp = find_child_grp(grp_name);
|
|
Packit |
a4aae4 |
return (grp == 0) ? 0: grp->var(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4EnumDef *
|
|
Packit |
a4aae4 |
D4Group::find_enum_def(const string &path)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string lpath = path; // get a mutable copy
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// special-case for the root group
|
|
Packit |
a4aae4 |
if (lpath[0] == '/') {
|
|
Packit |
a4aae4 |
if (name() != "/")
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
lpath = lpath.substr(1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string::size_type pos = lpath.find('/');
|
|
Packit |
a4aae4 |
if (pos == string::npos) {
|
|
Packit |
a4aae4 |
// name looks like 'bar'
|
|
Packit |
a4aae4 |
return enum_defs()->find_enum_def(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// name looks like foo/bar/baz where foo and bar must be groups
|
|
Packit |
a4aae4 |
string grp_name = lpath.substr(0, pos);
|
|
Packit |
a4aae4 |
lpath = lpath.substr(pos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *grp = find_child_grp(grp_name);
|
|
Packit |
a4aae4 |
return (grp == 0) ? 0: grp->enum_defs()->find_enum_def(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Find a variable using it's FUlly Qualified Name (FQN). The leading '/' is optional.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param path The FQN to the variable
|
|
Packit |
a4aae4 |
* @return A BaseType* to the variable of null if it was not found
|
|
Packit |
a4aae4 |
* @see BaseType::FQN()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4Group::find_var(const string &path)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string lpath = path; // get a mutable copy
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// special-case for the root group
|
|
Packit |
a4aae4 |
if (lpath[0] == '/') {
|
|
Packit |
a4aae4 |
if (name() != "/")
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
lpath = lpath.substr(1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string::size_type pos = lpath.find('/');
|
|
Packit |
a4aae4 |
if (pos == string::npos) {
|
|
Packit |
a4aae4 |
// name looks like 'bar' or bar.baz; lookup in the Constructor that's part of the Group
|
|
Packit |
a4aae4 |
return var(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// name looks like foo/bar/baz where foo and bar must be groups
|
|
Packit |
a4aae4 |
string grp_name = lpath.substr(0, pos);
|
|
Packit |
a4aae4 |
lpath = lpath.substr(pos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Group *grp = find_child_grp(grp_name);
|
|
Packit |
a4aae4 |
return (grp == 0) ? 0 : grp->find_var(lpath);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Compute the size of all of the variables in this group and it's children,
|
|
Packit |
a4aae4 |
* in kilobytes
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param constrained Should the current constraint be taken into account?
|
|
Packit |
a4aae4 |
* @return The size in kilobytes
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
long
|
|
Packit |
a4aae4 |
D4Group::request_size(bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
long long size = 0;
|
|
Packit |
a4aae4 |
// variables
|
|
Packit |
a4aae4 |
Constructor::Vars_iter v = var_begin();
|
|
Packit |
a4aae4 |
while (v != var_end()) {
|
|
Packit |
a4aae4 |
if (constrained) {
|
|
Packit |
a4aae4 |
if ((*v)->send_p())
|
|
Packit |
a4aae4 |
size += (*v)->width(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
size += (*v)->width(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
++v;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// groups
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end())
|
|
Packit |
a4aae4 |
size += (*g++)->request_size(constrained);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return size / 1024;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4Group::set_read_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end())
|
|
Packit |
a4aae4 |
(*g++)->set_read_p(state);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Constructor::set_read_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4Group::set_send_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end())
|
|
Packit |
a4aae4 |
(*g++)->set_send_p(state);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Constructor::set_send_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4Group::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end())
|
|
Packit |
a4aae4 |
(*g++)->intern_data(/*checksum, dmr, eval*/);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Specialize how the top-level variables in any Group are sent; include
|
|
Packit |
a4aae4 |
// a checksum for them. A subset operation might make an interior set of
|
|
Packit |
a4aae4 |
// variables, but the parent structure will still be present and the checksum
|
|
Packit |
a4aae4 |
// will be computed for that structure. In other words, DAP4 does not try
|
|
Packit |
a4aae4 |
// to sort out which variables are the 'real' top-level variables and instead
|
|
Packit |
a4aae4 |
// simply computes the CRC for whatever appears as a variable in the root
|
|
Packit |
a4aae4 |
// group.
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
// Only send the stuff in the current subset.
|
|
Packit |
a4aae4 |
if ((*i)->send_p()) {
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
checksum.Reset();
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
(*i)->intern_data(/*checksum, dmr, eval*/);
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
D4Attribute *a = new D4Attribute("DAP4_Checksum_CRC32", attr_str_c);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
oss.setf(ios::hex, ios::basefield);
|
|
Packit |
a4aae4 |
oss << setfill('0') << setw(8) << checksum.GetCrc32();
|
|
Packit |
a4aae4 |
a->add_value(oss.str());
|
|
Packit |
a4aae4 |
#if INCLUDE_SOURCE_BYTE_ORDER
|
|
Packit |
a4aae4 |
if (um.is_source_big_endian())
|
|
Packit |
a4aae4 |
a->add_value("source:big-endian");
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
a->add_value("source:little-endian");
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
(*i)->attributes()->add_attribute_nocopy(a);
|
|
Packit |
a4aae4 |
DBG(cerr << "CRC32: " << oss.str() << " for " << (*i)->name() << endl);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Serialize a Group
|
|
Packit |
a4aae4 |
* @param m The DAP4 Stream Marshaller. This object serializes the data values and
|
|
Packit |
a4aae4 |
* writes checksums (using CRC32) for the top level variables in every Group for which
|
|
Packit |
a4aae4 |
* one or more variables are sent. The DAP4 Marshaller object can be made so that only
|
|
Packit |
a4aae4 |
* the checksums are written.
|
|
Packit |
a4aae4 |
* @param dmr Unused
|
|
Packit |
a4aae4 |
* @param eval Unused
|
|
Packit |
a4aae4 |
* @param filter Unused
|
|
Packit |
a4aae4 |
* @exception Error is thrown if the value needs to be read and that operation fails.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4Group::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// This will call Constructor read which will, for everything but a Sequence,
|
|
Packit |
a4aae4 |
// read all of the data in one shot. However, the serialize() methods for the
|
|
Packit |
a4aae4 |
// Arrays, Structures, etc., also have read() calls in them and those can be
|
|
Packit |
a4aae4 |
// used to control how long the data are in memory, e.g., limiting the lifetime
|
|
Packit |
a4aae4 |
// of a large array and avoiding having overlapping arrays when they are not
|
|
Packit |
a4aae4 |
// needed. For a sequence read() has different semantics. It is called once
|
|
Packit |
a4aae4 |
// for every instance and the read_p flag is not used.
|
|
Packit |
a4aae4 |
if (!read_p())
|
|
Packit |
a4aae4 |
read(); // read() throws Error
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end())
|
|
Packit |
a4aae4 |
(*g++)->serialize(m, dmr, filter);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Specialize how the top-level variables in any Group are sent; include
|
|
Packit |
a4aae4 |
// a checksum for them. A subset operation might make an interior set of
|
|
Packit |
a4aae4 |
// variables, but the parent structure will still be present and the checksum
|
|
Packit |
a4aae4 |
// will be computed for that structure. In other words, DAP4 does not try
|
|
Packit |
a4aae4 |
// to sort out which variables are the 'real' top-level variables and instead
|
|
Packit |
a4aae4 |
// simply computes the CRC for whatever appears as a variable in the root
|
|
Packit |
a4aae4 |
// group.
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
// Only send the stuff in the current subset.
|
|
Packit |
a4aae4 |
if ((*i)->send_p()) {
|
|
Packit |
a4aae4 |
m.reset_checksum();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Serializing variable " << (*i)->type_name() << " " << (*i)->name() << endl);
|
|
Packit |
a4aae4 |
(*i)->serialize(m, dmr, filter);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Wrote CRC32: " << m.get_checksum() << " for " << (*i)->name() << endl);
|
|
Packit |
a4aae4 |
m.put_checksum();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void D4Group::deserialize(D4StreamUnMarshaller &um, DMR &dmr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end()) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Deserializing group " << (*g)->name() << endl);
|
|
Packit |
a4aae4 |
(*g++)->deserialize(um, dmr);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// Specialize how the top-level variables in any Group are received; read
|
|
Packit |
a4aae4 |
// their checksum and store the value in a magic attribute of the variable
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Deserializing variable " << (*i)->type_name() << " " << (*i)->name() << endl);
|
|
Packit |
a4aae4 |
(*i)->deserialize(um, dmr);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4Attribute *a = new D4Attribute("DAP4_Checksum_CRC32", attr_str_c);
|
|
Packit |
a4aae4 |
string crc = um.get_checksum_str();
|
|
Packit |
a4aae4 |
a->add_value(crc);
|
|
Packit |
a4aae4 |
#if INCLUDE_SOURCE_BYTE_ORDER
|
|
Packit |
a4aae4 |
if (um.is_source_big_endian())
|
|
Packit |
a4aae4 |
a->add_value("source:big-endian");
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
a->add_value("source:little-endian");
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
DBG(cerr << "Read CRC32: " << crc << " for " << (*i)->name() << endl);
|
|
Packit |
a4aae4 |
(*i)->attributes()->add_attribute_nocopy(a);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4Group::print_dap4(XMLWriter &xml, bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!name().empty() && name() != "/") {
|
|
Packit |
a4aae4 |
// For named groups, if constrained is true only print if this group
|
|
Packit |
a4aae4 |
// has variables that are marked for transmission. For the root group
|
|
Packit |
a4aae4 |
// this test is not made.
|
|
Packit |
a4aae4 |
if (constrained && !send_p())
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) type_name().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
|
|
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 |
|
|
Packit |
a4aae4 |
// dims
|
|
Packit |
a4aae4 |
if (!dims()->empty())
|
|
Packit |
a4aae4 |
dims()->print_dap4(xml, constrained);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// enums
|
|
Packit |
a4aae4 |
if (!enum_defs()->empty())
|
|
Packit |
a4aae4 |
enum_defs()->print_dap4(xml, constrained);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// variables
|
|
Packit |
a4aae4 |
Constructor::Vars_iter v = var_begin();
|
|
Packit |
a4aae4 |
while (v != var_end())
|
|
Packit |
a4aae4 |
(*v++)->print_dap4(xml, constrained);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// attributes
|
|
Packit |
a4aae4 |
attributes()->print_dap4(xml);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// groups
|
|
Packit |
a4aae4 |
groupsIter g = d_groups.begin();
|
|
Packit |
a4aae4 |
while (g != d_groups.end())
|
|
Packit |
a4aae4 |
(*g++)->print_dap4(xml, constrained);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!name().empty() && name() != "/") {
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief DAP4 to DAP2 transform
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* D4Group objects, with the exception of the root group, "disappear"
|
|
Packit |
a4aae4 |
* into the names of their member variables. Specifically the Group
|
|
Packit |
a4aae4 |
* name is add as a prefix followed by a "/" separator to the names
|
|
Packit |
a4aae4 |
* of all of the Group's member groups variables. The Group attributes
|
|
Packit |
a4aae4 |
* (metadata) are transfered to the parent_attr_table. The Group
|
|
Packit |
a4aae4 |
* members are collected returned in vector.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param The AttrTable pointer parent_attr_table is used by Groups, which disappear
|
|
Packit |
a4aae4 |
* from the DAP2 representation. Their children are returned in the the BAseType vector
|
|
Packit |
a4aae4 |
* their attributes are added to parent_attr_table;
|
|
Packit |
a4aae4 |
* @return A pointer to a vector of BaseType pointers (right?). In this D4Group case the
|
|
Packit |
a4aae4 |
* vector will contain DAP2 versions of all of the member variables of the D4Group instance.
|
|
Packit |
a4aae4 |
* (ex: UInt64) the will return a NULL pointer and so this must be tested!
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
vector<BaseType *> *
|
|
Packit |
a4aae4 |
D4Group::transform_to_dap2(AttrTable *parent_attr_table){
|
|
Packit |
a4aae4 |
return transform_to_dap2(parent_attr_table,false);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
vector<BaseType *> *
|
|
Packit |
a4aae4 |
D4Group::transform_to_dap2(AttrTable *parent_attr_table, bool is_root)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - BEGIN ("<< name() << " is_root: "<< (is_root?"true":"false") << ")" << endl;);
|
|
Packit |
a4aae4 |
vector<BaseType *> *results = new vector<BaseType *>();
|
|
Packit |
a4aae4 |
vector<BaseType *> dropped_vars;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable *group_attrs;
|
|
Packit |
a4aae4 |
group_attrs = attributes()->get_AttrTable(name());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* If this is the root group then we handle the attributes differently.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
if(is_root){
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Promoting group attributes to parent" << endl;);
|
|
Packit |
a4aae4 |
// If it's a root group we copy all the stuff up into the parent attr table
|
|
Packit |
a4aae4 |
for (AttrTable::Attr_iter i = group_attrs->attr_begin(), e = group_attrs->attr_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->type == Attr_container) {
|
|
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 |
parent_attr_table->append_container(at, at->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
parent_attr_table->append_attr(
|
|
Packit |
a4aae4 |
(*i)->name,
|
|
Packit |
a4aae4 |
AttrType_to_String((*i)->type),
|
|
Packit |
a4aae4 |
(*i)->attr);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete group_attrs;
|
|
Packit |
a4aae4 |
group_attrs = parent_attr_table;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Now we process the child variables of this group
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
for (D4Group::Vars_citer varIter = var_begin(), e = var_end(); varIter != e; ++varIter) {
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Processing member variable '" << (*varIter)->name() <<
|
|
Packit |
a4aae4 |
"' root: " << (is_root?"true":"false") << endl;);
|
|
Packit |
a4aae4 |
vector<BaseType *> *new_vars = (*varIter)->transform_to_dap2(group_attrs);
|
|
Packit |
a4aae4 |
if (new_vars) { // Might be un-mappable
|
|
Packit |
a4aae4 |
// It's not so game on..
|
|
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 |
|
|
Packit |
a4aae4 |
string new_name = (is_root?"":FQN()) + new_var->name();
|
|
Packit |
a4aae4 |
new_var->set_name(new_name);
|
|
Packit |
a4aae4 |
results->push_back(new_var);
|
|
Packit |
a4aae4 |
(*vIter) = NULL;
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Added member variable '" << (*varIter)->name() << "' " <<
|
|
Packit |
a4aae4 |
"to results vector. root: "<< (is_root?"true":"false") << endl;);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete new_vars;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Dropping member variable " << (*varIter)->name() <<
|
|
Packit |
a4aae4 |
" root: " << (is_root?"true":"false") << endl;);
|
|
Packit |
a4aae4 |
// Got back a NULL, so we are dropping this var.
|
|
Packit |
a4aae4 |
dropped_vars.push_back(*varIter);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// Process dropped DAP4 vars
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Processing " << dropped_vars.size() << " Dropped Variable(s)" << endl;);
|
|
Packit |
a4aae4 |
AttrTable *dv_attr_table = make_dropped_vars_attr_table(&dropped_vars);
|
|
Packit |
a4aae4 |
if(dv_attr_table){
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - Adding Dropped Variables AttrTable" << endl;);
|
|
Packit |
a4aae4 |
group_attrs->append_container(dv_attr_table,dv_attr_table->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - No Dropped Variables AttrTable returned." << endl;);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Get all the child groups.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
D4Group::groupsIter gIter = grp_begin();
|
|
Packit |
a4aae4 |
D4Group::groupsIter gEnd = 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(group_attrs);
|
|
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 |
results->push_back(*vIter);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if(!is_root){
|
|
Packit |
a4aae4 |
group_attrs->set_name(name());
|
|
Packit |
a4aae4 |
parent_attr_table->append_container(group_attrs,group_attrs->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
DBG( cerr << __func__ << "() - END" << endl;);
|
|
Packit |
a4aae4 |
return results;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} /* namespace libdap */
|