libdap
Updated for version 3.17.0
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <sstream> 00041 #include <functional> 00042 #include <algorithm> 00043 00044 #include "Grid.h" 00045 #include "DDS.h" 00046 #include "Array.h" // for downcasts 00047 #include "util.h" 00048 #include "InternalErr.h" 00049 #include "escaping.h" 00050 #include "XDRStreamMarshaller.h" 00051 #include "debug.h" 00052 00053 #include "XMLWriter.h" 00054 #include "DMR.h" 00055 #include "D4Group.h" 00056 #include "D4Maps.h" 00057 #include "D4Attributes.h" 00058 00059 using namespace std; 00060 00061 namespace libdap { 00062 00063 void 00064 Grid::m_duplicate(const Grid &s) 00065 { 00066 // TODO revisit this code once/if the class is switched from using it's 00067 // own vars to those in Constructor. jhrg 4/3/13 00068 00069 // copy the weak pointer - Constructor will take care of copying 00070 // the 'strong' pointers. 00071 //d_array_var = s.d_array_var; 00072 d_is_array_set = s.d_is_array_set; 00073 } 00074 00084 Grid::Grid(const string &n) : Constructor(n, dods_grid_c), d_is_array_set(false) 00085 {} 00086 00098 Grid::Grid(const string &n, const string &d) 00099 : Constructor(n, d, dods_grid_c), d_is_array_set(false) 00100 {} 00101 00103 Grid::Grid(const Grid &rhs) : Constructor(rhs) 00104 { 00105 m_duplicate(rhs); 00106 } 00107 00108 Grid::~Grid() 00109 { 00110 //d_array_var = 0; // Weak pointer; object will be freed by Constructor 00111 } 00112 00113 BaseType * 00114 Grid::ptr_duplicate() 00115 { 00116 return new Grid(*this); 00117 } 00118 00119 Grid & 00120 Grid::operator=(const Grid &rhs) 00121 { 00122 if (this == &rhs) 00123 return *this; 00124 00125 // Removed this; it makes this operator= work differently than the rest 00126 #if 0 00127 delete d_array_var; d_array_var = 0; 00128 00129 for (Map_iter i = d_map_vars.begin(); i != d_map_vars.end(); i++) { 00130 BaseType *btp = *i ; 00131 delete btp ; 00132 } 00133 #endif 00134 00135 dynamic_cast<Constructor &>(*this) = rhs; 00136 00137 m_duplicate(rhs); 00138 00139 return *this; 00140 } 00141 00142 // FIXME transform_to_dap4 probably needs to run for side effect only. 00143 // drop the return BT and add variables to the D4Group that is passed 00144 // in instead of the DMR. 00145 // 00146 // Also need to handle the case where a Grid is part of a Structure 00147 BaseType * 00148 Grid::transform_to_dap4(D4Group *root, Constructor *container) 00149 { 00150 BaseType *btp = array_var()->transform_to_dap4(root, container); 00151 Array *coverage = static_cast<Array*>(btp); 00152 if (!coverage) 00153 throw InternalErr(__FILE__, __LINE__, "Expected an Array while transforming a Grid (coverage)"); 00154 00155 coverage->set_parent(container); 00156 00157 // Next find the maps; add them to the coverage and to the container, 00158 // the latter only on the condition that they are not already there. 00159 00160 for (Map_iter i = map_begin(), e = map_end(); i != e; ++i) { 00161 btp = (*i)->transform_to_dap4(root, container); 00162 Array *map = static_cast<Array*>(btp); 00163 if (!map) 00164 throw InternalErr(__FILE__, __LINE__, "Expected an Array while transforming a Grid (map)"); 00165 00166 // map must be non-null (Grids cannot contain Grids in DAP2) 00167 if (map) { 00168 // Only add the map/array if it not already present; given the scoping rules 00169 // for DAP2 and the assumption the DDS is valid, testing for the same name 00170 // is good enough. 00171 if (!root->var(map->name())) { 00172 map->set_parent(container); 00173 container->add_var_nocopy(map); // this adds the array to the container 00174 } 00175 D4Map *dap4_map = new D4Map(map->name(), map, coverage); // bind the 'map' to the coverage 00176 coverage->maps()->add_map(dap4_map); // bind the coverage to the map 00177 } 00178 else { 00179 throw InternalErr(__FILE__, __LINE__, 00180 "transform_to_dap4() returned a null value where there can be no Grid."); 00181 } 00182 } 00183 00184 container->add_var_nocopy(coverage); 00185 00186 // Since a Grid (DAP2) to a Coverage (DAP4) removes a lexical scope 00187 // in favor of a set of relations, Grid::transform_to_dap4() does not 00188 // return a BaseType*. Callers should assume it has correctly added 00189 // stuff to the container and group. 00190 return 0; 00191 } 00192 00193 00199 bool 00200 Grid::is_dap2_only_type() 00201 { 00202 return true; 00203 } 00204 00217 void 00218 Grid::add_var(BaseType *bt, Part part) 00219 { 00220 if (!bt) 00221 throw InternalErr(__FILE__, __LINE__, "Passing NULL pointer as variable to be added."); 00222 00223 if (part == array && d_is_array_set/*get_array()*/) { 00224 // Avoid leaking memory... Function is add, not set, so it is an error to call again for the array part. 00225 throw InternalErr(__FILE__, __LINE__, "Error: Grid::add_var called with part==Array, but the array was already set!"); 00226 } 00227 00228 // avoid obvious broken semantics 00229 if (!dynamic_cast<Array*>(bt)) { 00230 throw InternalErr(__FILE__, __LINE__, "Grid::add_var(): object is not an Array!"); 00231 } 00232 00233 // Set to the clone of bt if we get that far. 00234 BaseType* bt_clone = 0; 00235 00236 switch (part) { 00237 00238 case array: { 00239 // Add it as a copy to preserve old semantics. This sets parent too. 00240 bt_clone = bt->ptr_duplicate(); 00241 set_array(static_cast<Array*>(bt_clone)); 00242 } 00243 break; 00244 00245 case maps: { 00246 bt_clone = bt->ptr_duplicate(); 00247 bt_clone->set_parent(this); 00248 d_vars.push_back(bt_clone); 00249 } 00250 break; 00251 00252 default: { 00253 if (!d_is_array_set) { 00254 // Add it as a copy to preserve old semantics. This sets parent too. 00255 bt_clone = bt->ptr_duplicate(); 00256 set_array(static_cast<Array*>(bt_clone)); 00257 } 00258 else { 00259 bt_clone = bt->ptr_duplicate(); 00260 bt_clone->set_parent(this); 00261 d_vars.push_back(bt_clone); 00262 } 00263 } 00264 break; 00265 } 00266 } 00267 00283 void 00284 Grid::add_var_nocopy(BaseType *bt, Part part) 00285 { 00286 if (!bt) 00287 throw InternalErr(__FILE__, __LINE__, "Passing NULL pointer as variable to be added."); 00288 00289 if (part == array && d_is_array_set/*get_array()*/) { 00290 // Avoid leaking memory... Function is add, not set, so it is an error to call again for the array part. 00291 throw InternalErr(__FILE__, __LINE__, "Error: Grid::add_var called with part==Array, but the array was already set!"); 00292 } 00293 00294 // avoid obvious broken semantics 00295 if (!dynamic_cast<Array*>(bt)) { 00296 throw InternalErr(__FILE__, __LINE__, "Grid::add_var(): object is not an Array!"); 00297 } 00298 00299 bt->set_parent(this); 00300 00301 switch (part) { 00302 00303 case array: { 00304 // Refactored to use new set_array ([mjohnson 11 nov 2009]) 00305 set_array(static_cast<Array*>(bt)); 00306 } 00307 break; 00308 00309 case maps: { 00310 // FIXME Why is this commented out? 00311 //bt->set_parent(this); 00312 d_vars.push_back(bt); 00313 } 00314 break; 00315 00316 default: { 00317 if (!d_is_array_set) { 00318 // Refactored to use new set_array ([mjohnson 11 nov 2009]) 00319 // avoid obvious broken semantics 00320 set_array(static_cast<Array*>(bt)); 00321 } 00322 else { 00323 d_vars.push_back(bt); 00324 } 00325 } 00326 break; 00327 } 00328 } 00329 00343 void Grid::set_array(Array* p_new_arr) 00344 { 00345 if (!p_new_arr) { 00346 throw InternalErr(__FILE__, __LINE__, "Grid::set_array(): Cannot set to null!"); 00347 } 00348 00349 // Make sure not same memory, this would be evil. 00350 if (p_new_arr == get_array()) { 00351 return; 00352 } 00353 00354 p_new_arr->set_parent(this); 00355 00356 // Three cases: 1. There are no variables set for this grid at all 00357 // 2. There are maps but no array 00358 // 3. There is already an array set (and maybe maps). 00359 // NB: d_array_var is a weak pointer to the Grid's Array 00360 if (d_vars.size() == 0) { 00361 d_vars.push_back(p_new_arr); 00362 } 00363 else if (!d_is_array_set) { 00364 d_vars.insert(d_vars.begin(), p_new_arr); 00365 } 00366 else { 00367 // clean out old array 00368 delete get_array(); 00369 d_vars[0] = p_new_arr; 00370 } 00371 00372 d_is_array_set = true; 00373 #if 0 00374 // store the array pointer locally 00375 d_array_var = p_new_arr; 00376 00377 // Set the parent 00378 d_array_var->set_parent(this); 00379 #endif 00380 } 00381 00408 Array* 00409 Grid::add_map(Array* p_new_map, bool add_as_copy) 00410 { 00411 if (!p_new_map) 00412 throw InternalErr(__FILE__, __LINE__, "Grid::add_map(): cannot have p_new_map null!"); 00413 00414 if (add_as_copy) 00415 p_new_map = static_cast<Array*>(p_new_map->ptr_duplicate()); 00416 00417 p_new_map->set_parent(this); 00418 00419 d_vars.push_back(p_new_map); 00420 00421 // return the one that got put into the Grid. 00422 return p_new_map; 00423 } 00424 00437 Array* 00438 Grid::prepend_map(Array* p_new_map, bool add_copy) 00439 { 00440 if (add_copy) 00441 { 00442 p_new_map = static_cast<Array*>(p_new_map->ptr_duplicate()); 00443 } 00444 00445 p_new_map->set_parent(this); 00446 d_vars.insert(map_begin(), p_new_map); 00447 00448 return p_new_map; 00449 } 00450 00454 BaseType * 00455 Grid::array_var() 00456 { 00457 //return d_array_var; 00458 // FIXME Should really test that the array has not be set; maps might be added first. jhrg 5/9/13 00459 #if 0 00460 if (d_array_var) 00461 cerr << "In array_var(), d_array_var holds a " << d_array_var->type_name() << endl; 00462 else 00463 cerr << "In array_var(), d_array_var is null" << endl; 00464 #endif 00465 return d_is_array_set /*d_vars.size() > 0*/ ? *d_vars.begin() : 0; 00466 } 00467 00471 Array * 00472 Grid::get_array() 00473 { 00474 return dynamic_cast<Array*>(array_var()); 00475 } 00476 00478 Grid::Map_iter 00479 Grid::map_begin() 00480 { 00481 // The maps are stored in the second and subsequent elements of the 00482 // d_var vector<BaseType*> of Constructor _unless_ the Array part 00483 // has yet to be set. In the latter case, there are only maps in 00484 // d_vars 00485 return d_is_array_set/*(d_array_var != 0)*/ ? d_vars.begin() + 1: d_vars.begin(); 00486 } 00487 00490 Grid::Map_iter 00491 Grid::map_end() 00492 { 00493 return d_vars.end(); 00494 } 00495 00497 Grid::Map_riter 00498 Grid::map_rbegin() 00499 { 00500 // see above 00501 // return d_is_array_set/*(d_array_var != 0)*/ ? d_vars.rbegin() + 1: d_vars.rbegin(); 00502 return d_vars.rbegin(); 00503 } 00504 00507 Grid::Map_riter 00508 Grid::map_rend() 00509 { 00510 return d_is_array_set ? d_vars.rend() - 1: d_vars.rend(); 00511 } 00512 00516 Grid::Map_iter 00517 Grid::get_map_iter(int i) 00518 { 00519 // return map_begin() + i; 00520 return d_is_array_set ? map_begin() + 1 + i : map_begin() + i; 00521 } 00522 00538 int 00539 Grid::components(bool constrained) 00540 { 00541 int comp; 00542 00543 if (constrained) { 00544 comp = get_array()->send_p() ? 1 : 0; 00545 00546 for (Map_iter i = map_begin(); i != map_end(); i++) { 00547 if ((*i)->send_p()) { 00548 comp++; 00549 } 00550 } 00551 } 00552 else { 00553 comp = d_vars.size(); 00554 } 00555 00556 return comp; 00557 } 00558 00559 void Grid::transfer_attributes(AttrTable *at_container) 00560 { 00561 AttrTable *at = at_container->get_attr_table(name()); 00562 00563 if (at) { 00564 at->set_is_global_attribute(false); 00565 00566 array_var()->transfer_attributes(at); 00567 00568 Map_iter map = map_begin(); 00569 while (map != map_end()) { 00570 (*map)->transfer_attributes(at); 00571 map++; 00572 } 00573 00574 // Trick: If an attribute that's within the container 'at' still has its 00575 // is_global_attribute property set, then it's not really a global attr 00576 // but instead an attribute that belongs to this Grid. 00577 AttrTable::Attr_iter at_p = at->attr_begin(); 00578 while (at_p != at->attr_end()) { 00579 if (at->is_global_attribute(at_p)) { 00580 if (at->get_attr_type(at_p) == Attr_container) 00581 get_attr_table().append_container(new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p)); 00582 else 00583 get_attr_table().append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p)); 00584 } 00585 00586 at_p++; 00587 } 00588 } 00589 } 00590 00591 // When projected (using whatever the current constraint provides in the way 00592 // of a projection), is the object still a Grid? 00593 00610 bool 00611 Grid::projection_yields_grid() 00612 { 00613 // For each dimension in the Array part, check the corresponding Map 00614 // vector to make sure it is present in the projected Grid. If for each 00615 // projected dimension in the Array component, there is a matching Map 00616 // vector, then the Grid is valid. 00617 bool valid = true; 00618 Array *a = get_array(); 00619 00620 // Don't bother checking if the Array component is not included. 00621 if (!a->send_p()) 00622 return false; 00623 00624 // If only one part is being sent, it's clearly not a grid (it must be 00625 // the array part of the Grid that's being sent (given that the above 00626 // test passed and the array is being sent). 00627 if (components(true) == 1) 00628 return false; 00629 00630 Array::Dim_iter d = a->dim_begin() ; 00631 Map_iter m = map_begin() ; 00632 00633 while (valid && d != a->dim_end() && m != map_end()) { 00634 Array &map = dynamic_cast<Array&>(**m); 00635 if (a->dimension_size(d, true) && map.send_p()) { 00636 // Check the matching Map vector; the Map projection must equal 00637 // the Array dimension projection 00638 Array::Dim_iter fd = map.dim_begin(); // Maps have only one dim! 00639 valid = map.dimension_start(fd, true) == a->dimension_start(d, true) 00640 && map.dimension_stop(fd, true) == a->dimension_stop(d, true) 00641 && map.dimension_stride(fd, true) == a->dimension_stride(d, true); 00642 } 00643 else { 00644 valid = false; 00645 } 00646 00647 d++, m++; 00648 } 00649 00650 return valid; 00651 } 00652 00654 void 00655 Grid::clear_constraint() 00656 { 00657 get_array()->clear_constraint(); 00658 for (Map_iter m = map_begin(); m != map_end(); ++m) 00659 dynamic_cast<Array&>(*(*m)).clear_constraint(); 00660 } 00661 00662 void 00663 Grid::print_decl(FILE *out, string space, bool print_semi, 00664 bool constraint_info, bool constrained) 00665 { 00666 ostringstream oss; 00667 print_decl(oss, space, print_semi, constraint_info, constrained); 00668 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 00669 } 00670 00671 void 00672 Grid::print_decl(ostream &out, string space, bool print_semi, 00673 bool constraint_info, bool constrained) 00674 { 00675 if (constrained && !send_p()) 00676 return; 00677 00678 // See comment for the FILE* version of this method. 00679 if (constrained && !projection_yields_grid()) { 00680 out << space << "Structure {\n" ; 00681 00682 get_array()->print_decl(out, space + " ", true, constraint_info, 00683 constrained); 00684 00685 for (Map_citer i = map_begin(); i != map_end(); i++) { 00686 (*i)->print_decl(out, space + " ", true, 00687 constraint_info, constrained); 00688 } 00689 00690 out << space << "} " << id2www(name()) ; 00691 } 00692 else { 00693 // The number of elements in the (projected) Grid must be such that 00694 // we have a valid Grid object; send it as such. 00695 out << space << type_name() << " {\n" ; 00696 00697 out << space << " Array:\n" ; 00698 get_array()->print_decl(out, space + " ", true, constraint_info, 00699 constrained); 00700 00701 out << space << " Maps:\n" ; 00702 for (Map_citer i = map_begin(); i != map_end(); i++) { 00703 (*i)->print_decl(out, space + " ", true, 00704 constraint_info, constrained); 00705 } 00706 00707 out << space << "} " << id2www(name()) ; 00708 } 00709 00710 if (constraint_info) { 00711 if (send_p()) 00712 out << ": Send True"; 00713 else 00714 out << ": Send False"; 00715 } 00716 00717 if (print_semi) 00718 out << ";\n" ; 00719 00720 return; 00721 } 00722 00726 void 00727 Grid::print_xml(FILE *out, string space, bool constrained) 00728 { 00729 XMLWriter xml(space); 00730 print_xml_writer(xml, constrained); 00731 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out); 00732 } 00733 00737 void 00738 Grid::print_xml(ostream &out, string space, bool constrained) 00739 { 00740 XMLWriter xml(space); 00741 print_xml_writer(xml, constrained); 00742 out << xml.get_doc(); 00743 } 00744 00745 00746 class PrintGridFieldXMLWriter : public unary_function<BaseType *, void> 00747 { 00748 XMLWriter &d_xml; 00749 bool d_constrained; 00750 string d_tag; 00751 public: 00752 PrintGridFieldXMLWriter(XMLWriter &x, bool c, const string &t = "Map") 00753 : d_xml(x), d_constrained(c), d_tag(t) 00754 {} 00755 00756 void operator()(BaseType *btp) 00757 { 00758 Array *a = dynamic_cast<Array*>(btp); 00759 if (!a) 00760 throw InternalErr(__FILE__, __LINE__, "Expected an Array."); 00761 a->print_xml_writer_core(d_xml, d_constrained, d_tag); 00762 } 00763 }; 00764 00765 void 00766 Grid::print_xml_writer(XMLWriter &xml, bool constrained) 00767 { 00768 if (constrained && !send_p()) 00769 return; 00770 00771 if (constrained && !projection_yields_grid()) { 00772 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"Structure") < 0) 00773 throw InternalErr(__FILE__, __LINE__, "Could not write Structure element"); 00774 00775 if (!name().empty()) 00776 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0) 00777 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name"); 00778 00779 get_attr_table().print_xml_writer(xml); 00780 00781 get_array()->print_xml_writer(xml, constrained); 00782 00783 for_each(map_begin(), map_end(), 00784 PrintGridFieldXMLWriter(xml, constrained, "Array")); 00785 00786 if (xmlTextWriterEndElement(xml.get_writer()) < 0) 00787 throw InternalErr(__FILE__, __LINE__, "Could not end Structure element"); 00788 } 00789 else { 00790 // The number of elements in the (projected) Grid must be such that 00791 // we have a valid Grid object; send it as such. 00792 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"Grid") < 0) 00793 throw InternalErr(__FILE__, __LINE__, "Could not write Grid element"); 00794 00795 if (!name().empty()) 00796 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0) 00797 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name"); 00798 00799 get_attr_table().print_xml_writer(xml); 00800 00801 get_array()->print_xml_writer(xml, constrained); 00802 00803 for_each(map_begin(), map_end(), 00804 PrintGridFieldXMLWriter(xml, constrained, "Map")); 00805 00806 if (xmlTextWriterEndElement(xml.get_writer()) < 0) 00807 throw InternalErr(__FILE__, __LINE__, "Could not end Grid element"); 00808 } 00809 } 00810 00811 void 00812 Grid::print_val(FILE *out, string space, bool print_decl_p) 00813 { 00814 ostringstream oss; 00815 print_val(oss, space, print_decl_p); 00816 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 00817 } 00818 00819 void 00820 Grid::print_val(ostream &out, string space, bool print_decl_p) 00821 { 00822 if (print_decl_p) { 00823 print_decl(out, space, false); 00824 out << " = " ; 00825 } 00826 00827 // If we are printing a value on the client-side, projection_yields_grid 00828 // should not be called since we don't *have* a projection without a 00829 // Constraint. I think that if we are here and send_p() is not true, then 00830 // the value of this function should be ignored. 4/6/2000 jhrg 00831 bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg 00832 if (pyg || !send_p()) 00833 out << "{ Array: " ; 00834 else 00835 out << "{" ; 00836 get_array()->print_val(out, "", false); 00837 if (pyg || !send_p()) 00838 out << " Maps: " ; 00839 for (Map_citer i = map_begin(); i != map_end(); i++, (void)(i != map_end() && out << ", ")) { 00840 (*i)->print_val(out, "", false); 00841 } 00842 out << " }" ; 00843 00844 if (print_decl_p) 00845 out << ";\n" ; 00846 } 00847 00848 // Grids have ugly semantics. 00849 00854 bool 00855 Grid::check_semantics(string &msg, bool all) 00856 { 00857 if (!BaseType::check_semantics(msg)) 00858 return false; 00859 00860 msg = ""; 00861 00862 if (!get_array()) { 00863 msg += "Null grid base array in `" + name() + "'\n"; 00864 return false; 00865 } 00866 00867 // Is it an array? 00868 if (get_array()->type() != dods_array_c) { 00869 msg += "Grid `" + name() + "'s' member `" + get_array()->name() + "' must be an array\n"; 00870 return false; 00871 } 00872 00873 Array *av = (Array *)get_array(); // past test above, must be an array 00874 00875 // Array must be of a simple_type. 00876 if (!av->var()->is_simple_type()) { 00877 msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n"; 00878 return false; 00879 } 00880 00881 // enough maps? 00882 if ((unsigned)d_vars.size()-1 != av->dimensions()) { 00883 msg += "The number of map variables for grid `" + this->name() + "' does not match the number of dimensions of `"; 00884 msg += av->name() + "'\n"; 00885 return false; 00886 } 00887 00888 const string array_var_name = av->name(); 00889 Array::Dim_iter asi = av->dim_begin() ; 00890 for (Map_iter mvi = map_begin(); mvi != map_end(); mvi++, asi++) { 00891 00892 BaseType *mv = *mvi; 00893 00894 // check names 00895 if (array_var_name == mv->name()) { 00896 msg += "Grid map variable `" + mv->name() + "' conflicts with the grid array name in grid `" + name() + "'\n"; 00897 return false; 00898 } 00899 // check types 00900 if (mv->type() != dods_array_c) { 00901 msg += "Grid map variable `" + mv->name() + "' is not an array\n"; 00902 return false; 00903 } 00904 00905 Array *mv_a = (Array *)mv; // downcast to (Array *) 00906 00907 // Array must be of a simple_type. 00908 if (!mv_a->var()->is_simple_type()) { 00909 msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n"; 00910 return false; 00911 } 00912 00913 // check shape 00914 if (mv_a->dimensions() != 1) {// maps must have one dimension 00915 msg += "Grid map variable `" + mv_a->name() + "' must be only one dimension\n"; 00916 return false; 00917 } 00918 // size of map must match corresponding array dimension 00919 Array::Dim_iter mv_asi = mv_a->dim_begin() ; 00920 int mv_a_size = mv_a->dimension_size(mv_asi) ; 00921 int av_size = av->dimension_size(asi) ; 00922 if (mv_a_size != av_size) { 00923 msg += "Grid map variable `" + mv_a->name() + "'s' size does not match the size of array variable '"; 00924 msg += get_array()->name() + "'s' cooresponding dimension\n"; 00925 return false; 00926 } 00927 } 00928 00929 if (all) { 00930 if (!get_array()->check_semantics(msg, true)) 00931 return false; 00932 for (Map_iter mvi = map_begin(); mvi != map_end(); mvi++) { 00933 if (!(*mvi)->check_semantics(msg, true)) { 00934 return false; 00935 } 00936 } 00937 } 00938 00939 return true; 00940 } 00941 00950 void 00951 Grid::dump(ostream &strm) const 00952 { 00953 strm << DapIndent::LMarg << "Grid::dump - (" 00954 << (void *)this << ")" << endl ; 00955 DapIndent::Indent() ; 00956 Constructor::dump(strm) ; 00957 00958 DapIndent::UnIndent() ; 00959 } 00960 00961 } // namespace libdap 00962