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 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