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

Generated on Wed Apr 15 19:20:23 2009 for libdap++ by  doxygen 1.4.7