libdap
Updated for version 3.17.0
|
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 ©_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