libdap++ Updated for version 3.8.2
|
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 00145 AttrTable * 00146 Constructor::find_matching_container(AttrTable::entry *source, 00147 BaseType **dest_variable) 00148 { 00149 // The attribute entry 'source' must be a container 00150 if (source->type != Attr_container) 00151 throw InternalErr(__FILE__, __LINE__, "Constructor::find_matching_container"); 00152 00153 // Use the name of the attribute container 'source' to figure out where 00154 // to put its contents. 00155 BaseType *btp; 00156 if ((btp = var(source->name))) { 00157 // ... matches a variable name? Use var's table 00158 *dest_variable = btp; 00159 return &btp->get_attr_table(); 00160 } 00161 // As more special-case attribute containers come to light, add clauses 00162 // here. 00163 else if ((btp = find_hdf4_dimension_attribute_home(source))) { 00164 // ... hdf4 dimension attribute? Make a sub table and use that. 00165 // btp can only be an Array or a Grid Map (which is an array) 00166 if (btp->get_parent()->type() == dods_grid_c) { 00167 DBG(cerr << "Found a Grid" << endl); 00168 *dest_variable = btp; 00169 return &btp->get_attr_table(); 00170 } 00171 else { // must be a plain Array 00172 string::size_type i = source->name.find("_dim_"); 00173 string ext = source->name.substr(i + 1); 00174 *dest_variable = btp; 00175 return btp->get_attr_table().append_container(ext); 00176 } 00177 } 00178 else { 00179 // ... otherwise assume it's a global attribute. 00180 AttrTable *at = get_attr_table().find_container(source->name); 00181 if (!at) { 00182 at = new AttrTable(); // Make a new global table if needed 00183 get_attr_table().append_container(at, source->name); 00184 } 00185 00186 *dest_variable = 0; 00187 return at; 00188 } 00189 } 00190 00208 void 00209 Constructor::transfer_attributes(AttrTable::entry * entry) 00210 { 00211 DBG(cerr << "Constructor::transfer_attributes, variable: " << name() << 00212 endl); 00213 DBG(cerr << "Working on the '" << entry-> 00214 name << "' container." << endl); 00215 if (entry->type != Attr_container) 00216 throw InternalErr(__FILE__, __LINE__, 00217 "Constructor::transfer_attributes"); 00218 00219 AttrTable *source = entry->attributes; 00220 BaseType *dest_variable = 0; 00221 AttrTable *dest = find_matching_container(entry, &dest_variable); 00222 00223 // foreach source attribute in the das_i container 00224 AttrTable::Attr_iter source_p = source->attr_begin(); 00225 while (source_p != source->attr_end()) { 00226 DBG(cerr << "Working on the '" << (*source_p)-> 00227 name << "' attribute" << endl); 00228 00229 if ((*source_p)->type == Attr_container) { 00230 if (dest_variable && dest_variable->is_constructor_type()) { 00231 dynamic_cast <Constructor & >(*dest_variable).transfer_attributes(*source_p); 00232 } 00233 else { 00234 dest->append_container(new AttrTable(*(*source_p)->attributes), 00235 (*source_p)->name); 00236 } 00237 } 00238 else { 00239 dest->append_attr(source->get_name(source_p), 00240 source->get_type(source_p), 00241 source->get_attr_vector(source_p)); 00242 } 00243 00244 ++source_p; 00245 } 00246 } 00247 00250 Constructor::Vars_iter 00251 Constructor::var_end() 00252 { 00253 return _vars.end() ; 00254 } 00255 00257 Constructor::Vars_riter 00258 Constructor::var_rbegin() 00259 { 00260 return _vars.rbegin(); 00261 } 00262 00265 Constructor::Vars_riter 00266 Constructor::var_rend() 00267 { 00268 return _vars.rend(); 00269 } 00270 00274 Constructor::Vars_iter 00275 Constructor::get_vars_iter(int i) 00276 { 00277 return _vars.begin() + i; 00278 } 00279 00283 BaseType * 00284 Constructor::get_var_index(int i) 00285 { 00286 return *(_vars.begin() + i); 00287 } 00288 00289 //#if FILE_METHODS 00290 void 00291 Constructor::print_decl(FILE *out, string space, bool print_semi, 00292 bool constraint_info, bool constrained) 00293 { 00294 if (constrained && !send_p()) 00295 return; 00296 00297 fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ; 00298 for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) { 00299 (*i)->print_decl(out, space + " ", true, 00300 constraint_info, constrained); 00301 } 00302 fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ; 00303 00304 if (constraint_info) { // Used by test drivers only. 00305 if (send_p()) 00306 cout << ": Send True"; 00307 else 00308 cout << ": Send False"; 00309 } 00310 00311 if (print_semi) 00312 fprintf(out, ";\n") ; 00313 } 00314 //#endif 00315 void 00316 Constructor::print_decl(ostream &out, string space, bool print_semi, 00317 bool constraint_info, bool constrained) 00318 { 00319 if (constrained && !send_p()) 00320 return; 00321 00322 out << space << type_name() << " {\n" ; 00323 for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) { 00324 (*i)->print_decl(out, space + " ", true, 00325 constraint_info, constrained); 00326 } 00327 out << space << "} " << id2www(name()) ; 00328 00329 if (constraint_info) { // Used by test drivers only. 00330 if (send_p()) 00331 out << ": Send True"; 00332 else 00333 out << ": Send False"; 00334 } 00335 00336 if (print_semi) 00337 out << ";\n" ; 00338 } 00339 //#if FILE_METHODS 00340 class PrintField : public unary_function<BaseType *, void> 00341 { 00342 FILE *d_out; 00343 string d_space; 00344 bool d_constrained; 00345 public: 00346 PrintField(FILE *o, string s, bool c) 00347 : d_out(o), d_space(s), d_constrained(c) 00348 {} 00349 00350 void operator()(BaseType *btp) 00351 { 00352 btp->print_xml(d_out, d_space, d_constrained); 00353 } 00354 }; 00355 00356 void 00357 Constructor::print_xml(FILE *out, string space, bool constrained) 00358 { 00359 if (constrained && !send_p()) 00360 return; 00361 00362 bool has_attributes = false; // *** fix me 00363 bool has_variables = (var_begin() != var_end()); 00364 00365 fprintf(out, "%s<%s", space.c_str(), type_name().c_str()); 00366 if (!name().empty()) 00367 fprintf(out, " name=\"%s\"", id2xml(name()).c_str()); 00368 00369 if (has_attributes || has_variables) { 00370 fprintf(out, ">\n"); 00371 00372 get_attr_table().print_xml(out, space + " ", constrained); 00373 00374 for_each(var_begin(), var_end(), 00375 PrintField(out, space + " ", constrained)); 00376 00377 fprintf(out, "%s</%s>\n", space.c_str(), type_name().c_str()); 00378 } 00379 else { 00380 fprintf(out, "/>\n"); 00381 } 00382 } 00383 //#endif 00384 class PrintFieldStrm : public unary_function<BaseType *, void> 00385 { 00386 ostream &d_out; 00387 string d_space; 00388 bool d_constrained; 00389 public: 00390 PrintFieldStrm(ostream &o, string s, bool c) 00391 : d_out(o), d_space(s), d_constrained(c) 00392 {} 00393 00394 void operator()(BaseType *btp) 00395 { 00396 btp->print_xml(d_out, d_space, d_constrained); 00397 } 00398 }; 00399 00400 void 00401 Constructor::print_xml(ostream &out, string space, bool constrained) 00402 { 00403 if (constrained && !send_p()) 00404 return; 00405 00406 bool has_attributes = false; // *** fix me 00407 bool has_variables = (var_begin() != var_end()); 00408 00409 out << space << "<" << type_name() ; 00410 if (!name().empty()) 00411 out << " name=\"" << id2xml(name()) << "\"" ; 00412 00413 if (has_attributes || has_variables) { 00414 out << ">\n" ; 00415 00416 get_attr_table().print_xml(out, space + " ", constrained); 00417 00418 for_each(var_begin(), var_end(), 00419 PrintFieldStrm(out, space + " ", constrained)); 00420 00421 out << space << "</" << type_name() << ">\n" ; 00422 } 00423 else { 00424 out << "/>\n" ; 00425 } 00426 } 00427 00440 bool 00441 Constructor::is_linear() 00442 { 00443 return false; 00444 } 00445 00454 void 00455 Constructor::dump(ostream &strm) const 00456 { 00457 strm << DapIndent::LMarg << "Constructor::dump - (" 00458 << (void *)this << ")" << endl ; 00459 DapIndent::Indent() ; 00460 BaseType::dump(strm) ; 00461 strm << DapIndent::LMarg << "vars: " << endl ; 00462 DapIndent::Indent() ; 00463 Vars_citer i = _vars.begin() ; 00464 Vars_citer ie = _vars.end() ; 00465 for (; i != ie; i++) { 00466 (*i)->dump(strm) ; 00467 } 00468 DapIndent::UnIndent() ; 00469 DapIndent::UnIndent() ; 00470 } 00471 00472 } // namespace libdap 00473