libdap  Updated for version 3.17.0
Constructor.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 1995-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 
00033 #include "config.h"
00034 
00035 #include <string>
00036 #include <sstream>
00037 #include <algorithm>
00038 #include <functional>
00039 
00040 #include <stdint.h>
00041 
00042 //#define DODS_DEBUG
00043 
00044 #include "crc.h"
00045 
00046 #include "Constructor.h"
00047 #include "Grid.h"
00048 
00049 #include "DMR.h"
00050 #include "XMLWriter.h"
00051 #include "D4StreamMarshaller.h"
00052 #include "D4StreamUnMarshaller.h"
00053 
00054 #include "D4Attributes.h"
00055 
00056 #include "debug.h"
00057 #include "escaping.h"
00058 #include "util.h"
00059 #include "Error.h"
00060 #include "InternalErr.h"
00061 
00062 using namespace std;
00063 
00064 namespace libdap {
00065 
00066 // Private member functions
00067 
00068 void
00069 Constructor::m_duplicate(const Constructor &c)
00070 {
00071         DBG(cerr << "In Constructor::m_duplicate for " << c.name() << endl);
00072         // Clear out any spurious vars in Constructor::d_vars
00073         // Moved from Grid::m_duplicate. jhrg 4/3/13
00074         d_vars.clear(); // [mjohnson 10 Sep 2009]
00075 
00076         Vars_citer i = c.d_vars.begin();
00077         while (i != c.d_vars.end()) {
00078                 BaseType *btp = (*i++)->ptr_duplicate();
00079                 btp->set_parent(this);
00080                 d_vars.push_back(btp);
00081         }
00082 
00083         DBG(cerr << "Exiting Constructor::m_duplicate for " << c.name() << endl);
00084 }
00085 
00086 // Public member functions
00087 
00088 Constructor::Constructor(const string &name, const Type &type, bool is_dap4)
00089         : BaseType(name, type, is_dap4)
00090 {}
00091 
00102 Constructor::Constructor(const string &name, const string &dataset, const Type &type, bool is_dap4)
00103         : BaseType(name, dataset, type, is_dap4)
00104 {}
00105 
00106 Constructor::Constructor(const Constructor &rhs) : BaseType(rhs), d_vars(0)
00107 {
00108     DBG(cerr << "In Constructor::copy_ctor for " << rhs.name() << endl);
00109     m_duplicate(rhs);
00110 }
00111 
00112 Constructor::~Constructor()
00113 {
00114     Vars_iter i = d_vars.begin();
00115     while (i != d_vars.end()) {
00116         delete *i++;
00117     }
00118 }
00119 
00120 Constructor &
00121 Constructor::operator=(const Constructor &rhs)
00122 {
00123     DBG(cerr << "Entering Constructor::operator=" << endl);
00124     if (this == &rhs)
00125         return *this;
00126 
00127     dynamic_cast<BaseType &>(*this) = rhs; // run BaseType=
00128 
00129     m_duplicate(rhs);
00130 
00131     DBG(cerr << "Exiting Constructor::operator=" << endl);
00132     return *this;
00133 }
00134 
00135 // A public method, but just barely..
00136 BaseType *
00137 Constructor::transform_to_dap4(D4Group *root, Constructor *dest)
00138 {
00139     for (Constructor::Vars_citer i = var_begin(), e = var_end(); i != e; ++i) {
00140         BaseType *new_var = (*i)->transform_to_dap4(root, dest);
00141         if (new_var) {  // Might be a Grid; see the comment in BaseType::transform_to_dap4()
00142                 new_var->set_parent(dest);
00143                 dest->add_var_nocopy(new_var);
00144         }
00145     }
00146 
00147     // Add attributes
00148         dest->attributes()->transform_to_dap4(get_attr_table());
00149 
00150     dest->set_is_dap4(true);
00151 
00152         return dest;
00153 }
00154 
00155 string
00156 Constructor::FQN() const
00157 {
00158         if (get_parent() == 0)
00159                 return name();
00160         else if (get_parent()->type() == dods_group_c)
00161                 return get_parent()->FQN() + name();
00162         else if (get_parent()->type() == dods_array_c)
00163                 return get_parent()->FQN();
00164         else
00165                 return get_parent()->FQN() + "." + name();
00166 }
00167 
00168 int
00169 Constructor::element_count(bool leaves)
00170 {
00171     if (!leaves)
00172         return d_vars.size();
00173     else {
00174         int i = 0;
00175         for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) {
00176             i += (*j)->element_count(leaves);
00177         }
00178         return i;
00179     }
00180 }
00181 
00182 void
00183 Constructor::set_send_p(bool state)
00184 {
00185     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00186         (*i)->set_send_p(state);
00187     }
00188 
00189     BaseType::set_send_p(state);
00190 }
00191 
00192 void
00193 Constructor::set_read_p(bool state)
00194 {
00195     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00196         (*i)->set_read_p(state);
00197     }
00198 
00199     BaseType::set_read_p(state);
00200 }
00201 
00202 #if 0
00203 // TODO Recode to use width(bool). Bur see comments in BaseType.h
00204 unsigned int
00205 Constructor::width()
00206 {
00207     unsigned int sz = 0;
00208 
00209     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00210         sz += (*i)->width();
00211     }
00212 
00213     return sz;
00214 }
00215 #endif
00216 
00223 unsigned int
00224 Constructor::width(bool constrained) const
00225 {
00226     unsigned int sz = 0;
00227 
00228     for (Vars_citer i = d_vars.begin(); i != d_vars.end(); i++) {
00229         if (constrained) {
00230             if ((*i)->send_p())
00231                 sz += (*i)->width(constrained);
00232         }
00233         else {
00234             sz += (*i)->width(constrained);
00235         }
00236     }
00237 
00238     return sz;
00239 }
00240 
00241 BaseType *
00242 Constructor::var(const string &name, bool exact_match, btp_stack *s)
00243 {
00244     string n = www2id(name);
00245 
00246     if (exact_match)
00247         return m_exact_match(n, s);
00248     else
00249         return m_leaf_match(n, s);
00250 }
00251 
00253 BaseType *
00254 Constructor::var(const string &n, btp_stack &s)
00255 {
00256         // This should probably be removed. The BES code should remove web encoding
00257         // with the possible exception of spaces. jhrg 11/25/13
00258     string name = www2id(n);
00259 
00260     BaseType *btp = m_exact_match(name, &s);
00261     if (btp)
00262         return btp;
00263 
00264     return m_leaf_match(name, &s);
00265 }
00266 
00267 // Protected method
00268 BaseType *
00269 Constructor::m_leaf_match(const string &name, btp_stack *s)
00270 {
00271     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00272         if ((*i)->name() == name) {
00273             if (s) {
00274                 DBG(cerr << "Pushing " << this->name() << endl);
00275                 s->push(static_cast<BaseType *>(this));
00276             }
00277             return *i;
00278         }
00279         if ((*i)->is_constructor_type()) {
00280             BaseType *btp = (*i)->var(name, false, s);
00281             if (btp) {
00282                 if (s) {
00283                     DBG(cerr << "Pushing " << this->name() << endl);
00284                     s->push(static_cast<BaseType *>(this));
00285                 }
00286                 return btp;
00287             }
00288         }
00289     }
00290 
00291     return 0;
00292 }
00293 
00294 // Protected method
00295 BaseType *
00296 Constructor::m_exact_match(const string &name, btp_stack *s)
00297 {
00298     // Look for name at the top level first.
00299     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00300         if ((*i)->name() == name) {
00301             if (s)
00302                 s->push(static_cast<BaseType *>(this));
00303 
00304             return *i;
00305         }
00306     }
00307 
00308     // If it was not found using the simple search, look for a dot and
00309     // search the hierarchy.
00310     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00311     if (dot_pos != string::npos) {
00312         string aggregate = name.substr(0, dot_pos);
00313         string field = name.substr(dot_pos + 1);
00314 
00315         BaseType *agg_ptr = var(aggregate);
00316         if (agg_ptr) {
00317             if (s)
00318                 s->push(static_cast<BaseType *>(this));
00319 
00320             return agg_ptr->var(field, true, s); // recurse
00321         }
00322         else
00323             return 0;  // qualified names must be *fully* qualified
00324     }
00325 
00326     return 0;
00327 }
00328 
00330 Constructor::Vars_iter
00331 Constructor::var_begin()
00332 {
00333     return d_vars.begin() ;
00334 }
00335 
00338 Constructor::Vars_iter
00339 Constructor::var_end()
00340 {
00341     return d_vars.end() ;
00342 }
00343 
00345 Constructor::Vars_riter
00346 Constructor::var_rbegin()
00347 {
00348     return d_vars.rbegin();
00349 }
00350 
00353 Constructor::Vars_riter
00354 Constructor::var_rend()
00355 {
00356     return d_vars.rend();
00357 }
00358 
00362 Constructor::Vars_iter
00363 Constructor::get_vars_iter(int i)
00364 {
00365     return d_vars.begin() + i;
00366 }
00367 
00371 BaseType *
00372 Constructor::get_var_index(int i)
00373 {
00374     return *(d_vars.begin() + i);
00375 }
00376 
00381 void
00382 Constructor::add_var(BaseType *bt, Part)
00383 {
00384     // Jose Garcia
00385     // Passing and invalid pointer to an object is a developer's error.
00386     if (!bt)
00387         throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
00388 #if 0
00389     if (bt->is_dap4_only_type())
00390         throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
00391 #endif
00392     // Jose Garcia
00393     // Now we add a copy of bt so the external user is able to destroy bt as
00394     // he/she wishes. The policy is: "If it is allocated outside, it is
00395     // deallocated outside, if it is allocated inside, it is deallocated
00396     // inside"
00397     BaseType *btp = bt->ptr_duplicate();
00398     btp->set_parent(this);
00399     d_vars.push_back(btp);
00400 }
00401 
00406 void
00407 Constructor::add_var_nocopy(BaseType *bt, Part)
00408 {
00409     if (!bt)
00410         throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
00411 #if 0
00412     if (bt->is_dap4_only_type())
00413         throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
00414 #endif
00415     bt->set_parent(this);
00416     d_vars.push_back(bt);
00417 }
00418 
00422 void
00423 Constructor::del_var(const string &n)
00424 {
00425         // TODO remove_if? find_if?
00426     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00427         if ((*i)->name() == n) {
00428             BaseType *bt = *i ;
00429             d_vars.erase(i) ;
00430             delete bt ; bt = 0;
00431             return;
00432         }
00433     }
00434 }
00435 
00436 void
00437 Constructor::del_var(Vars_iter i)
00438 {
00439     if (*i != 0) {
00440         BaseType *bt = *i;
00441         d_vars.erase(i);
00442         delete bt;
00443     }
00444 }
00445 
00451 bool Constructor::read()
00452 {
00453         DBG(cerr << "Entering  Constructor::read..." << endl);
00454     if (!read_p()) {
00455         for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00456             (*i)->read();
00457         }
00458         set_read_p(true);
00459     }
00460 
00461     return false;
00462 }
00463 
00464 void
00465 Constructor::intern_data(ConstraintEvaluator & eval, DDS & dds)
00466 {
00467     DBG(cerr << "Constructor::intern_data: " << name() << endl);
00468     if (!read_p())
00469         read();          // read() throws Error and InternalErr
00470 
00471     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00472         if ((*i)->send_p()) {
00473             (*i)->intern_data(eval, dds);
00474         }
00475     }
00476 }
00477 
00478 bool
00479 Constructor::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
00480 {
00481 #if USE_LOCAL_TIMEOUT_SCHEME
00482     dds.timeout_on();
00483 #endif
00484     if (!read_p())
00485         read();  // read() throws Error and InternalErr
00486 
00487     if (ce_eval && !eval.eval_selection(dds, dataset()))
00488         return true;
00489 #if USE_LOCAL_TIMEOUT_SCHEME
00490     dds.timeout_off();
00491 #endif
00492     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00493         if ((*i)->send_p()) {
00494 #ifdef CHECKSUMS
00495             XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
00496             if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
00497                 sm->reset_checksum();
00498 
00499             (*i)->serialize(eval, dds, m, false);
00500 
00501             if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
00502                 sm->get_checksum();
00503 #else
00504             // (*i)->serialize(eval, dds, m, false);
00505             // Only Sequence and Vector run the evaluator.
00506             (*i)->serialize(eval, dds, m, true);
00507 #endif
00508         }
00509     }
00510 
00511     return true;
00512 }
00513 
00514 bool
00515 Constructor::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
00516 {
00517     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00518         (*i)->deserialize(um, dds, reuse);
00519     }
00520 
00521     return false;
00522 }
00523 
00524 void
00525 Constructor::compute_checksum(Crc32 &)
00526 {
00527         throw InternalErr(__FILE__, __LINE__, "Computing a checksum alone is not supported for Constructor types.");
00528 }
00529 
00530 void
00531 Constructor::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator & eval*/)
00532 {
00533     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00534         if ((*i)->send_p()) {
00535             (*i)->intern_data(/*checksum, dmr, eval*/);
00536         }
00537     }
00538 }
00539 
00540 
00552 void
00553 Constructor::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter)
00554 {
00555 #if 1
00556         // Not used for the same reason the equivalent code in D4Group::serialize()
00557         // is not used. Fail for D4Sequence and general issues with memory use.
00558         //
00559         // Revisit this - I had to uncomment this to get the netcdf_handler code
00560         // to work - it relies on having NCStructure::read() called. The D4Sequence
00561         // ::serialize() method calls read_next_instance(). What seems to be happening
00562         // is that this call to read gets the first set of values, but does not store
00563         // them; the call to serialize then runs the D4Sequence::serialize() method that
00564         // _does_ read all of the sequence data and then serialize it. However, the first
00565         // sequence instance is missing...
00566     if (!read_p())
00567         read();  // read() throws Error
00568 #endif
00569 #if 0
00570     // place holder for now. There may be no need for this; only Array and Seq?
00571     // jhrg 9/6/13
00572     if (filter && !eval.eval_selection(dmr, dataset()))
00573         return true;
00574 #endif
00575 
00576     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00577         if ((*i)->send_p()) {
00578             (*i)->serialize(m, dmr, /*eval,*/ filter);
00579         }
00580     }
00581 }
00582 
00583 void
00584 Constructor::deserialize(D4StreamUnMarshaller &um, DMR &dmr)
00585 {
00586     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00587         (*i)->deserialize(um, dmr);
00588     }
00589 }
00590 
00591 void
00592 Constructor::print_decl(FILE *out, string space, bool print_semi,
00593                         bool constraint_info, bool constrained)
00594 {
00595     ostringstream oss;
00596     print_decl(oss, space, print_semi, constraint_info, constrained);
00597     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
00598 }
00599 
00600 void
00601 Constructor::print_decl(ostream &out, string space, bool print_semi,
00602                         bool constraint_info, bool constrained)
00603 {
00604     if (constrained && !send_p())
00605         return;
00606 
00607     out << space << type_name() << " {\n" ;
00608     for (Vars_citer i = d_vars.begin(); i != d_vars.end(); i++) {
00609         (*i)->print_decl(out, space + "    ", true, constraint_info, constrained);
00610     }
00611     out << space << "} " << id2www(name()) ;
00612 
00613     if (constraint_info) { // Used by test drivers only.
00614         if (send_p())
00615             out << ": Send True";
00616         else
00617             out << ": Send False";
00618     }
00619 
00620     if (print_semi)
00621         out << ";\n" ;
00622 }
00623 
00624 void
00625 Constructor::print_val(FILE *out, string space, bool print_decl_p)
00626 {
00627     ostringstream oss;
00628     print_val(oss, space, print_decl_p);
00629     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
00630 }
00631 
00632 void
00633 Constructor::print_val(ostream &out, string space, bool print_decl_p)
00634 {
00635     if (print_decl_p) {
00636         print_decl(out, space, false);
00637         out << " = " ;
00638     }
00639 
00640     out << "{ " ;
00641     for (Vars_citer i = d_vars.begin(); i != d_vars.end();
00642          i++, (void)(i != d_vars.end() && out << ", ")) {
00643         (*i)->print_val(out, "", false);
00644     }
00645 
00646     out << " }" ;
00647 
00648     if (print_decl_p)
00649         out << ";\n" ;
00650 }
00651 
00655 void
00656 Constructor::print_xml(FILE *out, string space, bool constrained)
00657 {
00658     XMLWriter xml(space);
00659     print_xml_writer(xml, constrained);
00660     fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
00661 }
00662 
00666 void
00667 Constructor::print_xml(ostream &out, string space, bool constrained)
00668 {
00669     XMLWriter xml(space);
00670     print_xml_writer(xml, constrained);
00671     out << xml.get_doc();
00672 }
00673 
00674 class PrintFieldXMLWriter : public unary_function<BaseType *, void>
00675 {
00676     XMLWriter &d_xml;
00677     bool d_constrained;
00678 public:
00679     PrintFieldXMLWriter(XMLWriter &x, bool c)
00680             : d_xml(x), d_constrained(c)
00681     {}
00682 
00683     void operator()(BaseType *btp)
00684     {
00685         btp->print_xml_writer(d_xml, d_constrained);
00686     }
00687 };
00688 
00689 void
00690 Constructor::print_xml_writer(XMLWriter &xml, bool constrained)
00691 {
00692     if (constrained && !send_p())
00693         return;
00694 
00695     if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0)
00696         throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
00697 
00698     if (!name().empty())
00699         if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
00700             throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
00701 
00702     // DAP2 prints attributes first. For some reason we decided that DAP4 should
00703     // print them second. No idea why... jhrg 8/15/14
00704     if (!is_dap4() && get_attr_table().get_size() > 0)
00705         get_attr_table().print_xml_writer(xml);
00706 
00707     bool has_variables = (var_begin() != var_end());
00708     if (has_variables)
00709         for_each(var_begin(), var_end(), PrintFieldXMLWriter(xml, constrained));
00710 
00711     if (is_dap4())
00712         attributes()->print_dap4(xml);
00713 
00714 #if 0
00715     // Moved up above so that the DDX tests for various handles will still work.
00716     // jhrg 8/15/14
00717     if (!is_dap4() && get_attr_table().get_size() > 0)
00718         get_attr_table().print_xml_writer(xml);
00719 #endif
00720 
00721     if (xmlTextWriterEndElement(xml.get_writer()) < 0)
00722         throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
00723 }
00724 
00725 class PrintDAP4FieldXMLWriter : public unary_function<BaseType *, void>
00726 {
00727     XMLWriter &d_xml;
00728     bool d_constrained;
00729 public:
00730     PrintDAP4FieldXMLWriter(XMLWriter &x, bool c) : d_xml(x), d_constrained(c) {}
00731 
00732     void operator()(BaseType *btp)
00733     {
00734         btp->print_dap4(d_xml, d_constrained);
00735     }
00736 };
00737 
00738 
00739 void
00740 Constructor::print_dap4(XMLWriter &xml, bool constrained)
00741 {
00742     if (constrained && !send_p())
00743         return;
00744 
00745     if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0)
00746         throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
00747 
00748     if (!name().empty())
00749         if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
00750             throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
00751 
00752     bool has_variables = (var_begin() != var_end());
00753     if (has_variables)
00754         for_each(var_begin(), var_end(), PrintDAP4FieldXMLWriter(xml, constrained));
00755 
00756     attributes()->print_dap4(xml);
00757 
00758     if (xmlTextWriterEndElement(xml.get_writer()) < 0)
00759         throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
00760 }
00761 
00762 
00763 bool
00764 Constructor::check_semantics(string &msg, bool all)
00765 {
00766     if (!BaseType::check_semantics(msg))
00767         return false;
00768 
00769     if (!unique_names(d_vars, name(), type_name(), msg))
00770         return false;
00771 
00772     if (all)
00773         for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00774             if (!(*i)->check_semantics(msg, true)) {
00775                 return false;
00776             }
00777         }
00778 
00779     return true;
00780 }
00781 
00794 bool
00795 Constructor::is_linear()
00796 {
00797     return false;
00798 }
00799 
00805 void
00806 Constructor::set_in_selection(bool state)
00807 {
00808     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00809         (*i)->set_in_selection(state);
00810     }
00811 
00812     BaseType::set_in_selection(state);
00813 }
00814 
00823 void
00824 Constructor::dump(ostream &strm) const
00825 {
00826     strm << DapIndent::LMarg << "Constructor::dump - ("
00827     << (void *)this << ")" << endl ;
00828     DapIndent::Indent() ;
00829     BaseType::dump(strm) ;
00830     strm << DapIndent::LMarg << "vars: " << endl ;
00831     DapIndent::Indent() ;
00832     Vars_citer i = d_vars.begin() ;
00833     Vars_citer ie = d_vars.end() ;
00834     for (; i != ie; i++) {
00835         (*i)->dump(strm) ;
00836     }
00837     DapIndent::UnIndent() ;
00838     DapIndent::UnIndent() ;
00839 }
00840 
00841 } // namespace libdap
00842