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

Generated on Wed Mar 5 15:27:10 2008 for libdap++ by  doxygen 1.5.4