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 // #define DODS_DEBUG 00039 00040 #include <functional> 00041 #include <algorithm> 00042 00043 #include "Grid.h" 00044 #include "DDS.h" 00045 #include "Array.h" // for downcasts 00046 #include "util.h" 00047 #include "InternalErr.h" 00048 #include "escaping.h" 00049 00050 #include "debug.h" 00051 00052 using namespace std; 00053 00054 namespace libdap { 00055 00056 void 00057 Grid::_duplicate(const Grid &s) 00058 { 00059 // Clear out any spurious vars in Constructor::_vars 00060 _vars.clear(); // [mjohnson 10 Sep 2009] 00061 00062 _array_var = s._array_var->ptr_duplicate(); 00063 _array_var->set_parent(this); 00064 _vars.push_back(_array_var); // so the Constructor::Vars_Iter sees it [mjohnson 10 Sep 2009] 00065 00066 Grid &cs = const_cast<Grid &>(s); 00067 00068 for (Map_iter i = cs._map_vars.begin(); i != cs._map_vars.end(); i++) { 00069 BaseType *btp = (*i)->ptr_duplicate(); 00070 btp->set_parent(this); 00071 _map_vars.push_back(btp); 00072 _vars.push_back(btp); // push all map vectors as weak refs into super::_vars which won't delete them [mjohnson 10 Sep 2009] 00073 } 00074 00075 } 00076 00086 Grid::Grid(const string &n) : Constructor(n, dods_grid_c), _array_var(0) 00087 {} 00088 00100 Grid::Grid(const string &n, const string &d) 00101 : Constructor(n, d, dods_grid_c), _array_var(0) 00102 {} 00103 00105 Grid::Grid(const Grid &rhs) : Constructor(rhs) 00106 { 00107 _duplicate(rhs); 00108 } 00109 00110 Grid::~Grid() 00111 { 00112 delete _array_var; _array_var = 0; 00113 00114 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00115 BaseType *btp = *i ; 00116 delete btp ; btp = 0; 00117 } 00118 } 00119 00120 BaseType * 00121 Grid::ptr_duplicate() 00122 { 00123 return new Grid(*this); 00124 } 00125 00126 Grid & 00127 Grid::operator=(const Grid &rhs) 00128 { 00129 if (this == &rhs) 00130 return *this; 00131 00132 delete _array_var; _array_var = 0; 00133 00134 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00135 BaseType *btp = *i ; 00136 delete btp ; 00137 } 00138 00139 // this doesn't copy Constructor::_vars so... 00140 dynamic_cast<Constructor &>(*this) = rhs; 00141 00142 // we do it in here... 00143 _duplicate(rhs); 00144 00145 return *this; 00146 } 00147 00148 int 00149 Grid::element_count(bool leaves) 00150 { 00151 if (!leaves) 00152 return _map_vars.size() + 1; 00153 else { 00154 int i = 0; 00155 for (Map_iter j = _map_vars.begin(); j != _map_vars.end(); j++) { 00156 j += (*j)->element_count(leaves); 00157 } 00158 00159 if (!get_array()) 00160 throw InternalErr(__FILE__, __LINE__, "No Grid arry!"); 00161 00162 i += get_array()->element_count(leaves); 00163 return i; 00164 } 00165 } 00166 00167 void 00168 Grid::set_send_p(bool state) 00169 { 00170 _array_var->set_send_p(state); 00171 00172 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00173 (*i)->set_send_p(state); 00174 } 00175 00176 BaseType::set_send_p(state); 00177 } 00178 00179 void 00180 Grid::set_read_p(bool state) 00181 { 00182 _array_var->set_read_p(state); 00183 00184 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00185 (*i)->set_read_p(state); 00186 } 00187 00188 BaseType::set_read_p(state); 00189 } 00190 00191 void 00192 Grid::set_in_selection(bool state) 00193 { 00194 _array_var->set_in_selection(state); 00195 00196 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00197 (*i)->set_in_selection(state); 00198 } 00199 00200 BaseType::set_in_selection(state); 00201 } 00202 00203 unsigned int 00204 Grid::width() 00205 { 00206 unsigned int sz = _array_var->width(); 00207 00208 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00209 sz += (*i)->width(); 00210 } 00211 00212 return sz; 00213 } 00214 00215 void 00216 Grid::intern_data(ConstraintEvaluator &eval, DDS &dds) 00217 { 00218 dds.timeout_on(); 00219 00220 if (!read_p()) 00221 read(); // read() throws Error and InternalErr 00222 00223 dds.timeout_off(); 00224 00225 if (_array_var->send_p()) 00226 _array_var->intern_data(eval, dds); 00227 00228 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00229 if ((*i)->send_p()) { 00230 (*i)->intern_data(eval, dds); 00231 } 00232 } 00233 } 00234 00235 bool 00236 Grid::serialize(ConstraintEvaluator &eval, DDS &dds, 00237 Marshaller &m, bool ce_eval) 00238 { 00239 dds.timeout_on(); 00240 00241 // Re ticket 560: Get an object from eval that describes how to sample 00242 // and rearrange the data, then perform those actions. Alternative: 00243 // implement this as a selection function. 00244 00245 if (!read_p()) 00246 read(); // read() throws Error and InternalErr 00247 00248 #if EVAL 00249 if (ce_eval && !eval.eval_selection(dds, dataset())) 00250 return true; 00251 #endif 00252 00253 dds.timeout_off(); 00254 00255 if (_array_var->send_p()) 00256 _array_var->serialize(eval, dds, m, false); 00257 00258 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00259 if ((*i)->send_p()) { 00260 (*i)->serialize(eval, dds, m, false); 00261 } 00262 } 00263 00264 return true; 00265 } 00266 00267 bool 00268 Grid::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00269 { 00270 _array_var->deserialize(um, dds, reuse); 00271 00272 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00273 (*i)->deserialize(um, dds, reuse); 00274 } 00275 00276 return false; 00277 } 00278 00286 unsigned int 00287 Grid::val2buf(void *, bool) 00288 { 00289 return sizeof(Grid); 00290 } 00291 00295 unsigned int 00296 Grid::buf2val(void **) 00297 { 00298 return sizeof(Grid); 00299 } 00300 00301 BaseType * 00302 Grid::var(const string &n, btp_stack &s) 00303 { 00304 return var(n, true, &s); 00305 } 00306 00311 BaseType * 00312 Grid::var(const string &n, bool, btp_stack *s) 00313 { 00314 string name = www2id(n); 00315 00316 if (_array_var->name() == name) { 00317 if (s) 00318 s->push(static_cast<BaseType *>(this)); 00319 return _array_var; 00320 } 00321 00322 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00323 if ((*i)->name() == name) { 00324 if (s) 00325 s->push(static_cast<BaseType *>(this)); 00326 return *i; 00327 } 00328 } 00329 00330 return 0; 00331 } 00332 00345 void 00346 Grid::add_var(BaseType *bt, Part part) 00347 { 00348 if (!bt) { 00349 throw InternalErr(__FILE__, __LINE__, 00350 "Passing NULL pointer as variable to be added."); 00351 } 00352 00353 if (part == array && _array_var) { 00354 // Avoid leaking memory... Function is add, not set, so it is an error to call again for the array part. 00355 throw InternalErr(__FILE__, __LINE__, "Error: Grid::add_var called with part==Array, but the array was already set!"); 00356 } 00357 00358 // Set to the clone of bt if we get that far. 00359 BaseType* bt_clone = 0; 00360 00361 switch (part) { 00362 00363 case array: { 00364 // Refactored to use new set_array ([mjohnson 11 nov 2009]) 00365 Array* p_arr = dynamic_cast<Array*>(bt); 00366 // avoid obvious broken semantics 00367 if (!p_arr) { 00368 throw InternalErr(__FILE__, __LINE__, 00369 "Grid::add_var(): with Part==array: object is not an Array!"); 00370 } 00371 // Add it as a copy to preserve old semantics. This sets parent too. 00372 bt_clone = p_arr->ptr_duplicate(); 00373 set_array(static_cast<Array*>(bt_clone)); 00374 } 00375 break; 00376 00377 case maps: { 00378 bt_clone = bt->ptr_duplicate(); 00379 bt_clone->set_parent(this); 00380 _map_vars.push_back(bt_clone); 00381 } 00382 break; 00383 00384 default: { 00385 if (!_array_var) { 00386 // Refactored to use new set_array ([mjohnson 11 nov 2009]) 00387 Array* p_arr = dynamic_cast<Array*>(bt); 00388 // avoid obvious broken semantics 00389 if (!p_arr) { 00390 throw InternalErr(__FILE__, __LINE__, 00391 "Grid::add_var(): with Part==array: object is not an Array!"); 00392 } 00393 // Add it as a copy to preserve old semantics. This sets parent too. 00394 bt_clone = p_arr->ptr_duplicate(); 00395 set_array(static_cast<Array*>(bt_clone)); 00396 } 00397 else { 00398 bt_clone = bt->ptr_duplicate(); 00399 bt_clone->set_parent(this); 00400 _map_vars.push_back(bt_clone); 00401 } 00402 } 00403 break; 00404 }// switch 00405 00406 // if we get ehre without exception, add the cloned object to the superclass variable iterator 00407 // mjohnson 10 Sep 2009 00408 // Add it to the superclass _vars list so we can iterate on superclass vars 00409 if (bt_clone) { 00410 _vars.push_back(bt_clone); 00411 } 00412 } 00413 00423 void 00424 Grid::set_array(Array* p_new_arr) 00425 { 00426 if (!p_new_arr) { 00427 throw InternalErr(__FILE__, __LINE__, 00428 "Grid::set_array(): Cannot set to null!"); 00429 } 00430 // Make sure not same memory, this would be evil. 00431 if (p_new_arr == _array_var) { 00432 return; 00433 } 00434 // clean out any old array 00435 delete _array_var; _array_var = 0; 00436 // Set the new, with parent 00437 _array_var = p_new_arr; 00438 _array_var->set_parent(this); 00439 } 00440 00467 Array* 00468 Grid::add_map(Array* p_new_map, bool add_as_copy) 00469 { 00470 if (!p_new_map) { 00471 throw InternalErr(__FILE__, __LINE__, 00472 "Grid::add_map(): cannot have p_new_map null!"); 00473 } 00474 00475 if (add_as_copy) { 00476 p_new_map = static_cast<Array*>(p_new_map->ptr_duplicate()); 00477 } 00478 00479 p_new_map->set_parent(this); 00480 _map_vars.push_back(p_new_map); 00481 _vars.push_back(p_new_map); // allow superclass iter to work as well. 00482 00483 // return the one that got put into the Grid. 00484 return p_new_map; 00485 } 00486 00499 Array* 00500 Grid::prepend_map(Array* p_new_map, bool add_copy) 00501 { 00502 if (add_copy) 00503 { 00504 p_new_map = static_cast<Array*>(p_new_map->ptr_duplicate()); 00505 } 00506 00507 p_new_map->set_parent(this); 00508 _map_vars.insert(_map_vars.begin(), p_new_map); 00509 _vars.insert(_vars.begin(), p_new_map); // allow superclass iter to work as well. 00510 00511 // return the one that got put into the Grid. 00512 return p_new_map; 00513 } 00514 00518 BaseType * 00519 Grid::array_var() 00520 { 00521 return _array_var; 00522 } 00523 00527 Array * 00528 Grid::get_array() 00529 { 00530 Array *a = dynamic_cast<Array*>(_array_var); 00531 if (a) 00532 return a; 00533 else 00534 throw InternalErr(__FILE__, __LINE__, "bad Cast"); 00535 } 00536 00538 Grid::Map_iter 00539 Grid::map_begin() 00540 { 00541 return _map_vars.begin() ; 00542 } 00543 00546 Grid::Map_iter 00547 Grid::map_end() 00548 { 00549 return _map_vars.end() ; 00550 } 00551 00553 Grid::Map_riter 00554 Grid::map_rbegin() 00555 { 00556 return _map_vars.rbegin() ; 00557 } 00558 00561 Grid::Map_riter 00562 Grid::map_rend() 00563 { 00564 return _map_vars.rend() ; 00565 } 00566 00570 Grid::Map_iter 00571 Grid::get_map_iter(int i) 00572 { 00573 return _map_vars.begin() + i; 00574 } 00575 00591 int 00592 Grid::components(bool constrained) 00593 { 00594 int comp; 00595 00596 if (constrained) { 00597 comp = _array_var->send_p() ? 1 : 0; 00598 00599 for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) { 00600 if ((*i)->send_p()) { 00601 comp++; 00602 } 00603 } 00604 } 00605 else { 00606 comp = 1 + _map_vars.size(); 00607 } 00608 00609 return comp; 00610 } 00611 00612 void Grid::transfer_attributes(AttrTable *at_container) 00613 { 00614 AttrTable *at = at_container->get_attr_table(name()); 00615 00616 if (at) { 00617 at->set_is_global_attribute(false); 00618 00619 array_var()->transfer_attributes(at); 00620 00621 Map_iter map = map_begin(); 00622 while (map != map_end()) { 00623 (*map)->transfer_attributes(at); 00624 map++; 00625 } 00626 00627 // Trick: If an attribute that's within the container 'at' still has its 00628 // is_global_attribute property set, then it's not really a global attr 00629 // but instead an attribute that belongs to this Grid. 00630 AttrTable::Attr_iter at_p = at->attr_begin(); 00631 while (at_p != at->attr_end()) { 00632 if (at->is_global_attribute(at_p)) { 00633 if (at->get_attr_type(at_p) == Attr_container) 00634 get_attr_table().append_container(new AttrTable( 00635 *at->get_attr_table(at_p)), at->get_name(at_p)); 00636 else 00637 get_attr_table().append_attr(at->get_name(at_p), 00638 at->get_type(at_p), at->get_attr_vector(at_p)); 00639 } 00640 00641 at_p++; 00642 } 00643 } 00644 } 00645 00646 // When projected (using whatever the current constraint provides in the way 00647 // of a projection), is the object still a Grid? 00648 00665 bool 00666 Grid::projection_yields_grid() 00667 { 00668 // For each dimension in the Array part, check the corresponding Map 00669 // vector to make sure it is present in the projected Grid. If for each 00670 // projected dimension in the Array component, there is a matching Map 00671 // vector, then the Grid is valid. 00672 bool valid = true; 00673 Array *a = (Array *)_array_var; 00674 00675 // Don't bother checking if the Array component is not included. 00676 if (!a->send_p()) 00677 return false; 00678 00679 // If only one part is being sent, it's clearly not a grid (it must be 00680 // the array part of the Grid that's being sent (given that the above 00681 // test passed and the array is being sent). 00682 if (components(true) == 1) 00683 return false; 00684 00685 Array::Dim_iter d = a->dim_begin() ; 00686 Map_iter m = map_begin() ; 00687 00688 while (valid && d != a->dim_end() && m != map_end()) { 00689 Array &map = dynamic_cast<Array&>(**m); 00690 if (a->dimension_size(d, true) && map.send_p()) { 00691 // Check the matching Map vector; the Map projection must equal 00692 // the Array dimension projection 00693 Array::Dim_iter fd = map.dim_begin(); // Maps have only one dim! 00694 valid = map.dimension_start(fd, true) == a->dimension_start(d, true) 00695 && map.dimension_stop(fd, true) == a->dimension_stop(d, true) 00696 && map.dimension_stride(fd, true) == a->dimension_stride(d, true); 00697 } 00698 else { 00699 valid = false; 00700 } 00701 00702 d++, m++; 00703 } 00704 00705 return valid; 00706 } 00707 00709 void 00710 Grid::clear_constraint() 00711 { 00712 dynamic_cast<Array&>(*_array_var).clear_constraint(); 00713 for (Map_iter m = map_begin(); m != map_end(); ++m) 00714 dynamic_cast<Array&>(*(*m)).clear_constraint(); 00715 } 00716 00717 #if FILE_METHODS 00718 void 00719 Grid::print_decl(FILE *out, string space, bool print_semi, 00720 bool constraint_info, bool constrained) 00721 { 00722 if (constrained && !send_p()) 00723 return; 00724 00725 // The problem with the above is that if two Grids are projected and each 00726 // contain one variable, say a map, and it happens to have the same name 00727 // in each Grid, then without the enclosing Structures, the returned dataset 00728 // has two variables with the same name at the same lexical level. So I'm 00729 // removing the code above. 00730 if (constrained && !projection_yields_grid()) { 00731 fprintf(out, "%sStructure {\n", space.c_str()) ; 00732 00733 _array_var->print_decl(out, space + " ", true, constraint_info, 00734 constrained); 00735 00736 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00737 (*i)->print_decl(out, space + " ", true, 00738 constraint_info, constrained); 00739 } 00740 00741 fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ; 00742 } 00743 else { 00744 // The number of elements in the (projected) Grid must be such that 00745 // we have a valid Grid object; send it as such. 00746 fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ; 00747 00748 fprintf(out, "%s Array:\n", space.c_str()) ; 00749 _array_var->print_decl(out, space + " ", true, constraint_info, 00750 constrained); 00751 00752 fprintf(out, "%s Maps:\n", space.c_str()) ; 00753 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00754 (*i)->print_decl(out, space + " ", true, 00755 constraint_info, constrained); 00756 } 00757 00758 fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ; 00759 } 00760 00761 if (constraint_info) { 00762 if (send_p()) 00763 fprintf( out, ": Send True"); 00764 else 00765 fprintf( out, ": Send False"); 00766 } 00767 00768 if (print_semi) 00769 fprintf(out, ";\n") ; 00770 00771 return; 00772 } 00773 #endif 00774 00775 void 00776 Grid::print_decl(ostream &out, string space, bool print_semi, 00777 bool constraint_info, bool constrained) 00778 { 00779 if (constrained && !send_p()) 00780 return; 00781 00782 // See comment for the FILE* version of this method. 00783 if (constrained && !projection_yields_grid()) { 00784 out << space << "Structure {\n" ; 00785 00786 _array_var->print_decl(out, space + " ", true, constraint_info, 00787 constrained); 00788 00789 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00790 (*i)->print_decl(out, space + " ", true, 00791 constraint_info, constrained); 00792 } 00793 00794 out << space << "} " << id2www(name()) ; 00795 } 00796 else { 00797 // The number of elements in the (projected) Grid must be such that 00798 // we have a valid Grid object; send it as such. 00799 out << space << type_name() << " {\n" ; 00800 00801 out << space << " Array:\n" ; 00802 _array_var->print_decl(out, space + " ", true, constraint_info, 00803 constrained); 00804 00805 out << space << " Maps:\n" ; 00806 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) { 00807 (*i)->print_decl(out, space + " ", true, 00808 constraint_info, constrained); 00809 } 00810 00811 out << space << "} " << id2www(name()) ; 00812 } 00813 00814 if (constraint_info) { 00815 if (send_p()) 00816 out << ": Send True"; 00817 else 00818 out << ": Send False"; 00819 } 00820 00821 if (print_semi) 00822 out << ";\n" ; 00823 00824 return; 00825 } 00826 00827 #if FILE_METHODS 00828 class PrintMapField : public unary_function<BaseType *, void> 00829 { 00830 FILE *d_out; 00831 string d_space; 00832 bool d_constrained; 00833 string d_tag; 00834 public: 00835 PrintMapField(FILE *o, string s, bool c, const string &t = "Map") 00836 : d_out(o), d_space(s), d_constrained(c), d_tag(t) 00837 {} 00838 00839 void operator()(BaseType *btp) 00840 { 00841 Array *a = dynamic_cast<Array*>(btp); 00842 if (!a) 00843 throw InternalErr(__FILE__, __LINE__, "Expected an Array."); 00844 a->print_xml_core(d_out, d_space, d_constrained, d_tag); 00845 } 00846 }; 00847 00848 void 00849 Grid::print_xml(FILE *out, string space, bool constrained) 00850 { 00851 if (constrained && !send_p()) 00852 return; 00853 00854 if (constrained && !projection_yields_grid()) { 00855 fprintf(out, "%s<Structure", space.c_str()); 00856 if (!name().empty()) 00857 fprintf(out, " name=\"%s\"", id2xml(name()).c_str()); 00858 00859 fprintf(out, ">\n"); 00860 00861 get_attr_table().print_xml(out, space + " ", constrained); 00862 00863 get_array()->print_xml(out, space + " ", constrained); 00864 00865 for_each(map_begin(), map_end(), 00866 PrintMapField(out, space + " ", constrained, "Array")); 00867 00868 fprintf(out, "%s</Structure>\n", space.c_str()); 00869 } 00870 else { 00871 // The number of elements in the (projected) Grid must be such that 00872 // we have a valid Grid object; send it as such. 00873 fprintf(out, "%s<Grid", space.c_str()); 00874 if (!name().empty()) 00875 fprintf(out, " name=\"%s\"", id2xml(name()).c_str()); 00876 00877 fprintf(out, ">\n"); 00878 00879 get_attr_table().print_xml(out, space + " ", constrained); 00880 00881 get_array()->print_xml(out, space + " ", constrained); 00882 00883 for_each(map_begin(), map_end(), 00884 PrintMapField(out, space + " ", constrained)); 00885 00886 fprintf(out, "%s</Grid>\n", space.c_str()); 00887 } 00888 } 00889 #endif 00890 00891 class PrintMapFieldStrm : public unary_function<BaseType *, void> 00892 { 00893 ostream &d_out; 00894 string d_space; 00895 bool d_constrained; 00896 string d_tag; 00897 public: 00898 PrintMapFieldStrm(ostream &o, string s, bool c, const string &t = "Map") 00899 : d_out(o), d_space(s), d_constrained(c), d_tag(t) 00900 {} 00901 00902 void operator()(BaseType *btp) 00903 { 00904 Array *a = dynamic_cast<Array*>(btp); 00905 if (!a) 00906 throw InternalErr(__FILE__, __LINE__, "Expected an Array."); 00907 a->print_xml_core(d_out, d_space, d_constrained, d_tag); 00908 } 00909 }; 00910 00911 void 00912 Grid::print_xml(ostream &out, string space, bool constrained) 00913 { 00914 if (constrained && !send_p()) 00915 return; 00916 00917 if (constrained && !projection_yields_grid()) { 00918 out << space << "<Structure" ; 00919 if (!name().empty()) 00920 out << " name=\"" << id2xml(name()) << "\"" ; 00921 00922 out << ">\n" ; 00923 00924 get_attr_table().print_xml(out, space + " ", constrained); 00925 00926 get_array()->print_xml(out, space + " ", constrained); 00927 00928 for_each(map_begin(), map_end(), 00929 PrintMapFieldStrm(out, space + " ", constrained, "Array")); 00930 00931 out << space << "</Structure>\n" ; 00932 } 00933 else { 00934 // The number of elements in the (projected) Grid must be such that 00935 // we have a valid Grid object; send it as such. 00936 out << space << "<Grid" ; 00937 if (!name().empty()) 00938 out << " name=\"" << id2xml(name()) << "\"" ; 00939 00940 out << ">\n" ; 00941 00942 get_attr_table().print_xml(out, space + " ", constrained); 00943 00944 get_array()->print_xml(out, space + " ", constrained); 00945 00946 for_each(map_begin(), map_end(), 00947 PrintMapFieldStrm(out, space + " ", constrained)); 00948 00949 out << space << "</Grid>\n" ; 00950 } 00951 } 00952 00953 #if FILE_METHODS 00954 void 00955 Grid::print_val(FILE *out, string space, bool print_decl_p) 00956 { 00957 if (print_decl_p) { 00958 print_decl(out, space, false); 00959 fprintf(out, " = ") ; 00960 } 00961 00962 // If we are printing a value on the client-side, projection_yields_grid 00963 // should not be called since we don't *have* a projection without a 00964 // contraint. I think that if we are here and send_p() is not true, then 00965 // the value of this function should be ignored. 4/6/2000 jhrg 00966 bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg 00967 if (pyg || !send_p()) 00968 fprintf(out, "{ Array: ") ; 00969 else 00970 fprintf(out, "{") ; 00971 _array_var->print_val(out, "", false); 00972 if (pyg || !send_p()) 00973 fprintf(out, " Maps: ") ; 00974 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); 00975 i++, (void)(i != _map_vars.end() && fprintf(out, ", "))) { 00976 (*i)->print_val(out, "", false); 00977 } 00978 fprintf(out, " }") ; 00979 00980 if (print_decl_p) 00981 fprintf(out, ";\n") ; 00982 } 00983 #endif 00984 00985 void 00986 Grid::print_val(ostream &out, string space, bool print_decl_p) 00987 { 00988 if (print_decl_p) { 00989 print_decl(out, space, false); 00990 out << " = " ; 00991 } 00992 00993 // If we are printing a value on the client-side, projection_yields_grid 00994 // should not be called since we don't *have* a projection without a 00995 // Constraint. I think that if we are here and send_p() is not true, then 00996 // the value of this function should be ignored. 4/6/2000 jhrg 00997 bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg 00998 if (pyg || !send_p()) 00999 out << "{ Array: " ; 01000 else 01001 out << "{" ; 01002 _array_var->print_val(out, "", false); 01003 if (pyg || !send_p()) 01004 out << " Maps: " ; 01005 for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); 01006 i++, (void)(i != _map_vars.end() && out << ", ")) { 01007 (*i)->print_val(out, "", false); 01008 } 01009 out << " }" ; 01010 01011 if (print_decl_p) 01012 out << ";\n" ; 01013 } 01014 01015 // Grids have ugly semantics. 01016 01021 bool 01022 Grid::check_semantics(string &msg, bool all) 01023 { 01024 if (!BaseType::check_semantics(msg)) 01025 return false; 01026 01027 msg = ""; 01028 01029 if (!_array_var) { 01030 msg += "Null grid base array in `" + name() + "'\n"; 01031 return false; 01032 } 01033 01034 // Is it an array? 01035 if (_array_var->type() != dods_array_c) { 01036 msg += "Grid `" + name() + "'s' member `" + _array_var->name() + "' must be an array\n"; 01037 return false; 01038 } 01039 01040 Array *av = (Array *)_array_var; // past test above, must be an array 01041 01042 // Array must be of a simple_type. 01043 if (!av->var()->is_simple_type()) { 01044 msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n"; 01045 return false; 01046 } 01047 01048 // enough maps? 01049 if ((unsigned)_map_vars.size() != av->dimensions()) { 01050 msg += "The number of map variables for grid `" + this->name() + "' does not match the number of dimensions of `"; 01051 msg += av->name() + "'\n"; 01052 return false; 01053 } 01054 01055 const string array_var_name = av->name(); 01056 Array::Dim_iter asi = av->dim_begin() ; 01057 for (Map_iter mvi = _map_vars.begin(); 01058 mvi != _map_vars.end(); mvi++, asi++) { 01059 01060 BaseType *mv = *mvi; 01061 01062 // check names 01063 if (array_var_name == mv->name()) { 01064 msg += "Grid map variable `" + mv->name() + "' conflicts with the grid array name in grid `" + name() + "'\n"; 01065 return false; 01066 } 01067 // check types 01068 if (mv->type() != dods_array_c) { 01069 msg += "Grid map variable `" + mv->name() + "' is not an array\n"; 01070 return false; 01071 } 01072 01073 Array *mv_a = (Array *)mv; // downcast to (Array *) 01074 01075 // Array must be of a simple_type. 01076 if (!mv_a->var()->is_simple_type()) { 01077 msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n"; 01078 return false; 01079 } 01080 01081 // check shape 01082 if (mv_a->dimensions() != 1) {// maps must have one dimension 01083 msg += "Grid map variable `" + mv_a->name() + "' must be only one dimension\n"; 01084 return false; 01085 } 01086 // size of map must match corresponding array dimension 01087 Array::Dim_iter mv_asi = mv_a->dim_begin() ; 01088 int mv_a_size = mv_a->dimension_size(mv_asi) ; 01089 int av_size = av->dimension_size(asi) ; 01090 if (mv_a_size != av_size) { 01091 msg += "Grid map variable `" + mv_a->name() + "'s' size does not match the size of array variable '"; 01092 msg += _array_var->name() + "'s' cooresponding dimension\n"; 01093 return false; 01094 } 01095 } 01096 01097 if (all) { 01098 if (!_array_var->check_semantics(msg, true)) 01099 return false; 01100 for (Map_iter mvi = _map_vars.begin(); mvi != _map_vars.end(); mvi++) { 01101 if (!(*mvi)->check_semantics(msg, true)) { 01102 return false; 01103 } 01104 } 01105 } 01106 01107 return true; 01108 } 01109 01118 void 01119 Grid::dump(ostream &strm) const 01120 { 01121 strm << DapIndent::LMarg << "Grid::dump - (" 01122 << (void *)this << ")" << endl ; 01123 DapIndent::Indent() ; 01124 Constructor::dump(strm) ; 01125 if (_array_var) { 01126 strm << DapIndent::LMarg << "array var: " << endl ; 01127 DapIndent::Indent() ; 01128 _array_var->dump(strm) ; 01129 DapIndent::UnIndent() ; 01130 } 01131 else { 01132 strm << DapIndent::LMarg << "array var: null" << endl ; 01133 } 01134 strm << DapIndent::LMarg << "map var: " << endl ; 01135 DapIndent::Indent() ; 01136 Map_citer i = _map_vars.begin() ; 01137 Map_citer ie = _map_vars.end() ; 01138 for (; i != ie; i++) { 01139 (*i)->dump(strm) ; 01140 } 01141 DapIndent::UnIndent() ; 01142 DapIndent::UnIndent() ; 01143 } 01144 01145 } // namespace libdap 01146