Blame Constructor.cc

Packit a4aae4
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 1995-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
#include "config.h"
Packit a4aae4
Packit a4aae4
//#define DODS_DEBUG
Packit a4aae4
Packit a4aae4
#include <string>
Packit a4aae4
#include <sstream>
Packit a4aae4
#include <algorithm>
Packit a4aae4
#include <functional>
Packit a4aae4
Packit a4aae4
#include <stdint.h>
Packit a4aae4
Packit a4aae4
#include "crc.h"
Packit a4aae4
Packit a4aae4
#include "Constructor.h"
Packit a4aae4
#include "Grid.h"
Packit a4aae4
Packit a4aae4
#include "DMR.h"
Packit a4aae4
#include "XMLWriter.h"
Packit a4aae4
#include "D4StreamMarshaller.h"
Packit a4aae4
#include "D4StreamUnMarshaller.h"
Packit a4aae4
#include "D4Group.h"
Packit a4aae4
Packit a4aae4
#include "D4Attributes.h"
Packit a4aae4
Packit a4aae4
#include "escaping.h"
Packit a4aae4
#include "util.h"
Packit a4aae4
#include "Error.h"
Packit a4aae4
#include "InternalErr.h"
Packit a4aae4
Packit a4aae4
Packit a4aae4
// #define DODS_DEBUG 1
Packit a4aae4
#include "debug.h"
Packit a4aae4
Packit a4aae4
using namespace std;
Packit a4aae4
Packit a4aae4
namespace libdap {
Packit a4aae4
Packit a4aae4
// Private member functions
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::m_duplicate(const Constructor &c)
Packit a4aae4
{
Packit a4aae4
	DBG(cerr << "In Constructor::m_duplicate for " << c.name() << endl);
Packit a4aae4
	// Clear out any spurious vars in Constructor::d_vars
Packit a4aae4
	// Moved from Grid::m_duplicate. jhrg 4/3/13
Packit a4aae4
	d_vars.clear(); // [mjohnson 10 Sep 2009]
Packit a4aae4
Packit a4aae4
	Vars_citer i = c.d_vars.begin();
Packit a4aae4
	while (i != c.d_vars.end()) {
Packit a4aae4
		BaseType *btp = (*i++)->ptr_duplicate();
Packit a4aae4
		btp->set_parent(this);
Packit a4aae4
		d_vars.push_back(btp);
Packit a4aae4
	}
Packit a4aae4
Packit a4aae4
	DBG(cerr << "Exiting Constructor::m_duplicate for " << c.name() << endl);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Public member functions
Packit a4aae4
Packit a4aae4
Constructor::Constructor(const string &name, const Type &type, bool is_dap4)
Packit a4aae4
        : BaseType(name, type, is_dap4)
Packit a4aae4
{}
Packit a4aae4
Packit a4aae4
/** Server-side constructor that takes the name of the variable to be
Packit a4aae4
 * created, the dataset name from which this variable is being created, and
Packit a4aae4
 * the type of data being stored in the Constructor. This is a protected
Packit a4aae4
 * constructor, available only to derived classes of Constructor
Packit a4aae4
 *
Packit a4aae4
 * @param name string containing the name of the variable to be created
Packit a4aae4
 * @param dataset string containing the name of the dataset from which this
Packit a4aae4
 * variable is being created
Packit a4aae4
 * @param type type of data being stored
Packit a4aae4
 */
Packit a4aae4
Constructor::Constructor(const string &name, const string &dataset, const Type &type, bool is_dap4)
Packit a4aae4
        : BaseType(name, dataset, type, is_dap4)
Packit a4aae4
{}
Packit a4aae4
Packit a4aae4
Constructor::Constructor(const Constructor &rhs) : BaseType(rhs), d_vars(0)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "In Constructor::copy_ctor for " << rhs.name() << endl);
Packit a4aae4
    m_duplicate(rhs);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Constructor::~Constructor()
Packit a4aae4
{
Packit a4aae4
    Vars_iter i = d_vars.begin();
Packit a4aae4
    while (i != d_vars.end()) {
Packit a4aae4
        delete *i++;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Constructor &
Packit a4aae4
Constructor::operator=(const Constructor &rhs)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Entering Constructor::operator=" << endl);
Packit a4aae4
    if (this == &rhs)
Packit a4aae4
        return *this;
Packit a4aae4
Packit a4aae4
    dynamic_cast<BaseType &>(*this) = rhs; // run BaseType=
Packit a4aae4
Packit a4aae4
    m_duplicate(rhs);
Packit a4aae4
Packit a4aae4
    DBG(cerr << "Exiting Constructor::operator=" << endl);
Packit a4aae4
    return *this;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// A public method, but just barely...
Packit a4aae4
void
Packit a4aae4
Constructor::transform_to_dap4(D4Group *root, Constructor *dest)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << __func__ << "() - BEGIN (name:"<< name() <<
Packit a4aae4
        ")(type:"<< type_name()<<
Packit a4aae4
        ")(root:'"<< root->name()<<"':"<<(void*)root <<
Packit a4aae4
        ")(dest:'"<< dest->name()<<"':"<< (void *) dest<< ")"
Packit a4aae4
        << endl;);
Packit a4aae4
Packit a4aae4
    for (Constructor::Vars_citer i = var_begin(), e = var_end(); i != e; ++i) {
Packit a4aae4
        BaseType *d4_var = dest->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
            /*
Packit a4aae4
            BaseType *new_var = (*i)->transform_to_dap4(root, dest);
Packit a4aae4
            if (new_var) {	// Might be a Grid; see the comment in BaseType::transform_to_dap4()
Packit a4aae4
                new_var->set_parent(dest);
Packit a4aae4
                dest->add_var_nocopy(new_var);
Packit a4aae4
            }
Packit a4aae4
            */
Packit a4aae4
            DBG(cerr << __func__ << "() - Transforming variable: '" <<
Packit a4aae4
                (*i)->name() << "'" << endl; );
Packit a4aae4
            (*i)->transform_to_dap4(root /*group*/, dest /*container*/);
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
    dest->attributes()->transform_to_dap4(get_attr_table());
Packit a4aae4
    dest->set_is_dap4(true);
Packit a4aae4
    DBG(cerr << __func__ << "() - END (name:"<< name() << ")(type:"<< type_name()<< ")" << endl;);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
Packit a4aae4
string
Packit a4aae4
Constructor::FQN() const
Packit a4aae4
{
Packit a4aae4
	if (get_parent() == 0)
Packit a4aae4
		return name();
Packit a4aae4
	else if (get_parent()->type() == dods_group_c)
Packit a4aae4
		return get_parent()->FQN() + name();
Packit a4aae4
	else if (get_parent()->type() == dods_array_c)
Packit a4aae4
		return get_parent()->FQN();
Packit a4aae4
	else
Packit a4aae4
		return get_parent()->FQN() + "." + name();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
int
Packit a4aae4
Constructor::element_count(bool leaves)
Packit a4aae4
{
Packit a4aae4
    if (!leaves)
Packit a4aae4
        return d_vars.size();
Packit a4aae4
    else {
Packit a4aae4
        int i = 0;
Packit a4aae4
        for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) {
Packit a4aae4
            i += (*j)->element_count(leaves);
Packit a4aae4
        }
Packit a4aae4
        return i;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::set_send_p(bool state)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        (*i)->set_send_p(state);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    BaseType::set_send_p(state);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::set_read_p(bool state)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        (*i)->set_read_p(state);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    BaseType::set_read_p(state);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
// TODO Recode to use width(bool). Bur see comments in BaseType.h
Packit a4aae4
unsigned int
Packit a4aae4
Constructor::width()
Packit a4aae4
{
Packit a4aae4
    unsigned int sz = 0;
Packit a4aae4
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        sz += (*i)->width();
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return sz;
Packit a4aae4
}
Packit a4aae4
#endif
Packit a4aae4
/** This version of width simply returns the same thing as width() for simple
Packit a4aae4
    types and Arrays. For Structure it returns the total size if constrained
Packit a4aae4
    is false, or the size of the elements in the current projection if true.
Packit a4aae4
Packit a4aae4
    @param constrained If true, return the size after applying a constraint.
Packit a4aae4
    @return  The number of bytes used by the variable.
Packit a4aae4
 */
Packit a4aae4
unsigned int
Packit a4aae4
Constructor::width(bool constrained) const
Packit a4aae4
{
Packit a4aae4
    unsigned int sz = 0;
Packit a4aae4
Packit a4aae4
    for (Vars_citer i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if (constrained) {
Packit a4aae4
            if ((*i)->send_p())
Packit a4aae4
                sz += (*i)->width(constrained);
Packit a4aae4
        }
Packit a4aae4
        else {
Packit a4aae4
            sz += (*i)->width(constrained);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return sz;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
BaseType *
Packit a4aae4
Constructor::var(const string &name, bool exact_match, btp_stack *s)
Packit a4aae4
{
Packit a4aae4
    string n = www2id(name);
Packit a4aae4
Packit a4aae4
    if (exact_match)
Packit a4aae4
        return m_exact_match(n, s);
Packit a4aae4
    else
Packit a4aae4
        return m_leaf_match(n, s);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @deprecated See comment in BaseType */
Packit a4aae4
BaseType *
Packit a4aae4
Constructor::var(const string &n, btp_stack &s)
Packit a4aae4
{
Packit a4aae4
	// This should probably be removed. The BES code should remove web encoding
Packit a4aae4
	// with the possible exception of spaces. jhrg 11/25/13
Packit a4aae4
    string name = www2id(n);
Packit a4aae4
Packit a4aae4
    BaseType *btp = m_exact_match(name, &s);
Packit a4aae4
    if (btp)
Packit a4aae4
        return btp;
Packit a4aae4
Packit a4aae4
    return m_leaf_match(name, &s);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Protected method
Packit a4aae4
BaseType *
Packit a4aae4
Constructor::m_leaf_match(const string &name, btp_stack *s)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->name() == name) {
Packit a4aae4
            if (s) {
Packit a4aae4
                DBG(cerr << "Pushing " << this->name() << endl);
Packit a4aae4
                s->push(static_cast<BaseType *>(this));
Packit a4aae4
            }
Packit a4aae4
            return *i;
Packit a4aae4
        }
Packit a4aae4
        if ((*i)->is_constructor_type()) {
Packit a4aae4
            BaseType *btp = (*i)->var(name, false, s);
Packit a4aae4
            if (btp) {
Packit a4aae4
                if (s) {
Packit a4aae4
                    DBG(cerr << "Pushing " << this->name() << endl);
Packit a4aae4
                    s->push(static_cast<BaseType *>(this));
Packit a4aae4
                }
Packit a4aae4
                return btp;
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return 0;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Protected method
Packit a4aae4
BaseType *
Packit a4aae4
Constructor::m_exact_match(const string &name, btp_stack *s)
Packit a4aae4
{
Packit a4aae4
    // Look for name at the top level first.
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->name() == name) {
Packit a4aae4
            if (s)
Packit a4aae4
                s->push(static_cast<BaseType *>(this));
Packit a4aae4
Packit a4aae4
            return *i;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // If it was not found using the simple search, look for a dot and
Packit a4aae4
    // search the hierarchy.
Packit a4aae4
    string::size_type dot_pos = name.find("."); // zero-based index of `.'
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);
Packit a4aae4
        if (agg_ptr) {
Packit a4aae4
            if (s)
Packit a4aae4
                s->push(static_cast<BaseType *>(this));
Packit a4aae4
Packit a4aae4
            return agg_ptr->var(field, true, s); // recurse
Packit a4aae4
        }
Packit a4aae4
        else
Packit a4aae4
            return 0;  // qualified names must be *fully* qualified
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return 0;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns an iterator referencing the first structure element. */
Packit a4aae4
Constructor::Vars_iter
Packit a4aae4
Constructor::var_begin()
Packit a4aae4
{
Packit a4aae4
    return d_vars.begin() ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns an iterator referencing the end of the list of structure
Packit a4aae4
    elements. Does not reference the last structure element. */
Packit a4aae4
Constructor::Vars_iter
Packit a4aae4
Constructor::var_end()
Packit a4aae4
{
Packit a4aae4
    return d_vars.end() ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Return a reverse iterator that references the last element. */
Packit a4aae4
Constructor::Vars_riter
Packit a4aae4
Constructor::var_rbegin()
Packit a4aae4
{
Packit a4aae4
    return d_vars.rbegin();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Return a reverse iterator that references a point 'before' the first
Packit a4aae4
    element. */
Packit a4aae4
Constructor::Vars_riter
Packit a4aae4
Constructor::var_rend()
Packit a4aae4
{
Packit a4aae4
    return d_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
Constructor::Vars_iter
Packit a4aae4
Constructor::get_vars_iter(int i)
Packit a4aae4
{
Packit a4aae4
    return d_vars.begin() + i;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Return the BaseType pointer for the \e ith variable.
Packit a4aae4
    @param i This index
Packit a4aae4
    @return The corresponding BaseType*. */
Packit a4aae4
BaseType *
Packit a4aae4
Constructor::get_var_index(int i)
Packit a4aae4
{
Packit a4aae4
    return *(d_vars.begin() + i);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Adds an element to a Constructor.
Packit a4aae4
Packit a4aae4
    @param bt A pointer to the variable to add to this Constructor.
Packit a4aae4
    @param part Not used by this class, defaults to nil */
Packit a4aae4
void
Packit a4aae4
Constructor::add_var(BaseType *bt, Part)
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
    // Passing and invalid pointer to an object is a developer's error.
Packit a4aae4
    if (!bt)
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
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 Structure.");
Packit a4aae4
#endif
Packit a4aae4
    // Jose Garcia
Packit a4aae4
    // Now we add a copy of bt so the external user is able to destroy bt as
Packit a4aae4
    // he/she wishes. The policy is: "If it is allocated outside, it is
Packit a4aae4
    // deallocated outside, if it is allocated inside, it is deallocated
Packit a4aae4
    // inside"
Packit a4aae4
    BaseType *btp = bt->ptr_duplicate();
Packit a4aae4
    btp->set_parent(this);
Packit a4aae4
    d_vars.push_back(btp);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Adds an element to a Constructor.
Packit a4aae4
Packit a4aae4
    @param bt A pointer to thee variable to add to this Constructor.
Packit a4aae4
    @param part Not used by this class, defaults to nil */
Packit a4aae4
void
Packit a4aae4
Constructor::add_var_nocopy(BaseType *bt, Part)
Packit a4aae4
{
Packit a4aae4
    if (!bt)
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
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 Structure.");
Packit a4aae4
#endif
Packit a4aae4
    bt->set_parent(this);
Packit a4aae4
    d_vars.push_back(bt);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Remove an element from a Constructor.
Packit a4aae4
Packit a4aae4
    @param n name of the variable to remove */
Packit a4aae4
void
Packit a4aae4
Constructor::del_var(const string &n)
Packit a4aae4
{
Packit a4aae4
	// TODO remove_if? find_if?
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->name() == n) {
Packit a4aae4
            BaseType *bt = *i ;
Packit a4aae4
            d_vars.erase(i) ;
Packit a4aae4
            delete bt ; bt = 0;
Packit a4aae4
            return;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::del_var(Vars_iter i)
Packit a4aae4
{
Packit a4aae4
    if (*i != 0) {
Packit a4aae4
        BaseType *bt = *i;
Packit a4aae4
        d_vars.erase(i);
Packit a4aae4
        delete bt;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief simple implementation of read that iterates through vars
Packit a4aae4
 *  and calls read on them
Packit a4aae4
 *
Packit a4aae4
 * @return returns false to signify all has been read
Packit a4aae4
 */
Packit a4aae4
bool Constructor::read()
Packit a4aae4
{
Packit a4aae4
	DBG(cerr << "Entering  Constructor::read..." << endl);
Packit a4aae4
    if (!read_p()) {
Packit a4aae4
        for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
            (*i)->read();
Packit a4aae4
        }
Packit a4aae4
        set_read_p(true);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::intern_data(ConstraintEvaluator & eval, DDS & dds)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Constructor::intern_data: " << name() << endl);
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read();          // read() throws Error and InternalErr
Packit a4aae4
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->send_p()) {
Packit a4aae4
            (*i)->intern_data(eval, dds);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool
Packit a4aae4
Constructor::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
Packit a4aae4
{
Packit a4aae4
#if USE_LOCAL_TIMEOUT_SCHEME
Packit a4aae4
    dds.timeout_on();
Packit a4aae4
#endif
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read();  // read() throws Error and InternalErr
Packit a4aae4
Packit a4aae4
    if (ce_eval && !eval.eval_selection(dds, dataset()))
Packit a4aae4
        return true;
Packit a4aae4
#if USE_LOCAL_TIMEOUT_SCHEME
Packit a4aae4
    dds.timeout_off();
Packit a4aae4
#endif
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->send_p()) {
Packit a4aae4
#ifdef CHECKSUMS
Packit a4aae4
            XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
Packit a4aae4
            if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
Packit a4aae4
                sm->reset_checksum();
Packit a4aae4
Packit a4aae4
            (*i)->serialize(eval, dds, m, false);
Packit a4aae4
Packit a4aae4
            if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
Packit a4aae4
                sm->get_checksum();
Packit a4aae4
#else
Packit a4aae4
            // (*i)->serialize(eval, dds, m, false);
Packit a4aae4
            // Only Sequence and Vector run the evaluator.
Packit a4aae4
            (*i)->serialize(eval, dds, m, true);
Packit a4aae4
#endif
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return true;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool
Packit a4aae4
Constructor::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        (*i)->deserialize(um, dds, reuse);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::compute_checksum(Crc32 &)
Packit a4aae4
{
Packit a4aae4
	throw InternalErr(__FILE__, __LINE__, "Computing a checksum alone is not supported for Constructor types.");
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator & eval*/)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->send_p()) {
Packit a4aae4
            (*i)->intern_data(/*checksum, dmr, eval*/);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @brief Serialize a Constructor
Packit a4aae4
 *
Packit a4aae4
 * @todo See notebook for 8/21/14
Packit a4aae4
 *
Packit a4aae4
 * @param m
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
Constructor::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter)
Packit a4aae4
{
Packit a4aae4
#if 1
Packit a4aae4
	// Not used for the same reason the equivalent code in D4Group::serialize()
Packit a4aae4
	// is not used. Fail for D4Sequence and general issues with memory use.
Packit a4aae4
	//
Packit a4aae4
	// Revisit this - I had to uncomment this to get the netcdf_handler code
Packit a4aae4
	// to work - it relies on having NCStructure::read() called. The D4Sequence
Packit a4aae4
	// ::serialize() method calls read_next_instance(). What seems to be happening
Packit a4aae4
	// is that this call to read gets the first set of values, but does not store
Packit a4aae4
	// them; the call to serialize then runs the D4Sequence::serialize() method that
Packit a4aae4
	// _does_ read all of the sequence data and then serialize it. However, the first
Packit a4aae4
	// sequence instance is missing...
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read();  // read() throws Error
Packit a4aae4
#endif
Packit a4aae4
#if 0
Packit a4aae4
    // place holder for now. There may be no need for this; only Array and Seq?
Packit a4aae4
    // jhrg 9/6/13
Packit a4aae4
    if (filter && !eval.eval_selection(dmr, dataset()))
Packit a4aae4
        return true;
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        if ((*i)->send_p()) {
Packit a4aae4
            (*i)->serialize(m, dmr, /*eval,*/ filter);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::deserialize(D4StreamUnMarshaller &um, DMR &dmr)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        (*i)->deserialize(um, dmr);
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::print_decl(FILE *out, string space, bool print_semi,
Packit a4aae4
                        bool constraint_info, bool constrained)
Packit a4aae4
{
Packit a4aae4
    ostringstream oss;
Packit a4aae4
    print_decl(oss, space, print_semi, constraint_info, constrained);
Packit a4aae4
    fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::print_decl(ostream &out, string space, bool print_semi,
Packit a4aae4
                        bool constraint_info, bool constrained)
Packit a4aae4
{
Packit a4aae4
    if (constrained && !send_p())
Packit a4aae4
        return;
Packit a4aae4
Packit a4aae4
    out << space << type_name() << " {\n" ;
Packit a4aae4
    for (Vars_citer i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        (*i)->print_decl(out, space + "    ", true, constraint_info, constrained);
Packit a4aae4
    }
Packit a4aae4
    out << space << "} " << id2www(name()) ;
Packit a4aae4
Packit a4aae4
    if (constraint_info) { // Used by test drivers only.
Packit a4aae4
        if (send_p())
Packit a4aae4
            out << ": Send True";
Packit a4aae4
        else
Packit a4aae4
            out << ": Send False";
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    if (print_semi)
Packit a4aae4
        out << ";\n" ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::print_val(FILE *out, string space, bool print_decl_p)
Packit a4aae4
{
Packit a4aae4
    ostringstream oss;
Packit a4aae4
    print_val(oss, space, print_decl_p);
Packit a4aae4
    fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::print_val(ostream &out, string space, bool print_decl_p)
Packit a4aae4
{
Packit a4aae4
    if (print_decl_p) {
Packit a4aae4
        print_decl(out, space, false);
Packit a4aae4
        out << " = " ;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    out << "{ " ;
Packit a4aae4
    for (Vars_citer i = d_vars.begin(), e = d_vars.end(); i != e;
Packit a4aae4
         i++, (void)(i != e && out << ", ")) {
Packit a4aae4
Packit a4aae4
        DBG(cerr << (*i)->name() << " isa " << (*i)->type_name() << endl);
Packit a4aae4
Packit a4aae4
        (*i)->print_val(out, "", false);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    out << " }" ;
Packit a4aae4
Packit a4aae4
    if (print_decl_p)
Packit a4aae4
        out << ";\n" ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @deprecated
Packit a4aae4
 */
Packit a4aae4
void
Packit a4aae4
Constructor::print_xml(FILE *out, string space, bool constrained)
Packit a4aae4
{
Packit a4aae4
    XMLWriter xml(space);
Packit a4aae4
    print_xml_writer(xml, constrained);
Packit a4aae4
    fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @deprecated
Packit a4aae4
 */
Packit a4aae4
void
Packit a4aae4
Constructor::print_xml(ostream &out, string space, bool constrained)
Packit a4aae4
{
Packit a4aae4
    XMLWriter xml(space);
Packit a4aae4
    print_xml_writer(xml, constrained);
Packit a4aae4
    out << xml.get_doc();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
class PrintFieldXMLWriter : public unary_function<BaseType *, void>
Packit a4aae4
{
Packit a4aae4
    XMLWriter &d_xml;
Packit a4aae4
    bool d_constrained;
Packit a4aae4
public:
Packit a4aae4
    PrintFieldXMLWriter(XMLWriter &x, bool c)
Packit a4aae4
            : d_xml(x), d_constrained(c)
Packit a4aae4
    {}
Packit a4aae4
Packit a4aae4
    void operator()(BaseType *btp)
Packit a4aae4
    {
Packit a4aae4
        btp->print_xml_writer(d_xml, d_constrained);
Packit a4aae4
    }
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::print_xml_writer(XMLWriter &xml, bool constrained)
Packit a4aae4
{
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 (!name().empty())
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
    // DAP2 prints attributes first. For some reason we decided that DAP4 should
Packit a4aae4
    // print them second. No idea why... jhrg 8/15/14
Packit a4aae4
    if (!is_dap4() && get_attr_table().get_size() > 0)
Packit a4aae4
        get_attr_table().print_xml_writer(xml);
Packit a4aae4
Packit a4aae4
    bool has_variables = (var_begin() != var_end());
Packit a4aae4
    if (has_variables)
Packit a4aae4
        for_each(var_begin(), var_end(), PrintFieldXMLWriter(xml, constrained));
Packit a4aae4
Packit a4aae4
    if (is_dap4())
Packit a4aae4
        attributes()->print_dap4(xml);
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
    // Moved up above so that the DDX tests for various handles will still work.
Packit a4aae4
    // jhrg 8/15/14
Packit a4aae4
    if (!is_dap4() && get_attr_table().get_size() > 0)
Packit a4aae4
        get_attr_table().print_xml_writer(xml);
Packit a4aae4
#endif
Packit a4aae4
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
class PrintDAP4FieldXMLWriter : public unary_function<BaseType *, void>
Packit a4aae4
{
Packit a4aae4
    XMLWriter &d_xml;
Packit a4aae4
    bool d_constrained;
Packit a4aae4
public:
Packit a4aae4
    PrintDAP4FieldXMLWriter(XMLWriter &x, bool c) : d_xml(x), d_constrained(c) {}
Packit a4aae4
Packit a4aae4
    void operator()(BaseType *btp)
Packit a4aae4
    {
Packit a4aae4
        btp->print_dap4(d_xml, d_constrained);
Packit a4aae4
    }
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Constructor::print_dap4(XMLWriter &xml, bool constrained)
Packit a4aae4
{
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 (!name().empty())
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
    bool has_variables = (var_begin() != var_end());
Packit a4aae4
    if (has_variables)
Packit a4aae4
        for_each(var_begin(), var_end(), PrintDAP4FieldXMLWriter(xml, constrained));
Packit a4aae4
Packit a4aae4
    attributes()->print_dap4(xml);
Packit a4aae4
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
bool
Packit a4aae4
Constructor::check_semantics(string &msg, bool all)
Packit a4aae4
{
Packit a4aae4
    if (!BaseType::check_semantics(msg))
Packit a4aae4
        return false;
Packit a4aae4
Packit a4aae4
    if (!unique_names(d_vars, name(), type_name(), msg))
Packit a4aae4
        return false;
Packit a4aae4
Packit a4aae4
    if (all)
Packit a4aae4
        for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
            if (!(*i)->check_semantics(msg, true)) {
Packit a4aae4
                return false;
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
    return true;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** True if the instance can be flattened and printed as a single table
Packit a4aae4
    of values. For Arrays and Grids this is always false. For Structures
Packit a4aae4
    and Sequences the conditions are more complex. The implementation
Packit a4aae4
    provided by this class always returns false. Other classes should
Packit a4aae4
    override this implementation.
Packit a4aae4
Packit a4aae4
    @todo Change the name to is_flattenable or something like that. 05/16/03
Packit a4aae4
    jhrg
Packit a4aae4
Packit a4aae4
    @brief Check to see whether this variable can be printed simply.
Packit a4aae4
    @return True if the instance can be printed as a single table of
Packit a4aae4
    values, false otherwise. */
Packit a4aae4
bool
Packit a4aae4
Constructor::is_linear()
Packit a4aae4
{
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Set the \e in_selection property for this variable and all of its
Packit a4aae4
    children.
Packit a4aae4
Packit a4aae4
    @brief Set the \e in_selection property.
Packit a4aae4
    @param state Set the property value to \e state. */
Packit a4aae4
void
Packit a4aae4
Constructor::set_in_selection(bool state)
Packit a4aae4
{
Packit a4aae4
    for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
        (*i)->set_in_selection(state);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    BaseType::set_in_selection(state);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
void Constructor::transfer_attributes(AttrTable *at_container)
Packit a4aae4
{
Packit a4aae4
    AttrTable *at = at_container->get_attr_table(name());
Packit a4aae4
    DBG(cerr << "Constructor::transfer_attributes() - processing " << name() << "'  addr: "<< (void*) at << endl);
Packit a4aae4
    if (at) {
Packit a4aae4
        BaseType::transfer_attributes(at_container);
Packit a4aae4
        for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
Packit a4aae4
            BaseType *bt  = (*i);
Packit a4aae4
            bt->transfer_attributes(at);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
AttrTable *
Packit a4aae4
Constructor::make_dropped_vars_attr_table(vector<BaseType *> *dropped_vars) {
Packit a4aae4
    DBG( cerr << __func__ << "() - BEGIN" << endl;);
Packit a4aae4
Packit a4aae4
    AttrTable *dv_table = NULL;
Packit a4aae4
    if(!dropped_vars->empty()){
Packit a4aae4
        dv_table = new AttrTable;
Packit a4aae4
        dv_table->set_name("dap4:dropped_members");
Packit a4aae4
        vector<BaseType *>::iterator dvIter = dropped_vars->begin();
Packit a4aae4
        vector<BaseType *>::iterator dvEnd = dropped_vars->end();
Packit a4aae4
        unsigned int i = 0;
Packit a4aae4
        for( ; dvIter!=dvEnd ; dvIter++, i++){
Packit a4aae4
            BaseType *bt = (*dvIter);
Packit a4aae4
            AttrTable *bt_attr_table = new AttrTable(bt->get_attr_table());
Packit a4aae4
            bt_attr_table->set_name(bt->name());
Packit a4aae4
            string type_name = bt->type_name();
Packit a4aae4
            if(bt->is_vector_type()){
Packit a4aae4
                Array *array = dynamic_cast <Array *>(bt);
Packit a4aae4
                if(array){
Packit a4aae4
                    type_name = array->prototype()->type_name();
Packit a4aae4
                    DBG( cerr << __func__ << "() - The variable " << bt->name() << " is an Array of '"<< type_name << "'" << endl;);
Packit a4aae4
                    Array::Dim_iter d_iter = array->dim_begin();
Packit a4aae4
                    Array::Dim_iter end = array->dim_end();
Packit a4aae4
                    for( ; d_iter< end ; d_iter++){
Packit a4aae4
Packit a4aae4
                        ostringstream dim_size;
Packit a4aae4
                        dim_size << (*d_iter).size;
Packit a4aae4
                        bt_attr_table->append_attr(
Packit a4aae4
                            "array_dimensions",
Packit a4aae4
                            AttrType_to_String(Attr_uint32),
Packit a4aae4
                            dim_size.str());
Packit a4aae4
                    }
Packit a4aae4
                }
Packit a4aae4
            }
Packit a4aae4
            bt_attr_table->append_attr("dap4:type","String", type_name);
Packit a4aae4
            dv_table->append_container(bt_attr_table,bt_attr_table->get_name());
Packit a4aae4
            // Clear entry now that we're done.
Packit a4aae4
            (*dvIter) = 0;
Packit a4aae4
        }
Packit a4aae4
   }
Packit a4aae4
    DBG( cerr << __func__ << "() - END " << endl;);
Packit a4aae4
    return dv_table;
Packit a4aae4
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 information about this
Packit a4aae4
 * instance.
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
Constructor::dump(ostream &strm) const
Packit a4aae4
{
Packit a4aae4
    strm << DapIndent::LMarg << "Constructor::dump - ("
Packit a4aae4
    << (void *)this << ")" << endl ;
Packit a4aae4
    DapIndent::Indent() ;
Packit a4aae4
    BaseType::dump(strm) ;
Packit a4aae4
    strm << DapIndent::LMarg << "vars: " << endl ;
Packit a4aae4
    DapIndent::Indent() ;
Packit a4aae4
    Vars_citer i = d_vars.begin() ;
Packit a4aae4
    Vars_citer ie = d_vars.end() ;
Packit a4aae4
    for (; i != ie; i++) {
Packit a4aae4
        (*i)->dump(strm) ;
Packit a4aae4
    }
Packit a4aae4
    DapIndent::UnIndent() ;
Packit a4aae4
    DapIndent::UnIndent() ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
} // namespace libdap
Packit a4aae4