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

Generated on Wed Nov 14 03:15:44 2007 for libdap++ by  doxygen 1.5.1