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 1994-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 // implementation for Grid. 00033 // 00034 // jhrg 9/15/94 00035 00036 #include "config.h" 00037 00038 #include <functional> 00039 #include <algorithm> 00040 00041 #include "Grid.h" 00042 #include "DDS.h" 00043 #include "Array.h" // for downcasts 00044 #include "util.h" 00045 #include "InternalErr.h" 00046 #include "escaping.h" 00047 //#include "BTIterAdapter.h" 00048 00049 00050 using namespace std; 00051 00052 namespace libdap { 00053 00054 void 00055 Grid::_duplicate(const Grid &s) 00056 { 00057 _array_var = s._array_var->ptr_duplicate(); 00058 _array_var->set_parent(this); 00059 00060 Grid &cs = const_cast<Grid &>(s); 00061 00062 for (Map_iter i = cs._map_vars.begin(); i != cs._map_vars.end(); i++) { 00063 BaseType *btp = (*i)->ptr_duplicate(); 00064 btp->set_parent(this); 00065 _map_vars.push_back(btp); 00066 } 00067 } 00068 00078 Grid::Grid(const string &n) : Constructor(n, dods_grid_c), _array_var(0) 00079 {} 00080 00092 Grid::Grid(const string &n, const string &d) 00093 : Constructor(n, d, dods_grid_c), _array_var(0) 00094 {} 00095 00097 Grid::Grid(const Grid &rhs) : Constructor(rhs) 00098 { 00099 _duplicate(rhs); 00100 } 00101 00102 Grid::~Grid() 00103 { 00104 delete _array_var; _array_var = 0; 00105 00106 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00107 BaseType *btp = *i ; 00108 delete btp ; btp = 0; 00109 } 00110 } 00111 00112 BaseType * 00113 Grid::ptr_duplicate() 00114 { 00115 return new Grid(*this); 00116 } 00117 00118 Grid & 00119 Grid::operator=(const Grid &rhs) 00120 { 00121 if (this == &rhs) 00122 return *this; 00123 00124 delete _array_var; _array_var = 0; 00125 00126 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00127 BaseType *btp = *i ; 00128 delete btp ; 00129 } 00130 00131 dynamic_cast<Constructor &>(*this) = rhs; 00132 00133 _duplicate(rhs); 00134 00135 return *this; 00136 } 00137 00138 int 00139 Grid::element_count(bool leaves) 00140 { 00141 if (!leaves) 00142 return _map_vars.size() + 1; 00143 else { 00144 int i = 0; 00145 for (Map_iter j = _map_vars.begin(); j != _map_vars.end(); j++) { 00146 j += (*j)->element_count(leaves); 00147 } 00148 00149 if (!get_array()) 00150 throw InternalErr(__FILE__, __LINE__, "No Grid arry!"); 00151 00152 i += get_array()->element_count(leaves); 00153 return i; 00154 } 00155 } 00156 00157 void 00158 Grid::set_send_p(bool state) 00159 { 00160 _array_var->set_send_p(state); 00161 00162 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00163 (*i)->set_send_p(state); 00164 } 00165 00166 BaseType::set_send_p(state); 00167 } 00168 00169 void 00170 Grid::set_read_p(bool state) 00171 { 00172 _array_var->set_read_p(state); 00173 00174 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00175 (*i)->set_read_p(state); 00176 } 00177 00178 BaseType::set_read_p(state); 00179 } 00180 00181 void 00182 Grid::set_in_selection(bool state) 00183 { 00184 _array_var->set_in_selection(state); 00185 00186 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00187 (*i)->set_in_selection(state); 00188 } 00189 00190 BaseType::set_in_selection(state); 00191 } 00192 00193 unsigned int 00194 Grid::width() 00195 { 00196 unsigned int sz = _array_var->width(); 00197 00198 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00199 sz += (*i)->width(); 00200 } 00201 00202 return sz; 00203 } 00204 00205 void 00206 Grid::intern_data(ConstraintEvaluator &eval, DDS &dds) 00207 { 00208 dds.timeout_on(); 00209 00210 if (!read_p()) 00211 read(); // read() throws Error and InternalErr 00212 00213 dds.timeout_off(); 00214 00215 if (_array_var->send_p()) 00216 _array_var->intern_data(eval, dds); 00217 00218 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00219 if ((*i)->send_p()) { 00220 (*i)->intern_data(eval, dds); 00221 } 00222 } 00223 } 00224 00225 bool 00226 Grid::serialize(ConstraintEvaluator &eval, DDS &dds, 00227 Marshaller &m, bool ce_eval) 00228 { 00229 dds.timeout_on(); 00230 00231 // Re ticket 560: Get an object from eval that describes how to sample 00232 // and rearrange the data, then perform those actions. Alternative: 00233 // implement this as a selection function. 00234 00235 if (!read_p()) 00236 read(); // read() throws Error and InternalErr 00237 00238 #if EVAL 00239 if (ce_eval && !eval.eval_selection(dds, dataset())) 00240 return true; 00241 #endif 00242 00243 dds.timeout_off(); 00244 00245 if (_array_var->send_p()) 00246 _array_var->serialize(eval, dds, m, false); 00247 00248 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00249 if ((*i)->send_p()) { 00250 (*i)->serialize(eval, dds, m, false); 00251 } 00252 } 00253 00254 return true; 00255 } 00256 00257 bool 00258 Grid::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00259 { 00260 _array_var->deserialize(um, dds, reuse); 00261 00262 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00263 (*i)->deserialize(um, dds, reuse); 00264 } 00265 00266 return false; 00267 } 00268 00276 unsigned int 00277 Grid::val2buf(void *, bool) 00278 { 00279 return sizeof(Grid); 00280 } 00281 00285 unsigned int 00286 Grid::buf2val(void **) 00287 { 00288 return sizeof(Grid); 00289 } 00290 00291 BaseType * 00292 Grid::var(const string &n, btp_stack &s) 00293 { 00294 return var(n, true, &s); 00295 } 00296 00301 BaseType * 00302 Grid::var(const string &n, bool, btp_stack *s) 00303 { 00304 string name = www2id(n); 00305 00306 if (_array_var->name() == name) { 00307 if (s) 00308 s->push(static_cast<BaseType *>(this)); 00309 return _array_var; 00310 } 00311 00312 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00313 if ((*i)->name() == name) { 00314 if (s) 00315 s->push(static_cast<BaseType *>(this)); 00316 return *i; 00317 } 00318 } 00319 00320 return 0; 00321 } 00322 00335 void 00336 Grid::add_var(BaseType *bt, Part part) 00337 { 00338 if (!bt) 00339 throw InternalErr(__FILE__, __LINE__, 00340 "Passing NULL pointer as variable to be added."); 00341 00342 // Jose Garcia 00343 // Now we get a copy of the maps or of the array 00344 // so the owner of bt which is external to libdap++ 00345 // is free to deallocate its object. 00346 switch (part) { 00347 case array: 00348 _array_var = bt->ptr_duplicate(); 00349 _array_var->set_parent(this); 00350 return; 00351 case maps: { 00352 BaseType *btp = bt->ptr_duplicate(); 00353 btp->set_parent(this); 00354 _map_vars.push_back(btp); 00355 return; 00356 } 00357 default: 00358 if (!_array_var) { 00359 _array_var = bt->ptr_duplicate(); 00360 _array_var->set_parent(this); 00361 } 00362 else { 00363 BaseType *btp = bt->ptr_duplicate(); 00364 btp->set_parent(this); 00365 _map_vars.push_back(btp); 00366 } 00367 return; 00368 } 00369 } 00370 00374 BaseType * 00375 Grid::array_var() 00376 { 00377 return _array_var; 00378 } 00379 00383 Array * 00384 Grid::get_array() 00385 { 00386 Array *a = dynamic_cast<Array*>(_array_var); 00387 if (a) 00388 return a; 00389 else 00390 throw InternalErr(__FILE__, __LINE__, "bad Cast"); 00391 } 00392 00394 Grid::Map_iter 00395 Grid::map_begin() 00396 { 00397 return _map_vars.begin() ; 00398 } 00399 00402 Grid::Map_iter 00403 Grid::map_end() 00404 { 00405 return _map_vars.end() ; 00406 } 00407 00409 Grid::Map_riter 00410 Grid::map_rbegin() 00411 { 00412 return _map_vars.rbegin() ; 00413 } 00414 00417 Grid::Map_riter 00418 Grid::map_rend() 00419 { 00420 return _map_vars.rend() ; 00421 } 00422 00426 Grid::Map_iter 00427 Grid::get_map_iter(int i) 00428 { 00429 return _map_vars.begin() + i; 00430 } 00431 00447 int 00448 Grid::components(bool constrained) 00449 { 00450 int comp; 00451 00452 if (constrained) { 00453 comp = _array_var->send_p() ? 1 : 0; 00454 00455 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00456 if ((*i)->send_p()) { 00457 comp++; 00458 } 00459 } 00460 } 00461 else { 00462 comp = 1 + _map_vars.size(); 00463 } 00464 00465 return comp; 00466 } 00467 00468 // When projected (using whatever the current constraint provides in the way 00469 // of a projection), is the object still a Grid? 00470 00487 bool 00488 Grid::projection_yields_grid() 00489 { 00490 // For each dimension in the Array part, check the corresponding Map 00491 // vector to make sure it is present in the projected Grid. If for each 00492 // projected dimension in the Array component, there is a matching Map 00493 // vector, then the Grid is valid. 00494 bool valid = true; 00495 Array *a = (Array *)_array_var; 00496 00497 // Don't bother checking if the Array component is not included. 00498 if (!a->send_p()) 00499 return false; 00500 00501 Array::Dim_iter i = a->dim_begin() ; 00502 Map_iter m = map_begin() ; 00503 for (; valid && i != a->dim_end() && m != map_end(); i++, m++) { 00504 if (a->dimension_size(i, true)) { 00505 // Check the matching Map vector; the Map projection must equal 00506 // the Array dimension projection 00507 Array *map = (Array *)(*m); 00508 Array::Dim_iter fd = map->dim_begin(); // Maps have only one dim! 00509 valid = map->dimension_start(fd, true) 00510 == a->dimension_start(i, true) 00511 && map->dimension_stop(fd, true) 00512 == a->dimension_stop(i, true) 00513 && map->dimension_stride(fd, true) 00514 == a->dimension_stride(i, true); 00515 } 00516 else { 00517 // Corresponding Map vector must be excluded from the projection. 00518 Array *map = (Array *)(*m); 00519 valid = !map->send_p(); 00520 } 00521 } 00522 00523 return valid; 00524 } 00525 00527 void 00528 Grid::clear_constraint() 00529 { 00530 dynamic_cast<Array&>(*_array_var).clear_constraint(); 00531 for (Map_iter m = map_begin(); m != map_end(); ++m) 00532 dynamic_cast<Array&>(*(*m)).clear_constraint(); 00533 } 00534 //#if FILE_METHODS 00535 void 00536 Grid::print_decl(FILE *out, string space, bool print_semi, 00537 bool constraint_info, bool constrained) 00538 { 00539 if (constrained && !send_p()) 00540 return; 00541 00542 // If we are printing the declaration of a constrained Grid then check for 00543 // the case where the projection removes all but one component; the 00544 // resulting object is a simple array. 00545 int projection = components(true); 00546 if (constrained && projection == 1) { 00547 _array_var->print_decl(out, space, print_semi /*true*/, constraint_info, 00548 constrained); 00549 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00550 (*i)->print_decl(out, space, print_semi /*true*/, constraint_info, constrained); 00551 } 00552 00553 goto exit; // Skip end material. 00554 } 00555 // If there are M (< N) componets (Array and Maps combined) in a N 00556 // component Grid, send the M components as elements of a Struture. 00557 // This will preserve the grouping without violating the rules for a 00558 // Grid. 00559 else if (constrained && !projection_yields_grid()) { 00560 fprintf(out, "%sStructure {\n", space.c_str()) ; 00561 00562 _array_var->print_decl(out, space + " ", true, constraint_info, 00563 constrained); 00564 00565 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00566 (*i)->print_decl(out, space + " ", true, 00567 constraint_info, constrained); 00568 } 00569 00570 fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ; 00571 } 00572 else { 00573 // The number of elements in the (projected) Grid must be such that 00574 // we have a valid Grid object; send it as such. 00575 fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ; 00576 00577 fprintf(out, "%s Array:\n", space.c_str()) ; 00578 _array_var->print_decl(out, space + " ", true, constraint_info, 00579 constrained); 00580 00581 fprintf(out, "%s Maps:\n", space.c_str()) ; 00582 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00583 (*i)->print_decl(out, space + " ", true, 00584 constraint_info, constrained); 00585 } 00586 00587 fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ; 00588 } 00589 00590 if (constraint_info) { 00591 if (send_p()) 00592 fprintf( out, ": Send True"); 00593 else 00594 fprintf( out, ": Send False"); 00595 } 00596 00597 if (print_semi) 00598 fprintf(out, ";\n") ; 00599 00600 // If sending just one comp, skip sending the terminal semicolon, etc. 00601 exit: 00602 return; 00603 } 00604 //#endif 00605 void 00606 Grid::print_decl(ostream &out, string space, bool print_semi, 00607 bool constraint_info, bool constrained) 00608 { 00609 if (constrained && !send_p()) 00610 return; 00611 00612 // If we are printing the declaration of a constrained Grid then check for 00613 // the case where the projection removes all but one component; the 00614 // resulting object is a simple array. 00615 // 00616 // I replaced the 'true' with the value of 'print_semi' passed in by the 00617 // caller. This fixes an issue with the intern_data tests and does not 00618 // seem to break anything else. jhrg 11/9/07 00619 int projection = components(true); 00620 if (constrained && projection == 1) { 00621 _array_var->print_decl(out, space, print_semi /*true*/, constraint_info, 00622 constrained); 00623 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00624 (*i)->print_decl(out, space, print_semi /*true*/, constraint_info, constrained); 00625 } 00626 00627 goto exit; // Skip end material. 00628 } 00629 // If there are M (< N) components (Array and Maps combined) in a N 00630 // component Grid, send the M components as elements of a Structure. 00631 // This will preserve the grouping without violating the rules for a 00632 // Grid. 00633 else if (constrained && !projection_yields_grid()) { 00634 out << space << "Structure {\n" ; 00635 00636 _array_var->print_decl(out, space + " ", true, constraint_info, 00637 constrained); 00638 00639 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00640 (*i)->print_decl(out, space + " ", true, 00641 constraint_info, constrained); 00642 } 00643 00644 out << space << "} " << id2www(name()) ; 00645 } 00646 else { 00647 // The number of elements in the (projected) Grid must be such that 00648 // we have a valid Grid object; send it as such. 00649 out << space << type_name() << " {\n" ; 00650 00651 out << space << " Array:\n" ; 00652 _array_var->print_decl(out, space + " ", true, constraint_info, 00653 constrained); 00654 00655 out << space << " Maps:\n" ; 00656 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00657 (*i)->print_decl(out, space + " ", true, 00658 constraint_info, constrained); 00659 } 00660 00661 out << space << "} " << id2www(name()) ; 00662 } 00663 00664 if (constraint_info) { 00665 if (send_p()) 00666 out << ": Send True"; 00667 else 00668 out << ": Send False"; 00669 } 00670 00671 if (print_semi) 00672 out << ";\n" ; 00673 00674 // If sending just one comp, skip sending the terminal semicolon, etc. 00675 exit: 00676 return; 00677 } 00678 00679 //#if FILE_METHODS 00680 class PrintMapField : public unary_function<BaseType *, void> 00681 { 00682 FILE *d_out; 00683 string d_space; 00684 bool d_constrained; 00685 string d_tag; 00686 public: 00687 PrintMapField(FILE *o, string s, bool c, const string &t = "Map") 00688 : d_out(o), d_space(s), d_constrained(c), d_tag(t) 00689 {} 00690 00691 void operator()(BaseType *btp) 00692 { 00693 Array *a = dynamic_cast<Array*>(btp); 00694 if (!a) 00695 throw InternalErr(__FILE__, __LINE__, "Expected an Array."); 00696 a->print_xml_core(d_out, d_space, d_constrained, d_tag); 00697 } 00698 }; 00699 00700 void 00701 Grid::print_xml(FILE *out, string space, bool constrained) 00702 { 00703 if (constrained && !send_p()) 00704 return; 00705 00706 // If we are printing the declaration of a constrained Grid then check for 00707 // the case where the projection removes all but one component; the 00708 // resulting object is a simple array. 00709 // 00710 // I replaced the 'true' with the value of 'print_semi' passed in by the 00711 // caller. This fixes an issue with the intern_data tests and does not 00712 // seem to break anything else. jhrg 11/9/07 00713 int projection = components(true); 00714 if (constrained && projection == 1) { 00715 get_attr_table().print_xml(out, space + " ", constrained); 00716 00717 get_array()->print_xml(out, space + " ", constrained); 00718 00719 for_each(map_begin(), map_end(), 00720 PrintMapField(out, space + " ", constrained, "Array")); 00721 } 00722 // If there are M (< N) components (Array and Maps combined) in a N 00723 // component Grid, send the M components as elements of a Structure. 00724 // This will preserve the grouping without violating the rules for a 00725 // Grid. 00726 else if (constrained && !projection_yields_grid()) { 00727 fprintf(out, "%s<Structure", space.c_str()); 00728 if (!name().empty()) 00729 fprintf(out, " name=\"%s\"", id2xml(name()).c_str()); 00730 00731 fprintf(out, ">\n"); 00732 00733 get_attr_table().print_xml(out, space + " ", constrained); 00734 00735 get_array()->print_xml(out, space + " ", constrained); 00736 00737 for_each(map_begin(), map_end(), 00738 PrintMapField(out, space + " ", constrained, "Array")); 00739 00740 fprintf(out, "%s</Structure>\n", space.c_str()); 00741 } 00742 else { 00743 // The number of elements in the (projected) Grid must be such that 00744 // we have a valid Grid object; send it as such. 00745 fprintf(out, "%s<Grid", space.c_str()); 00746 if (!name().empty()) 00747 fprintf(out, " name=\"%s\"", id2xml(name()).c_str()); 00748 00749 fprintf(out, ">\n"); 00750 00751 get_attr_table().print_xml(out, space + " ", constrained); 00752 00753 get_array()->print_xml(out, space + " ", constrained); 00754 00755 for_each(map_begin(), map_end(), 00756 PrintMapField(out, space + " ", constrained)); 00757 00758 fprintf(out, "%s</Grid>\n", space.c_str()); 00759 } 00760 } 00761 //#endif 00762 00763 class PrintMapFieldStrm : public unary_function<BaseType *, void> 00764 { 00765 ostream &d_out; 00766 string d_space; 00767 bool d_constrained; 00768 string d_tag; 00769 public: 00770 PrintMapFieldStrm(ostream &o, string s, bool c, const string &t = "Map") 00771 : d_out(o), d_space(s), d_constrained(c), d_tag(t) 00772 {} 00773 00774 void operator()(BaseType *btp) 00775 { 00776 Array *a = dynamic_cast<Array*>(btp); 00777 if (!a) 00778 throw InternalErr(__FILE__, __LINE__, "Expected an Array."); 00779 a->print_xml_core(d_out, d_space, d_constrained, d_tag); 00780 } 00781 }; 00782 00783 void 00784 Grid::print_xml(ostream &out, string space, bool constrained) 00785 { 00786 if (constrained && !send_p()) 00787 return; 00788 00789 // If we are printing the declaration of a constrained Grid then check for 00790 // the case where the projection removes all but one component; the 00791 // resulting object is a simple array. 00792 // 00793 // I replaced the 'true' with the value of 'print_semi' passed in by the 00794 // caller. This fixes an issue with the intern_data tests and does not 00795 // seem to break anything else. jhrg 11/9/07 00796 int projection = components(true); 00797 if (constrained && projection == 1) { 00798 get_attr_table().print_xml(out, space + " ", constrained); 00799 00800 get_array()->print_xml(out, space + " ", constrained); 00801 00802 for_each(map_begin(), map_end(), 00803 PrintMapFieldStrm(out, space + " ", constrained, "Array")); 00804 } 00805 // If there are M (< N) components (Array and Maps combined) in a N 00806 // component Grid, send the M components as elements of a Structure. 00807 // This will preserve the grouping without violating the rules for a 00808 // Grid. 00809 else if (constrained && !projection_yields_grid()) { 00810 out << space << "<Structure" ; 00811 if (!name().empty()) 00812 out << " name=\"" << id2xml(name()) << "\"" ; 00813 00814 out << ">\n" ; 00815 00816 get_attr_table().print_xml(out, space + " ", constrained); 00817 00818 get_array()->print_xml(out, space + " ", constrained); 00819 00820 for_each(map_begin(), map_end(), 00821 PrintMapFieldStrm(out, space + " ", constrained, "Array")); 00822 00823 out << space << "</Structure>\n" ; 00824 } 00825 else { 00826 // The number of elements in the (projected) Grid must be such that 00827 // we have a valid Grid object; send it as such. 00828 out << space << "<Grid" ; 00829 if (!name().empty()) 00830 out << " name=\"" << id2xml(name()) << "\"" ; 00831 00832 out << ">\n" ; 00833 00834 get_attr_table().print_xml(out, space + " ", constrained); 00835 00836 get_array()->print_xml(out, space + " ", constrained); 00837 00838 for_each(map_begin(), map_end(), 00839 PrintMapFieldStrm(out, space + " ", constrained)); 00840 00841 out << space << "</Grid>\n" ; 00842 } 00843 } 00844 00845 //#if FILE_METHODS 00846 void 00847 Grid::print_val(FILE *out, string space, bool print_decl_p) 00848 { 00849 if (print_decl_p) { 00850 print_decl(out, space, false); 00851 fprintf(out, " = ") ; 00852 } 00853 00854 // If we are printing a value on the client-side, projection_yields_grid 00855 // should not be called since we don't *have* a projection without a 00856 // contraint. I think that if we are here and send_p() is not true, then 00857 // the value of this function should be ignored. 4/6/2000 jhrg 00858 bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg 00859 if (pyg || !send_p()) 00860 fprintf(out, "{ Array: ") ; 00861 else 00862 fprintf(out, "{") ; 00863 _array_var->print_val(out, "", false); 00864 if (pyg || !send_p()) 00865 fprintf(out, " Maps: ") ; 00866 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); 00867 i++, (void)(i != _map_vars.end() && fprintf(out, ", "))) { 00868 (*i)->print_val(out, "", false); 00869 } 00870 fprintf(out, " }") ; 00871 00872 if (print_decl_p) 00873 fprintf(out, ";\n") ; 00874 } 00875 //#endif 00876 void 00877 Grid::print_val(ostream &out, string space, bool print_decl_p) 00878 { 00879 if (print_decl_p) { 00880 print_decl(out, space, false); 00881 out << " = " ; 00882 } 00883 00884 // If we are printing a value on the client-side, projection_yields_grid 00885 // should not be called since we don't *have* a projection without a 00886 // Constraint. I think that if we are here and send_p() is not true, then 00887 // the value of this function should be ignored. 4/6/2000 jhrg 00888 bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg 00889 if (pyg || !send_p()) 00890 out << "{ Array: " ; 00891 else 00892 out << "{" ; 00893 _array_var->print_val(out, "", false); 00894 if (pyg || !send_p()) 00895 out << " Maps: " ; 00896 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); 00897 i++, (void)(i != _map_vars.end() && out << ", ")) { 00898 (*i)->print_val(out, "", false); 00899 } 00900 out << " }" ; 00901 00902 if (print_decl_p) 00903 out << ";\n" ; 00904 } 00905 00906 // Grids have ugly semantics. 00907 00912 bool 00913 Grid::check_semantics(string &msg, bool all) 00914 { 00915 if (!BaseType::check_semantics(msg)) 00916 return false; 00917 #if 0 00918 // Actually, the spec doesn't say this. jhrg 2/13/06 00919 if (!unique_names(_map_vars, name(), type_name(), msg)) 00920 return false; 00921 #endif 00922 00923 msg = ""; 00924 00925 if (!_array_var) { 00926 msg += "Null grid base array in `" + name() + "'\n"; 00927 return false; 00928 } 00929 00930 // Is it an array? 00931 if (_array_var->type() != dods_array_c) { 00932 msg += "Grid `" + name() + "'s' member `" + _array_var->name() + "' must be an array\n"; 00933 return false; 00934 } 00935 00936 Array *av = (Array *)_array_var; // past test above, must be an array 00937 00938 // Array must be of a simple_type. 00939 if (!av->var()->is_simple_type()) { 00940 msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n"; 00941 return false; 00942 } 00943 00944 // enough maps? 00945 if ((unsigned)_map_vars.size() != av->dimensions()) { 00946 msg += "The number of map variables for grid `" + this->name() + "' does not match the number of dimensions of `"; 00947 msg += av->name() + "'\n"; 00948 return false; 00949 } 00950 00951 const string array_var_name = av->name(); 00952 Array::Dim_iter asi = av->dim_begin() ; 00953 for (Map_iter mvi = _map_vars.begin(); 00954 mvi != _map_vars.end(); mvi++, asi++) { 00955 00956 BaseType *mv = *mvi; 00957 00958 // check names 00959 if (array_var_name == mv->name()) { 00960 msg += "Grid map variable `" + mv->name() + "' conflicts with the grid array name in grid `" + name() + "'\n"; 00961 return false; 00962 } 00963 // check types 00964 if (mv->type() != dods_array_c) { 00965 msg += "Grid map variable `" + mv->name() + "' is not an array\n"; 00966 return false; 00967 } 00968 00969 Array *mv_a = (Array *)mv; // downcast to (Array *) 00970 00971 // Array must be of a simple_type. 00972 if (!mv_a->var()->is_simple_type()) { 00973 msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n"; 00974 return false; 00975 } 00976 00977 // check shape 00978 if (mv_a->dimensions() != 1) {// maps must have one dimension 00979 msg += "Grid map variable `" + mv_a->name() + "' must be only one dimension\n"; 00980 return false; 00981 } 00982 // size of map must match corresponding array dimension 00983 Array::Dim_iter mv_asi = mv_a->dim_begin() ; 00984 int mv_a_size = mv_a->dimension_size(mv_asi) ; 00985 int av_size = av->dimension_size(asi) ; 00986 if (mv_a_size != av_size) { 00987 msg += "Grid map variable `" + mv_a->name() + "'s' size does not match the size of array variable '"; 00988 msg += _array_var->name() + "'s' cooresponding dimension\n"; 00989 return false; 00990 } 00991 } 00992 00993 if (all) { 00994 if (!_array_var->check_semantics(msg, true)) 00995 return false; 00996 for (Map_iter mvi = _map_vars.begin(); mvi != _map_vars.end(); mvi++) { 00997 if (!(*mvi)->check_semantics(msg, true)) { 00998 return false; 00999 } 01000 } 01001 } 01002 01003 return true; 01004 } 01005 01014 void 01015 Grid::dump(ostream &strm) const 01016 { 01017 strm << DapIndent::LMarg << "Grid::dump - (" 01018 << (void *)this << ")" << endl ; 01019 DapIndent::Indent() ; 01020 Constructor::dump(strm) ; 01021 if (_array_var) { 01022 strm << DapIndent::LMarg << "array var: " << endl ; 01023 DapIndent::Indent() ; 01024 _array_var->dump(strm) ; 01025 DapIndent::UnIndent() ; 01026 } 01027 else { 01028 strm << DapIndent::LMarg << "array var: null" << endl ; 01029 } 01030 strm << DapIndent::LMarg << "map var: " << endl ; 01031 DapIndent::Indent() ; 01032 Map_citer i = _map_vars.begin() ; 01033 Map_citer ie = _map_vars.end() ; 01034 for (; i != ie; i++) { 01035 (*i)->dump(strm) ; 01036 } 01037 DapIndent::UnIndent() ; 01038 DapIndent::UnIndent() ; 01039 } 01040 01041 } // namespace libdap 01042