libdap++ Updated for version 3.8.2

Constructor.cc

Go to the documentation of this file.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 <algorithm>
00037 #include <functional>
00038 
00039 //#define DODS_DEBUG
00040 
00041 #include "Constructor.h"
00042 #include "Grid.h"
00043 
00044 #include "debug.h"
00045 #include "escaping.h"
00046 #include "Error.h"
00047 #include "InternalErr.h"
00048 
00049 
00050 using namespace std;
00051 
00052 namespace libdap {
00053 
00054 // Private member functions
00055 
00056 void
00057 Constructor::_duplicate(const Constructor &)
00058 {}
00059 
00060 // Public member functions
00061 
00062 Constructor::Constructor(const string &n, const Type &t)
00063         : BaseType(n, t)
00064 {}
00065 
00076 Constructor::Constructor(const string &n, const string &d, const Type &t)
00077         : BaseType(n, d, t)
00078 {}
00079 
00080 Constructor::Constructor(const Constructor &rhs) : BaseType(rhs)
00081 {}
00082 
00083 Constructor::~Constructor()
00084 {}
00085 
00086 Constructor &
00087 Constructor::operator=(const Constructor &rhs)
00088 {
00089     if (this == &rhs)
00090         return *this;
00091 
00092     dynamic_cast<BaseType &>(*this) = rhs; // run BaseType=
00093 
00094     _duplicate(rhs);
00095 
00096     return *this;
00097 }
00098 
00100 Constructor::Vars_iter
00101 Constructor::var_begin()
00102 {
00103     return _vars.begin() ;
00104 }
00105 
00121 BaseType *
00122 Constructor::find_hdf4_dimension_attribute_home(AttrTable::entry *source)
00123 {
00124     BaseType *btp;
00125     string::size_type i = source->name.find("_dim_");
00126     if (i != string::npos && (btp = var(source->name.substr(0, i)))) {
00127         if (btp->is_vector_type()) {
00128             return btp;
00129         }
00130         else if (btp->type() == dods_grid_c) {
00131             // For a Grid, the hdf4 handler uses _dim_n for the n-th Map
00132             // i+5 points to the character holding 'n'
00133             int n = atoi(source->name.substr(i + 5).c_str());
00134             DBG(cerr << "Found a Grid (" << btp->name() << ") and "
00135                 << source->name.substr(i) << ", extracted n: " << n << endl);
00136             return *(dynamic_cast<Grid&>(*btp).map_begin() + n);
00137         }
00138     }
00139 
00140     return 0;
00141 }
00142 
00143 #if 0
00144 
00146 AttrTable *
00147 Constructor::find_matching_container(AttrTable::entry *source,
00148                                      BaseType **dest_variable)
00149 {
00150     // The attribute entry 'source' must be a container
00151     if (source->type != Attr_container)
00152         throw InternalErr(__FILE__, __LINE__, "Constructor::find_matching_container");
00153 
00154     // Use the name of the attribute container 'source' to figure out where
00155     // to put its contents.
00156     BaseType *btp;
00157     if ((btp = var(source->name))) {
00158         // ... matches a variable name? Use var's table
00159         *dest_variable = btp;
00160         return &btp->get_attr_table();
00161     }
00162     // As more special-case attribute containers come to light, add clauses
00163     // here.
00164     else if ((btp = find_hdf4_dimension_attribute_home(source))) {
00165         // ... hdf4 dimension attribute? Make a sub table and use that.
00166         // btp can only be an Array or a Grid Map (which is an array)
00167         if (btp->get_parent()->type() == dods_grid_c) {
00168             DBG(cerr << "Found a Grid" << endl);
00169             *dest_variable = btp;
00170             return &btp->get_attr_table();
00171         }
00172         else { // must be a plain Array
00173             string::size_type i = source->name.find("_dim_");
00174             string ext = source->name.substr(i + 1);
00175             *dest_variable = btp;
00176             return btp->get_attr_table().append_container(ext);
00177         }
00178     }
00179     else {
00180         // ... otherwise assume it's a global attribute.
00181         AttrTable *at = get_attr_table().find_container(source->name);
00182         if (!at) {
00183             at = new AttrTable();       // Make a new global table if needed
00184             get_attr_table().append_container(at, source->name);
00185         }
00186 
00187         *dest_variable = 0;
00188         return at;
00189     }
00190 }
00191 #endif
00192 #if 0
00193 
00210 void
00211 Constructor::transfer_attributes(AttrTable::entry * entry)
00212 {
00213     DBG(cerr << "Constructor::transfer_attributes, variable: " << name() <<
00214         endl);
00215     DBG(cerr << "Working on the '" << entry->
00216         name << "' container." << endl);
00217     if (entry->type != Attr_container)
00218         throw InternalErr(__FILE__, __LINE__,
00219                           "Constructor::transfer_attributes");
00220 
00221     AttrTable *source = entry->attributes;
00222     BaseType *dest_variable = 0;
00223     AttrTable *dest = find_matching_container(entry, &dest_variable);
00224 
00225     // foreach source attribute in the das_i container
00226     AttrTable::Attr_iter source_p = source->attr_begin();
00227     while (source_p != source->attr_end()) {
00228         DBG(cerr << "Working on the '" << (*source_p)->
00229             name << "' attribute" << endl);
00230 
00231         if ((*source_p)->type == Attr_container) {
00232             if (dest_variable && dest_variable->is_constructor_type()) {
00233                 dynamic_cast <Constructor & >(*dest_variable).transfer_attributes(*source_p);
00234             }
00235             else {
00236                 dest->append_container(new AttrTable(*(*source_p)->attributes),
00237                                        (*source_p)->name);
00238             }
00239         }
00240         else {
00241             dest->append_attr(source->get_name(source_p),
00242                               source->get_type(source_p),
00243                               source->get_attr_vector(source_p));
00244         }
00245 
00246         ++source_p;
00247     }
00248 }
00249 #endif
00250 
00260 void Constructor::transfer_attributes(AttrTable *at_container)
00261 {
00262     AttrTable *at = at_container->get_attr_table(name());
00263 
00264     if (at) {
00265         at->set_is_global_attribute(false);
00266 
00267         Vars_iter var = var_begin();
00268         while (var != var_end()) {
00269             (*var)->transfer_attributes(at);
00270             var++;
00271         }
00272 
00273         // Trick: If an attribute that's within the container 'at' still has its
00274         // is_global_attribute property set, then it's not really a global attr
00275         // but instead an attribute that belongs to this Constructor.
00276         AttrTable::Attr_iter at_p = at->attr_begin();
00277         while (at_p != at->attr_end()) {
00278             if (at->is_global_attribute(at_p)) {
00279                 if (at->get_attr_type(at_p) == Attr_container)
00280                     get_attr_table().append_container(new AttrTable(
00281                             *at->get_attr_table(at_p)), at->get_name(at_p));
00282                 else
00283                     get_attr_table().append_attr(at->get_name(at_p),
00284                             at->get_type(at_p), at->get_attr_vector(at_p));
00285             }
00286             at_p++;
00287         }
00288 
00289     }
00290 }
00291 
00294 Constructor::Vars_iter
00295 Constructor::var_end()
00296 {
00297     return _vars.end() ;
00298 }
00299 
00301 Constructor::Vars_riter
00302 Constructor::var_rbegin()
00303 {
00304     return _vars.rbegin();
00305 }
00306 
00309 Constructor::Vars_riter
00310 Constructor::var_rend()
00311 {
00312     return _vars.rend();
00313 }
00314 
00318 Constructor::Vars_iter
00319 Constructor::get_vars_iter(int i)
00320 {
00321     return _vars.begin() + i;
00322 }
00323 
00327 BaseType *
00328 Constructor::get_var_index(int i)
00329 {
00330     return *(_vars.begin() + i);
00331 }
00332 
00333 #if FILE_METHODS
00334 void
00335 Constructor::print_decl(FILE *out, string space, bool print_semi,
00336                         bool constraint_info, bool constrained)
00337 {
00338     if (constrained && !send_p())
00339         return;
00340 
00341     fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ;
00342     for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
00343         (*i)->print_decl(out, space + "    ", true,
00344                          constraint_info, constrained);
00345     }
00346     fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
00347 
00348     if (constraint_info) { // Used by test drivers only.
00349         if (send_p())
00350             cout << ": Send True";
00351         else
00352             cout << ": Send False";
00353     }
00354 
00355     if (print_semi)
00356         fprintf(out, ";\n") ;
00357 }
00358 #endif
00359 
00360 void
00361 Constructor::print_decl(ostream &out, string space, bool print_semi,
00362                         bool constraint_info, bool constrained)
00363 {
00364     if (constrained && !send_p())
00365         return;
00366 
00367     out << space << type_name() << " {\n" ;
00368     for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
00369         (*i)->print_decl(out, space + "    ", true,
00370                          constraint_info, constrained);
00371     }
00372     out << space << "} " << id2www(name()) ;
00373 
00374     if (constraint_info) { // Used by test drivers only.
00375         if (send_p())
00376             out << ": Send True";
00377         else
00378             out << ": Send False";
00379     }
00380 
00381     if (print_semi)
00382         out << ";\n" ;
00383 }
00384 
00385 #if FILE_METHODS
00386 class PrintField : public unary_function<BaseType *, void>
00387 {
00388     FILE *d_out;
00389     string d_space;
00390     bool d_constrained;
00391 public:
00392     PrintField(FILE *o, string s, bool c)
00393             : d_out(o), d_space(s), d_constrained(c)
00394     {}
00395 
00396     void operator()(BaseType *btp)
00397     {
00398         btp->print_xml(d_out, d_space, d_constrained);
00399     }
00400 };
00401 
00402 void
00403 Constructor::print_xml(FILE *out, string space, bool constrained)
00404 {
00405     if (constrained && !send_p())
00406         return;
00407 
00408     bool has_attributes = false; // *** fix me
00409     bool has_variables = (var_begin() != var_end());
00410 
00411     fprintf(out, "%s<%s", space.c_str(), type_name().c_str());
00412     if (!name().empty())
00413         fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00414 
00415     if (has_attributes || has_variables) {
00416         fprintf(out, ">\n");
00417 
00418         get_attr_table().print_xml(out, space + "    ", constrained);
00419 
00420         for_each(var_begin(), var_end(),
00421                  PrintField(out, space + "    ", constrained));
00422 
00423         fprintf(out, "%s</%s>\n", space.c_str(), type_name().c_str());
00424     }
00425     else {
00426         fprintf(out, "/>\n");
00427     }
00428 }
00429 #endif
00430 
00431 class PrintFieldStrm : public unary_function<BaseType *, void>
00432 {
00433     ostream &d_out;
00434     string d_space;
00435     bool d_constrained;
00436 public:
00437     PrintFieldStrm(ostream &o, string s, bool c)
00438             : d_out(o), d_space(s), d_constrained(c)
00439     {}
00440 
00441     void operator()(BaseType *btp)
00442     {
00443         btp->print_xml(d_out, d_space, d_constrained);
00444     }
00445 };
00446 
00447 void
00448 Constructor::print_xml(ostream &out, string space, bool constrained)
00449 {
00450     if (constrained && !send_p())
00451         return;
00452 
00453     bool has_attributes = false; // *** fix me
00454     bool has_variables = (var_begin() != var_end());
00455 
00456     out << space << "<" << type_name() ;
00457     if (!name().empty())
00458         out << " name=\"" << id2xml(name()) << "\"" ;
00459 
00460     if (has_attributes || has_variables) {
00461         out << ">\n" ;
00462 
00463         get_attr_table().print_xml(out, space + "    ", constrained);
00464 
00465         for_each(var_begin(), var_end(),
00466                  PrintFieldStrm(out, space + "    ", constrained));
00467 
00468         out << space << "</" << type_name() << ">\n" ;
00469     }
00470     else {
00471         out << "/>\n" ;
00472     }
00473 }
00474 
00487 bool
00488 Constructor::is_linear()
00489 {
00490     return false;
00491 }
00492 
00501 void
00502 Constructor::dump(ostream &strm) const
00503 {
00504     strm << DapIndent::LMarg << "Constructor::dump - ("
00505     << (void *)this << ")" << endl ;
00506     DapIndent::Indent() ;
00507     BaseType::dump(strm) ;
00508     strm << DapIndent::LMarg << "vars: " << endl ;
00509     DapIndent::Indent() ;
00510     Vars_citer i = _vars.begin() ;
00511     Vars_citer ie = _vars.end() ;
00512     for (; i != ie; i++) {
00513         (*i)->dump(strm) ;
00514     }
00515     DapIndent::UnIndent() ;
00516     DapIndent::UnIndent() ;
00517 }
00518 
00519 } // namespace libdap
00520