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 // Private member functions
00053 
00054 void
00055 Constructor::_duplicate(const Constructor &)
00056 {}
00057 
00058 // Public member functions
00059 
00060 Constructor::Constructor(const string &n, const Type &t)
00061         : BaseType(n, t)
00062 {}
00063 
00064 Constructor::Constructor(const Constructor &rhs) : BaseType(rhs)
00065 {}
00066 
00067 Constructor::~Constructor()
00068 {}
00069 
00070 Constructor &
00071 Constructor::operator=(const Constructor &rhs)
00072 {
00073     if (this == &rhs)
00074         return *this;
00075 
00076     dynamic_cast<BaseType &>(*this) = rhs; // run BaseType=
00077 
00078     _duplicate(rhs);
00079 
00080     return *this;
00081 }
00082 
00084 Constructor::Vars_iter
00085 Constructor::var_begin()
00086 {
00087     return _vars.begin() ;
00088 }
00089 
00105 BaseType *
00106 Constructor::find_hdf4_dimension_attribute_home(AttrTable::entry *source)
00107 {
00108     BaseType *btp;
00109     string::size_type i = source->name.find("_dim_");
00110     if (i != string::npos && (btp = var(source->name.substr(0, i)))) {
00111         if (btp->is_vector_type()) {
00112             return btp;
00113         }
00114         else if (btp->type() == dods_grid_c) {
00115             // For a Grid, the hdf4 handler uses _dim_n for the n-th Map
00116             // i+5 points to the character holding 'n'
00117             int n = atoi(source->name.substr(i + 5).c_str());
00118             DBG(cerr << "Found a Grid (" << btp->name() << ") and "
00119                 << source->name.substr(i) << ", extracted n: " << n << endl);
00120             return *(dynamic_cast<Grid&>(*btp).map_begin() + n);
00121         }
00122     }
00123 
00124     return 0;
00125 }
00126 
00129 AttrTable *
00130 Constructor::find_matching_container(AttrTable::entry *source,
00131                                      BaseType **dest_variable)
00132 {
00133     // The attribute entry 'source' must be a container
00134     if (source->type != Attr_container)
00135         throw InternalErr(__FILE__, __LINE__, "Constructor::find_matching_container");
00136 
00137     // Use the name of the attribute container 'source' to figure out where
00138     // to put its contents.
00139     BaseType *btp;
00140     if ((btp = var(source->name))) {
00141         // ... matches a variable name? Use var's table
00142         *dest_variable = btp;
00143         return &btp->get_attr_table();
00144     }
00145     // As more special-case attribute containers come to light, add clauses
00146     // here.
00147     else if ((btp = find_hdf4_dimension_attribute_home(source))) {
00148         // ... hdf4 dimension attribute? Make a sub table and use that.
00149         // btp can only be an Array or a Grid Map (which is an array)
00150         if (btp->get_parent()->type() == dods_grid_c) {
00151             DBG(cerr << "Found a Grid" << endl);
00152             *dest_variable = btp;
00153             return &btp->get_attr_table();
00154         }
00155         else { // must be a plain Array
00156             string::size_type i = source->name.find("_dim_");
00157             string ext = source->name.substr(i + 1);
00158             *dest_variable = btp;
00159             return btp->get_attr_table().append_container(ext);
00160         }
00161     }
00162     else {
00163         // ... otherwise assume it's a global attribute.
00164         AttrTable *at = get_attr_table().find_container(source->name);
00165         if (!at) {
00166             at = new AttrTable();       // Make a new global table if needed
00167             get_attr_table().append_container(at, source->name);
00168         }
00169 
00170         *dest_variable = 0;
00171         return at;
00172     }
00173 }
00174 
00192 void
00193 Constructor::transfer_attributes(AttrTable::entry * entry)
00194 {
00195     DBG(cerr << "Constructor::transfer_attributes, variable: " << name() <<
00196         endl);
00197     DBG(cerr << "Working on the '" << entry->
00198         name << "' container." << endl);
00199     if (entry->type != Attr_container)
00200         throw InternalErr(__FILE__, __LINE__,
00201                           "Constructor::transfer_attributes");
00202 
00203     AttrTable *source = entry->attributes;
00204     BaseType *dest_variable = 0;
00205     AttrTable *dest = find_matching_container(entry, &dest_variable);
00206 
00207     // foreach source attribute in the das_i container
00208     AttrTable::Attr_iter source_p = source->attr_begin();
00209     while (source_p != source->attr_end()) {
00210         DBG(cerr << "Working on the '" << (*source_p)->
00211             name << "' attribute" << endl);
00212 
00213         if ((*source_p)->type == Attr_container) {
00214             if (dest_variable && dest_variable->is_constructor_type()) {
00215                 dynamic_cast <Constructor & >(*dest_variable).transfer_attributes(*source_p);
00216             }
00217             else {
00218                 dest->append_container(new AttrTable(*(*source_p)->attributes),
00219                                        (*source_p)->name);
00220             }
00221         }
00222         else {
00223             dest->append_attr(source->get_name(source_p),
00224                               source->get_type(source_p),
00225                               source->get_attr_vector(source_p));
00226         }
00227 
00228         ++source_p;
00229     }
00230 }
00231 
00234 Constructor::Vars_iter
00235 Constructor::var_end()
00236 {
00237     return _vars.end() ;
00238 }
00239 
00241 Constructor::Vars_riter
00242 Constructor::var_rbegin()
00243 {
00244     return _vars.rbegin();
00245 }
00246 
00249 Constructor::Vars_riter
00250 Constructor::var_rend()
00251 {
00252     return _vars.rend();
00253 }
00254 
00258 Constructor::Vars_iter
00259 Constructor::get_vars_iter(int i)
00260 {
00261     return _vars.begin() + i;
00262 }
00263 
00267 BaseType *
00268 Constructor::get_var_index(int i)
00269 {
00270     return *(_vars.begin() + i);
00271 }
00272 
00273 
00274 void
00275 Constructor::print_decl(FILE *out, string space, bool print_semi,
00276                         bool constraint_info, bool constrained)
00277 {
00278     if (constrained && !send_p())
00279         return;
00280 
00281     fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ;
00282     for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
00283         (*i)->print_decl(out, space + "    ", true,
00284                          constraint_info, constrained);
00285     }
00286     fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
00287 
00288     if (constraint_info) { // Used by test drivers only.
00289         if (send_p())
00290             cout << ": Send True";
00291         else
00292             cout << ": Send False";
00293     }
00294 
00295     if (print_semi)
00296         fprintf(out, ";\n") ;
00297 }
00298 
00299 void
00300 Constructor::print_decl(ostream &out, string space, bool print_semi,
00301                         bool constraint_info, bool constrained)
00302 {
00303     if (constrained && !send_p())
00304         return;
00305 
00306     out << space << type_name() << " {\n" ;
00307     for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
00308         (*i)->print_decl(out, space + "    ", true,
00309                          constraint_info, constrained);
00310     }
00311     out << space << "} " << id2www(name()) ;
00312 
00313     if (constraint_info) { // Used by test drivers only.
00314         if (send_p())
00315             out << ": Send True";
00316         else
00317             out << ": Send False";
00318     }
00319 
00320     if (print_semi)
00321         out << ";\n" ;
00322 }
00323 
00324 class PrintField : public unary_function<BaseType *, void>
00325 {
00326     FILE *d_out;
00327     string d_space;
00328     bool d_constrained;
00329 public:
00330     PrintField(FILE *o, string s, bool c)
00331             : d_out(o), d_space(s), d_constrained(c)
00332     {}
00333 
00334     void operator()(BaseType *btp)
00335     {
00336         btp->print_xml(d_out, d_space, d_constrained);
00337     }
00338 };
00339 
00340 void
00341 Constructor::print_xml(FILE *out, string space, bool constrained)
00342 {
00343     if (constrained && !send_p())
00344         return;
00345 
00346     bool has_attributes = false; // *** fix me
00347     bool has_variables = (var_begin() != var_end());
00348 
00349     fprintf(out, "%s<%s", space.c_str(), type_name().c_str());
00350     if (!name().empty())
00351         fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00352 
00353     if (has_attributes || has_variables) {
00354         fprintf(out, ">\n");
00355 
00356         get_attr_table().print_xml(out, space + "    ", constrained);
00357 
00358         for_each(var_begin(), var_end(),
00359                  PrintField(out, space + "    ", constrained));
00360 
00361         fprintf(out, "%s</%s>\n", space.c_str(), type_name().c_str());
00362     }
00363     else {
00364         fprintf(out, "/>\n");
00365     }
00366 }
00367 
00368 class PrintFieldStrm : public unary_function<BaseType *, void>
00369 {
00370     ostream &d_out;
00371     string d_space;
00372     bool d_constrained;
00373 public:
00374     PrintFieldStrm(ostream &o, string s, bool c)
00375             : d_out(o), d_space(s), d_constrained(c)
00376     {}
00377 
00378     void operator()(BaseType *btp)
00379     {
00380         btp->print_xml(d_out, d_space, d_constrained);
00381     }
00382 };
00383 
00384 void
00385 Constructor::print_xml(ostream &out, string space, bool constrained)
00386 {
00387     if (constrained && !send_p())
00388         return;
00389 
00390     bool has_attributes = false; // *** fix me
00391     bool has_variables = (var_begin() != var_end());
00392 
00393     out << space << "<" << type_name() ;
00394     if (!name().empty())
00395         out << " name=\"" << id2xml(name()) << "\"" ;
00396 
00397     if (has_attributes || has_variables) {
00398         out << ">\n" ;
00399 
00400         get_attr_table().print_xml(out, space + "    ", constrained);
00401 
00402         for_each(var_begin(), var_end(),
00403                  PrintFieldStrm(out, space + "    ", constrained));
00404 
00405         out << space << "</" << type_name() << ">\n" ;
00406     }
00407     else {
00408         out << "/>\n" ;
00409     }
00410 }
00411 
00424 bool
00425 Constructor::is_linear()
00426 {
00427     return false;
00428 }
00429 
00438 void
00439 Constructor::dump(ostream &strm) const
00440 {
00441     strm << DapIndent::LMarg << "Constructor::dump - ("
00442     << (void *)this << ")" << endl ;
00443     DapIndent::Indent() ;
00444     BaseType::dump(strm) ;
00445     strm << DapIndent::LMarg << "vars: " << endl ;
00446     DapIndent::Indent() ;
00447     Vars_citer i = _vars.begin() ;
00448     Vars_citer ie = _vars.end() ;
00449     for (; i != ie; i++) {
00450         (*i)->dump(strm) ;
00451     }
00452     DapIndent::UnIndent() ;
00453     DapIndent::UnIndent() ;
00454 }
00455 

Generated on Wed Jan 2 04:11:02 2008 for libdap++ by  doxygen 1.5.4