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), _vars(0)
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 
00106 #if 0
00107 
00125 BaseType *
00126 Constructor::find_hdf4_dimension_attribute_home(AttrTable::entry *source)
00127 {
00128     BaseType *btp;
00129     string::size_type i = source->name.find("_dim_");
00130     if (i != string::npos && (btp = var(source->name.substr(0, i)))) {
00131         if (btp->is_vector_type()) {
00132             return btp;
00133         }
00134         else if (btp->type() == dods_grid_c) {
00135             // For a Grid, the hdf4 handler uses _dim_n for the n-th Map
00136             // i+5 points to the character holding 'n'
00137             int n = atoi(source->name.substr(i + 5).c_str());
00138             DBG(cerr << "Found a Grid (" << btp->name() << ") and "
00139                 << source->name.substr(i) << ", extracted n: " << n << endl);
00140             return *(dynamic_cast<Grid&>(*btp).map_begin() + n);
00141         }
00142     }
00143 
00144     return 0;
00145 }
00146 #endif
00147 #if 0
00148 
00150 AttrTable *
00151 Constructor::find_matching_container(AttrTable::entry *source,
00152                                      BaseType **dest_variable)
00153 {
00154     // The attribute entry 'source' must be a container
00155     if (source->type != Attr_container)
00156         throw InternalErr(__FILE__, __LINE__, "Constructor::find_matching_container");
00157 
00158     // Use the name of the attribute container 'source' to figure out where
00159     // to put its contents.
00160     BaseType *btp;
00161     if ((btp = var(source->name))) {
00162         // ... matches a variable name? Use var's table
00163         *dest_variable = btp;
00164         return &btp->get_attr_table();
00165     }
00166     // As more special-case attribute containers come to light, add clauses
00167     // here.
00168     else if ((btp = find_hdf4_dimension_attribute_home(source))) {
00169         // ... hdf4 dimension attribute? Make a sub table and use that.
00170         // btp can only be an Array or a Grid Map (which is an array)
00171         if (btp->get_parent()->type() == dods_grid_c) {
00172             DBG(cerr << "Found a Grid" << endl);
00173             *dest_variable = btp;
00174             return &btp->get_attr_table();
00175         }
00176         else { // must be a plain Array
00177             string::size_type i = source->name.find("_dim_");
00178             string ext = source->name.substr(i + 1);
00179             *dest_variable = btp;
00180             return btp->get_attr_table().append_container(ext);
00181         }
00182     }
00183     else {
00184         // ... otherwise assume it's a global attribute.
00185         AttrTable *at = get_attr_table().find_container(source->name);
00186         if (!at) {
00187             at = new AttrTable();       // Make a new global table if needed
00188             get_attr_table().append_container(at, source->name);
00189         }
00190 
00191         *dest_variable = 0;
00192         return at;
00193     }
00194 }
00195 #endif
00196 #if 0
00197 
00214 void
00215 Constructor::transfer_attributes(AttrTable::entry * entry)
00216 {
00217     DBG(cerr << "Constructor::transfer_attributes, variable: " << name() <<
00218         endl);
00219     DBG(cerr << "Working on the '" << entry->
00220         name << "' container." << endl);
00221     if (entry->type != Attr_container)
00222         throw InternalErr(__FILE__, __LINE__,
00223                           "Constructor::transfer_attributes");
00224 
00225     AttrTable *source = entry->attributes;
00226     BaseType *dest_variable = 0;
00227     AttrTable *dest = find_matching_container(entry, &dest_variable);
00228 
00229     // foreach source attribute in the das_i container
00230     AttrTable::Attr_iter source_p = source->attr_begin();
00231     while (source_p != source->attr_end()) {
00232         DBG(cerr << "Working on the '" << (*source_p)->
00233             name << "' attribute" << endl);
00234 
00235         if ((*source_p)->type == Attr_container) {
00236             if (dest_variable && dest_variable->is_constructor_type()) {
00237                 dynamic_cast <Constructor & >(*dest_variable).transfer_attributes(*source_p);
00238             }
00239             else {
00240                 dest->append_container(new AttrTable(*(*source_p)->attributes),
00241                                        (*source_p)->name);
00242             }
00243         }
00244         else {
00245             dest->append_attr(source->get_name(source_p),
00246                               source->get_type(source_p),
00247                               source->get_attr_vector(source_p));
00248         }
00249 
00250         ++source_p;
00251     }
00252 }
00253 #endif
00254 
00264 void Constructor::transfer_attributes(AttrTable *at_container) {
00265         AttrTable *at = at_container->get_attr_table(name());
00266 
00267         if (at) {
00268                 at->set_is_global_attribute(false);
00269 
00270                 Vars_iter var = var_begin();
00271                 while (var != var_end()) {
00272                         try {
00273                                 DBG(cerr << "Processing the attributes for: " << (*var)->name() << " a " << (*var)->type_name() << endl);
00274                                 (*var)->transfer_attributes(at);
00275                                 var++;
00276                         } catch (Error &e) {
00277                                 DBG(cerr << "Got this exception: " << e.get_error_message() << endl);
00278                                 var++;
00279                                 throw e;
00280                         }
00281                 }
00282 
00283                 // Trick: If an attribute that's within the container 'at' still has its
00284                 // is_global_attribute property set, then it's not really a global attr
00285                 // but instead an attribute that belongs to this Constructor.
00286                 AttrTable::Attr_iter at_p = at->attr_begin();
00287                 while (at_p != at->attr_end()) {
00288                         if (at->is_global_attribute(at_p)) {
00289                                 if (at->get_attr_type(at_p) == Attr_container)
00290                                         get_attr_table().append_container(new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p));
00291                                 else
00292                                         get_attr_table().append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p));
00293                         }
00294                         at_p++;
00295                 }
00296 
00297         }
00298 }
00299 
00302 Constructor::Vars_iter
00303 Constructor::var_end()
00304 {
00305     return _vars.end() ;
00306 }
00307 
00309 Constructor::Vars_riter
00310 Constructor::var_rbegin()
00311 {
00312     return _vars.rbegin();
00313 }
00314 
00317 Constructor::Vars_riter
00318 Constructor::var_rend()
00319 {
00320     return _vars.rend();
00321 }
00322 
00326 Constructor::Vars_iter
00327 Constructor::get_vars_iter(int i)
00328 {
00329     return _vars.begin() + i;
00330 }
00331 
00335 BaseType *
00336 Constructor::get_var_index(int i)
00337 {
00338     return *(_vars.begin() + i);
00339 }
00340 
00341 #if FILE_METHODS
00342 void
00343 Constructor::print_decl(FILE *out, string space, bool print_semi,
00344                         bool constraint_info, bool constrained)
00345 {
00346     if (constrained && !send_p())
00347         return;
00348 
00349     fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ;
00350     for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
00351         (*i)->print_decl(out, space + "    ", true,
00352                          constraint_info, constrained);
00353     }
00354     fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
00355 
00356     if (constraint_info) { // Used by test drivers only.
00357         if (send_p())
00358             cout << ": Send True";
00359         else
00360             cout << ": Send False";
00361     }
00362 
00363     if (print_semi)
00364         fprintf(out, ";\n") ;
00365 }
00366 #endif
00367 
00368 void
00369 Constructor::print_decl(ostream &out, string space, bool print_semi,
00370                         bool constraint_info, bool constrained)
00371 {
00372     if (constrained && !send_p())
00373         return;
00374 
00375     out << space << type_name() << " {\n" ;
00376     for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
00377         (*i)->print_decl(out, space + "    ", true,
00378                          constraint_info, constrained);
00379     }
00380     out << space << "} " << id2www(name()) ;
00381 
00382     if (constraint_info) { // Used by test drivers only.
00383         if (send_p())
00384             out << ": Send True";
00385         else
00386             out << ": Send False";
00387     }
00388 
00389     if (print_semi)
00390         out << ";\n" ;
00391 }
00392 
00393 #if FILE_METHODS
00394 class PrintField : public unary_function<BaseType *, void>
00395 {
00396     FILE *d_out;
00397     string d_space;
00398     bool d_constrained;
00399 public:
00400     PrintField(FILE *o, string s, bool c)
00401             : d_out(o), d_space(s), d_constrained(c)
00402     {}
00403 
00404     void operator()(BaseType *btp)
00405     {
00406         btp->print_xml(d_out, d_space, d_constrained);
00407     }
00408 };
00409 
00413 void
00414 Constructor::print_xml(FILE *out, string space, bool constrained)
00415 {
00416     if (constrained && !send_p())
00417         return;
00418 
00419     bool has_attributes = false; // *** fix me
00420     bool has_variables = (var_begin() != var_end());
00421 
00422     fprintf(out, "%s<%s", space.c_str(), type_name().c_str());
00423     if (!name().empty())
00424         fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00425 
00426     if (has_attributes || has_variables) {
00427         fprintf(out, ">\n");
00428 
00429         get_attr_table().print_xml(out, space + "    ", constrained);
00430 
00431         for_each(var_begin(), var_end(),
00432                  PrintField(out, space + "    ", constrained));
00433 
00434         fprintf(out, "%s</%s>\n", space.c_str(), type_name().c_str());
00435     }
00436     else {
00437         fprintf(out, "/>\n");
00438     }
00439 }
00440 #endif
00441 
00442 class PrintFieldStrm : public unary_function<BaseType *, void>
00443 {
00444     ostream &d_out;
00445     string d_space;
00446     bool d_constrained;
00447 public:
00448     PrintFieldStrm(ostream &o, string s, bool c)
00449             : d_out(o), d_space(s), d_constrained(c)
00450     {}
00451 
00452     void operator()(BaseType *btp)
00453     {
00454         btp->print_xml(d_out, d_space, d_constrained);
00455     }
00456 };
00457 
00461 void
00462 Constructor::print_xml(ostream &out, string space, bool constrained)
00463 {
00464     if (constrained && !send_p())
00465         return;
00466 
00467     bool has_attributes = false; // *** fix me
00468     bool has_variables = (var_begin() != var_end());
00469 
00470     out << space << "<" << type_name() ;
00471     if (!name().empty())
00472     out << " name=\"" << id2xml(name()) << "\"" ;
00473 
00474     if (has_attributes || has_variables) {
00475     out << ">\n" ;
00476 
00477         get_attr_table().print_xml(out, space + "    ", constrained);
00478 
00479         for_each(var_begin(), var_end(),
00480                  PrintFieldStrm(out, space + "    ", constrained));
00481 
00482     out << space << "</" << type_name() << ">\n" ;
00483     }
00484     else {
00485     out << "/>\n" ;
00486     }
00487 }
00488 
00489 class PrintFieldXMLWriter : public unary_function<BaseType *, void>
00490 {
00491     XMLWriter &d_xml;
00492     bool d_constrained;
00493 public:
00494     PrintFieldXMLWriter(XMLWriter &x, bool c)
00495             : d_xml(x), d_constrained(c)
00496     {}
00497 
00498     void operator()(BaseType *btp)
00499     {
00500         btp->print_xml_writer(d_xml, d_constrained);
00501     }
00502 };
00503 
00504 void
00505 Constructor::print_xml_writer(XMLWriter &xml, bool constrained)
00506 {
00507     if (constrained && !send_p())
00508         return;
00509 
00510     if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0)
00511         throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
00512 
00513     if (!name().empty())
00514         if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
00515             throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
00516 
00517     bool has_attributes = false; // FIXME
00518     bool has_variables = (var_begin() != var_end());
00519     if (has_attributes || has_variables) {
00520         get_attr_table().print_xml_writer(xml);
00521 
00522         for_each(var_begin(), var_end(), PrintFieldXMLWriter(xml, constrained));
00523     }
00524 
00525     if (xmlTextWriterEndElement(xml.get_writer()) < 0)
00526         throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
00527 }
00528 
00541 bool
00542 Constructor::is_linear()
00543 {
00544     return false;
00545 }
00546 
00555 void
00556 Constructor::dump(ostream &strm) const
00557 {
00558     strm << DapIndent::LMarg << "Constructor::dump - ("
00559     << (void *)this << ")" << endl ;
00560     DapIndent::Indent() ;
00561     BaseType::dump(strm) ;
00562     strm << DapIndent::LMarg << "vars: " << endl ;
00563     DapIndent::Indent() ;
00564     Vars_citer i = _vars.begin() ;
00565     Vars_citer ie = _vars.end() ;
00566     for (; i != ie; i++) {
00567         (*i)->dump(strm) ;
00568     }
00569     DapIndent::UnIndent() ;
00570     DapIndent::UnIndent() ;
00571 }
00572 
00573 } // namespace libdap
00574