libdap++  Updated for version 3.11.7
Grid.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1994-1999
27 // Please read the full copyright statement in the file COPYRIGHT_URI.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31 
32 // implementation for Grid.
33 //
34 // jhrg 9/15/94
35 
36 #include "config.h"
37 
38 // #define DODS_DEBUG
39 
40 #include <functional>
41 #include <algorithm>
42 
43 #include "Grid.h"
44 #include "DDS.h"
45 #include "Array.h" // for downcasts
46 #include "util.h"
47 #include "InternalErr.h"
48 #include "escaping.h"
49 #include "XDRStreamMarshaller.h"
50 #include "debug.h"
51 
52 using namespace std;
53 
54 namespace libdap {
55 
56 void
57 Grid::_duplicate(const Grid &s)
58 {
59  // Clear out any spurious vars in Constructor::_vars
60  _vars.clear(); // [mjohnson 10 Sep 2009]
61 
62  _array_var = s._array_var->ptr_duplicate();
63  _array_var->set_parent(this);
64  _vars.push_back(_array_var); // so the Constructor::Vars_Iter sees it [mjohnson 10 Sep 2009]
65 
66  Grid &cs = const_cast<Grid &>(s);
67 
68  for (Map_iter i = cs._map_vars.begin(); i != cs._map_vars.end(); i++) {
69  BaseType *btp = (*i)->ptr_duplicate();
70  btp->set_parent(this);
71  _map_vars.push_back(btp);
72  _vars.push_back(btp); // push all map vectors as weak refs into super::_vars which won't delete them [mjohnson 10 Sep 2009]
73  }
74 
75 }
76 
86 Grid::Grid(const string &n) : Constructor(n, dods_grid_c), _array_var(0)
87 {}
88 
100 Grid::Grid(const string &n, const string &d)
101  : Constructor(n, d, dods_grid_c), _array_var(0)
102 {}
103 
105 Grid::Grid(const Grid &rhs) : Constructor(rhs)
106 {
107  _duplicate(rhs);
108 }
109 
111 {
112  delete _array_var; _array_var = 0;
113 
114  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
115  BaseType *btp = *i ;
116  delete btp ; btp = 0;
117  }
118 }
119 
120 BaseType *
122 {
123  return new Grid(*this);
124 }
125 
126 Grid &
128 {
129  if (this == &rhs)
130  return *this;
131 
132  delete _array_var; _array_var = 0;
133 
134  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
135  BaseType *btp = *i ;
136  delete btp ;
137  }
138 
139  // this doesn't copy Constructor::_vars so...
140  dynamic_cast<Constructor &>(*this) = rhs;
141 
142  // we do it in here...
143  _duplicate(rhs);
144 
145  return *this;
146 }
147 
148 int
150 {
151  if (!leaves)
152  return _map_vars.size() + 1;
153  else {
154  int i = 0;
155  for (Map_iter j = _map_vars.begin(); j != _map_vars.end(); j++) {
156  j += (*j)->element_count(leaves);
157  }
158 
159  if (!get_array())
160  throw InternalErr(__FILE__, __LINE__, "No Grid arry!");
161 
162  i += get_array()->element_count(leaves);
163  return i;
164  }
165 }
166 
167 void
168 Grid::set_send_p(bool state)
169 {
170  _array_var->set_send_p(state);
171 
172  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
173  (*i)->set_send_p(state);
174  }
175 
176  BaseType::set_send_p(state);
177 }
178 
179 void
180 Grid::set_read_p(bool state)
181 {
182  _array_var->set_read_p(state);
183 
184  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
185  (*i)->set_read_p(state);
186  }
187 
188  BaseType::set_read_p(state);
189 }
190 
191 void
193 {
194  _array_var->set_in_selection(state);
195 
196  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
197  (*i)->set_in_selection(state);
198  }
199 
201 }
202 
203 unsigned int
205 {
206  unsigned int sz = _array_var->width();
207 
208  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
209  sz += (*i)->width();
210  }
211 
212  return sz;
213 }
214 
222 unsigned int
223 Grid::width(bool constrained)
224 {
225  unsigned int sz = 0;
226 
227  if (constrained) {
228  if (_array_var->send_p())
229  sz = _array_var->width(constrained);
230  }
231  else {
232  sz = _array_var->width(constrained);
233  }
234 
235  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
236  if (constrained) {
237  if ((*i)->send_p())
238  sz += (*i)->width(constrained);
239  }
240  else {
241  sz += (*i)->width(constrained);
242  }
243  }
244 
245  return sz;
246 }
247 
248 void
250 {
251  dds.timeout_on();
252 
253  if (!read_p())
254  read(); // read() throws Error and InternalErr
255 
256  dds.timeout_off();
257 
258  if (_array_var->send_p())
259  _array_var->intern_data(eval, dds);
260 
261  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
262  if ((*i)->send_p()) {
263  (*i)->intern_data(eval, dds);
264  }
265  }
266 }
267 
268 bool
269 Grid::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
270 {
271  DBG(cerr << "In Grid::serialize()" << endl);
272 
273  dds.timeout_on();
274 
275  // Re ticket 560: Get an object from eval that describes how to sample
276  // and rearrange the data, then perform those actions. Alternative:
277  // implement this as a selection function.
278  DBG(cerr << "In Grid::serialize(), before read() - read_p() returned: " << read_p() << endl);
279 
280  if (!read_p())
281  read(); // read() throws Error and InternalErr
282 
283  DBG(cerr << "In Grid::serialize(), past read() - read_p() returned: " << read_p() << endl);
284 
285  #if EVAL
286  if (ce_eval && !eval.eval_selection(dds, dataset()))
287  return true;
288 #endif
289 
290  dds.timeout_off();
291 
292  if (_array_var->send_p()) {
293 #ifdef CHECKSUMS
294  XDRStreamMarshaller &sm = dynamic_cast<XDRStreamMarshaller &>(m);
295  sm.reset_checksum();
296 
297  _array_var->serialize(eval, dds, m, false);
298 
299  //cerr << _array_var->name() << ": " <<
300  sm.get_checksum();// << endl;
301 #else
302  DBG(cerr << "About to call Array::serialize() in Grid::serialize" << endl);
303  _array_var->serialize(eval, dds, m, false);
304 #endif
305  }
306 
307  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
308  if ((*i)->send_p()) {
309 #ifdef CHECKSUMS
310  XDRStreamMarshaller &sm = dynamic_cast<XDRStreamMarshaller &>(m);
311  sm.reset_checksum();
312 
313  (*i)->serialize(eval, dds, m, false);
314 
315  //cerr << (*i)->name() << ": " <<
316  sm.get_checksum(); // << endl;
317 #else
318  (*i)->serialize(eval, dds, m, false);
319 #endif
320  }
321  }
322 
323  return true;
324 }
325 
326 bool
327 Grid::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
328 {
329  _array_var->deserialize(um, dds, reuse);
330 
331  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
332  (*i)->deserialize(um, dds, reuse);
333  }
334 
335  return false;
336 }
337 
345 unsigned int
346 Grid::val2buf(void *, bool)
347 {
348  return sizeof(Grid);
349 }
350 
354 unsigned int
356 {
357  return sizeof(Grid);
358 }
359 
360 BaseType *
361 Grid::var(const string &n, btp_stack &s)
362 {
363  return var(n, true, &s);
364 }
365 
370 BaseType *
371 Grid::var(const string &n, bool, btp_stack *s)
372 {
373  string name = www2id(n);
374 
375  if (_array_var->name() == name) {
376  if (s)
377  s->push(static_cast<BaseType *>(this));
378  return _array_var;
379  }
380 
381  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
382  if ((*i)->name() == name) {
383  if (s)
384  s->push(static_cast<BaseType *>(this));
385  return *i;
386  }
387  }
388 
389  return 0;
390 }
391 
404 void
406 {
407  if (!bt) {
408  throw InternalErr(__FILE__, __LINE__,
409  "Passing NULL pointer as variable to be added.");
410  }
411 
412  if (part == array && _array_var) {
413  // Avoid leaking memory... Function is add, not set, so it is an error to call again for the array part.
414  throw InternalErr(__FILE__, __LINE__, "Error: Grid::add_var called with part==Array, but the array was already set!");
415  }
416 
417  // Set to the clone of bt if we get that far.
418  BaseType* bt_clone = 0;
419 
420  switch (part) {
421 
422  case array: {
423  // Refactored to use new set_array ([mjohnson 11 nov 2009])
424  Array* p_arr = dynamic_cast<Array*>(bt);
425  // avoid obvious broken semantics
426  if (!p_arr) {
427  throw InternalErr(__FILE__, __LINE__,
428  "Grid::add_var(): with Part==array: object is not an Array!");
429  }
430  // Add it as a copy to preserve old semantics. This sets parent too.
431  bt_clone = p_arr->ptr_duplicate();
432  set_array(static_cast<Array*>(bt_clone));
433  }
434  break;
435 
436  case maps: {
437  bt_clone = bt->ptr_duplicate();
438  bt_clone->set_parent(this);
439  _map_vars.push_back(bt_clone);
440  }
441  break;
442 
443  default: {
444  if (!_array_var) {
445  // Refactored to use new set_array ([mjohnson 11 nov 2009])
446  Array* p_arr = dynamic_cast<Array*>(bt);
447  // avoid obvious broken semantics
448  if (!p_arr) {
449  throw InternalErr(__FILE__, __LINE__,
450  "Grid::add_var(): with Part==array: object is not an Array!");
451  }
452  // Add it as a copy to preserve old semantics. This sets parent too.
453  bt_clone = p_arr->ptr_duplicate();
454  set_array(static_cast<Array*>(bt_clone));
455  }
456  else {
457  bt_clone = bt->ptr_duplicate();
458  bt_clone->set_parent(this);
459  _map_vars.push_back(bt_clone);
460  }
461  }
462  break;
463  }// switch
464 
465  // if we get ehre without exception, add the cloned object to the superclass variable iterator
466  // mjohnson 10 Sep 2009
467  // Add it to the superclass _vars list so we can iterate on superclass vars
468  if (bt_clone) {
469  _vars.push_back(bt_clone);
470  }
471 }
472 
488 void
490 {
491  if (!bt) {
492  throw InternalErr(__FILE__, __LINE__,
493  "Passing NULL pointer as variable to be added.");
494  }
495 
496  if (part == array && _array_var) {
497  // Avoid leaking memory... Function is add, not set, so it is an error to call again for the array part.
498  throw InternalErr(__FILE__, __LINE__, "Error: Grid::add_var called with part==Array, but the array was already set!");
499  }
500 
501  bt->set_parent(this);
502 
503  switch (part) {
504 
505  case array: {
506  // Refactored to use new set_array ([mjohnson 11 nov 2009])
507  Array* p_arr = dynamic_cast<Array*>(bt);
508  // avoid obvious broken semantics
509  if (!p_arr) {
510  throw InternalErr(__FILE__, __LINE__,
511  "Grid::add_var(): with Part==array: object is not an Array!");
512  }
513  set_array(static_cast<Array*>(bt));
514  }
515  break;
516 
517  case maps: {
518  //bt->set_parent(this);
519  _map_vars.push_back(bt);
520  }
521  break;
522 
523  default: {
524  if (!_array_var) {
525  // Refactored to use new set_array ([mjohnson 11 nov 2009])
526  Array* p_arr = dynamic_cast<Array*>(bt);
527  // avoid obvious broken semantics
528  if (!p_arr) {
529  throw InternalErr(__FILE__, __LINE__,
530  "Grid::add_var(): with Part==array: object is not an Array!");
531  }
532  set_array(static_cast<Array*>(bt));
533  }
534  else {
535  _map_vars.push_back(bt);
536  }
537  }
538  break;
539  }// switch
540 
541  // if we get here without exception, add the cloned object to the superclass variable iterator
542  // mjohnson 10 Sep 2009
543  // Add it to the superclass _vars list so we can iterate on superclass vars
544  if (bt) {
545  _vars.push_back(bt);
546  }
547 }
548 
558 void
560 {
561  if (!p_new_arr) {
562  throw InternalErr(__FILE__, __LINE__,
563  "Grid::set_array(): Cannot set to null!");
564  }
565  // Make sure not same memory, this would be evil.
566  if (p_new_arr == _array_var) {
567  return;
568  }
569  // clean out any old array
570  delete _array_var; _array_var = 0;
571  // Set the new, with parent
572  _array_var = p_new_arr;
573  _array_var->set_parent(this);
574 }
575 
602 Array*
603 Grid::add_map(Array* p_new_map, bool add_as_copy)
604 {
605  if (!p_new_map) {
606  throw InternalErr(__FILE__, __LINE__,
607  "Grid::add_map(): cannot have p_new_map null!");
608  }
609 
610  if (add_as_copy) {
611  p_new_map = static_cast<Array*>(p_new_map->ptr_duplicate());
612  }
613 
614  p_new_map->set_parent(this);
615  _map_vars.push_back(p_new_map);
616  _vars.push_back(p_new_map); // allow superclass iter to work as well.
617 
618  // return the one that got put into the Grid.
619  return p_new_map;
620 }
621 
634 Array*
635 Grid::prepend_map(Array* p_new_map, bool add_copy)
636 {
637  if (add_copy)
638  {
639  p_new_map = static_cast<Array*>(p_new_map->ptr_duplicate());
640  }
641 
642  p_new_map->set_parent(this);
643  _map_vars.insert(_map_vars.begin(), p_new_map);
644  _vars.insert(_vars.begin(), p_new_map); // allow superclass iter to work as well.
645 
646  // return the one that got put into the Grid.
647  return p_new_map;
648 }
649 
653 BaseType *
655 {
656  return _array_var;
657 }
658 
662 Array *
664 {
665  Array *a = dynamic_cast<Array*>(_array_var);
666  if (a)
667  return a;
668  else
669  throw InternalErr(__FILE__, __LINE__, "bad Cast");
670 }
671 
675 {
676  return _map_vars.begin() ;
677 }
678 
683 {
684  return _map_vars.end() ;
685 }
686 
690 {
691  return _map_vars.rbegin() ;
692 }
693 
698 {
699  return _map_vars.rend() ;
700 }
701 
707 {
708  return _map_vars.begin() + i;
709 }
710 
726 int
727 Grid::components(bool constrained)
728 {
729  int comp;
730 
731  if (constrained) {
732  comp = _array_var->send_p() ? 1 : 0;
733 
734  for (Map_iter i = _map_vars.begin(); i != _map_vars.end(); i++) {
735  if ((*i)->send_p()) {
736  comp++;
737  }
738  }
739  }
740  else {
741  comp = 1 + _map_vars.size();
742  }
743 
744  return comp;
745 }
746 
748 {
749  AttrTable *at = at_container->get_attr_table(name());
750 
751  if (at) {
752  at->set_is_global_attribute(false);
753 
755 
756  Map_iter map = map_begin();
757  while (map != map_end()) {
758  (*map)->transfer_attributes(at);
759  map++;
760  }
761 
762  // Trick: If an attribute that's within the container 'at' still has its
763  // is_global_attribute property set, then it's not really a global attr
764  // but instead an attribute that belongs to this Grid.
765  AttrTable::Attr_iter at_p = at->attr_begin();
766  while (at_p != at->attr_end()) {
767  if (at->is_global_attribute(at_p)) {
768  if (at->get_attr_type(at_p) == Attr_container)
770  *at->get_attr_table(at_p)), at->get_name(at_p));
771  else
772  get_attr_table().append_attr(at->get_name(at_p),
773  at->get_type(at_p), at->get_attr_vector(at_p));
774  }
775 
776  at_p++;
777  }
778  }
779 }
780 
781 // When projected (using whatever the current constraint provides in the way
782 // of a projection), is the object still a Grid?
783 
800 bool
802 {
803  // For each dimension in the Array part, check the corresponding Map
804  // vector to make sure it is present in the projected Grid. If for each
805  // projected dimension in the Array component, there is a matching Map
806  // vector, then the Grid is valid.
807  bool valid = true;
808  Array *a = (Array *)_array_var;
809 
810  // Don't bother checking if the Array component is not included.
811  if (!a->send_p())
812  return false;
813 
814  // If only one part is being sent, it's clearly not a grid (it must be
815  // the array part of the Grid that's being sent (given that the above
816  // test passed and the array is being sent).
817  if (components(true) == 1)
818  return false;
819 
820  Array::Dim_iter d = a->dim_begin() ;
821  Map_iter m = map_begin() ;
822 
823  while (valid && d != a->dim_end() && m != map_end()) {
824  Array &map = dynamic_cast<Array&>(**m);
825  if (a->dimension_size(d, true) && map.send_p()) {
826  // Check the matching Map vector; the Map projection must equal
827  // the Array dimension projection
828  Array::Dim_iter fd = map.dim_begin(); // Maps have only one dim!
829  valid = map.dimension_start(fd, true) == a->dimension_start(d, true)
830  && map.dimension_stop(fd, true) == a->dimension_stop(d, true)
831  && map.dimension_stride(fd, true) == a->dimension_stride(d, true);
832  }
833  else {
834  valid = false;
835  }
836 
837  d++, m++;
838  }
839 
840  return valid;
841 }
842 
844 void
846 {
847  dynamic_cast<Array&>(*_array_var).clear_constraint();
848  for (Map_iter m = map_begin(); m != map_end(); ++m)
849  dynamic_cast<Array&>(*(*m)).clear_constraint();
850 }
851 
852 #if FILE_METHODS
853 void
854 Grid::print_decl(FILE *out, string space, bool print_semi,
855  bool constraint_info, bool constrained)
856 {
857  if (constrained && !send_p())
858  return;
859 
860  // The problem with the above is that if two Grids are projected and each
861  // contain one variable, say a map, and it happens to have the same name
862  // in each Grid, then without the enclosing Structures, the returned dataset
863  // has two variables with the same name at the same lexical level. So I'm
864  // removing the code above.
865  if (constrained && !projection_yields_grid()) {
866  fprintf(out, "%sStructure {\n", space.c_str()) ;
867 
868  _array_var->print_decl(out, space + " ", true, constraint_info,
869  constrained);
870 
871  for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
872  (*i)->print_decl(out, space + " ", true,
873  constraint_info, constrained);
874  }
875 
876  fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
877  }
878  else {
879  // The number of elements in the (projected) Grid must be such that
880  // we have a valid Grid object; send it as such.
881  fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ;
882 
883  fprintf(out, "%s Array:\n", space.c_str()) ;
884  _array_var->print_decl(out, space + " ", true, constraint_info,
885  constrained);
886 
887  fprintf(out, "%s Maps:\n", space.c_str()) ;
888  for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
889  (*i)->print_decl(out, space + " ", true,
890  constraint_info, constrained);
891  }
892 
893  fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
894  }
895 
896  if (constraint_info) {
897  if (send_p())
898  fprintf( out, ": Send True");
899  else
900  fprintf( out, ": Send False");
901  }
902 
903  if (print_semi)
904  fprintf(out, ";\n") ;
905 
906  return;
907 }
908 #endif
909 
910 void
911 Grid::print_decl(ostream &out, string space, bool print_semi,
912  bool constraint_info, bool constrained)
913 {
914  if (constrained && !send_p())
915  return;
916 
917  // See comment for the FILE* version of this method.
918  if (constrained && !projection_yields_grid()) {
919  out << space << "Structure {\n" ;
920 
921  _array_var->print_decl(out, space + " ", true, constraint_info,
922  constrained);
923 
924  for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
925  (*i)->print_decl(out, space + " ", true,
926  constraint_info, constrained);
927  }
928 
929  out << space << "} " << id2www(name()) ;
930  }
931  else {
932  // The number of elements in the (projected) Grid must be such that
933  // we have a valid Grid object; send it as such.
934  out << space << type_name() << " {\n" ;
935 
936  out << space << " Array:\n" ;
937  _array_var->print_decl(out, space + " ", true, constraint_info,
938  constrained);
939 
940  out << space << " Maps:\n" ;
941  for (Map_citer i = _map_vars.begin(); i != _map_vars.end(); i++) {
942  (*i)->print_decl(out, space + " ", true,
943  constraint_info, constrained);
944  }
945 
946  out << space << "} " << id2www(name()) ;
947  }
948 
949  if (constraint_info) {
950  if (send_p())
951  out << ": Send True";
952  else
953  out << ": Send False";
954  }
955 
956  if (print_semi)
957  out << ";\n" ;
958 
959  return;
960 }
961 
962 #if FILE_METHODS
963 class PrintMapField : public unary_function<BaseType *, void>
964 {
965  FILE *d_out;
966  string d_space;
967  bool d_constrained;
968  string d_tag;
969 public:
970  PrintMapField(FILE *o, string s, bool c, const string &t = "Map")
971  : d_out(o), d_space(s), d_constrained(c), d_tag(t)
972  {}
973 
974  void operator()(BaseType *btp)
975  {
976  Array *a = dynamic_cast<Array*>(btp);
977  if (!a)
978  throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
979  a->print_xml_core(d_out, d_space, d_constrained, d_tag);
980  }
981 };
982 
986 void
987 Grid::print_xml(FILE *out, string space, bool constrained)
988 {
989  if (constrained && !send_p())
990  return;
991 
992  if (constrained && !projection_yields_grid()) {
993  fprintf(out, "%s<Structure", space.c_str());
994  if (!name().empty())
995  fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
996 
997  fprintf(out, ">\n");
998 
999  get_attr_table().print_xml(out, space + " ", constrained);
1000 
1001  get_array()->print_xml(out, space + " ", constrained);
1002 
1003  for_each(map_begin(), map_end(),
1004  PrintMapField(out, space + " ", constrained, "Array"));
1005 
1006  fprintf(out, "%s</Structure>\n", space.c_str());
1007  }
1008  else {
1009  // The number of elements in the (projected) Grid must be such that
1010  // we have a valid Grid object; send it as such.
1011  fprintf(out, "%s<Grid", space.c_str());
1012  if (!name().empty())
1013  fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
1014 
1015  fprintf(out, ">\n");
1016 
1017  get_attr_table().print_xml(out, space + " ", constrained);
1018 
1019  get_array()->print_xml(out, space + " ", constrained);
1020 
1021  for_each(map_begin(), map_end(),
1022  PrintMapField(out, space + " ", constrained));
1023 
1024  fprintf(out, "%s</Grid>\n", space.c_str());
1025  }
1026 }
1027 #endif
1028 
1029 class PrintMapFieldStrm : public unary_function<BaseType *, void>
1030 {
1031  ostream &d_out;
1032  string d_space;
1033  bool d_constrained;
1034  string d_tag;
1035 public:
1036  PrintMapFieldStrm(ostream &o, string s, bool c, const string &t = "Map")
1037  : d_out(o), d_space(s), d_constrained(c), d_tag(t)
1038  {}
1039 
1040  void operator()(BaseType *btp)
1041  {
1042  Array *a = dynamic_cast<Array*>(btp);
1043  if (!a)
1044  throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
1045  a->print_xml_core(d_out, d_space, d_constrained, d_tag);
1046  }
1047 };
1048 
1052 void
1053 Grid::print_xml(ostream &out, string space, bool constrained)
1054 {
1055  if (constrained && !send_p())
1056  return;
1057 
1058  if (constrained && !projection_yields_grid()) {
1059  out << space << "<Structure" ;
1060  if (!name().empty())
1061  out << " name=\"" << id2xml(name()) << "\"" ;
1062 
1063  out << ">\n" ;
1064 
1065  get_attr_table().print_xml(out, space + " ", constrained);
1066 
1067  get_array()->print_xml(out, space + " ", constrained);
1068 
1069  for_each(map_begin(), map_end(),
1070  PrintMapFieldStrm(out, space + " ", constrained, "Array"));
1071 
1072  out << space << "</Structure>\n" ;
1073  }
1074  else {
1075  // The number of elements in the (projected) Grid must be such that
1076  // we have a valid Grid object; send it as such.
1077  out << space << "<Grid" ;
1078  if (!name().empty())
1079  out << " name=\"" << id2xml(name()) << "\"" ;
1080 
1081  out << ">\n" ;
1082 
1083  get_attr_table().print_xml(out, space + " ", constrained);
1084 
1085  get_array()->print_xml(out, space + " ", constrained);
1086 
1087  for_each(map_begin(), map_end(),
1088  PrintMapFieldStrm(out, space + " ", constrained));
1089 
1090  out << space << "</Grid>\n" ;
1091  }
1092 }
1093 
1094 
1095 class PrintGridFieldXMLWriter : public unary_function<BaseType *, void>
1096 {
1097  XMLWriter &d_xml;
1098  bool d_constrained;
1099  string d_tag;
1100 public:
1101  PrintGridFieldXMLWriter(XMLWriter &x, bool c, const string &t = "Map")
1102  : d_xml(x), d_constrained(c), d_tag(t)
1103  {}
1104 
1105  void operator()(BaseType *btp)
1106  {
1107  Array *a = dynamic_cast<Array*>(btp);
1108  if (!a)
1109  throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
1110  a->print_xml_writer_core(d_xml, d_constrained, d_tag);
1111  }
1112 };
1113 
1114 void
1115 Grid::print_xml_writer(XMLWriter &xml, bool constrained)
1116 {
1117  if (constrained && !send_p())
1118  return;
1119 
1120  if (constrained && !projection_yields_grid()) {
1121  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"Structure") < 0)
1122  throw InternalErr(__FILE__, __LINE__, "Could not write Structure element");
1123 
1124  if (!name().empty())
1125  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
1126  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1127 
1129 
1130  get_array()->print_xml_writer(xml, constrained);
1131 
1132  for_each(map_begin(), map_end(),
1133  PrintGridFieldXMLWriter(xml, constrained, "Array"));
1134 
1135  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1136  throw InternalErr(__FILE__, __LINE__, "Could not end Structure element");
1137  }
1138  else {
1139  // The number of elements in the (projected) Grid must be such that
1140  // we have a valid Grid object; send it as such.
1141  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"Grid") < 0)
1142  throw InternalErr(__FILE__, __LINE__, "Could not write Grid element");
1143 
1144  if (!name().empty())
1145  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
1146  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1147 
1149 
1150  get_array()->print_xml_writer(xml, constrained);
1151 
1152  for_each(map_begin(), map_end(),
1153  PrintGridFieldXMLWriter(xml, constrained, "Map"));
1154 
1155  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1156  throw InternalErr(__FILE__, __LINE__, "Could not end Grid element");
1157  }
1158 }
1159 
1160 #if FILE_METHODS
1161 void
1162 Grid::print_val(FILE *out, string space, bool print_decl_p)
1163 {
1164  if (print_decl_p) {
1165  print_decl(out, space, false);
1166  fprintf(out, " = ") ;
1167  }
1168 
1169  // If we are printing a value on the client-side, projection_yields_grid
1170  // should not be called since we don't *have* a projection without a
1171  // contraint. I think that if we are here and send_p() is not true, then
1172  // the value of this function should be ignored. 4/6/2000 jhrg
1173  bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg
1174  if (pyg || !send_p())
1175  fprintf(out, "{ Array: ") ;
1176  else
1177  fprintf(out, "{") ;
1178  _array_var->print_val(out, "", false);
1179  if (pyg || !send_p())
1180  fprintf(out, " Maps: ") ;
1181  for (Map_citer i = _map_vars.begin(); i != _map_vars.end();
1182  i++, (void)(i != _map_vars.end() && fprintf(out, ", "))) {
1183  (*i)->print_val(out, "", false);
1184  }
1185  fprintf(out, " }") ;
1186 
1187  if (print_decl_p)
1188  fprintf(out, ";\n") ;
1189 }
1190 #endif
1191 
1192 void
1193 Grid::print_val(ostream &out, string space, bool print_decl_p)
1194 {
1195  if (print_decl_p) {
1196  print_decl(out, space, false);
1197  out << " = " ;
1198  }
1199 
1200  // If we are printing a value on the client-side, projection_yields_grid
1201  // should not be called since we don't *have* a projection without a
1202  // Constraint. I think that if we are here and send_p() is not true, then
1203  // the value of this function should be ignored. 4/6/2000 jhrg
1204  bool pyg = projection_yields_grid(); // hack 12/1/99 jhrg
1205  if (pyg || !send_p())
1206  out << "{ Array: " ;
1207  else
1208  out << "{" ;
1209  _array_var->print_val(out, "", false);
1210  if (pyg || !send_p())
1211  out << " Maps: " ;
1212  for (Map_citer i = _map_vars.begin(); i != _map_vars.end();
1213  i++, (void)(i != _map_vars.end() && out << ", ")) {
1214  (*i)->print_val(out, "", false);
1215  }
1216  out << " }" ;
1217 
1218  if (print_decl_p)
1219  out << ";\n" ;
1220 }
1221 
1222 // Grids have ugly semantics.
1223 
1228 bool
1229 Grid::check_semantics(string &msg, bool all)
1230 {
1231  if (!BaseType::check_semantics(msg))
1232  return false;
1233 
1234  msg = "";
1235 
1236  if (!_array_var) {
1237  msg += "Null grid base array in `" + name() + "'\n";
1238  return false;
1239  }
1240 
1241  // Is it an array?
1242  if (_array_var->type() != dods_array_c) {
1243  msg += "Grid `" + name() + "'s' member `" + _array_var->name() + "' must be an array\n";
1244  return false;
1245  }
1246 
1247  Array *av = (Array *)_array_var; // past test above, must be an array
1248 
1249  // Array must be of a simple_type.
1250  if (!av->var()->is_simple_type()) {
1251  msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n";
1252  return false;
1253  }
1254 
1255  // enough maps?
1256  if ((unsigned)_map_vars.size() != av->dimensions()) {
1257  msg += "The number of map variables for grid `" + this->name() + "' does not match the number of dimensions of `";
1258  msg += av->name() + "'\n";
1259  return false;
1260  }
1261 
1262  const string array_var_name = av->name();
1263  Array::Dim_iter asi = av->dim_begin() ;
1264  for (Map_iter mvi = _map_vars.begin();
1265  mvi != _map_vars.end(); mvi++, asi++) {
1266 
1267  BaseType *mv = *mvi;
1268 
1269  // check names
1270  if (array_var_name == mv->name()) {
1271  msg += "Grid map variable `" + mv->name() + "' conflicts with the grid array name in grid `" + name() + "'\n";
1272  return false;
1273  }
1274  // check types
1275  if (mv->type() != dods_array_c) {
1276  msg += "Grid map variable `" + mv->name() + "' is not an array\n";
1277  return false;
1278  }
1279 
1280  Array *mv_a = (Array *)mv; // downcast to (Array *)
1281 
1282  // Array must be of a simple_type.
1283  if (!mv_a->var()->is_simple_type()) {
1284  msg += "The field variable `" + this->name() + "' must be an array of simple type elements (e.g., int32, String)\n";
1285  return false;
1286  }
1287 
1288  // check shape
1289  if (mv_a->dimensions() != 1) {// maps must have one dimension
1290  msg += "Grid map variable `" + mv_a->name() + "' must be only one dimension\n";
1291  return false;
1292  }
1293  // size of map must match corresponding array dimension
1294  Array::Dim_iter mv_asi = mv_a->dim_begin() ;
1295  int mv_a_size = mv_a->dimension_size(mv_asi) ;
1296  int av_size = av->dimension_size(asi) ;
1297  if (mv_a_size != av_size) {
1298  msg += "Grid map variable `" + mv_a->name() + "'s' size does not match the size of array variable '";
1299  msg += _array_var->name() + "'s' cooresponding dimension\n";
1300  return false;
1301  }
1302  }
1303 
1304  if (all) {
1305  if (!_array_var->check_semantics(msg, true))
1306  return false;
1307  for (Map_iter mvi = _map_vars.begin(); mvi != _map_vars.end(); mvi++) {
1308  if (!(*mvi)->check_semantics(msg, true)) {
1309  return false;
1310  }
1311  }
1312  }
1313 
1314  return true;
1315 }
1316 
1325 void
1326 Grid::dump(ostream &strm) const
1327 {
1328  strm << DapIndent::LMarg << "Grid::dump - ("
1329  << (void *)this << ")" << endl ;
1330  DapIndent::Indent() ;
1331  Constructor::dump(strm) ;
1332  if (_array_var) {
1333  strm << DapIndent::LMarg << "array var: " << endl ;
1334  DapIndent::Indent() ;
1335  _array_var->dump(strm) ;
1337  }
1338  else {
1339  strm << DapIndent::LMarg << "array var: null" << endl ;
1340  }
1341  strm << DapIndent::LMarg << "map var: " << endl ;
1342  DapIndent::Indent() ;
1343  Map_citer i = _map_vars.begin() ;
1344  Map_citer ie = _map_vars.end() ;
1345  for (; i != ie; i++) {
1346  (*i)->dump(strm) ;
1347  }
1350 }
1351 
1352 } // namespace libdap
1353 
virtual void print_xml_writer(XMLWriter &xml, bool constrained=false)
Definition: Array.cc:775
std::vector< entry * >::iterator Attr_iter
Definition: AttrTable.h:237
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:788
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:444
Map_riter map_rend()
Definition: Grid.cc:697
static void UnIndent()
Definition: DapIndent.cc:49
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
virtual void print_decl(FILE *out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: BaseType.cc:851
virtual Attr_iter attr_end()
Definition: AttrTable.cc:724
virtual unsigned int dimensions(bool constrained=false)
Return the total number of dimensions in the array.
Definition: Array.cc:382
virtual Array * prepend_map(Array *p_new_map, bool add_copy)
Definition: Grid.cc:635
virtual void add_var_nocopy(BaseType *bt, Part part)
Definition: Grid.cc:489
Part
Names the parts of multi-section constructor data types.
Definition: BaseType.h:102
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Move data to the net.
Definition: Grid.cc:269
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Grid.cc:1326
Contains the attributes for a dataset.
Definition: AttrTable.h:150
virtual unsigned int width()
Returns the size of the class instance data.
Definition: Grid.cc:204
Grid & operator=(const Grid &rhs)
Definition: Grid.cc:127
virtual string get_type(const string &name)
Get the type name of an attribute within this attribute table.
Definition: AttrTable.cc:618
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)=0
Receive data from the net.
virtual void print_xml(ostream &out, string space=" ", bool constrained=false)
Definition: Grid.cc:1053
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
Definition: BaseType.cc:797
std::vector< BaseType * > _vars
Definition: Constructor.h:48
virtual void print_xml(FILE *out, string pad=" ", bool constrained=false)
Definition: AttrTable.cc:1303
virtual bool is_global_attribute() const
Definition: AttrTable.h:284
string id2xml(string in, const string &not_allowed)
Definition: escaping.cc:270
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)=0
Move data to the net.
virtual unsigned int width()=0
Returns the size of the class instance data.
virtual void set_in_selection(bool state)
Definition: Grid.cc:192
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition: Vector.cc:309
virtual void set_is_global_attribute(bool ga)
Definition: AttrTable.h:285
void print_xml_writer(XMLWriter &xml)
Definition: AttrTable.cc:1409
Map_iter map_end()
Definition: Grid.cc:682
virtual void set_send_p(bool state)
Definition: Grid.cc:168
void timeout_off()
Definition: DDS.cc:758
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:238
virtual unsigned int val2buf(void *buf, bool reuse=false)
Returns the size of the Grid type.
Definition: Grid.cc:346
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:242
virtual void set_in_selection(bool state)
Definition: BaseType.cc:620
stack< BaseType * > btp_stack
Definition: BaseType.h:218
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:635
A class for software fault reporting.
Definition: InternalErr.h:64
Dim_iter dim_end()
Definition: Array.cc:367
std::vector< BaseType * >::const_iterator Map_citer
Definition: Grid.h:139
virtual int components(bool constrained=false)
Returns the number of components in the Grid object.
Definition: Grid.cc:727
Map_riter map_rbegin()
Returns an iterator referencing the first Map vector.
Definition: Grid.cc:689
virtual void set_array(Array *p_new_arr)
Definition: Grid.cc:559
string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:231
bool eval_selection(DDS &dds, const string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator ans is called ...
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:366
xmlTextWriterPtr get_writer()
Definition: XMLWriter.h:36
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Grid.cc:149
virtual bool projection_yields_grid()
Definition: Grid.cc:801
Map_iter map_begin()
Returns an iterator referencing the first Map vector.
Definition: Grid.cc:674
#define DBG(x)
Definition: debug.h:58
string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:252
virtual int dimension_size(Dim_iter i, bool constrained=false)
Returns the size of the dimension.
Definition: Array.cc:410
virtual BaseType * ptr_duplicate()
Definition: Grid.cc:121
Map_iter get_map_iter(int i)
Definition: Grid.cc:706
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
Definition: Grid.cc:249
virtual void set_send_p(bool state)
Definition: BaseType.cc:517
virtual void add_var(BaseType *bt, Part part)
Definition: Grid.cc:405
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition: AttrTable.cc:414
virtual void transfer_attributes(AttrTable *at_container)
Definition: Grid.cc:747
static void Indent()
Definition: DapIndent.cc:43
virtual void clear_constraint()
Definition: Grid.cc:845
virtual ~Grid()
Definition: Grid.cc:110
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
Definition: AttrTable.cc:612
std::vector< dimension >::iterator Dim_iter
Definition: Array.h:156
virtual void dump(ostream &strm) const
dumps information about this object
Definition: BaseType.cc:186
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Grid.cc:180
virtual BaseType * ptr_duplicate()
Definition: Array.cc:138
virtual int dimension_stride(Dim_iter i, bool constrained=false)
Returns the stride value of the constraint.
Definition: Array.cc:492
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:483
Holds the Grid data type.
Definition: Grid.h:123
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:556
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Grid.cc:1193
virtual Array * add_map(Array *p_new_map, bool add_copy)
Definition: Grid.cc:603
Array * get_array()
Returns the Grid Array. This method returns the array using an Array*, so no cast is required...
Definition: Grid.cc:663
std::vector< BaseType * >::iterator Map_iter
Definition: Grid.h:140
std::vector< BaseType * >::reverse_iterator Map_riter
Definition: Grid.h:141
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:210
virtual void print_xml(ostream &out, string space=" ", bool constrained=false)
Definition: Array.cc:649
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:716
virtual BaseType * ptr_duplicate()=0
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:218
virtual int dimension_stop(Dim_iter i, bool constrained=false)
Return the stop index of the constraint.
Definition: Array.cc:467
void timeout_on()
Definition: DDS.cc:750
virtual void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: Grid.cc:911
Evaluate a constraint expression.
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Grid.cc:327
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
virtual int dimension_start(Dim_iter i, bool constrained=false)
Return the start index of a dimension.
Definition: Array.cc:443
virtual AttrTable & get_attr_table()
Definition: BaseType.cc:531
virtual BaseType * var(const string &n, bool exact=true, btp_stack *s=0)
Definition: Grid.cc:371
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
Definition: AttrTable.cc:311
The basic data type for the DODS DAP types.
Definition: BaseType.h:194
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
Definition: AttrTable.cc:626
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:53
virtual unsigned int buf2val(void **val)
Definition: Grid.cc:355
Dim_iter dim_begin()
Definition: Array.cc:360
virtual bool check_semantics(string &msg, bool all=false)
Return true if this Grid is well formed.
Definition: Grid.cc:1229
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
Definition: AttrTable.cc:658
virtual bool is_simple_type()
Returns true if the instance is a numeric, string or URL type variable.
Definition: BaseType.cc:295
void _duplicate(const Grid &s)
Definition: Grid.cc:57
BaseType * array_var()
Returns the Grid Array.
Definition: Grid.cc:654
virtual void transfer_attributes(AttrTable *at)
Definition: BaseType.cc:570
marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using XDR ...
A multidimensional array of identical data types.
Definition: Array.h:105
virtual bool send_p()
Should this variable be sent?
Definition: BaseType.cc:503
virtual void print_xml_writer(XMLWriter &xml, bool constrained=false)
Definition: Grid.cc:1115
Grid(const string &n)
The Grid constructor.
Definition: Grid.cc:86
string id2www(string in, const string &allowable)
Definition: escaping.cc:151
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)=0
Prints the value of the variable.
virtual void clear_constraint()
Clears the projection; add each projected dimension explicitly using add_constraint.
Definition: Array.cc:302
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: BaseType.cc:1063