Grid.cc

Go to the documentation of this file.
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 
00082 Grid::Grid(const Grid &rhs) : Constructor(rhs)
00083 {
00084     _duplicate(rhs);
00085 }
00086 
00087 Grid::~Grid()
00088 {
00089     delete _array_var; _array_var = 0;
00090 
00091     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00092         BaseType *btp = *i ;
00093         delete btp ; btp = 0;
00094     }
00095 }
00096 
00097 BaseType *
00098 Grid::ptr_duplicate()
00099 {
00100     return new Grid(*this);
00101 }
00102 
00103 Grid &
00104 Grid::operator=(const Grid &rhs)
00105 {
00106     if (this == &rhs)
00107         return *this;
00108 
00109     delete _array_var; _array_var = 0;
00110 
00111     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00112         BaseType *btp = *i ;
00113         delete btp ;
00114     }
00115 
00116     dynamic_cast<Constructor &>(*this) = rhs;
00117 
00118     _duplicate(rhs);
00119 
00120     return *this;
00121 }
00122 
00123 int
00124 Grid::element_count(bool leaves)
00125 {
00126     if (!leaves)
00127         return _map_vars.size() + 1;
00128     else {
00129         int i = 0;
00130         for (Map_iter j = _map_vars.begin(); j != _map_vars.end(); j++) {
00131             j += (*j)->element_count(leaves);
00132         }
00133 
00134         i += get_array()->element_count(leaves);
00135         return i;
00136     }
00137 }
00138 
00139 void
00140 Grid::set_send_p(bool state)
00141 {
00142     _array_var->set_send_p(state);
00143 
00144     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00145         (*i)->set_send_p(state);
00146     }
00147 
00148     BaseType::set_send_p(state);
00149 }
00150 
00151 void
00152 Grid::set_read_p(bool state)
00153 {
00154     _array_var->set_read_p(state);
00155 
00156     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00157         (*i)->set_read_p(state);
00158     }
00159 
00160     BaseType::set_read_p(state);
00161 }
00162 
00163 void
00164 Grid::set_in_selection(bool state)
00165 {
00166     _array_var->set_in_selection(state);
00167 
00168     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00169         (*i)->set_in_selection(state);
00170     }
00171 
00172     BaseType::set_in_selection(state);
00173 }
00174 
00175 unsigned int
00176 Grid::width()
00177 {
00178     unsigned int sz = _array_var->width();
00179 
00180     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00181         sz += (*i)->width();
00182     }
00183 
00184     return sz;
00185 }
00186 
00187 void
00188 Grid::intern_data(const string &dataset, ConstraintEvaluator &eval, DDS &dds)
00189 {
00190     dds.timeout_on();
00191 
00192     if (!read_p())
00193         read(dataset);  // read() throws Error and InternalErr
00194 
00195     dds.timeout_off();
00196 
00197     if (_array_var->send_p())
00198         _array_var->intern_data(dataset, eval, dds);
00199 
00200     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00201         if ((*i)->send_p()) {
00202             (*i)->intern_data(dataset, eval, dds);
00203         }
00204     }
00205 }
00206 
00207 bool
00208 Grid::serialize(const string &dataset, ConstraintEvaluator &eval, DDS &dds,
00209                 Marshaller &m, bool ce_eval)
00210 {
00211     dds.timeout_on();
00212 
00213     // Re ticket 560: Get an object from eval that describes how to sample
00214     // and rearrange the data, then perform those actions. Alternative:
00215     // implement this as a selection function.
00216 
00217     if (!read_p())
00218         read(dataset);  // read() throws Error and InternalErr
00219 
00220 #if EVAL
00221     if (ce_eval && !eval.eval_selection(dds, dataset))
00222         return true;
00223 #endif
00224 
00225     dds.timeout_off();
00226 
00227     if (_array_var->send_p())
00228         _array_var->serialize(dataset, eval, dds, m, false);
00229 
00230     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00231         if ((*i)->send_p()) {
00232             (*i)->serialize(dataset, eval, dds, m, false);
00233         }
00234     }
00235 
00236     return true;
00237 }
00238 
00239 bool
00240 Grid::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
00241 {
00242     _array_var->deserialize(um, dds, reuse);
00243 
00244     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00245         (*i)->deserialize(um, dds, reuse);
00246     }
00247 
00248     return false;
00249 }
00250 
00258 unsigned int
00259 Grid::val2buf(void *, bool)
00260 {
00261     return sizeof(Grid);
00262 }
00263 
00267 unsigned int
00268 Grid::buf2val(void **)
00269 {
00270     return sizeof(Grid);
00271 }
00272 
00273 BaseType *
00274 Grid::var(const string &n, btp_stack &s)
00275 {
00276     return var(n, true, &s);
00277 }
00278 
00283 BaseType *
00284 Grid::var(const string &n, bool, btp_stack *s)
00285 {
00286     string name = www2id(n);
00287 
00288     if (_array_var->name() == name) {
00289         if (s)
00290             s->push(static_cast<BaseType *>(this));
00291         return _array_var;
00292     }
00293 
00294     for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00295         if ((*i)->name() == name) {
00296             if (s)
00297                 s->push(static_cast<BaseType *>(this));
00298             return *i;
00299         }
00300     }
00301 
00302     return 0;
00303 }
00304 
00317 void
00318 Grid::add_var(BaseType *bt, Part part)
00319 {
00320     if (!bt)
00321         throw InternalErr(__FILE__, __LINE__,
00322                           "Passing NULL pointer as variable to be added.");
00323 
00324     // Jose Garcia
00325     // Now we get a copy of the maps or of the array
00326     // so the owner of bt which is external to libdap++
00327     // is free to deallocate its object.
00328     switch (part) {
00329     case array:
00330         _array_var = bt->ptr_duplicate();
00331         _array_var->set_parent(this);
00332         return;
00333     case maps: {
00334             BaseType *btp = bt->ptr_duplicate();
00335             btp->set_parent(this);
00336             _map_vars.push_back(btp);
00337             return;
00338         }
00339     default:
00340         if (!_array_var) {
00341             _array_var = bt->ptr_duplicate();
00342             _array_var->set_parent(this);
00343         }
00344         else {
00345             BaseType *btp = bt->ptr_duplicate();
00346             btp->set_parent(this);
00347             _map_vars.push_back(btp);
00348         }
00349         return;
00350     }
00351 }
00352 
00356 BaseType *
00357 Grid::array_var()
00358 {
00359     return _array_var;
00360 }
00361 
00365 Array *
00366 Grid::get_array()
00367 {
00368     return dynamic_cast<Array*>(_array_var);
00369 }
00370 
00372 Grid::Map_iter
00373 Grid::map_begin()
00374 {
00375     return _map_vars.begin() ;
00376 }
00377 
00380 Grid::Map_iter
00381 Grid::map_end()
00382 {
00383     return _map_vars.end() ;
00384 }
00385 
00387 Grid::Map_riter
00388 Grid::map_rbegin()
00389 {
00390     return _map_vars.rbegin() ;
00391 }
00392 
00395 Grid::Map_riter
00396 Grid::map_rend()
00397 {
00398     return _map_vars.rend() ;
00399 }
00400 
00404 Grid::Map_iter
00405 Grid::get_map_iter(int i)
00406 {
00407     return _map_vars.begin() + i;
00408 }
00409 
00425 int
00426 Grid::components(bool constrained)
00427 {
00428     int comp;
00429 
00430     if (constrained) {
00431         comp = _array_var->send_p() ? 1 : 0;
00432 
00433         for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
00434             if ((*i)->send_p()) {
00435                 comp++;
00436             }
00437         }
00438     }
00439     else {
00440         comp = 1 + _map_vars.size();
00441     }
00442 
00443     return comp;
00444 }
00445 
00446 // When projected (using whatever the current constraint provides in the way
00447 // of a projection), is the object still a Grid?
00448 
00465 bool
00466 Grid::projection_yields_grid()
00467 {
00468     // For each dimension in the Array part, check the corresponding Map
00469     // vector to make sure it is present in the projected Grid. If for each
00470     // projected dimension in the Array component, there is a matching Map
00471     // vector, then the Grid is valid.
00472     bool valid = true;
00473     Array *a = (Array *)_array_var;
00474 
00475     // Don't bother checking if the Array component is not included.
00476     if (!a->send_p())
00477         return false;
00478 
00479     Array::Dim_iter i = a->dim_begin() ;
00480     Map_iter m = map_begin() ;
00481     for (; valid && i != a->dim_end() && m != map_end(); i++, m++) {
00482         if (a->dimension_size(i, true)) {
00483             // Check the matching Map vector; the Map projection must equal
00484             // the Array dimension projection
00485             Array *map = (Array *)(*m);
00486             Array::Dim_iter fd = map->dim_begin(); // Maps have only one dim!
00487             valid = map->dimension_start(fd, true)
00488                     == a->dimension_start(i, true)
00489                     && map->dimension_stop(fd, true)
00490                     == a->dimension_stop(i, true)
00491                     && map->dimension_stride(fd, true)
00492                     == a->dimension_stride(i, true);
00493         }
00494         else {
00495             // Corresponding Map vector must be excluded from the projection.
00496             Array *map = (Array *)(*m);
00497             valid = !map->send_p();
00498         }
00499     }
00500 
00501     return valid;
00502 }
00503 
00505 void
00506 Grid::clear_constraint()
00507 {
00508     dynamic_cast<Array&>(*_array_var).clear_constraint();
00509     for (Map_iter m = map_begin(); m != map_end(); ++m)
00510         dynamic_cast<Array&>(*(*m)).clear_constraint();
00511 }
00512 
00513 void
00514 Grid::print_decl(FILE *out, string space, bool print_semi,
00515                  bool constraint_info, bool constrained)
00516 {
00517     if (constrained && !send_p())
00518         return;
00519 
00520     // If we are printing the declaration of a constrained Grid then check for
00521     // the case where the projection removes all but one component; the
00522     // resulting object is a simple array.
00523     int projection = components(true);
00524     if (constrained && projection == 1) {
00525         _array_var->print_decl(out, space, print_semi /*true*/, constraint_info,
00526                                constrained);
00527         for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
00528             (*i)->print_decl(out, space, print_semi /*true*/, constraint_info, constrained);
00529         }
00530 
00531         goto exit;  // Skip end material.
00532     }
00533     // If there are M (< N) componets (Array and Maps combined) in a N
00534     // component Grid, send the M components as elements of a Struture.
00535     // This will preserve the grouping without violating the rules for a
00536     // Grid.
00537     else if (constrained && !projection_yields_grid()) {
00538         fprintf(out, "%sStructure {\n", space.c_str()) ;
00539 
00540         _array_var->print_decl(out, space + "    ", true, constraint_info,
00541                                constrained);
00542 
00543         for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
00544             (*i)->print_decl(out, space + "    ", true,
00545                              constraint_info, constrained);
00546         }
00547 
00548         fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
00549     }
00550     else {
00551         // The number of elements in the (projected) Grid must be such that
00552         // we have a valid Grid object; send it as such.
00553         fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ;
00554 
00555         fprintf(out, "%s  Array:\n", space.c_str()) ;
00556         _array_var->print_decl(out, space + "    ", true, constraint_info,
00557                                constrained);
00558 
00559         fprintf(out, "%s  Maps:\n", space.c_str()) ;
00560         for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
00561             (*i)->print_decl(out, space + "    ", true,
00562                              constraint_info, constrained);
00563         }
00564 
00565         fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
00566     }
00567 
00568     if (constraint_info) {
00569         if (send_p())
00570             fprintf( out, ": Send True");
00571         else
00572             fprintf( out, ": Send False");
00573     }
00574 
00575     if (print_semi)
00576         fprintf(out, ";\n") ;
00577 
00578     // If sending just one comp, skip sending the terminal semicolon, etc.
00579 exit:
00580     return;
00581 }
00582 
00583 void
00584 Grid::print_decl(ostream &out, string space, bool print_semi,
00585                  bool constraint_info, bool constrained)
00586 {
00587     if (constrained && !send_p())
00588         return;
00589 
00590     // If we are printing the declaration of a constrained Grid then check for
00591     // the case where the projection removes all but one component; the
00592     // resulting object is a simple array.
00593     //
00594     // I replaced the 'true' with the value of 'print_semi' passed in by the 
00595     // caller. This fixes an issue with the intern_data tests and does not
00596     // seem to break anything else. jhrg 11/9/07
00597     int projection = components(true);
00598     if (constrained && projection == 1) {
00599         _array_var->print_decl(out, space, print_semi /*true*/, constraint_info,
00600                                constrained);
00601         for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
00602             (*i)->print_decl(out, space, print_semi /*true*/, constraint_info, constrained);
00603         }
00604 
00605         goto exit;  // Skip end material.
00606     }
00607     // If there are M (< N) componets (Array and Maps combined) in a N
00608     // component Grid, send the M components as elements of a Struture.
00609     // This will preserve the grouping without violating the rules for a
00610     // Grid.
00611     else if (constrained && !projection_yields_grid()) {
00612         out << space << "Structure {\n" ;
00613 
00614         _array_var->print_decl(out, space + "    ", true, constraint_info,
00615                                constrained);
00616 
00617         for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
00618             (*i)->print_decl(out, space + "    ", true,
00619                              constraint_info, constrained);
00620         }
00621 
00622         out << space << "} " << id2www(name()) ;
00623     }
00624     else {
00625         // The number of elements in the (projected) Grid must be such that
00626         // we have a valid Grid object; send it as such.
00627         out << space << type_name() << " {\n" ;
00628 
00629         out << space << "  Array:\n" ;
00630         _array_var->print_decl(out, space + "    ", true, constraint_info,
00631                                constrained);
00632 
00633         out << space << "  Maps:\n" ;
00634         for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
00635             (*i)->print_decl(out, space + "    ", true,
00636                              constraint_info, constrained);
00637         }
00638 
00639         out << space << "} " << id2www(name()) ;
00640     }
00641 
00642     if (constraint_info) {
00643         if (send_p())
00644             out << ": Send True";
00645         else
00646             out << ": Send False";
00647     }
00648 
00649     if (print_semi)
00650         out << ";\n" ;
00651 
00652     // If sending just one comp, skip sending the terminal semicolon, etc.
00653 exit:
00654     return;
00655 }
00656 
00657 class PrintMapField : public unary_function<BaseType *, void>
00658 {
00659     FILE *d_out;
00660     string d_space;
00661     bool d_constrained;
00662 public:
00663     PrintMapField(FILE *o, string s, bool c)
00664             : d_out(o), d_space(s), d_constrained(c)
00665     {}
00666 
00667     void operator()(BaseType *btp)
00668     {
00669         Array *a = dynamic_cast<Array*>(btp);
00670         if (!a)
00671             throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
00672         a->print_as_map_xml(d_out, d_space, d_constrained);
00673     }
00674 };
00675 
00676 void
00677 Grid::print_xml(FILE *out, string space, bool constrained)
00678 {
00679     if (constrained && !send_p())
00680         return;
00681 
00682     fprintf(out, "%s<Grid", space.c_str());
00683     if (!name().empty())
00684         fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00685 
00686     fprintf(out, ">\n");
00687 
00688     get_attr_table().print_xml(out, space + "    ", constrained);
00689 
00690     get_array()->print_xml(out, space + "    ", constrained);
00691 
00692     for_each(map_begin(), map_end(),
00693              PrintMapField(out, space + "    ", constrained));
00694 
00695     fprintf(out, "%s</Grid>\n", space.c_str());
00696 }
00697 
00698 class PrintMapFieldStrm : public unary_function<BaseType *, void>
00699 {
00700     ostream &d_out;
00701     string d_space;
00702     bool d_constrained;
00703 public:
00704     PrintMapFieldStrm(ostream &o, string s, bool c)
00705             : d_out(o), d_space(s), d_constrained(c)
00706     {}
00707 
00708     void operator()(BaseType *btp)
00709     {
00710         Array *a = dynamic_cast<Array*>(btp);
00711         if (!a)
00712             throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
00713         a->print_as_map_xml(d_out, d_space, d_constrained);
00714     }
00715 };
00716 
00717 void
00718 Grid::print_xml(ostream &out, string space, bool constrained)
00719 {
00720     if (constrained && !send_p())
00721         return;
00722 
00723     out << space << "<Grid" ;
00724     if (!name().empty())
00725         out << " name=\"" << id2xml(name()) << "\"" ;
00726 
00727     out << ">\n" ;
00728 
00729     get_attr_table().print_xml(out, space + "    ", constrained);
00730 
00731     get_array()->print_xml(out, space + "    ", constrained);
00732 
00733     for_each(map_begin(), map_end(),
00734              PrintMapFieldStrm(out, space + "    ", constrained));
00735 
00736     out << space << "</Grid>\n" ;
00737 }
00738 
00739 void
00740 Grid::print_val(FILE *out, string space, bool print_decl_p)
00741 {
00742     if (print_decl_p) {
00743         print_decl(out, space, false);
00744         fprintf(out, " = ") ;
00745     }
00746 
00747     // If we are printing a value on the client-side, projection_yields_grid
00748     // should not be called since we don't *have* a projection without a
00749     // contraint. I think that if we are here and send_p() is not true, then
00750     // the value of this function should be ignored. 4/6/2000 jhrg
00751     bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg
00752     if (pyg || !send_p())
00753         fprintf(out, "{  Array: ") ;
00754     else
00755         fprintf(out, "{") ;
00756     _array_var->print_val(out, "", false);
00757     if (pyg || !send_p())
00758         fprintf(out, "  Maps: ") ;
00759     for (Map_citer i = _map_vars.begin(); i != _map_vars.end();
00760          i++, (void)(i != _map_vars.end() && fprintf(out, ", "))) {
00761         (*i)->print_val(out, "", false);
00762     }
00763     fprintf(out, " }") ;
00764 
00765     if (print_decl_p)
00766         fprintf(out, ";\n") ;
00767 }
00768 
00769 void
00770 Grid::print_val(ostream &out, string space, bool print_decl_p)
00771 {
00772     if (print_decl_p) {
00773         print_decl(out, space, false);
00774         out << " = " ;
00775     }
00776 
00777     // If we are printing a value on the client-side, projection_yields_grid
00778     // should not be called since we don't *have* a projection without a
00779     // contraint. I think that if we are here and send_p() is not true, then
00780     // the value of this function should be ignored. 4/6/2000 jhrg
00781     bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg
00782     if (pyg || !send_p())
00783         out << "{  Array: " ;
00784     else
00785         out << "{" ;
00786     _array_var->print_val(out, "", false);
00787     if (pyg || !send_p())
00788         out << "  Maps: " ;
00789     for (Map_citer i = _map_vars.begin(); i != _map_vars.end();
00790          i++, (void)(i != _map_vars.end() && out << ", ")) {
00791         (*i)->print_val(out, "", false);
00792     }
00793     out << " }" ;
00794 
00795     if (print_decl_p)
00796         out << ";\n" ;
00797 }
00798 
00799 // Grids have ugly semantics.
00800 
00805 bool
00806 Grid::check_semantics(string &msg, bool all)
00807 {
00808     if (!BaseType::check_semantics(msg))
00809         return false;
00810 #if 0
00811     // Actually, the spec doesn't say this. jhrg 2/13/06
00812     if (!unique_names(_map_vars, name(), type_name(), msg))
00813         return false;
00814 #endif
00815 
00816     msg = "";
00817 
00818     if (!_array_var) {
00819         msg += "Null grid base array in `" + name() + "'\n";
00820         return false;
00821     }
00822 
00823     // Is it an array?
00824     if (_array_var->type() != dods_array_c) {
00825         msg += "Grid `" + name() + "'s' member `" + _array_var->name() + "' must be an array\n";
00826         return false;
00827     }
00828 
00829     Array *av = (Array *)_array_var; // past test above, must be an array
00830 
00831     // Array must be of a simple_type.
00832     if (!av->var()->is_simple_type()) {
00833         msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n";
00834         return false;
00835     }
00836 
00837     // enough maps?
00838     if ((unsigned)_map_vars.size() != av->dimensions()) {
00839         msg += "The number of map variables for grid `" + this->name() + "' does not match the number of dimensions of `";
00840         msg += av->name() + "'\n";
00841         return false;
00842     }
00843 
00844     const string array_var_name = av->name();
00845     Array::Dim_iter asi = av->dim_begin() ;
00846     for (Map_iter mvi = _map_vars.begin();
00847          mvi != _map_vars.end(); mvi++, asi++) {
00848 
00849         BaseType *mv = *mvi;
00850 
00851         // check names
00852         if (array_var_name == mv->name()) {
00853             msg += "Grid map variable `" + mv->name() + "' conflicts with the grid array name in grid `" + name() + "'\n";
00854             return false;
00855         }
00856         // check types
00857         if (mv->type() != dods_array_c) {
00858             msg += "Grid map variable  `" + mv->name() + "' is not an array\n";
00859             return false;
00860         }
00861 
00862         Array *mv_a = (Array *)mv; // downcast to (Array *)
00863 
00864         // Array must be of a simple_type.
00865         if (!mv_a->var()->is_simple_type()) {
00866             msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n";
00867             return false;
00868         }
00869 
00870         // check shape
00871         if (mv_a->dimensions() != 1) {// maps must have one dimension
00872             msg += "Grid map variable  `" + mv_a->name() + "' must be only one dimension\n";
00873             return false;
00874         }
00875         // size of map must match corresponding array dimension
00876         Array::Dim_iter mv_asi = mv_a->dim_begin() ;
00877         int mv_a_size = mv_a->dimension_size(mv_asi) ;
00878         int av_size = av->dimension_size(asi) ;
00879         if (mv_a_size != av_size) {
00880             msg += "Grid map variable  `" + mv_a->name() + "'s' size does not match the size of array variable '";
00881             msg += _array_var->name() + "'s' cooresponding dimension\n";
00882             return false;
00883         }
00884     }
00885 
00886     if (all) {
00887         if (!_array_var->check_semantics(msg, true))
00888             return false;
00889         for (Map_iter mvi = _map_vars.begin(); mvi != _map_vars.end(); mvi++) {
00890             if (!(*mvi)->check_semantics(msg, true)) {
00891                 return false;
00892             }
00893         }
00894     }
00895 
00896     return true;
00897 }
00898 
00907 void
00908 Grid::dump(ostream &strm) const
00909 {
00910     strm << DapIndent::LMarg << "Grid::dump - ("
00911     << (void *)this << ")" << endl ;
00912     DapIndent::Indent() ;
00913     Constructor::dump(strm) ;
00914     if (_array_var) {
00915         strm << DapIndent::LMarg << "array var: " << endl ;
00916         DapIndent::Indent() ;
00917         _array_var->dump(strm) ;
00918         DapIndent::UnIndent() ;
00919     }
00920     else {
00921         strm << DapIndent::LMarg << "array var: null" << endl ;
00922     }
00923     strm << DapIndent::LMarg << "map var: " << endl ;
00924     DapIndent::Indent() ;
00925     Map_citer i = _map_vars.begin() ;
00926     Map_citer ie = _map_vars.end() ;
00927     for (; i != ie; i++) {
00928         (*i)->dump(strm) ;
00929     }
00930     DapIndent::UnIndent() ;
00931     DapIndent::UnIndent() ;
00932 }
00933 
00934 } // namespace libdap
00935 

Generated on Wed Mar 5 15:27:11 2008 for libdap++ by  doxygen 1.5.4