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), _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