|
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 1994-1999
|
|
Packit |
a4aae4 |
// Please read the full copyright statement in the file COPYRIGHT_URI.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Authors:
|
|
Packit |
a4aae4 |
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Implementation for BaseType.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// jhrg 9/6/94
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cstdio> // for stdin and stdout
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
#include <string>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "BaseType.h"
|
|
Packit |
a4aae4 |
#include "Byte.h"
|
|
Packit |
a4aae4 |
#include "Int16.h"
|
|
Packit |
a4aae4 |
#include "UInt16.h"
|
|
Packit |
a4aae4 |
#include "Int32.h"
|
|
Packit |
a4aae4 |
#include "UInt32.h"
|
|
Packit |
a4aae4 |
#include "Float32.h"
|
|
Packit |
a4aae4 |
#include "Float64.h"
|
|
Packit |
a4aae4 |
#include "Str.h"
|
|
Packit |
a4aae4 |
#include "Url.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
#include "Structure.h"
|
|
Packit |
a4aae4 |
#include "Sequence.h"
|
|
Packit |
a4aae4 |
#include "Grid.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "D4Attributes.h"
|
|
Packit |
a4aae4 |
#include "DMR.h"
|
|
Packit |
a4aae4 |
#include "XMLWriter.h"
|
|
Packit |
a4aae4 |
#include "D4BaseTypeFactory.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "InternalErr.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace std;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Protected copy mfunc
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Perform a deep copy. Copies the values of \e bt into \c *this. Pointers
|
|
Packit |
a4aae4 |
are dereferenced and their values are copied into a newly allocated
|
|
Packit |
a4aae4 |
instance.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Perform a deep copy.
|
|
Packit |
a4aae4 |
@param bt The source object. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::m_duplicate(const BaseType &bt)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "In BaseType::m_duplicate for " << bt.name() << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_name = bt.d_name;
|
|
Packit |
a4aae4 |
d_type = bt.d_type;
|
|
Packit |
a4aae4 |
d_dataset = bt.d_dataset;
|
|
Packit |
a4aae4 |
d_is_read = bt.d_is_read; // added, reza
|
|
Packit |
a4aae4 |
d_is_send = bt.d_is_send; // added, reza
|
|
Packit |
a4aae4 |
d_in_selection = bt.d_in_selection;
|
|
Packit |
a4aae4 |
d_is_synthesized = bt.d_is_synthesized; // 5/11/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_parent = bt.d_parent; // copy pointers 6/4/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_attr = bt.d_attr; // Deep copy.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (bt.d_attributes)
|
|
Packit |
a4aae4 |
d_attributes = new D4Attributes(*bt.d_attributes); // deep copy
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
d_attributes = 0; // init to null if not used.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_is_dap4 = bt.d_is_dap4;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Exiting BaseType::m_duplicate for " << bt.name() << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Public mfuncs
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The BaseType constructor needs a name and a type.
|
|
Packit |
a4aae4 |
The BaseType class exists to provide data to
|
|
Packit |
a4aae4 |
type classes that inherit from it. The constructors of those
|
|
Packit |
a4aae4 |
classes call the BaseType constructor; it is never called
|
|
Packit |
a4aae4 |
directly.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief The BaseType constructor.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n A string containing the name of the new variable.
|
|
Packit |
a4aae4 |
@param t The type of the variable.
|
|
Packit |
a4aae4 |
@param is_dap4 True if this is a DAP4 variable. Default is False
|
|
Packit |
a4aae4 |
@see Type */
|
|
Packit |
a4aae4 |
BaseType::BaseType(const string &n, const Type &t, bool is_dap4)
|
|
Packit |
a4aae4 |
: d_name(n), d_type(t), d_dataset(""), d_is_read(false), d_is_send(false),
|
|
Packit |
a4aae4 |
d_parent(0), d_attributes(0), d_is_dap4(is_dap4),
|
|
Packit |
a4aae4 |
d_in_selection(false), d_is_synthesized(false)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The BaseType constructor needs a name, a dataset, and a type.
|
|
Packit |
a4aae4 |
The BaseType class exists to provide data to
|
|
Packit |
a4aae4 |
type classes that inherit from it. The constructors of those
|
|
Packit |
a4aae4 |
classes call the BaseType constructor; it is never called
|
|
Packit |
a4aae4 |
directly.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief The BaseType constructor.
|
|
Packit |
a4aae4 |
@param n A string containing the name of the new variable.
|
|
Packit |
a4aae4 |
@param d A string containing the dataset name.
|
|
Packit |
a4aae4 |
@param t The type of the variable. Default is False
|
|
Packit |
a4aae4 |
@param is_dap4 True if this is a DAP4 variable.
|
|
Packit |
a4aae4 |
@see Type */
|
|
Packit |
a4aae4 |
BaseType::BaseType(const string &n, const string &d, const Type &t, bool is_dap4)
|
|
Packit |
a4aae4 |
: d_name(n), d_type(t), d_dataset(d), d_is_read(false), d_is_send(false),
|
|
Packit |
a4aae4 |
d_parent(0), d_attributes(0), d_is_dap4(is_dap4),
|
|
Packit |
a4aae4 |
d_in_selection(false), d_is_synthesized(false)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief The BaseType copy constructor. */
|
|
Packit |
a4aae4 |
BaseType::BaseType(const BaseType ©_from) : DapObj()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "In BaseTpe::copy_ctor for " << copy_from.name() << endl);
|
|
Packit |
a4aae4 |
m_duplicate(copy_from);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType::~BaseType()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG2(cerr << "Entering ~BaseType (" << this << ")" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_attributes)
|
|
Packit |
a4aae4 |
delete d_attributes;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG2(cerr << "Exiting ~BaseType" << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType &
|
|
Packit |
a4aae4 |
BaseType::operator=(const BaseType &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering BaseType::operator=" << endl);
|
|
Packit |
a4aae4 |
if (this == &rhs)
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
m_duplicate(rhs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Exiting BaseType::operator=" << endl);
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Write out the object's internal fields in a string. To be used for
|
|
Packit |
a4aae4 |
debugging when regular inspection w/ddd or gdb isn't enough.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return A string which shows the object's internal stuff. */
|
|
Packit |
a4aae4 |
string BaseType::toString()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
oss << "BaseType (" << this << "):" << endl
|
|
Packit |
a4aae4 |
<< " _name: " << name() << endl
|
|
Packit |
a4aae4 |
<< " _type: " << type_name() << endl
|
|
Packit |
a4aae4 |
<< " _dataset: " << d_dataset << endl
|
|
Packit |
a4aae4 |
<< " _read_p: " << d_is_read << endl
|
|
Packit |
a4aae4 |
<< " _send_p: " << d_is_send << endl
|
|
Packit |
a4aae4 |
<< " _synthesized_p: " << d_is_synthesized << endl
|
|
Packit |
a4aae4 |
<< " d_parent: " << d_parent << endl
|
|
Packit |
a4aae4 |
<< " d_attr: " << hex << &d_attr << dec << endl;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return oss.str();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief DAP2 to DAP4 transform
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* For the current BaseType, return a DAP4 'copy' of the variable.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note For most DAP2 types, in this implementation of DAP4 the corresponding
|
|
Packit |
a4aae4 |
* DAP4 type is the same. The different types are Sequences (which are D4Sequences
|
|
Packit |
a4aae4 |
* in the DAP4 implementation), Grids (which are coverages) and Arrays (which use
|
|
Packit |
a4aae4 |
* shared dimensions).
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param root The root group that should hold this new variable. Add Group-level
|
|
Packit |
a4aae4 |
* stuff here (e.g., D4Dimensions).
|
|
Packit |
a4aae4 |
* @param container Add the new variable to this container.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @return A pointer to the transformed variable
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::transform_to_dap4(D4Group */*root*/, Constructor *container)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *dest = ptr_duplicate();
|
|
Packit |
a4aae4 |
// If it's already a DAP4 object then we can just return it!
|
|
Packit |
a4aae4 |
if(!is_dap4()){
|
|
Packit |
a4aae4 |
dest->attributes()->transform_to_dap4(get_attr_table());
|
|
Packit |
a4aae4 |
dest->set_is_dap4(true);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
container->add_var_nocopy(dest);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief DAP4 to DAP2 transform
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* For the current BaseType, return a DAP2 'copy' of the variable.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note For most DAP4 types, in this implementation of DAP2 the corresponding
|
|
Packit |
a4aae4 |
* DAP4 type is the same.
|
|
Packit |
a4aae4 |
* These types have a different representations in DAP2 and DAP4:
|
|
Packit |
a4aae4 |
* Sequences (which are D4Sequences in the DAP4 implementation),
|
|
Packit |
a4aae4 |
* - Grids (which are semantically subsumed by coverages in DAP4)
|
|
Packit |
a4aae4 |
* - Arrays (which use shared dimensions in DAP4)
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Additionally DAP4 adds the following types:
|
|
Packit |
a4aae4 |
* - UInt8, Int8, and Char which map to Byte in DAP2.
|
|
Packit |
a4aae4 |
* - Int64, Unit64 which have no natural representation in DAP2.
|
|
Packit |
a4aae4 |
* - Opaque Possible Byte stuff[] plus metadata?
|
|
Packit |
a4aae4 |
* - Enum's can be represented as Int32.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* - Groups, with the exception of the root group "disappear" into the
|
|
Packit |
a4aae4 |
* names of their member variables. Specifically the Group name is add as a prefix
|
|
Packit |
a4aae4 |
* followed by a "/" separator to the names of all of the Group's member groups
|
|
Packit |
a4aae4 |
* variables.
|
|
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 most cases this vector
|
|
Packit |
a4aae4 |
* will contain a single pointer but DAP4 types 'disappear' such as Group will return all
|
|
Packit |
a4aae4 |
* of their member variables in the vector. DAP4 types with no representation in DAP2
|
|
Packit |
a4aae4 |
* (ex: UInt64) the will return a NULL pointer and so this must be tested!
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
std::vector<BaseType *> *
|
|
Packit |
a4aae4 |
BaseType::transform_to_dap2(AttrTable *)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *dest = this->ptr_duplicate();
|
|
Packit |
a4aae4 |
// convert the d4 attributes to a dap2 attribute table.
|
|
Packit |
a4aae4 |
AttrTable *attrs = this->attributes()->get_AttrTable(name());
|
|
Packit |
a4aae4 |
dest->set_attr_table(*attrs);
|
|
Packit |
a4aae4 |
dest->set_is_dap4(false);
|
|
Packit |
a4aae4 |
// attrs->print(cerr,"",true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<BaseType *> *result = new vector<BaseType *>();
|
|
Packit |
a4aae4 |
result->push_back(dest);
|
|
Packit |
a4aae4 |
return result;
|
|
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 displays information
|
|
Packit |
a4aae4 |
* about this base type.
|
|
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 |
BaseType::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "BaseType::dump - ("
|
|
Packit |
a4aae4 |
<< (void *)this << ")" << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "name: " << name() << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "type: " << type_name() << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "dataset: " << d_dataset << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "read_p: " << d_is_read << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "send_p: " << d_is_send << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "synthesized_p: " << d_is_synthesized << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "parent: " << (void *)d_parent << endl ;
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "attributes: " << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (d_attributes)
|
|
Packit |
a4aae4 |
d_attributes->dump(strm);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
d_attr.dump(strm) ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the name of the class instance.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
BaseType::name() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Return the FQN for this variable. This will include the D4 Group
|
|
Packit |
a4aae4 |
* component of the name.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @return The FQN in a string
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
BaseType::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
|
|
Packit |
a4aae4 |
return get_parent()->FQN() + "." + name();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Sets the name of the class instance. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_name(const string &n)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = n;
|
|
Packit |
a4aae4 |
d_name = www2id(name); // www2id writes into its param.
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the name of the dataset used to create this instance
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
A dataset from which the data is to be read. The meaning of this string
|
|
Packit |
a4aae4 |
will vary among different types of data sources. It \e may be the name
|
|
Packit |
a4aae4 |
of a data file or an identifier used to read data from a relational
|
|
Packit |
a4aae4 |
database.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
BaseType::dataset() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_dataset;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the type of the class instance. */
|
|
Packit |
a4aae4 |
Type
|
|
Packit |
a4aae4 |
BaseType::type() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_type;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Sets the type of the class instance. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_type(const Type &t)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_type = t;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the type of the class instance as a string. */
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
BaseType::type_name() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (is_dap4())
|
|
Packit |
a4aae4 |
return libdap::D4type_name(d_type);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return libdap::D2type_name(d_type);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns true if the instance is a numeric, string or URL
|
|
Packit |
a4aae4 |
type variable.
|
|
Packit |
a4aae4 |
@return True if the instance is a scalar numeric, String or URL variable,
|
|
Packit |
a4aae4 |
False otherwise. Arrays (even of simple types) return False.
|
|
Packit |
a4aae4 |
@see is_vector_type() */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::is_simple_type() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return libdap::is_simple_type(type());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns true if the instance is a vector (i.e., array) type
|
|
Packit |
a4aae4 |
variable.
|
|
Packit |
a4aae4 |
@return True if the instance is an Array, False otherwise. */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::is_vector_type() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return libdap::is_vector_type(type());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns true if the instance is a constructor (i.e., Structure,
|
|
Packit |
a4aae4 |
Sequence or Grid) type variable.
|
|
Packit |
a4aae4 |
@return True if the instance is a Structure, Sequence or Grid, False
|
|
Packit |
a4aae4 |
otherwise. */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::is_constructor_type() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return libdap::is_constructor_type(type());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Return a count of the total number of variables in this variable.
|
|
Packit |
a4aae4 |
This is used to count the number of variables held by a constructor
|
|
Packit |
a4aae4 |
variable - for simple type and vector variables it always
|
|
Packit |
a4aae4 |
returns 1.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
For compound data types, there are two ways to count members.
|
|
Packit |
a4aae4 |
You can count the members, or you can count the simple members
|
|
Packit |
a4aae4 |
and add that to the count of the compound members. For
|
|
Packit |
a4aae4 |
example, if a Structure contains an Int32 and another
|
|
Packit |
a4aae4 |
Structure that itself contains two Int32 members, the element
|
|
Packit |
a4aae4 |
count of the top-level structure could be two (one Int32 and
|
|
Packit |
a4aae4 |
one Structure) or three (one Int32 by itself and two Int32's
|
|
Packit |
a4aae4 |
in the subsidiary Structure). Use the leaves parameter
|
|
Packit |
a4aae4 |
to control which kind of counting you desire.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Count the members of constructor types.
|
|
Packit |
a4aae4 |
@return Returns 1 for simple
|
|
Packit |
a4aae4 |
types. For compound members, the count depends on the
|
|
Packit |
a4aae4 |
leaves argument.
|
|
Packit |
a4aae4 |
@param leaves This parameter is only relevant if the object
|
|
Packit |
a4aae4 |
contains other compound data types. If FALSE, the function
|
|
Packit |
a4aae4 |
counts only the data variables mentioned in the object's
|
|
Packit |
a4aae4 |
declaration. If TRUE, it counts the simple members, and adds
|
|
Packit |
a4aae4 |
that to the sum of the counts for the compound members.
|
|
Packit |
a4aae4 |
This parameter has no effect for simple type variables. */
|
|
Packit |
a4aae4 |
int
|
|
Packit |
a4aae4 |
BaseType::element_count(bool)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return 1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns true if the variable is a synthesized variable. A synthesized
|
|
Packit |
a4aae4 |
variable is one that is added to the dataset by the server (usually
|
|
Packit |
a4aae4 |
with a `projection function'. */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::synthesized_p()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_is_synthesized;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set the synthesized flag. Before setting this flag be sure to set the
|
|
Packit |
a4aae4 |
<tt>read_p()</tt> state. Once this flag is set you cannot
|
|
Packit |
a4aae4 |
alter the state of the <tt>read_p</tt> flag!
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see synthesized_p() */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_synthesized_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_is_synthesized = state;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Return the state of d_is_read (true if the value of the variable has been
|
|
Packit |
a4aae4 |
// read (and is in memory) false otherwise).
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns true if the value(s) for this variable have been read from the
|
|
Packit |
a4aae4 |
data source, otherwise returns false. This method is used to determine
|
|
Packit |
a4aae4 |
when values need to be read using the read() method. When read_p()
|
|
Packit |
a4aae4 |
returns true, this library assumes that buf2val() (and other methods
|
|
Packit |
a4aae4 |
such as get_vec()) can be used to access the value(s) of a variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Has this variable been read?
|
|
Packit |
a4aae4 |
@return True if the variable's value(s) have been read, false otherwise. */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::read_p()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_is_read;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Sets the value of the <tt>read_p</tt> property. This indicates that the
|
|
Packit |
a4aae4 |
value(s) of this variable has/have been read. An implementation of the
|
|
Packit |
a4aae4 |
read() method should use this to set the \c read_p property to true.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note If the is_synthesized property is true, this method will _not_
|
|
Packit |
a4aae4 |
alter the is_read property. If you need that behavior, specialize the
|
|
Packit |
a4aae4 |
method in your subclasses if the various types.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note For most of the types the default implementation of this method is
|
|
Packit |
a4aae4 |
fine. However, if you're building a server which must handle data
|
|
Packit |
a4aae4 |
represented using nested sequences, then you may need to provide a
|
|
Packit |
a4aae4 |
specialization of Sequence::set_read_p(). By default Sequence::set_read_p()
|
|
Packit |
a4aae4 |
recursively sets the \e read_p property for all child variables to
|
|
Packit |
a4aae4 |
\e state. For servers where one Sequence reads an outer set of values
|
|
Packit |
a4aae4 |
and another reads an inner set, this is cumbersome. In such a case, it is
|
|
Packit |
a4aae4 |
easier to specialize Sequence::set_read_p() so that it does \e not
|
|
Packit |
a4aae4 |
recursively set the \e read_p property for the inner Sequence. Be sure
|
|
Packit |
a4aae4 |
to see the documentation for the read() method!
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo Look at making synthesized variables easier to implement and at
|
|
Packit |
a4aae4 |
making them more integrated into the overall CE evaluation process.
|
|
Packit |
a4aae4 |
Maybe the code that computes the synthesized var's value should be in the
|
|
Packit |
a4aae4 |
that variable's read() method? This might provide a way to get rid of the
|
|
Packit |
a4aae4 |
awkward 'projection functions' by replacing them with real children of
|
|
Packit |
a4aae4 |
BaseType. It would also provide a way to clean up the way the
|
|
Packit |
a4aae4 |
\e synthesized_p prop intrudes on the \e read_p prop.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see BaseType::read()
|
|
Packit |
a4aae4 |
@brief Sets the value of the \e read_p property.
|
|
Packit |
a4aae4 |
@param state Set the \e read_p property to this state. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_read_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// The this comment is/was wrong!
|
|
Packit |
a4aae4 |
// The is_synthesized property was not being used and the more I thought
|
|
Packit |
a4aae4 |
// about how this was coded, the more this code below seemed like a bad idea.
|
|
Packit |
a4aae4 |
// Once the property was set, the read_p property could not be changed.
|
|
Packit |
a4aae4 |
// That seems a little silly. Also, I think I need to use this is_synthesized
|
|
Packit |
a4aae4 |
// property for some of the server function code I'm working on for Raytheon,
|
|
Packit |
a4aae4 |
// and I'd like to be able to control the read_p property! jhrg 3/9/15
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// What's true: The is_synthesized property is used by
|
|
Packit |
a4aae4 |
// 'projection functions' in the freeform handler. It might be better
|
|
Packit |
a4aae4 |
// to modify the FFtypes to support this behavior, but for now I'm returning
|
|
Packit |
a4aae4 |
// the library to its old behavior. That this change (setting is_read
|
|
Packit |
a4aae4 |
// of the value of is_syn...) broke the FF handler was not detected
|
|
Packit |
a4aae4 |
// because the FF tests were not being run due to an error in the FF
|
|
Packit |
a4aae4 |
// bes-testsuite Makefile.am). jhrg 9/9/15
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 1
|
|
Packit |
a4aae4 |
if (!d_is_synthesized) {
|
|
Packit |
a4aae4 |
d_is_read = state;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
d_is_read = state;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns the state of the \c send_p property. If true, this variable
|
|
Packit |
a4aae4 |
should be sent to the client, if false, it should not. If no constraint
|
|
Packit |
a4aae4 |
expression (CE) has been evaluated, this property is true for all
|
|
Packit |
a4aae4 |
variables in a data source (i.e., for all the variables listed in a DDS).
|
|
Packit |
a4aae4 |
If a CE has been evaluated, this property is true only for those
|
|
Packit |
a4aae4 |
variables listed in the projection part of the CE.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Should this variable be sent?
|
|
Packit |
a4aae4 |
@return True if the variable should be sent to the client, false
|
|
Packit |
a4aae4 |
otherwise. */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::send_p()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_is_send;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Sets the value of the <tt>send_p</tt> flag. This
|
|
Packit |
a4aae4 |
function is meant to be called from within the constraint evaluator of
|
|
Packit |
a4aae4 |
other code which determines that this variable should be returned to the
|
|
Packit |
a4aae4 |
client. Data are ready to be sent when both the <tt>d_is_send</tt>
|
|
Packit |
a4aae4 |
and <tt>d_is_read</tt> flags are set to TRUE.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param state The logical state to set the <tt>send_p</tt> flag.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_send_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG2(cerr << "Calling BaseType::set_send_p() for: " << this->name()
|
|
Packit |
a4aae4 |
<< endl);
|
|
Packit |
a4aae4 |
d_is_send = state;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get this variable's AttrTable. It's generally a bad idea to return a
|
|
Packit |
a4aae4 |
reference to a contained object, but in this case it seems that building
|
|
Packit |
a4aae4 |
an interface inside BaseType is overkill.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Use the AttrTable methods to manipulate the table. */
|
|
Packit |
a4aae4 |
AttrTable &
|
|
Packit |
a4aae4 |
BaseType::get_attr_table()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_attr;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set this variable's attribute table.
|
|
Packit |
a4aae4 |
@param at Source of the attributes. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_attr_table(const AttrTable &at)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_attr = at;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** DAP4 Attribute methods
|
|
Packit |
a4aae4 |
* @{
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
D4Attributes *
|
|
Packit |
a4aae4 |
BaseType::attributes()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!d_attributes) d_attributes = new D4Attributes();
|
|
Packit |
a4aae4 |
return d_attributes;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_attributes(D4Attributes *attrs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_attributes = new D4Attributes(*attrs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_attributes_nocopy(D4Attributes *attrs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_attributes = attrs;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
///@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Transfer attributes from a DAS object into this variable. Because of the
|
|
Packit |
a4aae4 |
* rough history of the DAS object and the way that various server code built
|
|
Packit |
a4aae4 |
* the DAS, this is necessarily a heuristic process. The intent is that this
|
|
Packit |
a4aae4 |
* method will be overridden by handlers that need to look for certain patterns
|
|
Packit |
a4aae4 |
* in the DAS (e.g., hdf4's odd variable_dim_n; where n = 0, 1, 2, ...)
|
|
Packit |
a4aae4 |
* attribute containers.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* There should be a one-to-one
|
|
Packit |
a4aae4 |
* mapping between variables and attribute containers. However, in some cases
|
|
Packit |
a4aae4 |
* one variable has attributes spread across several top level containers and
|
|
Packit |
a4aae4 |
* in some cases one container is used by several variables
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note This method is technically \e unnecessary because a server (or
|
|
Packit |
a4aae4 |
* client) can easily add attributes directly using the DDS::get_attr_table
|
|
Packit |
a4aae4 |
* or BaseType::get_attr_table methods and then poke values in using any
|
|
Packit |
a4aae4 |
* of the methods AttrTable provides. This method exists to ease the
|
|
Packit |
a4aae4 |
* transition to DDS objects which contain attribute information for the
|
|
Packit |
a4aae4 |
* existing servers (Since they all make DAS objects separately from the
|
|
Packit |
a4aae4 |
* DDS). They could be modified to use the same AttrTable methods but
|
|
Packit |
a4aae4 |
* operate on the AttrTable instances in a DDS/BaseType instead of those in
|
|
Packit |
a4aae4 |
* a DAS.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param at_container Transfer attributes from this container.
|
|
Packit |
a4aae4 |
* @return void
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void BaseType::transfer_attributes(AttrTable *at_container) {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - BEGIN name:'" << name() << "'" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable *at = at_container->get_attr_table(name());
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - at: "<< (void *) at << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (at) {
|
|
Packit |
a4aae4 |
at->set_is_global_attribute(false);
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Processing AttrTable: " << at->get_name() << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter at_p = at->attr_begin();
|
|
Packit |
a4aae4 |
while (at_p != at->attr_end()) {
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Attribute '" << at->get_name(at_p) << "' is type: " << at->get_type(at_p) << endl);
|
|
Packit |
a4aae4 |
if (at->get_attr_type(at_p) == Attr_container){
|
|
Packit |
a4aae4 |
// An attribute container may actually represent a child member variable. When
|
|
Packit |
a4aae4 |
// that's the case we don't want to add the container to the parent type, but
|
|
Packit |
a4aae4 |
// rather let any child of BaseType deal with those containers in the child's
|
|
Packit |
a4aae4 |
// overridden transfer_attributes() method.
|
|
Packit |
a4aae4 |
// We capitalize on the magic of the BaseType API and utilize the var() method
|
|
Packit |
a4aae4 |
// to check for a child variable of the same name and, if one exists, we'll skip
|
|
Packit |
a4aae4 |
// this AttrTable and let a child constructor class like Grid or Constructor
|
|
Packit |
a4aae4 |
// deal with it.
|
|
Packit |
a4aae4 |
BaseType *bt = var(at->get_name(at_p),true);
|
|
Packit |
a4aae4 |
if(bt==0){
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Adding container '" << at->get_name(at_p) << endl);
|
|
Packit |
a4aae4 |
get_attr_table().append_container(new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Found child var: '"<< bt->type_name()<< " " << bt->name() << " (address:" << (void *) bt << ")" << endl);
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Skipping container '" << at->get_name(at_p) << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Adding Attribute '" << at->get_name(at_p) << endl);
|
|
Packit |
a4aae4 |
get_attr_table().append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
at_p++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ << "() - Unable to locate AttrTable '" << name() << "' SKIPPING" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Does this variable appear in either the selection part or as a function
|
|
Packit |
a4aae4 |
argument in the current constrain expression. If this property is set
|
|
Packit |
a4aae4 |
(true) then implementations of the read() method should read this
|
|
Packit |
a4aae4 |
variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This method does not check, nor does it know about the semantics of,
|
|
Packit |
a4aae4 |
string arguments passed to functions. Those functions might include
|
|
Packit |
a4aae4 |
variable names in strings; they are responsible for reading those variables.
|
|
Packit |
a4aae4 |
See the grid (func_grid_select()) for an example.
|
|
Packit |
a4aae4 |
@see BaseType::read()
|
|
Packit |
a4aae4 |
@brief Is this variable part of the current selection? */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::is_in_selection()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_in_selection;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Set the \e in_selection property to \e state. This property indicates
|
|
Packit |
a4aae4 |
that the variable is used as a parameter to a constraint expression
|
|
Packit |
a4aae4 |
function or that it appears as an argument in a selection sub-expression.
|
|
Packit |
a4aae4 |
If set (true), implementations of the BaseType::read() method should read
|
|
Packit |
a4aae4 |
this variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param state Set the \e in_selection property to this state.
|
|
Packit |
a4aae4 |
@see BaseType::read()
|
|
Packit |
a4aae4 |
@see BaseType::is_in_selection() for more information. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_in_selection(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_in_selection = state;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Protected method.
|
|
Packit |
a4aae4 |
/** Set the <tt>parent</tt> property for this variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note Added ability to set parent to null. 10/19/12 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param parent Pointer to the Constructor of Vector parent variable or null
|
|
Packit |
a4aae4 |
if the variable has no parent (if it is at the top-level of a DAP2/3 DDS).
|
|
Packit |
a4aae4 |
@exception InternalErr thrown if called with anything other than a
|
|
Packit |
a4aae4 |
Constructor, Vector or Null. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::set_parent(BaseType *parent)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!dynamic_cast<Constructor *>(parent)
|
|
Packit |
a4aae4 |
&& !dynamic_cast<Vector *>(parent)
|
|
Packit |
a4aae4 |
&& parent != 0)
|
|
Packit |
a4aae4 |
throw InternalErr("Call to set_parent with incorrect variable type.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_parent = parent;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Public method.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Return a pointer to the Constructor or Vector which holds (contains)
|
|
Packit |
a4aae4 |
this variable. If this variable is at the top level, this method
|
|
Packit |
a4aae4 |
returns null.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return A BaseType pointer to the variable's parent. */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
BaseType::get_parent() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_parent;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Documented in the header file.
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
BaseType::var(const string &/*name*/, bool /*exact_match*/, btp_stack */*s*/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return static_cast<BaseType *>(0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This version of var(...) searches for name and returns a
|
|
Packit |
a4aae4 |
pointer to the BaseType object if found. It uses the same search
|
|
Packit |
a4aae4 |
algorithm as BaseType::var(const string &, bool, btp_stack *) when
|
|
Packit |
a4aae4 |
exact_match is false. In addition to returning a pointer to
|
|
Packit |
a4aae4 |
the variable, it pushes onto s a BaseType pointer to each
|
|
Packit |
a4aae4 |
constructor type that ultimately contains name.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note The BaseType implementation always returns null. There are no default
|
|
Packit |
a4aae4 |
values for the parameters. If var() is called w/o any params, the three
|
|
Packit |
a4aae4 |
parameter version will be used.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@deprecated This method is deprecated because it tries first to use
|
|
Packit |
a4aae4 |
exact_match and, if that fails, then tries leaf_match. It's better to use
|
|
Packit |
a4aae4 |
the alternate form of var(...) and specify exactly what you'd like to do.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return A pointer to the named variable. */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
BaseType::var(const string &, btp_stack &)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return static_cast<BaseType *>(0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Adds a variable to an instance of a constructor class, such as Array,
|
|
Packit |
a4aae4 |
Structure et cetera. This function is only used by those
|
|
Packit |
a4aae4 |
classes. For constructors with more than one variable, the variables
|
|
Packit |
a4aae4 |
appear in the same order in which they were added (i.e., the order in
|
|
Packit |
a4aae4 |
which add_var() was called). Since this method is only for use by Vectors
|
|
Packit |
a4aae4 |
and Constructors, the BaseType implementation throws InternalErr.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note For the implementation of this method in Structure, Sequence, et c.,
|
|
Packit |
a4aae4 |
first copy \e bt and then insert the copy. If \e bt is itself a constructor
|
|
Packit |
a4aae4 |
type you must either use the var() method to get a pointer to the actual
|
|
Packit |
a4aae4 |
instance added to \c *this or you must first add all of bt's
|
|
Packit |
a4aae4 |
children to it before adding it to \c *this. The implementations should use
|
|
Packit |
a4aae4 |
m_duplicate() to perform a deep copy of \e bt.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Add a variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo We should get rid of the Part parameter and adopt the convention
|
|
Packit |
a4aae4 |
that the first variable is the Array and all subsequent ones are Maps
|
|
Packit |
a4aae4 |
(when dealing with a Grid, the only time Part matters). This would enable
|
|
Packit |
a4aae4 |
several methods to migrate from Structure, Sequence and Grid to
|
|
Packit |
a4aae4 |
Constructor.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param bt The variable to be added to this instance. The caller of this
|
|
Packit |
a4aae4 |
method must free memory it allocates for <tt>v</tt>. This method
|
|
Packit |
a4aae4 |
will make a deep copy of the object pointed to by <tt>v</tt>.
|
|
Packit |
a4aae4 |
@param part The part of the constructor data to be modified. Only
|
|
Packit |
a4aae4 |
meaningful for Grid variables.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see Part */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::add_var(BaseType *, Part)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "BaseType::add_var unimplemented");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::add_var_nocopy(BaseType *, Part)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "BaseType::add_var_nocopy unimplemented");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This method should be implemented for each of the data type classes (Byte,
|
|
Packit |
a4aae4 |
..., Grid) when using the DAP class library to build a server. This
|
|
Packit |
a4aae4 |
method is only for DAP servers. The library provides a default
|
|
Packit |
a4aae4 |
definition here which throws an InternalErr exception \e unless the read_p
|
|
Packit |
a4aae4 |
property has been set. In that case it returns false, indicating that all
|
|
Packit |
a4aae4 |
the data have been read. The latter case can happen when building a
|
|
Packit |
a4aae4 |
constant value that needs to be passed to a function. The variable/constant
|
|
Packit |
a4aae4 |
is loaded with a value when it is created.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
When implementing a new DAP server, the Byte, ..., Grid data type classes
|
|
Packit |
a4aae4 |
are usually specialized. In each of those specializations read() should
|
|
Packit |
a4aae4 |
be defined to read values from the data source and store them in the
|
|
Packit |
a4aae4 |
object's local buffer. The read() method is called by other methods in
|
|
Packit |
a4aae4 |
this library. When writing read(), follow these rules:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
read() should throw Error if it encounters an error. The message
|
|
Packit |
a4aae4 |
should be verbose enough to be understood by someone running a
|
|
Packit |
a4aae4 |
client on a different machine.
|
|
Packit |
a4aae4 |
The value(s) should be read if and only if either send_p() or
|
|
Packit |
a4aae4 |
is_in_selection() return true. If neither of these return true, the
|
|
Packit |
a4aae4 |
value(s) should not be read. This is important when writing read()
|
|
Packit |
a4aae4 |
for a Constructor type such as Grid where a client may ask for only
|
|
Packit |
a4aae4 |
the map vectors (and thus reading the much larger Array part is not
|
|
Packit |
a4aae4 |
needed).
|
|
Packit |
a4aae4 |
For each specialization of read(), the method should first test
|
|
Packit |
a4aae4 |
the value of the \c read_p property (using the read_p() method)
|
|
Packit |
a4aae4 |
and read values only if the value of read_p() is false. Once the
|
|
Packit |
a4aae4 |
read() method reads data and stores it in the instance, it must
|
|
Packit |
a4aae4 |
set the value of the \c read_p property to true using set_read_p().
|
|
Packit |
a4aae4 |
If your read() methods fail to do this data may not serialize
|
|
Packit |
a4aae4 |
correctly.
|
|
Packit |
a4aae4 |
The Array::read() and Grid::read() methods should take into account
|
|
Packit |
a4aae4 |
any restrictions on Array sizes.
|
|
Packit |
a4aae4 |
If you are writing Sequence::read(), be sure to check the
|
|
Packit |
a4aae4 |
documentation for Sequence::read_row() and Sequence::serialize()
|
|
Packit |
a4aae4 |
so you understand how Sequence::read() is being called.
|
|
Packit |
a4aae4 |
For Sequence::read(), your specialization must correctly manage the
|
|
Packit |
a4aae4 |
\c unsent_data property and row count in addition to the \c read_p
|
|
Packit |
a4aae4 |
property (handle the \c read_p property as describe above). For a
|
|
Packit |
a4aae4 |
Sequence to serialize correctly, once all data from the Sequence
|
|
Packit |
a4aae4 |
has been read, \c unsent_data property must be set to false (use
|
|
Packit |
a4aae4 |
Sequence::set_unsent_data()). Also, at that time the row number
|
|
Packit |
a4aae4 |
counter must be reset (use Sequence::reset_row_counter()). Typically
|
|
Packit |
a4aae4 |
the correct time to set \c unsent_data to false and reset the row
|
|
Packit |
a4aae4 |
counter is the time when Sequence::read() return false indicating
|
|
Packit |
a4aae4 |
that all the data for the Sequence have been read. Failure to
|
|
Packit |
a4aae4 |
handle these tasks will break serialization of nested Sequences. Note
|
|
Packit |
a4aae4 |
that when Sequence::read() returns with a result of true (indicating
|
|
Packit |
a4aae4 |
there is more data to send, the value of the \c unsent_data property
|
|
Packit |
a4aae4 |
should be true.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Also, if you server must handle nested sequences, be sure to read
|
|
Packit |
a4aae4 |
about subclassing set_read_p().
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Read data into a local buffer.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo Modify the D4 serialize code so that it supports the true/false
|
|
Packit |
a4aae4 |
behavior of read() for arrays.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo Modify all of the stock handlers so they conform to this!
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return False means more data remains to be read, True indicates that no
|
|
Packit |
a4aae4 |
more data need to be read. For Sequence and D4Sequence, this method will
|
|
Packit |
a4aae4 |
generally read one instance of the Sequence; for other types it will generally
|
|
Packit |
a4aae4 |
read the entire variable modulo any limitations due to a constraint. However,
|
|
Packit |
a4aae4 |
the library should be written so that read can return less than all of the data
|
|
Packit |
a4aae4 |
for a variable - serialize() would then call the function until it returns
|
|
Packit |
a4aae4 |
True.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see BaseType */
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::read()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_is_read)
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
throw InternalErr("Unimplemented BaseType::read() method called for the variable named: " + name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::intern_data(ConstraintEvaluator &, DDS &/*dds*/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
dds.timeout_on();
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
DBG2(cerr << "BaseType::intern_data: " << name() << endl);
|
|
Packit |
a4aae4 |
if (!read_p())
|
|
Packit |
a4aae4 |
read(); // read() throws Error and InternalErr
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
dds.timeout_off();
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Read data into this variable
|
|
Packit |
a4aae4 |
* @param eval Evaluator for a constraint expression
|
|
Packit |
a4aae4 |
* @param dmr DMR for the whole dataset
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::intern_data(/*Crc32 &checksum, DMR &, ConstraintEvaluator &*/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!read_p())
|
|
Packit |
a4aae4 |
read(); // read() throws Error and InternalErr
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
compute_checksum(checksum);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::serialize(ConstraintEvaluator &, DDS &, Marshaller &, bool)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The DAP2 serialize() method has not been implemented for " + type_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::deserialize(UnMarshaller &, DDS *, bool)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The DAP2 deserialize() method has not been implemented for " + type_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::serialize(D4StreamMarshaller &, DMR &, /*ConstraintEvaluator &,*/ bool)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The DAP4 serialize() method has not been implemented for " + type_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::deserialize(D4StreamUnMarshaller &, DMR &)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The DAP4 deserialize() method has not been implemented for " + type_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Write the variable's declaration in a C-style syntax. This
|
|
Packit |
a4aae4 |
function is used to create textual representation of the Data
|
|
Packit |
a4aae4 |
Descriptor Structure (DDS). See The DODS User Manual for
|
|
Packit |
a4aae4 |
information about this structure.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
A simple array declaration might look like this:
|
|
Packit |
a4aae4 |
\verbatim
|
|
Packit |
a4aae4 |
Float64 lat[lat = 180];
|
|
Packit |
a4aae4 |
\endverbatim
|
|
Packit |
a4aae4 |
While a more complex declaration (for a Grid, in this case),
|
|
Packit |
a4aae4 |
would look like this:
|
|
Packit |
a4aae4 |
\verbatim
|
|
Packit |
a4aae4 |
Grid {
|
|
Packit |
a4aae4 |
ARRAY:
|
|
Packit |
a4aae4 |
Int32 sst[time = 404][lat = 180][lon = 360];
|
|
Packit |
a4aae4 |
MAPS:
|
|
Packit |
a4aae4 |
Float64 time[time = 404];
|
|
Packit |
a4aae4 |
Float64 lat[lat = 180];
|
|
Packit |
a4aae4 |
Float64 lon[lon = 360];
|
|
Packit |
a4aae4 |
} sst;
|
|
Packit |
a4aae4 |
\endverbatim
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Print an ASCII representation of the variable structure.
|
|
Packit |
a4aae4 |
@param out The output stream on which to print the
|
|
Packit |
a4aae4 |
declaration.
|
|
Packit |
a4aae4 |
@param space Each line of the declaration will begin with the
|
|
Packit |
a4aae4 |
characters in this string. Usually used for leading spaces.
|
|
Packit |
a4aae4 |
@param print_semi A boolean value indicating whether to print a
|
|
Packit |
a4aae4 |
semicolon at the end of the declaration.
|
|
Packit |
a4aae4 |
@param constraint_info A boolean value indicating whether
|
|
Packit |
a4aae4 |
constraint information is to be printed with the declaration.
|
|
Packit |
a4aae4 |
If the value of this parameter is TRUE, <tt>print_decl()</tt> prints
|
|
Packit |
a4aae4 |
the value of the variable's <tt>send_p()</tt> flag after the
|
|
Packit |
a4aae4 |
declaration.
|
|
Packit |
a4aae4 |
@param constrained If this boolean value is TRUE, the variable's
|
|
Packit |
a4aae4 |
declaration is only printed if is the <tt>send_p()</tt> flag is TRUE.
|
|
Packit |
a4aae4 |
If a constraint expression is in place, and this variable is not
|
|
Packit |
a4aae4 |
requested, the <tt>send_p()</tt> flag is FALSE.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see DDS
|
|
Packit |
a4aae4 |
@see DDS::CE
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::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 |
/** Write the variable's declaration in a C-style syntax. This
|
|
Packit |
a4aae4 |
function is used to create textual representation of the Data
|
|
Packit |
a4aae4 |
Descriptor Structure (DDS). See The DODS User Manual for
|
|
Packit |
a4aae4 |
information about this structure.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
A simple array declaration might look like this:
|
|
Packit |
a4aae4 |
\verbatim
|
|
Packit |
a4aae4 |
Float64 lat[lat = 180];
|
|
Packit |
a4aae4 |
\endverbatim
|
|
Packit |
a4aae4 |
While a more complex declaration (for a Grid, in this case),
|
|
Packit |
a4aae4 |
would look like this:
|
|
Packit |
a4aae4 |
\verbatim
|
|
Packit |
a4aae4 |
Grid {
|
|
Packit |
a4aae4 |
ARRAY:
|
|
Packit |
a4aae4 |
Int32 sst[time = 404][lat = 180][lon = 360];
|
|
Packit |
a4aae4 |
MAPS:
|
|
Packit |
a4aae4 |
Float64 time[time = 404];
|
|
Packit |
a4aae4 |
Float64 lat[lat = 180];
|
|
Packit |
a4aae4 |
Float64 lon[lon = 360];
|
|
Packit |
a4aae4 |
} sst;
|
|
Packit |
a4aae4 |
\endverbatim
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Print an ASCII representation of the variable structure.
|
|
Packit |
a4aae4 |
@param out The output stream on which to print the
|
|
Packit |
a4aae4 |
declaration.
|
|
Packit |
a4aae4 |
@param space Each line of the declaration will begin with the
|
|
Packit |
a4aae4 |
characters in this string. Usually used for leading spaces.
|
|
Packit |
a4aae4 |
@param print_semi A boolean value indicating whether to print a
|
|
Packit |
a4aae4 |
semicolon at the end of the declaration.
|
|
Packit |
a4aae4 |
@param constraint_info A boolean value indicating whether
|
|
Packit |
a4aae4 |
constraint information is to be printed with the declaration.
|
|
Packit |
a4aae4 |
If the value of this parameter is TRUE, <tt>print_decl()</tt> prints
|
|
Packit |
a4aae4 |
the value of the variable's <tt>send_p()</tt> flag after the
|
|
Packit |
a4aae4 |
declaration.
|
|
Packit |
a4aae4 |
@param constrained If this boolean value is TRUE, the variable's
|
|
Packit |
a4aae4 |
declaration is only printed if is the <tt>send_p()</tt> flag is TRUE.
|
|
Packit |
a4aae4 |
If a constraint expression is in place, and this variable is not
|
|
Packit |
a4aae4 |
requested, the <tt>send_p()</tt> flag is FALSE.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see DDS
|
|
Packit |
a4aae4 |
@see DDS::CE
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::print_decl(ostream &out, string space, bool print_semi,
|
|
Packit |
a4aae4 |
bool constraint_info, bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// if printing the constrained declaration, exit if this variable was not
|
|
Packit |
a4aae4 |
// selected.
|
|
Packit |
a4aae4 |
if (constrained && !send_p())
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << space << type_name() << " " << id2www(name()) ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (constraint_info) {
|
|
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 |
/** Prints the value of the variable, with its declaration. This
|
|
Packit |
a4aae4 |
function is primarily intended for debugging DODS
|
|
Packit |
a4aae4 |
applications. However, it can be overloaded and used to do
|
|
Packit |
a4aae4 |
some useful things. Take a look at the asciival and writeval
|
|
Packit |
a4aae4 |
clients, both of which overload this to output the values of
|
|
Packit |
a4aae4 |
variables in different ways.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Prints the value of the variable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param out The output stream on which to print the value.
|
|
Packit |
a4aae4 |
@param space This value is passed to the print_decl()
|
|
Packit |
a4aae4 |
function, and controls the leading spaces of the output.
|
|
Packit |
a4aae4 |
@param print_decl_p A boolean value controlling whether the
|
|
Packit |
a4aae4 |
variable declaration is printed as well as the value. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::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 |
/** Write the XML representation of this variable. This method is used to
|
|
Packit |
a4aae4 |
build the DDX XML response.
|
|
Packit |
a4aae4 |
@param out Destination.
|
|
Packit |
a4aae4 |
@param space Use this to indent child declarations. Default is "".
|
|
Packit |
a4aae4 |
@param constrained If true, only print this if it's part part of the
|
|
Packit |
a4aae4 |
current projection. Default is False.
|
|
Packit |
a4aae4 |
@deprecated */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::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 |
/** Write the XML representation of this variable. This method is used to
|
|
Packit |
a4aae4 |
build the DDX XML response.
|
|
Packit |
a4aae4 |
@param out Destination output stream
|
|
Packit |
a4aae4 |
@param space Use this to indent child declarations. Default is "".
|
|
Packit |
a4aae4 |
@param constrained If true, only print this if it's part part of the
|
|
Packit |
a4aae4 |
current projection. Default is False.
|
|
Packit |
a4aae4 |
@deprecated */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::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 |
/** Write the XML representation of this variable. This method is used to
|
|
Packit |
a4aae4 |
build the DDX XML response.
|
|
Packit |
a4aae4 |
@param out Destination output stream
|
|
Packit |
a4aae4 |
@param space Use this to indent child declarations. Default is "".
|
|
Packit |
a4aae4 |
@param constrained If true, only print this if it's part part of the
|
|
Packit |
a4aae4 |
current projection. Default is False. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::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 |
if (is_dap4())
|
|
Packit |
a4aae4 |
attributes()->print_dap4(xml);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!is_dap4() && get_attr_table().get_size() > 0)
|
|
Packit |
a4aae4 |
get_attr_table().print_xml_writer(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 |
/** Write the DAP4 XML representation for this variable. This method is used
|
|
Packit |
a4aae4 |
* to build the DAP4 DMR response object.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param xml An XMLWriter that will do the serialization
|
|
Packit |
a4aae4 |
* @param constrained True if the response should show the variables subject
|
|
Packit |
a4aae4 |
* to the current constraint expression.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
BaseType::print_dap4(XMLWriter &xml, bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
print_xml_writer(xml, constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Compares the object's current state with the semantics of a particular
|
|
Packit |
a4aae4 |
// type. This will typically be defined in ctor classes (which have
|
|
Packit |
a4aae4 |
// complicated semantics). For BaseType, an object is semantically correct if
|
|
Packit |
a4aae4 |
// it has both a non-null name and type.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// NB: This is not the same as an invariant -- during the parse objects exist
|
|
Packit |
a4aae4 |
// but have no name. Also, the bool ALL defaults to false for BaseType. It is
|
|
Packit |
a4aae4 |
// used by children of CtorType.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Returns: true if the object is semantically correct, false otherwise.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This function checks the class instance for internal
|
|
Packit |
a4aae4 |
consistency. This is important to check for complex constructor
|
|
Packit |
a4aae4 |
classes. For BaseType, an object is semantically correct if it
|
|
Packit |
a4aae4 |
has both a non-null name and type.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
For example, an Int32 instance would return FALSE if it had no
|
|
Packit |
a4aae4 |
name or no type defined. A Grid instance might return FALSE for
|
|
Packit |
a4aae4 |
more complex reasons, such as having Map arrays of the wrong
|
|
Packit |
a4aae4 |
size or shape.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This function is used by the DDS class, and will rarely, if
|
|
Packit |
a4aae4 |
ever, be explicitly called by a DODS application program. A
|
|
Packit |
a4aae4 |
variable must pass this test before it is sent, but there may be
|
|
Packit |
a4aae4 |
many other stages in a retrieve operation where it would fail.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Compare an object's current state with the semantics of its
|
|
Packit |
a4aae4 |
type.
|
|
Packit |
a4aae4 |
@return Returns FALSE when the current state violates some
|
|
Packit |
a4aae4 |
aspect of the type semantics, TRUE otherwise.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param msg A returned string, containing a message indicating
|
|
Packit |
a4aae4 |
the source of any problem.
|
|
Packit |
a4aae4 |
@param all For complex constructor types (Grid,
|
|
Packit |
a4aae4 |
Sequence, Structure), this flag indicates whether to check the
|
|
Packit |
a4aae4 |
semantics of the member variables, too.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@see DDS::check_semantics
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::check_semantics(string &msg, bool)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
bool sem = (d_type != dods_null_c && name().length());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!sem)
|
|
Packit |
a4aae4 |
msg = "Every variable must have both a name and a type\n";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return sem;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This method contains the relational operators used by the constraint
|
|
Packit |
a4aae4 |
expression evaluator in the DDS class. Each class that wants to be able
|
|
Packit |
a4aae4 |
to evaluate relational expressions must overload this function. The
|
|
Packit |
a4aae4 |
implementation in BaseType throws an InternalErr exception. The DAP
|
|
Packit |
a4aae4 |
library classes Byte, ..., Url provide specializations of this method. It
|
|
Packit |
a4aae4 |
is not meaningful for classes such as Array because relational
|
|
Packit |
a4aae4 |
expressions using Array are not supported.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
The op argument refers to a table generated by bison from
|
|
Packit |
a4aae4 |
the constraint expression parser. Use statements like the
|
|
Packit |
a4aae4 |
following to correctly interpret its value:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
\verbatim
|
|
Packit |
a4aae4 |
switch (op) {
|
|
Packit |
a4aae4 |
case EQUAL: return i1 == i2;
|
|
Packit |
a4aae4 |
case NOT_EQUAL: return i1 != i2;
|
|
Packit |
a4aae4 |
case GREATER: return i1 > i2;
|
|
Packit |
a4aae4 |
case GREATER_EQL: return i1 >= i2;
|
|
Packit |
a4aae4 |
case LESS: return i1 < i2;
|
|
Packit |
a4aae4 |
case LESS_EQL: return i1 <= i2;
|
|
Packit |
a4aae4 |
case REGEXP: throw Error("Regular expressions are not supported for integer values");
|
|
Packit |
a4aae4 |
default: throw Error("Unknown operator");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
\endverbatim
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This function is used by the constraint expression evaluator.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Evaluate relational operators.
|
|
Packit |
a4aae4 |
@param b Compare the value of this instance with \e b.
|
|
Packit |
a4aae4 |
@param op An integer index indicating which relational operator
|
|
Packit |
a4aae4 |
is implied. Choose one from the following: <tt>EQUAL</tt>,
|
|
Packit |
a4aae4 |
<tt>NOT_EQUAL</tt>, <tt>GREATER</tt>, <tt>GREATER_EQL</tt>,
|
|
Packit |
a4aae4 |
<tt>LESS</tt>, <tt>LESS_EQL</tt>, and <tt>REGEXP</tt>.
|
|
Packit |
a4aae4 |
@return The boolean value of the comparison.
|
|
Packit |
a4aae4 |
@see BaseType::d4_ops(BaseType *, int)
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::ops(BaseType *, int)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Even though ops is a public method, it can never be called because
|
|
Packit |
a4aae4 |
// they will never have a BaseType object since this class is abstract,
|
|
Packit |
a4aae4 |
// however any of the child classes could by mistake call BaseType::ops
|
|
Packit |
a4aae4 |
// so this is an internal error. Jose Garcia
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Unimplemented operator.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Evaluator a relop for DAP4
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* This method is used by the filter expression evaluation code in DAP4.
|
|
Packit |
a4aae4 |
* Each of the 'data type' classes that support relops must overload this
|
|
Packit |
a4aae4 |
* method. In an expression of the form arg1 op arg2, this object is arg1,
|
|
Packit |
a4aae4 |
* the parameter 'b' is arg2 and op is the relational operator.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note I used the same relop codes for DAP4 as in the DAP2 parser/scanner
|
|
Packit |
a4aae4 |
* which makes for some coupling between them, but cuts way down on the
|
|
Packit |
a4aae4 |
* duplication of the evaluator logic, which is somewhat involved.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param b The second argument in the relational expression
|
|
Packit |
a4aae4 |
* @param op The infix relational operator
|
|
Packit |
a4aae4 |
* @return True if the expression is true, False otherwise.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
BaseType::d4_ops(BaseType *, int)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Unimplemented operator.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief How many bytes does this use
|
|
Packit |
a4aae4 |
* Return the number of bytes of storage this variable uses. For scalar types,
|
|
Packit |
a4aae4 |
* this is pretty simple (an int32 uses 4 bytes, etc.). For arrays and Constructors,
|
|
Packit |
a4aae4 |
* it is a bit more complex. Note that a scalar String variable uses sizeof(String*)
|
|
Packit |
a4aae4 |
* bytes, not the length of the string. In other words, the value returned is
|
|
Packit |
a4aae4 |
* independent of the type. Also note width() of a String array returns the number of
|
|
Packit |
a4aae4 |
* elements in the array times sizeof(String*). That is, each different array size
|
|
Packit |
a4aae4 |
* is a different data type.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param constrained Should the current constraint be taken into account?
|
|
Packit |
a4aae4 |
* @return Bytes of storage
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
unsigned int
|
|
Packit |
a4aae4 |
BaseType::width(bool /* constrained */) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "not implemented");
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
return width(constrained);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|