libdap  Updated for version 3.19.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
D4Group.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2013 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 //#define DODS_DEBUG
28 
29 #include <iostream>
30 #include <sstream>
31 #include <iomanip>
32 
33 #include <stdint.h>
34 
35 #include "crc.h"
36 
37 #include "BaseType.h"
38 #include "Array.h"
39 
40 #include "XMLWriter.h"
41 #include "D4Attributes.h"
42 #include "D4Dimensions.h"
43 #include "D4Group.h"
44 #include "D4Enum.h"
45 
46 #include "D4StreamMarshaller.h"
47 #include "D4StreamUnMarshaller.h"
48 
49 #include "debug.h"
50 
56 #undef INCLUDE_SOURCE_BYTE_ORDER
57 
58 namespace libdap {
59 
60 void D4Group::m_duplicate(const D4Group &g)
61 {
62  DBG(cerr << "In D4Group::m_duplicate for " << g.name() << endl);
63 
64  // dims; deep copy, this is the parent
65  if (g.d_dims) {
66  d_dims = new D4Dimensions(*(g.d_dims));
67  d_dims->set_parent(this);
68 
69  // Update all of the D4Dimension weak pointers in the Array objects.
70  // This is a hack - we know that Constructor::m_duplicate() has been
71  // called at this point and any Array instances have dimension pointers
72  // that reference the 'old' dimensions (g.d_dims) and not the 'new'
73  // dimensions made above. Scan every array and re-wire the weak pointers.
74  // jhrg 8/15/14
75  Vars_citer vi = d_vars.begin();
76  while (vi != d_vars.end()) {
77  if ((*vi)->type() == dods_array_c)
78  static_cast<Array*>(*vi)->update_dimension_pointers(g.d_dims, d_dims);
79  ++vi;
80  }
81  }
82 
83 #if 0
84  // Moved this block up inside the if because g.d_dims might be false. jhrg 9/14/15
85  Vars_citer vi = d_vars.begin();
86  while (vi != d_vars.end()) {
87  if ((*vi)->type() == dods_array_c)
88  static_cast<Array*>(*vi)->update_dimension_pointers(g.d_dims, d_dims);
89  ++vi;
90  }
91 #endif
92 
93  // enums; deep copy
94  if (g.d_enum_defs) d_enum_defs = new D4EnumDefs(*g.d_enum_defs);
95 
96  // groups
97  groupsCIter i = g.d_groups.begin();
98  while(i != g.d_groups.end()) {
99  // Only D4Groups are in the d_groups container.
100  D4Group *g = static_cast<D4Group*>((*i++)->ptr_duplicate());
101  add_group_nocopy(g);
102  }
103 
104  DBG(cerr << "Exiting D4Group::m_duplicate" << endl);
105 }
106 
117 D4Group::D4Group(const string &name)
118  : Constructor(name, dods_group_c, /*is_dap4*/true), d_dims(0), d_enum_defs(0)
119 {}
120 
131 D4Group::D4Group(const string &name, const string &dataset)
132  : Constructor(name, dataset, dods_group_c, /*is_dap4*/true), d_dims(0), d_enum_defs(0)
133 {}
134 
136 D4Group::D4Group(const D4Group &rhs) : Constructor(rhs), d_dims(0), d_enum_defs(0)
137 {
138  DBG(cerr << "In D4Group::copy_ctor for " << rhs.name() << endl);
139  m_duplicate(rhs);
140 }
141 
142 D4Group::~D4Group()
143 {
144  delete d_dims;
145  delete d_enum_defs;
146 
147  groupsIter i = d_groups.begin();
148  while(i != d_groups.end())
149  delete *i++;
150 }
151 
152 #if 0
153 D4Group *
154 
155 // I think this was a mistake. jhrg 11/17/16
156 #endif
157 BaseType *
159 {
160  return new D4Group(*this);
161 }
162 
163 D4Group &
164 D4Group::operator=(const D4Group &rhs)
165 {
166  if (this == &rhs)
167  return *this;
168 
169  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
170 
171  m_duplicate(rhs);
172 
173  return *this;
174 }
175 
182 string
184 {
185  // The root group is named "/" (always)
186  return (name() == "/") ? "/" : static_cast<D4Group*>(get_parent())->FQN() + name() + "/";
187 }
188 
189 // Note that in order for this to work the second argument must not be a reference.
190 // jhrg 8/20/13
191 static bool
192 name_eq(D4Group *g, const string name)
193 {
194  return g->name() == name;
195 }
196 
197 D4Group *
198 D4Group::find_child_grp(const string &grp_name)
199 {
200  groupsIter g = find_if(grp_begin(), grp_end(), bind2nd(ptr_fun(name_eq), grp_name));
201  return (g == grp_end()) ? 0: *g;
202 }
203 
204 // TODO Add constraint param? jhrg 11/17/13
205 BaseType *
206 D4Group::find_first_var_that_uses_dimension(D4Dimension *dim)
207 {
208  // for each group, starting with the root group
209  // for each variable in the group that is marked to send and is an array
210  // return the btp if it uses the D4Dimension
211  // if it contains child groups, search those
212  // return the btp if it uses the D4Dimension
213  // return null
214 
215  // exhaustive breadth-first search for 'dim
216 
217  // root group
218  for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
219  if ((*i)->send_p() && (*i)->type() == dods_array_c) {
220  Array *a = static_cast<Array*>(*i);
221  for (Array::Dim_iter di = a->dim_begin(), de = a->dim_end(); di != de; ++di) {
222  if (a->dimension_D4dim(di) == dim)
223  return a;
224  }
225  }
226  }
227 
228  for (groupsIter i = grp_begin(), e = grp_end(); i != e; ++i) {
229  BaseType *btp = (*i)->find_first_var_that_uses_dimension(dim);
230  if (btp) return btp;
231  }
232 
233  return 0;
234 }
235 
236 BaseType *
237 D4Group::find_first_var_that_uses_enumeration(D4EnumDef *enum_def)
238 {
239  // for each group, starting with the root group
240  // for each variable in the group that is marked to send and is an array
241  // return the btp if it uses the D4EnumDef
242  // if it contains child groups, search those
243  // return the btp if it uses the D4EnumDef
244  // return null
245 
246  // exhaustive breadth-first search for 'dim
247 
248  // root group
249  for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
250  if ((*i)->send_p() && (*i)->type() == dods_enum_c) {
251  D4Enum *e = static_cast<D4Enum*>(*i);
252  if (e->enumeration() == enum_def)
253  return e;
254  }
255  }
256 
257  for (groupsIter i = grp_begin(), e = grp_end(); i != e; ++i) {
258  BaseType *btp = (*i)->find_first_var_that_uses_enumeration(enum_def);
259  if (btp) return btp;
260  }
261 
262  return 0;
263 }
264 
274 D4Dimension *
275 D4Group::find_dim(const string &path)
276 {
277  string lpath = path; // get a mutable copy
278 
279  // special-case for the root group
280  if (lpath[0] == '/') {
281  if (name() != "/")
282  throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
283  else
284  lpath = lpath.substr(1);
285  }
286 
287  string::size_type pos = lpath.find('/');
288  if (pos == string::npos) {
289  // name looks like 'bar'
290  return dims()->find_dim(lpath);
291  }
292 
293  // name looks like foo/bar/baz where foo and bar must be groups
294  string grp_name = lpath.substr(0, pos);
295  lpath = lpath.substr(pos + 1);
296 
297  D4Group *grp = find_child_grp(grp_name);
298  return (grp == 0) ? 0: grp->find_dim(lpath);
299 }
300 
301 Array *
302 D4Group::find_map_source(const string &path)
303 {
304  BaseType *map_source = m_find_map_source_helper(path);
305 
306  // TODO more complete semantic checking jhrg 10/16/13
307  if (map_source && map_source->type() == dods_array_c) return static_cast<Array*>(map_source);
308 
309  return 0;
310 }
311 
312 BaseType *
313 D4Group::m_find_map_source_helper(const string &path)
314 {
315  string lpath = path; // get a mutable copy
316 
317  // special-case for the root group
318  if (lpath[0] == '/') {
319  if (name() != "/")
320  throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
321  else
322  lpath = lpath.substr(1);
323  }
324 
325  string::size_type pos = lpath.find('/');
326  if (pos == string::npos) {
327  // name looks like 'bar'
328  return var(lpath);
329  }
330 
331  // name looks like foo/bar/baz where foo an bar must be groups
332  string grp_name = lpath.substr(0, pos);
333  lpath = lpath.substr(pos + 1);
334 
335  D4Group *grp = find_child_grp(grp_name);
336  return (grp == 0) ? 0: grp->var(lpath);
337 }
338 
339 D4EnumDef *
340 D4Group::find_enum_def(const string &path)
341 {
342  string lpath = path; // get a mutable copy
343 
344  // special-case for the root group
345  if (lpath[0] == '/') {
346  if (name() != "/")
347  throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
348  else
349  lpath = lpath.substr(1);
350  }
351 
352  string::size_type pos = lpath.find('/');
353  if (pos == string::npos) {
354  // name looks like 'bar'
355  return enum_defs()->find_enum_def(lpath);
356  }
357 
358  // name looks like foo/bar/baz where foo and bar must be groups
359  string grp_name = lpath.substr(0, pos);
360  lpath = lpath.substr(pos + 1);
361 
362  D4Group *grp = find_child_grp(grp_name);
363  return (grp == 0) ? 0: grp->enum_defs()->find_enum_def(lpath);
364 }
365 
373 BaseType *
374 D4Group::find_var(const string &path)
375 {
376  string lpath = path; // get a mutable copy
377 
378  // special-case for the root group
379  if (lpath[0] == '/') {
380  if (name() != "/")
381  throw InternalErr(__FILE__, __LINE__, "Lookup of a FQN starting in non-root group.");
382  else
383  lpath = lpath.substr(1);
384  }
385 
386  string::size_type pos = lpath.find('/');
387  if (pos == string::npos) {
388  // name looks like 'bar' or bar.baz; lookup in the Constructor that's part of the Group
389  return var(lpath);
390  }
391 
392  // name looks like foo/bar/baz where foo and bar must be groups
393  string grp_name = lpath.substr(0, pos);
394  lpath = lpath.substr(pos + 1);
395 
396  D4Group *grp = find_child_grp(grp_name);
397  return (grp == 0) ? 0 : grp->find_var(lpath);
398 }
399 
406 long
407 D4Group::request_size(bool constrained)
408 {
409  long long size = 0;
410  // variables
411  Constructor::Vars_iter v = var_begin();
412  while (v != var_end()) {
413  if (constrained) {
414  if ((*v)->send_p())
415  size += (*v)->width(constrained);
416  }
417  else {
418  size += (*v)->width(constrained);
419  }
420 
421  ++v;
422  }
423 
424  // groups
425  groupsIter g = d_groups.begin();
426  while (g != d_groups.end())
427  size += (*g++)->request_size(constrained);
428 
429  return size / 1024;
430 }
431 
432 void
434 {
435  groupsIter g = d_groups.begin();
436  while (g != d_groups.end())
437  (*g++)->set_read_p(state);
438 
440 }
441 
442 void
444 {
445  groupsIter g = d_groups.begin();
446  while (g != d_groups.end())
447  (*g++)->set_send_p(state);
448 
450 }
451 
452 void
453 D4Group::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
454 {
455  groupsIter g = d_groups.begin();
456  while (g != d_groups.end())
457  (*g++)->intern_data(/*checksum, dmr, eval*/);
458 
459  // Specialize how the top-level variables in any Group are sent; include
460  // a checksum for them. A subset operation might make an interior set of
461  // variables, but the parent structure will still be present and the checksum
462  // will be computed for that structure. In other words, DAP4 does not try
463  // to sort out which variables are the 'real' top-level variables and instead
464  // simply computes the CRC for whatever appears as a variable in the root
465  // group.
466  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
467  // Only send the stuff in the current subset.
468  if ((*i)->send_p()) {
469 #if 0
470  checksum.Reset();
471 #endif
472  (*i)->intern_data(/*checksum, dmr, eval*/);
473 #if 0
474  D4Attribute *a = new D4Attribute("DAP4_Checksum_CRC32", attr_str_c);
475 
476  ostringstream oss;
477  oss.setf(ios::hex, ios::basefield);
478  oss << setfill('0') << setw(8) << checksum.GetCrc32();
479  a->add_value(oss.str());
480 #if INCLUDE_SOURCE_BYTE_ORDER
481  if (um.is_source_big_endian())
482  a->add_value("source:big-endian");
483  else
484  a->add_value("source:little-endian");
485 #endif
486  (*i)->attributes()->add_attribute_nocopy(a);
487  DBG(cerr << "CRC32: " << oss.str() << " for " << (*i)->name() << endl);
488 #endif
489  }
490  }
491 }
492 
504 void
505 D4Group::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter)
506 {
507 #if 0
508  // This will call Constructor read which will, for everything but a Sequence,
509  // read all of the data in one shot. However, the serialize() methods for the
510  // Arrays, Structures, etc., also have read() calls in them and those can be
511  // used to control how long the data are in memory, e.g., limiting the lifetime
512  // of a large array and avoiding having overlapping arrays when they are not
513  // needed. For a sequence read() has different semantics. It is called once
514  // for every instance and the read_p flag is not used.
515  if (!read_p())
516  read(); // read() throws Error
517 #endif
518 
519  groupsIter g = d_groups.begin();
520  while (g != d_groups.end())
521  (*g++)->serialize(m, dmr, filter);
522 
523  // Specialize how the top-level variables in any Group are sent; include
524  // a checksum for them. A subset operation might make an interior set of
525  // variables, but the parent structure will still be present and the checksum
526  // will be computed for that structure. In other words, DAP4 does not try
527  // to sort out which variables are the 'real' top-level variables and instead
528  // simply computes the CRC for whatever appears as a variable in the root
529  // group.
530  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
531  // Only send the stuff in the current subset.
532  if ((*i)->send_p()) {
533  m.reset_checksum();
534 
535  DBG(cerr << "Serializing variable " << (*i)->type_name() << " " << (*i)->name() << endl);
536  (*i)->serialize(m, dmr, filter);
537 
538  DBG(cerr << "Wrote CRC32: " << m.get_checksum() << " for " << (*i)->name() << endl);
539  m.put_checksum();
540  }
541  }
542 }
543 
545 {
546  groupsIter g = d_groups.begin();
547  while (g != d_groups.end()) {
548  DBG(cerr << "Deserializing group " << (*g)->name() << endl);
549  (*g++)->deserialize(um, dmr);
550  }
551  // Specialize how the top-level variables in any Group are received; read
552  // their checksum and store the value in a magic attribute of the variable
553  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
554  DBG(cerr << "Deserializing variable " << (*i)->type_name() << " " << (*i)->name() << endl);
555  (*i)->deserialize(um, dmr);
556 
557  D4Attribute *a = new D4Attribute("DAP4_Checksum_CRC32", attr_str_c);
558  string crc = um.get_checksum_str();
559  a->add_value(crc);
560 #if INCLUDE_SOURCE_BYTE_ORDER
561  if (um.is_source_big_endian())
562  a->add_value("source:big-endian");
563  else
564  a->add_value("source:little-endian");
565 #endif
566  DBG(cerr << "Read CRC32: " << crc << " for " << (*i)->name() << endl);
567  (*i)->attributes()->add_attribute_nocopy(a);
568  }
569 }
570 
571 void
572 D4Group::print_dap4(XMLWriter &xml, bool constrained)
573 {
574  if (!name().empty() && name() != "/") {
575  // For named groups, if constrained is true only print if this group
576  // has variables that are marked for transmission. For the root group
577  // this test is not made.
578  if (constrained && !send_p())
579  return;
580 
581  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) type_name().c_str()) < 0)
582  throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
583 
584  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) name().c_str()) < 0)
585  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
586  }
587 
588  // dims
589  if (!dims()->empty())
590  dims()->print_dap4(xml, constrained);
591 
592  // enums
593  if (!enum_defs()->empty())
594  enum_defs()->print_dap4(xml, constrained);
595 
596  // variables
597  Constructor::Vars_iter v = var_begin();
598  while (v != var_end())
599  (*v++)->print_dap4(xml, constrained);
600 
601  // attributes
602  attributes()->print_dap4(xml);
603 
604  // groups
605  groupsIter g = d_groups.begin();
606  while (g != d_groups.end())
607  (*g++)->print_dap4(xml, constrained);
608 
609  if (!name().empty() && name() != "/") {
610  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
611  throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
612  }
613 }
614 
615 
633 vector<BaseType *> *
635  return transform_to_dap2(parent_attr_table,false);
636 }
637 vector<BaseType *> *
638 D4Group::transform_to_dap2(AttrTable *parent_attr_table, bool is_root)
639 {
640  DBG( cerr << __func__ << "() - BEGIN ("<< name() << " is_root: "<< (is_root?"true":"false") << ")" << endl;);
641  vector<BaseType *> *results = new vector<BaseType *>();
642  vector<BaseType *> dropped_vars;
643 
644  AttrTable *group_attrs;
645  group_attrs = attributes()->get_AttrTable(name());
646 
650  if(is_root){
651  DBG( cerr << __func__ << "() - Promoting group attributes to parent" << endl;);
652  // If it's a root group we copy all the stuff up into the parent attr table
653  for (AttrTable::Attr_iter i = group_attrs->attr_begin(), e = group_attrs->attr_end(); i != e; ++i) {
654  if ((*i)->type == Attr_container) {
655  // copy the source container so that the DAS passed in can be
656  // deleted after calling this method.
657  AttrTable *at = new AttrTable(*(*i)->attributes);
658  parent_attr_table->append_container(at, at->get_name());
659  }
660  else {
661  parent_attr_table->append_attr(
662  (*i)->name,
663  AttrType_to_String((*i)->type),
664  (*i)->attr);
665  }
666  }
667  delete group_attrs;
668  group_attrs = parent_attr_table;
669  }
670 
674  for (D4Group::Vars_citer varIter = var_begin(), e = var_end(); varIter != e; ++varIter) {
675  DBG( cerr << __func__ << "() - Processing member variable '" << (*varIter)->name() <<
676  "' root: " << (is_root?"true":"false") << endl;);
677  vector<BaseType *> *new_vars = (*varIter)->transform_to_dap2(group_attrs);
678  if (new_vars) { // Might be un-mappable
679  // It's not so game on..
680  vector<BaseType*>::iterator vIter = new_vars->begin();
681  vector<BaseType*>::iterator end = new_vars->end();
682  for( ; vIter!=end ; vIter++ ){
683  BaseType *new_var = (*vIter);
684 
685  string new_name = (is_root?"":FQN()) + new_var->name();
686  new_var->set_name(new_name);
687  results->push_back(new_var);
688  (*vIter) = NULL;
689  DBG( cerr << __func__ << "() - Added member variable '" << (*varIter)->name() << "' " <<
690  "to results vector. root: "<< (is_root?"true":"false") << endl;);
691  }
692  delete new_vars;
693  }
694  else {
695  DBG( cerr << __func__ << "() - Dropping member variable " << (*varIter)->name() <<
696  " root: " << (is_root?"true":"false") << endl;);
697  // Got back a NULL, so we are dropping this var.
698  dropped_vars.push_back(*varIter);
699  }
700  }
701  // Process dropped DAP4 vars
702  DBG( cerr << __func__ << "() - Processing " << dropped_vars.size() << " Dropped Variable(s)" << endl;);
703  AttrTable *dv_attr_table = make_dropped_vars_attr_table(&dropped_vars);
704  if(dv_attr_table){
705  DBG( cerr << __func__ << "() - Adding Dropped Variables AttrTable" << endl;);
706  group_attrs->append_container(dv_attr_table,dv_attr_table->get_name());
707  }
708  else {
709  DBG( cerr << __func__ << "() - No Dropped Variables AttrTable returned." << endl;);
710 
711  }
712 
716  D4Group::groupsIter gIter = grp_begin();
717  D4Group::groupsIter gEnd = grp_end();
718  for( ; gIter!=gEnd ; gIter++){
719  D4Group *grp = *gIter;
720  DBG( cerr << __func__ << "() - Processing D4Group " << grp->name() << endl;);
721  vector<BaseType *> *d2_vars = grp->transform_to_dap2(group_attrs);
722  if(d2_vars){
723  DBG( cerr << __func__ << "() - Processing " << grp->name() << " Member Variables." << endl;);
724  vector<BaseType *>::iterator vIter = d2_vars->begin();
725  vector<BaseType *>::iterator vEnd = d2_vars->end();
726  for( ; vIter!=vEnd; vIter++){
727  DBG( cerr << __func__ << "() - Processing " << grp->name() << " Member Variable: " << (*vIter)->name() << endl;);
728  results->push_back(*vIter);
729  }
730  }
731 
732 
733 
734  }
735 
736  if(!is_root){
737  group_attrs->set_name(name());
738  parent_attr_table->append_container(group_attrs,group_attrs->get_name());
739  }
740  DBG( cerr << __func__ << "() - END" << endl;);
741  return results;
742 }
743 
744 
745 } /* namespace libdap */
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:471
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:311
AttrTable * get_AttrTable(const std::string name)
copy attributes from DAP4 to DAP2
bool is_source_big_endian() const
Is the data source we are reading from a big-endian machine? We need this because the value of the CR...
virtual Attr_iter attr_end()
Definition: AttrTable.cc:718
virtual BaseType * var(const string &name, bool exact_match=true, btp_stack *s=0)
btp_stack no longer needed; use back pointers (BaseType::get_parent())
Definition: Constructor.cc:267
Contains the attributes for a dataset.
Definition: AttrTable.h:142
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:335
string AttrType_to_String(const AttrType at)
Definition: AttrTable.cc:96
D4Dimension * find_dim(const string &path)
Find the dimension using a path. Using the DAP4 name syntax, lookup a dimension. The dimension must b...
Definition: D4Group.cc:275
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:237
Read data from the stream made by D4StreamMarshaller.
D4Group(const string &name)
Definition: D4Group.cc:117
virtual void serialize(D4StreamMarshaller &m, DMR &dmr, bool filter=false)
Serialize a Group.
Definition: D4Group.cc:505
A class for software fault reporting.
Definition: InternalErr.h:64
Dim_iter dim_end()
Definition: Array.cc:704
Holds a DAP4 enumeration.
Definition: D4Enum.h:61
virtual BaseType * ptr_duplicate()
Definition: D4Group.cc:158
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4&#39;s receiv...
long request_size(bool constrained)
Definition: D4Group.cc:407
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition: AttrTable.cc:409
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:356
std::vector< dimension >::iterator Dim_iter
Definition: Array.h:206
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:476
groupsIter grp_end()
Get an iterator to the end of the values.
Definition: D4Group.h:114
virtual D4Attributes * attributes()
Definition: BaseType.cc:590
virtual void deserialize(D4StreamUnMarshaller &um, DMR &dmr)
Definition: D4Group.cc:544
virtual void intern_data()
Read data into this variable.
Definition: D4Group.cc:453
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:710
groupsIter grp_begin()
Get an iterator to the start of the values.
Definition: D4Group.h:111
virtual std::vector< BaseType * > * transform_to_dap2(AttrTable *parent_attr_table)
DAP4 to DAP2 transform.
Definition: D4Group.cc:634
virtual BaseType * get_parent() const
Definition: BaseType.cc:742
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
Definition: AttrTable.cc:306
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
Dim_iter dim_begin()
Definition: Array.cc:697
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:370
Vars_iter var_begin()
Definition: Constructor.cc:356
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition: D4Group.cc:572
virtual std::string FQN() const
Definition: D4Group.cc:183
Vars_iter var_end()
Definition: Constructor.cc:364
virtual void set_name(const string &n)
Set the name of this attribute table.
Definition: AttrTable.cc:244
virtual void put_checksum()
Write the checksum Write the checksum for the data sent since the last call to reset_checksum() to th...
D4EnumDefs * enum_defs()
Get the enumerations defined for this Group.
Definition: D4Group.h:97
virtual void set_send_p(bool state)
Definition: Constructor.cc:208
A multidimensional array of identical data types.
Definition: Array.h:112
virtual bool send_p()
Should this variable be sent?
Definition: BaseType.cc:545
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: D4Group.cc:433
virtual void set_send_p(bool state)
Definition: D4Group.cc:443
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:349
BaseType * find_var(const string &name)
Definition: D4Group.cc:374
D4Dimensions * dims()
Get the dimensions defined for this Group.
Definition: D4Group.h:82
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:218