libdap  Updated for version 3.17.0
BaseType.cc
00001 
00002 // -*- mode: c++; c-basic-offset:4 -*-
00003 
00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00005 // Access Protocol.
00006 
00007 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00008 // Author: James Gallagher <jgallagher@opendap.org>
00009 //
00010 // This library is free software; you can redistribute it and/or
00011 // modify it under the terms of the GNU Lesser General Public
00012 // License as published by the Free Software Foundation; either
00013 // version 2.1 of the License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023 //
00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00025 
00026 // (c) COPYRIGHT URI/MIT 1994-1999
00027 // Please read the full copyright statement in the file COPYRIGHT_URI.
00028 //
00029 // Authors:
00030 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00031 
00032 // Implementation for BaseType.
00033 //
00034 // jhrg 9/6/94
00035 
00036 #include "config.h"
00037 
00038 #include <cstdio>  // for stdin and stdout
00039 
00040 #include <sstream>
00041 #include <string>
00042 
00043 //#define DODS_DEBUG
00044 
00045 #include "BaseType.h"
00046 #include "Byte.h"
00047 #include "Int16.h"
00048 #include "UInt16.h"
00049 #include "Int32.h"
00050 #include "UInt32.h"
00051 #include "Float32.h"
00052 #include "Float64.h"
00053 #include "Str.h"
00054 #include "Url.h"
00055 #include "Array.h"
00056 #include "Structure.h"
00057 #include "Sequence.h"
00058 #include "Grid.h"
00059 
00060 #include "D4Attributes.h"
00061 #include "DMR.h"
00062 #include "XMLWriter.h"
00063 #include "D4BaseTypeFactory.h"
00064 
00065 #include "InternalErr.h"
00066 
00067 #include "util.h"
00068 #include "escaping.h"
00069 
00070 #include "debug.h"
00071 
00072 using namespace std;
00073 
00074 namespace libdap {
00075 
00076 // Protected copy mfunc
00077 
00084 void
00085 BaseType::m_duplicate(const BaseType &bt)
00086 {
00087     DBG(cerr << "In BaseType::m_duplicate for " << bt.name() << endl);
00088 
00089     d_name = bt.d_name;
00090     d_type = bt.d_type;
00091     d_dataset = bt.d_dataset;
00092     d_is_read = bt.d_is_read; // added, reza
00093     d_is_send = bt.d_is_send; // added, reza
00094     d_in_selection = bt.d_in_selection;
00095     d_is_synthesized = bt.d_is_synthesized; // 5/11/2001 jhrg
00096 
00097     d_parent = bt.d_parent; // copy pointers 6/4/2001 jhrg
00098 
00099     d_attr = bt.d_attr;  // Deep copy.
00100 
00101     if (bt.d_attributes)
00102         d_attributes = new D4Attributes(*bt.d_attributes); // deep copy
00103     else
00104         d_attributes = 0; // init to null if not used.
00105 
00106     d_is_dap4 = bt.d_is_dap4;
00107 
00108     DBG(cerr << "Exiting BaseType::m_duplicate for " << bt.name() << endl);
00109 }
00110 
00111 // Public mfuncs
00112 
00125 BaseType::BaseType(const string &n, const Type &t, bool is_dap4)
00126         : d_name(n), d_type(t), d_dataset(""), d_is_read(false), d_is_send(false),
00127         d_parent(0), d_attributes(0), d_is_dap4(is_dap4),
00128                 d_in_selection(false), d_is_synthesized(false)
00129 {}
00130 
00143 BaseType::BaseType(const string &n, const string &d, const Type &t, bool is_dap4)
00144         : d_name(n), d_type(t), d_dataset(d), d_is_read(false), d_is_send(false),
00145         d_parent(0), d_attributes(0), d_is_dap4(is_dap4),
00146                 d_in_selection(false), d_is_synthesized(false)
00147 {}
00148 
00150 BaseType::BaseType(const BaseType &copy_from) : DapObj()
00151 {
00152     DBG(cerr << "In BaseTpe::copy_ctor for " << copy_from.name() << endl);
00153     m_duplicate(copy_from);
00154 }
00155 
00156 BaseType::~BaseType()
00157 {
00158     DBG2(cerr << "Entering ~BaseType (" << this << ")" << endl);
00159 
00160     if (d_attributes)
00161         delete d_attributes;
00162 
00163     DBG2(cerr << "Exiting ~BaseType" << endl);
00164 }
00165 
00166 BaseType &
00167 BaseType::operator=(const BaseType &rhs)
00168 {
00169     DBG(cerr << "Entering BaseType::operator=" << endl);
00170     if (this == &rhs)
00171         return *this;
00172 
00173     m_duplicate(rhs);
00174 
00175     DBG(cerr << "Exiting BaseType::operator=" << endl);
00176     return *this;
00177 }
00178 
00183 string BaseType::toString()
00184 {
00185     ostringstream oss;
00186     oss << "BaseType (" << this << "):" << endl
00187     << "          _name: " << name() << endl
00188     << "          _type: " << type_name() << endl
00189     << "          _dataset: " << d_dataset << endl
00190     << "          _read_p: " << d_is_read << endl
00191     << "          _send_p: " << d_is_send << endl
00192     << "          _synthesized_p: " << d_is_synthesized << endl
00193     << "          d_parent: " << d_parent << endl
00194     << "          d_attr: " << hex << &d_attr << dec << endl;
00195 
00196     return oss.str();
00197 }
00198 
00214 BaseType *
00215 BaseType::transform_to_dap4(D4Group */*root*/, Constructor */*container*/)
00216 {
00217         BaseType *dest = ptr_duplicate();
00218 
00219         // Copy the D2 attributes from 'this' to dest's D4 Attributes
00220         dest->attributes()->transform_to_dap4(get_attr_table());
00221 
00222         dest->set_is_dap4(true);
00223 
00224         return dest;
00225 }
00226 
00235 void
00236 BaseType::dump(ostream &strm) const
00237 {
00238     strm << DapIndent::LMarg << "BaseType::dump - ("
00239     << (void *)this << ")" << endl ;
00240     DapIndent::Indent() ;
00241 
00242     strm << DapIndent::LMarg << "name: " << name() << endl ;
00243     strm << DapIndent::LMarg << "type: " << type_name() << endl ;
00244     strm << DapIndent::LMarg << "dataset: " << d_dataset << endl ;
00245     strm << DapIndent::LMarg << "read_p: " << d_is_read << endl ;
00246     strm << DapIndent::LMarg << "send_p: " << d_is_send << endl ;
00247     strm << DapIndent::LMarg << "synthesized_p: " << d_is_synthesized << endl ;
00248     strm << DapIndent::LMarg << "parent: " << (void *)d_parent << endl ;
00249     strm << DapIndent::LMarg << "attributes: " << endl ;
00250     DapIndent::Indent() ;
00251     d_attr.dump(strm) ;
00252     DapIndent::UnIndent() ;
00253 
00254     DapIndent::UnIndent() ;
00255 }
00256 
00259 string
00260 BaseType::name() const
00261 {
00262     return d_name;
00263 }
00264 
00271 string
00272 BaseType::FQN() const
00273 {
00274         if (get_parent() == 0)
00275                 return name();
00276         else if (get_parent()->type() == dods_group_c)
00277                 return get_parent()->FQN() + name();
00278         else
00279                 return get_parent()->FQN() + "." + name();
00280 }
00281 
00283 void
00284 BaseType::set_name(const string &n)
00285 {
00286     string name = n;
00287     d_name = www2id(name); // www2id writes into its param.
00288 }
00289 
00297 string
00298 BaseType::dataset() const
00299 {
00300     return d_dataset;
00301 }
00302 
00304 Type
00305 BaseType::type() const
00306 {
00307     return d_type;
00308 }
00309 
00311 void
00312 BaseType::set_type(const Type &t)
00313 {
00314     d_type = t;
00315 }
00316 
00318 string
00319 BaseType::type_name() const
00320 {
00321         if (is_dap4())
00322                 return libdap::D4type_name(d_type);
00323         else
00324                 return libdap::D2type_name(d_type);
00325 }
00326 
00332 bool
00333 BaseType::is_simple_type() const
00334 {
00335     return libdap::is_simple_type(type());
00336 }
00337 
00341 bool
00342 BaseType::is_vector_type() const
00343 {
00344     return libdap::is_vector_type(type());
00345 }
00346 
00351 bool
00352 BaseType::is_constructor_type() const
00353 {
00354     return libdap::is_constructor_type(type());
00355 }
00356 
00382 int
00383 BaseType::element_count(bool)
00384 {
00385     return 1;
00386 }
00387 
00391 bool
00392 BaseType::synthesized_p()
00393 {
00394     return d_is_synthesized;
00395 }
00396 
00402 void
00403 BaseType::set_synthesized_p(bool state)
00404 {
00405     d_is_synthesized = state;
00406 }
00407 
00408 // Return the state of d_is_read (true if the value of the variable has been
00409 // read (and is in memory) false otherwise).
00410 
00419 bool
00420 BaseType::read_p()
00421 {
00422     return d_is_read;
00423 }
00424 
00455 void
00456 BaseType::set_read_p(bool state)
00457 {
00458     // The this comment is/was wrong!
00459     // The is_synthesized property was not being used and the more I thought
00460     // about how this was coded, the more this code below seemed like a bad idea.
00461     // Once the property was set, the read_p property could not be changed.
00462     // That seems a little silly. Also, I think I need to use this is_synthesized
00463     // property for some of the server function code I'm working on for Raytheon,
00464     // and I'd like to be able to control the read_p property! jhrg 3/9/15
00465 
00466     // What's true: The is_synthesized property is used by
00467     // 'projection functions' in the freeform handler. It might be better
00468     // to modify the FFtypes to support this behavior, but for now I'm returning
00469     // the library to its old behavior. That this change (setting is_read
00470     // of the value of is_syn...) broke the FF handler was not detected
00471     // because the FF tests were not being run due to an error in the FF
00472     // bes-testsuite Makefile.am). jhrg 9/9/15
00473 
00474 #if 1
00475     if (!d_is_synthesized) {
00476         d_is_read = state;
00477     }
00478 #else
00479     d_is_read = state;
00480 #endif
00481 }
00482 
00493 bool
00494 BaseType::send_p()
00495 {
00496     return d_is_send;
00497 }
00498 
00507 void
00508 BaseType::set_send_p(bool state)
00509 {
00510     DBG2(cerr << "Calling BaseType::set_send_p() for: " << this->name()
00511         << endl);
00512     d_is_send = state;
00513 }
00514 
00515 
00521 AttrTable &
00522 BaseType::get_attr_table()
00523 {
00524     return d_attr;
00525 }
00526 
00529 void
00530 BaseType::set_attr_table(const AttrTable &at)
00531 {
00532     d_attr = at;
00533 }
00534 
00538 D4Attributes *
00539 BaseType::attributes()
00540 {
00541     if (!d_attributes) d_attributes = new D4Attributes();
00542     return d_attributes;
00543 }
00544 
00545 void
00546 BaseType::set_attributes(D4Attributes *attrs)
00547 {
00548     d_attributes = new D4Attributes(*attrs);
00549 }
00550 
00551 void
00552 BaseType::set_attributes_nocopy(D4Attributes *attrs)
00553 {
00554     d_attributes = attrs;
00555 }
00557 
00584 void BaseType::transfer_attributes(AttrTable *at_container) {
00585         AttrTable *at = at_container->get_attr_table(name());
00586 
00587         DBG(cerr << "In BaseType::transfer_attributes; processing " << name() << endl);
00588 
00589         if (at) {
00590                 at->set_is_global_attribute(false);
00591                 DBG(cerr << "Processing AttrTable: " << at->get_name() << endl);
00592 
00593                 AttrTable::Attr_iter at_p = at->attr_begin();
00594                 while (at_p != at->attr_end()) {
00595                         DBG(cerr << "About to append " << "attr name, type:" << at->get_name(at_p) << ", " << at->get_type(at_p) << endl);
00596 
00597                         if (at->get_attr_type(at_p) == Attr_container)
00598                                 get_attr_table().append_container(new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p));
00599                         else
00600                                 get_attr_table().append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p));
00601 
00602                         at_p++;
00603                 }
00604         }
00605 }
00606 
00618 bool
00619 BaseType::is_in_selection()
00620 {
00621     return d_in_selection;
00622 }
00623 
00633 void
00634 BaseType::set_in_selection(bool state)
00635 {
00636     d_in_selection = state;
00637 }
00638 
00639 // Protected method.
00648 void
00649 BaseType::set_parent(BaseType *parent)
00650 {
00651     if (!dynamic_cast<Constructor *>(parent)
00652         && !dynamic_cast<Vector *>(parent)
00653         && parent != 0)
00654         throw InternalErr("Call to set_parent with incorrect variable type.");
00655 
00656     d_parent = parent;
00657 }
00658 
00659 // Public method.
00660 
00666 BaseType *
00667 BaseType::get_parent() const
00668 {
00669     return d_parent;
00670 }
00671 
00672 // Documented in the header file.
00673 BaseType *
00674 BaseType::var(const string &/*name*/, bool /*exact_match*/, btp_stack */*s*/)
00675 {
00676     return static_cast<BaseType *>(0);
00677 }
00678 
00695 BaseType *
00696 BaseType::var(const string &, btp_stack &)
00697 {
00698     return static_cast<BaseType *>(0);
00699 }
00700 
00730 void
00731 BaseType::add_var(BaseType *, Part)
00732 {
00733     throw InternalErr(__FILE__, __LINE__, "BaseType::add_var unimplemented");
00734 }
00735 
00736 void
00737 BaseType::add_var_nocopy(BaseType *, Part)
00738 {
00739     throw InternalErr(__FILE__, __LINE__, "BaseType::add_var_nocopy unimplemented");
00740 }
00741 
00814 bool
00815 BaseType::read()
00816 {
00817     if (d_is_read)
00818         return true;
00819 
00820     throw InternalErr("Unimplemented BaseType::read() method called for the variable named: " + name());
00821 }
00822 
00823 void
00824 BaseType::intern_data(ConstraintEvaluator &, DDS &dds)
00825 {
00826 #if USE_LOCAL_TIMEOUT_SCHEME
00827     dds.timeout_on();
00828 #endif
00829     DBG2(cerr << "BaseType::intern_data: " << name() << endl);
00830     if (!read_p())
00831         read();          // read() throws Error and InternalErr
00832 #if USE_LOCAL_TIMEOUT_SCHEME
00833     dds.timeout_off();
00834 #endif
00835 }
00836 
00842 void
00843 BaseType::intern_data(/*Crc32 &checksum, DMR &, ConstraintEvaluator &*/)
00844 {
00845     if (!read_p())
00846         read();          // read() throws Error and InternalErr
00847 #if 0
00848     compute_checksum(checksum);
00849 #endif
00850 }
00851 
00852 bool
00853 BaseType::serialize(ConstraintEvaluator &, DDS &,  Marshaller &, bool)
00854 {
00855         throw InternalErr(__FILE__, __LINE__, "The DAP2 serialize() method has not been implemented for " + type_name());
00856 }
00857 
00858 bool
00859 BaseType::deserialize(UnMarshaller &, DDS *, bool)
00860 {
00861         throw InternalErr(__FILE__, __LINE__, "The DAP2 deserialize() method has not been implemented for " + type_name());
00862 }
00863 
00864 void
00865 BaseType::serialize(D4StreamMarshaller &, DMR &, /*ConstraintEvaluator &,*/ bool)
00866 {
00867         throw InternalErr(__FILE__, __LINE__, "The DAP4 serialize() method has not been implemented for " + type_name());
00868 }
00869 
00870 void
00871 BaseType::deserialize(D4StreamUnMarshaller &, DMR &)
00872 {
00873         throw InternalErr(__FILE__, __LINE__, "The DAP4 deserialize() method has not been implemented for " + type_name());
00874 }
00875 
00918 void
00919 BaseType::print_decl(FILE *out, string space, bool print_semi,
00920                      bool constraint_info, bool constrained)
00921 {
00922     ostringstream oss;
00923     print_decl(oss, space, print_semi, constraint_info, constrained);
00924     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
00925 }
00926 
00969 void
00970 BaseType::print_decl(ostream &out, string space, bool print_semi,
00971                      bool constraint_info, bool constrained)
00972 {
00973     // if printing the constrained declaration, exit if this variable was not
00974     // selected.
00975     if (constrained && !send_p())
00976         return;
00977 
00978     out << space << type_name() << " " << id2www(name()) ;
00979 
00980     if (constraint_info) {
00981         if (send_p())
00982             out << ": Send True" ;
00983         else
00984             out << ": Send False" ;
00985     }
00986 
00987     if (print_semi)
00988         out << ";\n" ;
00989 }
00990 
01005 void
01006 BaseType::print_val(FILE *out, string space, bool print_decl_p)
01007 {
01008     ostringstream oss;
01009     print_val(oss, space, print_decl_p);
01010     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
01011 }
01012 
01020 void
01021 BaseType::print_xml(FILE *out, string space, bool constrained)
01022 {
01023     XMLWriter xml(space);
01024     print_xml_writer(xml, constrained);
01025     fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
01026 }
01027 
01035 void
01036 BaseType::print_xml(ostream &out, string space, bool constrained)
01037 {
01038     XMLWriter xml(space);
01039     print_xml_writer(xml, constrained);
01040     out << xml.get_doc();
01041 }
01042 
01049 void
01050 BaseType::print_xml_writer(XMLWriter &xml, bool constrained)
01051 {
01052     if (constrained && !send_p())
01053         return;
01054 
01055     if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0)
01056         throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
01057 
01058     if (!name().empty())
01059     if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
01060         throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
01061 
01062     if (is_dap4())
01063         attributes()->print_dap4(xml);
01064 
01065     if (!is_dap4() && get_attr_table().get_size() > 0)
01066         get_attr_table().print_xml_writer(xml);
01067 
01068     if (xmlTextWriterEndElement(xml.get_writer()) < 0)
01069         throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
01070 }
01071 
01079 void
01080 BaseType::print_dap4(XMLWriter &xml, bool constrained)
01081 {
01082     print_xml_writer(xml, constrained);
01083 }
01084 
01085 // Compares the object's current state with the semantics of a particular
01086 // type. This will typically be defined in ctor classes (which have
01087 // complicated semantics). For BaseType, an object is semantically correct if
01088 // it has both a non-null name and type.
01089 //
01090 // NB: This is not the same as an invariant -- during the parse objects exist
01091 // but have no name. Also, the bool ALL defaults to false for BaseType. It is
01092 // used by children of CtorType.
01093 //
01094 // Returns: true if the object is semantically correct, false otherwise.
01095 
01124 bool
01125 BaseType::check_semantics(string &msg, bool)
01126 {
01127     bool sem = (d_type != dods_null_c && name().length());
01128 
01129     if (!sem)
01130         msg = "Every variable must have both a name and a type\n";
01131 
01132     return sem;
01133 }
01134 
01169 bool
01170 BaseType::ops(BaseType *, int)
01171 {
01172     // Even though ops is a public method, it can never be called because
01173     // they will never have a BaseType object since this class is abstract,
01174     // however any of the child classes could by mistake call BaseType::ops
01175     // so this is an internal error. Jose Garcia
01176     throw InternalErr(__FILE__, __LINE__, "Unimplemented operator.");
01177 }
01178 
01192 unsigned int
01193 BaseType::width(bool /* constrained */) const
01194 {
01195         throw InternalErr(__FILE__, __LINE__, "not implemented");
01196 #if 0
01197         return width(constrained);
01198 #endif
01199 }
01200 
01201 } // namespace libdap