libdap  Updated for version 3.19.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
DDS.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) 2002,2003 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 // (c) COPYRIGHT URI/MIT 1994-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 // Authors:
29 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30 
31 //
32 // jhrg 9/7/94
33 
34 #include "config.h"
35 
36 #include <cstdio>
37 #include <cmath>
38 #include <sys/types.h>
39 
40 #ifdef WIN32
41 #include <io.h>
42 #include <process.h>
43 #include <fstream>
44 #else
45 #include <unistd.h> // for alarm and dup
46 #include <sys/wait.h>
47 #endif
48 
49 #include <iostream>
50 #include <sstream>
51 #include <algorithm>
52 #include <functional>
53 
54 // #define DODS_DEBUG
55 //#define DODS_DEBUG2
56 
57 #include "GNURegex.h"
58 
59 #include "DAS.h"
60 #include "Clause.h"
61 #include "Error.h"
62 #include "InternalErr.h"
63 #include "Keywords2.h"
64 
65 #include "parser.h"
66 #include "debug.h"
67 #include "util.h"
68 
69 #include "Byte.h"
70 #include "Int16.h"
71 #include "UInt16.h"
72 #include "Int32.h"
73 #include "UInt32.h"
74 #include "Float32.h"
75 #include "Float64.h"
76 #include "Str.h"
77 #include "Url.h"
78 #include "Array.h"
79 #include "Structure.h"
80 #include "Sequence.h"
81 #include "Grid.h"
82 
83 #include "escaping.h"
84 
95 const string c_xml_xsi = "http://www.w3.org/2001/XMLSchema-instance";
96 const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
97 
98 const string grddl_transformation_dap32 = "http://xml.opendap.org/transforms/ddxToRdfTriples.xsl";
99 
100 const string c_default_dap20_schema_location = "http://xml.opendap.org/dap/dap2.xsd";
101 const string c_default_dap32_schema_location = "http://xml.opendap.org/dap/dap3.2.xsd";
102 const string c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
103 
104 const string c_dap20_namespace = "http://xml.opendap.org/ns/DAP2";
105 const string c_dap32_namespace = "http://xml.opendap.org/ns/DAP/3.2#";
106 const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
107 
108 const string c_dap_20_n_sl = c_dap20_namespace + " " + c_default_dap20_schema_location;
109 const string c_dap_32_n_sl = c_dap32_namespace + " " + c_default_dap32_schema_location;
110 const string c_dap_40_n_sl = c_dap40_namespace + " " + c_default_dap40_schema_location;
121 using namespace std;
122 
123 int ddsparse(libdap::parser_arg *arg);
124 
125 // Glue for the DDS parser defined in dds.lex
126 void dds_switch_to_buffer(void *new_buffer);
127 void dds_delete_buffer(void * buffer);
128 void *dds_buffer(FILE *fp);
129 
130 namespace libdap {
131 
132 void
133 DDS::duplicate(const DDS &dds)
134 {
135  DBG(cerr << "Entering DDS::duplicate... " <<endl);
136 #if 0
137  BaseTypeFactory *d_factory;
138 
139  string d_name; // The dataset d_name
140  string d_filename; // File d_name (or other OS identifier) for
141  string d_container_name; // d_name of container structure
142  Structure *d_container; // current container for container d_name
143  // dataset or part of dataset.
144 
145  int d_dap_major; // The protocol major version number
146  int d_dap_minor; // ... and minor version number
147  string d_dap_version; // String version of the protocol
148  string d_request_xml_base;
149  string d_namespace;
150 
151  AttrTable d_attr; // Global attributes.
152 
153  vector<BaseType *> vars; // Variables at the top level
154 
155  int d_timeout; // alarm time in seconds. If greater than
156  // zero, raise the alarm signal if more than
157  // d_timeout seconds are spent reading data.
158  Keywords d_keywords; // Holds keywords parsed from the CE
159 
160  long d_max_response_size; // In bytes
161 #endif
162 
163  d_factory = dds.d_factory;
164 
165  d_name = dds.d_name;
166  d_filename = dds.d_filename;
167  d_container_name = dds.d_container_name;
168  d_container = dds.d_container;
169 
170  d_dap_major = dds.d_dap_major;
171  d_dap_minor = dds.d_dap_minor;
172 
173  d_dap_version = dds.d_dap_version; // String version of the protocol
174  d_request_xml_base = dds.d_request_xml_base;
175  d_namespace = dds.d_namespace;
176 
177  d_attr = dds.d_attr;
178 
179  DDS &dds_tmp = const_cast<DDS &>(dds);
180 
181  // copy the things pointed to by the list, not just the pointers
182  for (Vars_iter i = dds_tmp.var_begin(); i != dds_tmp.var_end(); i++) {
183  add_var(*i); // add_var() dups the BaseType.
184  }
185 
186  d_timeout = dds.d_timeout;
187 
188  d_keywords = dds.d_keywords; // value copy; Keywords contains no pointers
189 
190  d_max_response_size = dds.d_max_response_size;
191 }
192 
205 DDS::DDS(BaseTypeFactory *factory, const string &name)
206  : d_factory(factory), d_name(name), d_container_name(""), d_container(0),
207  d_request_xml_base(""),
208  d_timeout(0), d_keywords(), d_max_response_size(0)
209 {
210  DBG(cerr << "Building a DDS for the default version (2.0)" << endl);
211 
212  // This method sets a number of values, including those returned by
213  // get_protocol_major(), ..., get_namespace().
214  set_dap_version("2.0");
215 }
216 
232 DDS::DDS(BaseTypeFactory *factory, const string &name, const string &version)
233  : d_factory(factory), d_name(name), d_container_name(""), d_container(0),
234  d_request_xml_base(""),
235  d_timeout(0), d_keywords(), d_max_response_size(0)
236 {
237  DBG(cerr << "Building a DDS for version: " << version << endl);
238 
239  // This method sets a number of values, including those returned by
240  // get_protocol_major(), ..., get_namespace().
241  set_dap_version(version);
242 }
243 
245 DDS::DDS(const DDS &rhs) : DapObj()
246 {
247  DBG(cerr << "Entering DDS(const DDS &rhs) ..." << endl);
248  duplicate(rhs);
249  DBG(cerr << " bye." << endl);
250 }
251 
252 DDS::~DDS()
253 {
254  // delete all the variables in this DDS
255  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
256  BaseType *btp = *i ;
257  delete btp ; btp = 0;
258  }
259 }
260 
261 DDS &
262 DDS::operator=(const DDS &rhs)
263 {
264  DBG(cerr << "Entering DDS::operator= ..." << endl);
265  if (this == &rhs)
266  return *this;
267 
268  duplicate(rhs);
269 
270  DBG(cerr << " bye." << endl);
271  return *this;
272 }
273 
288 {
289  // If there is a container set in the DDS then check the container from
290  // the DAS. If they are not the same container, then throw an exception
291  // (should be working on the same container). If the container does not
292  // exist in the DAS, then throw an exception
293  if (d_container && das->container_name() != d_container_name)
294  throw InternalErr(__FILE__, __LINE__,
295  "Error transferring attributes: working on a container in dds, but not das");
296 
297  // Give each variable a chance to claim its attributes.
298  AttrTable *top = das->get_top_level_attributes();
299 
300  for (DDS::Vars_iter i = var_begin(), e = var_end(); i != e; i++) {
301  (*i)->transfer_attributes(top);
302  }
303 #if 0
304  Vars_iter var = var_begin();
305  while (var != var_end()) {
306  try {
307  DBG(cerr << "Processing the attributes for: " << (*var)->d_name() << " a " << (*var)->type_name() << endl);
308  (*var)->transfer_attributes(top);
309  var++;
310  }
311  catch (Error &e) {
312  DBG(cerr << "Got this exception: " << e.get_error_message() << endl);
313  var++;
314  throw e;
315  }
316  }
317 #endif
318  // Now we transfer all of the attributes still marked as global to the
319  // global container in the DDS.
320  for (AttrTable::Attr_iter i = top->attr_begin(), e = top->attr_end(); i != e; ++i) {
321  if ((*i)->type == Attr_container && (*i)->attributes->is_global_attribute()) {
322  // copy the source container so that the DAS passed in can be
323  // deleted after calling this method.
324  AttrTable *at = new AttrTable(*(*i)->attributes);
325  d_attr.append_container(at, at->get_name());
326  }
327  }
328 #if 0
329  AttrTable::Attr_iter at_cont_p = top_level->attr_begin();
330  while (at_cont_p != top_level->attr_end()) {
331  // In truth, all of the top level attributes should be containers, but
332  // this test handles the abnormal case where somehow someone makes a
333  // top level attribute that is not a container by silently dropping it.
334  if ((*at_cont_p)->type == Attr_container && (*at_cont_p)->attributes->is_global_attribute()) {
335  DBG(cerr << (*at_cont_p)->d_name << " is a global attribute." << endl);
336  // copy the source container so that the DAS passed in can be
337  // deleted after calling this method.
338  AttrTable *at = new AttrTable(*(*at_cont_p)->attributes);
339  d_attr.append_container(at, at->get_name());
340  }
341 
342  at_cont_p++;
343  }
344 #endif
345 }
346 
354 
356 string
358 {
359  return d_name;
360 }
361 
363 void
364 DDS::set_dataset_name(const string &n)
365 {
366  d_name = n;
367 }
368 
370 
372 AttrTable &
374 {
375  return d_attr;
376 }
377 
387 string
389 {
390  return d_filename;
391 }
392 
394 void
395 DDS::filename(const string &fn)
396 {
397  d_filename = fn;
398 }
400 
404 void
406 {
407  d_dap_major = p;
408 
409  // This works because regardless of the order set_dap_major and set_dap_minor
410  // are called, once they both are called, the value in the string is
411  // correct. I protect against negative numbers because that would be
412  // nonsensical.
413  if (d_dap_minor >= 0) {
414  ostringstream oss;
415  oss << d_dap_major << "." << d_dap_minor;
416  d_dap_version = oss.str();
417  }
418 }
419 
423 void
425 {
426  d_dap_minor = p;
427 
428  if (d_dap_major >= 0) {
429  ostringstream oss;
430  oss << d_dap_major << "." << d_dap_minor;
431  d_dap_version = oss.str();
432  }
433 }
434 
440 void
441 DDS::set_dap_version(const string &v /* = "2.0" */)
442 {
443  istringstream iss(v);
444 
445  int major = -1, minor = -1;
446  char dot;
447  if (!iss.eof() && !iss.fail())
448  iss >> major;
449  if (!iss.eof() && !iss.fail())
450  iss >> dot;
451  if (!iss.eof() && !iss.fail())
452  iss >> minor;
453 
454  if (major == -1 || minor == -1 or dot != '.')
455  throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
456 
457  d_dap_version = v;
458 
459  d_dap_major = major;
460  d_dap_minor = minor;
461 
462  // Now set the related XML constants. These might be overwritten if
463  // the DDS instance is being built from a document parse, but if it's
464  // being constructed by a server the code to generate the XML document
465  // needs these values to match the DAP version information.
466  switch (d_dap_major) {
467  case 2:
468  d_namespace = c_dap20_namespace;
469  break;
470  case 3:
471  d_namespace = c_dap32_namespace;
472  break;
473  case 4:
474  d_namespace = c_dap40_namespace;
475  break;
476  default:
477  throw InternalErr(__FILE__, __LINE__, "Unknown DAP version.");
478  }
479 }
480 
488 void
490 {
491  int major = floor(d);
492  int minor = (d-major)*10;
493 
494  DBG(cerr << "Major: " << major << ", Minor: " << minor << endl);
495 
496  ostringstream oss;
497  oss << major << "." << minor;
498 
499  set_dap_version(oss.str());
500 }
501 
511 string
513 {
514  return d_container_name;
515 }
516 
519 void
520 DDS::container_name(const string &cn)
521 {
522  // we want to search the DDS for the top level structure with the given
523  // d_name. Set the container to null so that we don't search some previous
524  // container.
525  d_container = 0 ;
526  if( !cn.empty() )
527  {
528  d_container = dynamic_cast<Structure *>( var( cn ) ) ;
529  if( !d_container )
530  {
531  // create a structure for this container. Calling add_var
532  // while_container is null will add the new structure to DDS and
533  // not some sub structure. Adding the new structure makes a copy
534  // of it. So after adding it, go get it and set d_container.
535  Structure *s = new Structure( cn ) ;
536  add_var( s ) ;
537  delete s ;
538  s = 0 ;
539  d_container = dynamic_cast<Structure *>( var( cn ) ) ;
540  }
541  }
542  d_container_name = cn;
543 
544 }
545 
547 Structure *
549 {
550  return d_container ;
551 }
552 
554 
565 int
566 DDS::get_request_size(bool constrained)
567 {
568  int w = 0;
569  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
570  if (constrained) {
571  if ((*i)->send_p())
572  w += (*i)->width(constrained);
573  }
574  else {
575  w += (*i)->width(constrained);
576  }
577  }
578 
579  return w;
580 }
581 
588  if (!bt)
589  throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
590 #if 0
591  if (bt->is_dap4_only_type())
592  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
593 #endif
594  DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
595 
596  BaseType *btp = bt->ptr_duplicate();
597  DBG2(cerr << "In DDS::add_var(), btp's address is: " << btp << endl);
598  if (d_container) {
599  // Mem leak fix [mjohnson nov 2009]
600  // Structure::add_var() creates ANOTHER copy.
601  d_container->add_var(bt);
602  // So we need to delete btp or else it leaks
603  delete btp;
604  btp = 0;
605  }
606  else {
607  vars.push_back(btp);
608  }
609 }
610 
613 void
615 {
616  if (!bt)
617  throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
618 #if 0
619  //FIXME There's no longer a DAP2 and DAP4 DDS
620  if (bt->is_dap4_only_type())
621  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
622 #endif
623 
624  DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
625 
626  if (d_container) {
627  d_container->add_var_nocopy(bt);
628  }
629  else {
630  vars.push_back(bt);
631  }
632 }
633 
634 
641 void
642 DDS::del_var(const string &n)
643 {
644  if( d_container )
645  {
646  d_container->del_var( n ) ;
647  return ;
648  }
649 
650  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
651  if ((*i)->name() == n) {
652  BaseType *bt = *i ;
653  vars.erase(i) ;
654  delete bt ; bt = 0;
655  return;
656  }
657  }
658 }
659 
664 void
665 DDS::del_var(Vars_iter i)
666 {
667  if (i != vars.end()) {
668  BaseType *bt = *i ;
669  vars.erase(i) ;
670  delete bt ; bt = 0;
671  }
672 }
673 
680 void
681 DDS::del_var(Vars_iter i1, Vars_iter i2)
682 {
683  for (Vars_iter i_tmp = i1; i_tmp != i2; i_tmp++) {
684  BaseType *bt = *i_tmp ;
685  delete bt ; bt = 0;
686  }
687  vars.erase(i1, i2) ;
688 }
689 
697 BaseType *
698 DDS::var(const string &n, BaseType::btp_stack &s)
699 {
700  return var(n, &s);
701 }
721 BaseType *
722 DDS::var(const string &n, BaseType::btp_stack *s)
723 {
724  string name = www2id(n);
725  if( d_container )
726  return d_container->var( name, false, s ) ;
727 
728  BaseType *v = exact_match(name, s);
729  if (v)
730  return v;
731 
732  return leaf_match(name, s);
733 }
734 
735 BaseType *
736 DDS::leaf_match(const string &n, BaseType::btp_stack *s)
737 {
738  DBG(cerr << "DDS::leaf_match: Looking for " << n << endl);
739 
740  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
741  BaseType *btp = *i;
742  DBG(cerr << "DDS::leaf_match: Looking for " << n << " in: " << btp->name() << endl);
743  // Look for the d_name in the dataset's top-level
744  if (btp->name() == n) {
745  DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
746  return btp;
747  }
748 
749  if (btp->is_constructor_type()) {
750  BaseType *found = btp->var(n, false, s);
751  if (found) {
752  DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
753  return found;
754  }
755  }
756 #if STRUCTURE_ARRAY_SYNTAX_OLD
757  if (btp->is_vector_type() && btp->var()->is_constructor_type()) {
758  s->push(btp);
759  BaseType *found = btp->var()->var(n, false, s);
760  if (found) {
761  DBG(cerr << "Found " << n << " in: " << btp->var()->d_name() << endl);
762  return found;
763  }
764  }
765 #endif
766  }
767 
768  return 0; // It is not here.
769 }
770 
771 BaseType *
772 DDS::exact_match(const string &name, BaseType::btp_stack *s)
773 {
774  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
775  BaseType *btp = *i;
776  DBG2(cerr << "Looking for " << d_name << " in: " << btp << endl);
777  // Look for the d_name in the current ctor type or the top level
778  if (btp->name() == name) {
779  DBG2(cerr << "Found " << d_name << " in: " << btp << endl);
780  return btp;
781  }
782  }
783 
784  string::size_type dot_pos = name.find(".");
785  if (dot_pos != string::npos) {
786  string aggregate = name.substr(0, dot_pos);
787  string field = name.substr(dot_pos + 1);
788 
789  BaseType *agg_ptr = var(aggregate, s);
790  if (agg_ptr) {
791  DBG2(cerr << "Descending into " << agg_ptr->name() << endl);
792  return agg_ptr->var(field, true, s);
793  }
794  else
795  return 0; // qualified names must be *fully* qualified
796  }
797 
798  return 0; // It is not here.
799 }
800 
801 
804 DDS::Vars_iter
806 {
807  return vars.begin();
808 }
809 
810 DDS::Vars_riter
812 {
813  return vars.rbegin();
814 }
815 
816 DDS::Vars_iter
818 {
819  return vars.end() ;
820 }
821 
822 DDS::Vars_riter
824 {
825  return vars.rend() ;
826 }
827 
831 DDS::Vars_iter
833 {
834  return vars.begin() + i;
835 }
836 
840 BaseType *
842 {
843  return *(vars.begin() + i);
844 }
845 
850 void
851 DDS::insert_var(Vars_iter i, BaseType *ptr)
852 {
853 #if 0
854  if (ptr->is_dap4_only_type())
855  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
856 #endif
857  vars.insert(i, ptr->ptr_duplicate());
858 }
859 
867 void
869 {
870 #if 0
871  if (ptr->is_dap4_only_type())
872  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
873 #endif
874  vars.insert(i, ptr);
875 }
876 
878 int
880 {
881  return vars.size();
882 }
883 
884 void
885 DDS::timeout_on()
886 {
887 #if USE_LOCAL_TIMEOUT_SCHEME
888 #ifndef WIN32
889  alarm(d_timeout);
890 #endif
891 #endif
892 }
893 
894 void
895 DDS::timeout_off()
896 {
897 #if USE_LOCAL_TIMEOUT_SCHEME
898 #ifndef WIN32
899  // Old behavior commented out. I think it is an error to change the value
900  // of d_timeout. The way this will likely be used is to set the timeout
901  // value once and then 'turn on' or turn off' that timeout as the situation
902  // dictates. The initeded use for the DDS timeout is so that timeouts for
903  // data responses will include the CPU resources needed to build the response
904  // but not the time spent transmitting the response. This may change when
905  // more parallelism is added to the server... These methods are called from
906  // BESDapResponseBuilder in bes/dap. jhrg 12/22/15
907 
908  // d_timeout = alarm(0);
909 
910  alarm(0);
911 #endif
912 #endif
913 }
914 
915 void
916 DDS::set_timeout(int)
917 {
918 #if USE_LOCAL_TIMEOUT_SCHEME
919  // Has no effect under win32
920  d_timeout = t;
921 #endif
922 }
923 
924 int
925 DDS::get_timeout()
926 {
927 #if USE_LOCAL_TIMEOUT_SCHEME
928  // Has to effect under win32
929  return d_timeout;
930 #endif
931  return 0;
932 }
933 
935 void
937 {
938  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
939  if ((*i)->type() == dods_sequence_c)
940  dynamic_cast<Sequence&>(**i).set_leaf_sequence();
941  else if ((*i)->type() == dods_structure_c)
942  dynamic_cast<Structure&>(**i).set_leaf_sequence();
943  }
944 }
945 
947 void
948 DDS::parse(string fname)
949 {
950  FILE *in = fopen(fname.c_str(), "r");
951 
952  if (!in) {
953  throw Error(cannot_read_file, "Could not open: " + fname);
954  }
955 
956  try {
957  parse(in);
958  fclose(in);
959  }
960  catch (Error &e) {
961  fclose(in);
962  throw ;
963  }
964 }
965 
966 
968 void
969 DDS::parse(int fd)
970 {
971 #ifdef WIN32
972  int new_fd = _dup(fd);
973 #else
974  int new_fd = dup(fd);
975 #endif
976 
977  if (new_fd < 0)
978  throw InternalErr(__FILE__, __LINE__, "Could not access file.");
979  FILE *in = fdopen(new_fd, "r");
980 
981  if (!in) {
982  throw InternalErr(__FILE__, __LINE__, "Could not access file.");
983  }
984 
985  try {
986  parse(in);
987  fclose(in);
988  }
989  catch (Error &e) {
990  fclose(in);
991  throw ;
992  }
993 }
994 
1001 void
1002 DDS::parse(FILE *in)
1003 {
1004  if (!in) {
1005  throw InternalErr(__FILE__, __LINE__, "Null input stream.");
1006  }
1007 
1008  void *buffer = dds_buffer(in);
1009  dds_switch_to_buffer(buffer);
1010 
1011  parser_arg arg(this);
1012 
1013  bool status = ddsparse(&arg) == 0;
1014 
1015  dds_delete_buffer(buffer);
1016 
1017  DBG2(cout << "Status from parser: " << status << endl);
1018 
1019  // STATUS is the result of the parser function; if a recoverable error
1020  // was found it will be true but arg.status() will be false.
1021  if (!status || !arg.status()) {// Check parse result
1022  if (arg.error())
1023  throw *arg.error();
1024  }
1025 }
1026 
1028 void
1029 DDS::print(FILE *out)
1030 {
1031  ostringstream oss;
1032  print(oss);
1033  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1034 }
1035 
1037 void
1038 DDS::print(ostream &out)
1039 {
1040  out << "Dataset {\n" ;
1041 
1042  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1043  (*i)->print_decl(out) ;
1044  }
1045 
1046  out << "} " << id2www(d_name) << ";\n" ;
1047 
1048  return ;
1049 }
1050 
1060 static string four_spaces = " ";
1061 void print_var_das(ostream &out, BaseType *bt, string indent=""){
1062 
1063  AttrTable attr_table = bt->get_attr_table();
1064  out << indent << add_space_encoding(bt->name()) << " {" << endl;
1065  attr_table.print(out, indent+four_spaces);
1066  Constructor *cnstrctr = dynamic_cast < Constructor * >(bt);
1067  if(cnstrctr) {
1068  Constructor::Vars_iter i = cnstrctr->var_begin();
1069  Constructor::Vars_iter e = cnstrctr->var_end();
1070  for (; i!=e; i++) {
1071  print_var_das(out,*i,indent+four_spaces);
1072  }
1073 
1074  }
1075  out << indent << "}" << endl;
1076 
1077 }
1078 
1079 void
1080 DDS::print_das(ostream &out)
1081 {
1082  string indent(" ");
1083  out << "Attributes {" << endl ;
1084  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1085  print_var_das(out, *i, four_spaces);
1086  }
1087  // Print the global attributes at the end.
1088  d_attr.print(out,indent);
1089  out << "}" << endl ;
1090 }
1091 
1102 void
1104 {
1105  ostringstream oss;
1106  print_constrained(oss);
1107  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1108 }
1109 
1120 void
1122 {
1123  out << "Dataset {\n" ;
1124 
1125  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1126  // for each variable, indent with four spaces, print a trailing
1127  // semicolon, do not print debugging information, print only
1128  // variables in the current projection.
1129  (*i)->print_decl(out, " ", true, false, true) ;
1130  }
1131 
1132  out << "} " << id2www(d_name) << ";\n" ;
1133 
1134  return;
1135 }
1136 
1148 void
1149 DDS::print_xml(FILE *out, bool constrained, const string &blob)
1150 {
1151  ostringstream oss;
1152  print_xml_writer(oss, constrained, blob);
1153  fwrite(oss.str().data(), 1, oss.str().length(), out);
1154 }
1155 
1167 void
1168 DDS::print_xml(ostream &out, bool constrained, const string &blob)
1169 {
1170  print_xml_writer(out, constrained, blob);
1171 }
1172 
1173 class VariablePrintXMLWriter : public unary_function<BaseType *, void>
1174 {
1175  XMLWriter &d_xml;
1176  bool d_constrained;
1177 public:
1178  VariablePrintXMLWriter(XMLWriter &xml, bool constrained)
1179  : d_xml(xml), d_constrained(constrained)
1180  {}
1181  void operator()(BaseType *bt)
1182  {
1183  bt->print_xml_writer(d_xml, d_constrained);
1184  }
1185 };
1186 
1203 void
1204 DDS::print_xml_writer(ostream &out, bool constrained, const string &blob)
1205 {
1206  XMLWriter xml(" ");
1207 
1208  // Stamp and repeat for these sections; trying to economize is makes it
1209  // even more confusing
1210  if (get_dap_major() >= 4) {
1211  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
1212  throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
1213  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1214  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1215 
1216  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)get_dap_version().c_str()) < 0)
1217  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1218 
1219  if (!get_request_xml_base().empty()) {
1220  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
1221  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1222 
1223  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
1224  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1225  }
1226  if (!get_namespace().empty()) {
1227  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)get_namespace().c_str()) < 0)
1228  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1229  }
1230  }
1231  else if (get_dap_major() == 3 && get_dap_minor() >= 2) {
1232  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
1233  throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
1234  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1235  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1236  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
1237  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1238 
1239  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_32_n_sl.c_str()) < 0)
1240  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1241 
1242  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:grddl", (const xmlChar*)"http://www.w3.org/2003/g/data-view#") < 0)
1243  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:grddl");
1244 
1245  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "grddl:transformation", (const xmlChar*)grddl_transformation_dap32.c_str()) < 0)
1246  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:transformation");
1247 
1248  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
1249  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1250  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:dap", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
1251  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:dap");
1252 
1253  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)"3.2") < 0)
1254  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1255 
1256  if (!get_request_xml_base().empty()) {
1257  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
1258  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1259 
1260  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
1261  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1262  }
1263  }
1264  else { // dap2
1265  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
1266  throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
1267  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1268  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1269  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
1270  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1271 
1272  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap20_namespace.c_str()) < 0)
1273  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1274 
1275  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_20_n_sl.c_str()) < 0)
1276  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1277  }
1278 
1279  // Print the global attributes
1280  d_attr.print_xml_writer(xml);
1281 
1282  // Print each variable
1283  for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
1284 
1285  // For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
1286  // the CID of the MIME part that holds the data. For DAP2 (which includes
1287  // 3.0 and 3.1), the blob is an href. For DAP4, only write the CID if it's
1288  // given.
1289  if (get_dap_major() >= 4) {
1290  if (!blob.empty()) {
1291  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1292  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1293  string cid = "cid:" + blob;
1294  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1295  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1296  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1297  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1298  }
1299  }
1300  else if (get_dap_major() == 3 && get_dap_minor() >= 2) {
1301  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1302  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1303  string cid = "cid:" + blob;
1304  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1305  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1306  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1307  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1308  }
1309  else { // dap2
1310  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "dataBLOB") < 0)
1311  throw InternalErr(__FILE__, __LINE__, "Could not write dataBLOB element");
1312  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) "") < 0)
1313  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1314  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1315  throw InternalErr(__FILE__, __LINE__, "Could not end dataBLOB element");
1316  }
1317 
1318  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1319  throw InternalErr(__FILE__, __LINE__, "Could not end Dataset element");
1320 
1321  out << xml.get_doc();// << ends;// << endl;
1322 }
1323 
1336 void
1337 DDS::print_dmr(ostream &out, bool constrained)
1338 {
1339  if (get_dap_major() < 4)
1340  throw InternalErr(__FILE__, __LINE__, "Tried to print a DMR with DAP major version less than 4");
1341 
1342  XMLWriter xml(" ");
1343 
1344  // DAP4 wraps a dataset in a top-level Group element.
1345  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
1346  throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
1347 
1348  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml",
1349  (const xmlChar*) c_xml_namespace.c_str()) < 0)
1350  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1351 
1352  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*) c_xml_xsi.c_str())
1353  < 0)
1354  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1355 
1356  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation",
1357  (const xmlChar*) c_dap_40_n_sl.c_str()) < 0)
1358  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1359 
1360  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns",
1361  (const xmlChar*) get_namespace().c_str()) < 0)
1362  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1363 
1364  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion",
1365  (const xmlChar*) get_dap_version().c_str()) < 0)
1366  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1367 
1368  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*) get_dmr_version().c_str()) < 0)
1369  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1370 
1371  if (!get_request_xml_base().empty()) {
1372  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
1373  (const xmlChar*) get_request_xml_base().c_str()) < 0)
1374  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1375  }
1376 
1377  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) d_name.c_str()) < 0)
1378  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1379 
1380  // Print the global attributes
1381  d_attr.print_xml_writer(xml);
1382 
1383  // Print each variable
1384  for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
1385 
1386 #if 0
1387  // For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
1388  // the CID of the MIME part that holds the data. For DAP2 (which includes
1389  // 3.0 and 3.1), the blob is an href. For DAP4, only write the CID if it's
1390  // given.
1391  if (get_dap_major() >= 4) {
1392  if (!blob.empty()) {
1393  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1394  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1395  string cid = "cid:" + blob;
1396  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1397  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1398  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1399  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1400  }
1401  }
1402 #endif
1403 
1404  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1405  throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
1406 
1407  out << xml.get_doc();
1408 }
1409 
1410 // Used by DDS::send() when returning data from a function call.
1425 bool
1427 {
1428  // The dataset must have a d_name
1429  if (d_name == "") {
1430  cerr << "A dataset must have a d_name" << endl;
1431  return false;
1432  }
1433 
1434  string msg;
1435  if (!unique_names(vars, d_name, "Dataset", msg))
1436  return false;
1437 
1438  if (all)
1439  for (Vars_iter i = vars.begin(); i != vars.end(); i++)
1440  if (!(*i)->check_semantics(msg, true))
1441  return false;
1442 
1443  return true;
1444 }
1445 
1471 bool
1472 DDS::mark(const string &n, bool state)
1473 {
1474  // TODO use auto_ptr
1475  BaseType::btp_stack *s = new BaseType::btp_stack;
1476 
1477  DBG2(cerr << "DDS::mark: Looking for " << n << endl);
1478 
1479  BaseType *variable = var(n, s);
1480  if (!variable) {
1481  DBG2(cerr << "Could not find variable " << n << endl);
1482  delete s; s = 0;
1483  return false;
1484  }
1485  variable->set_send_p(state);
1486 
1487  DBG2(cerr << "DDS::mark: Set variable " << variable->d_name()
1488  << " (a " << variable->type_name() << ")" << endl);
1489 
1490  // Now check the btp_stack and run BaseType::set_send_p for every
1491  // BaseType pointer on the stack. Using BaseType::set_send_p() will
1492  // set the property for a Constructor but not its contained variables
1493  // which preserves the semantics of projecting just one field.
1494  while (!s->empty()) {
1495  s->top()->BaseType::set_send_p(state);
1496 
1497  DBG2(cerr << "DDS::mark: Set variable " << s->top()->d_name()
1498  << " (a " << s->top()->type_name() << ")" << endl);
1499  // FIXME get_parent() hosed?
1500 #if 1
1501  string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
1502  string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
1503  DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
1504 #endif
1505  s->pop();
1506  }
1507 
1508  delete s ; s = 0;
1509 
1510  return true;
1511 }
1512 
1518 void
1519 DDS::mark_all(bool state)
1520 {
1521  for (Vars_iter i = vars.begin(); i != vars.end(); i++)
1522  (*i)->set_send_p(state);
1523 }
1524 
1532 void
1533 DDS::dump(ostream &strm) const
1534 {
1535  strm << DapIndent::LMarg << "DDS::dump - ("
1536  << (void *)this << ")" << endl ;
1537  DapIndent::Indent() ;
1538  strm << DapIndent::LMarg << "d_name: " << d_name << endl ;
1539  strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
1540  strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
1541  strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
1542  strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
1543 
1544  strm << DapIndent::LMarg << "global attributes:" << endl ;
1545  DapIndent::Indent() ;
1546  d_attr.dump(strm) ;
1547  DapIndent::UnIndent() ;
1548 
1549  if (vars.size()) {
1550  strm << DapIndent::LMarg << "vars:" << endl ;
1551  DapIndent::Indent() ;
1552  Vars_citer i = vars.begin() ;
1553  Vars_citer ie = vars.end() ;
1554  for (; i != ie; i++) {
1555  (*i)->dump(strm) ;
1556  }
1557  DapIndent::UnIndent() ;
1558  }
1559  else {
1560  strm << DapIndent::LMarg << "vars: none" << endl ;
1561  }
1562 
1563  DapIndent::UnIndent() ;
1564 }
1565 
1566 } // namespace libdap
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:311
void print(FILE *out)
Print the entire DDS to the specified file.
Definition: DDS.cc:1029
virtual Attr_iter attr_end()
Definition: AttrTable.cc:718
void insert_var_nocopy(Vars_iter i, BaseType *ptr)
Definition: DDS.cc:868
Contains the attributes for a dataset.
Definition: AttrTable.h:142
Vars_iter get_vars_iter(int i)
Get an iterator.
Definition: DDS.cc:832
void insert_var(Vars_iter i, BaseType *ptr)
Insert a variable before the referenced element.
Definition: DDS.cc:851
Vars_iter var_begin()
Return an iterator to the first variable.
Definition: DDS.cc:805
virtual void print_xml_writer(XMLWriter &xml, bool constrained=false)
Definition: BaseType.cc:1125
string add_space_encoding(const string &s)
Definition: AttrTable.cc:77
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:237
DDS(BaseTypeFactory *factory, const string &name="")
Definition: DDS.cc:205
int get_request_size(bool constrained)
Get the estimated response size.
Definition: DDS.cc:566
STL namespace.
BaseType * var(const string &n, BaseType::btp_stack &s)
Definition: DDS.cc:698
virtual void transfer_attributes(DAS *das)
Definition: DDS.cc:287
string filename() const
Definition: DDS.cc:388
void print_xml(FILE *out, bool constrained, const string &blob="")
Definition: DDS.cc:1149
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
Definition: AttrTable.cc:1242
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
Definition: DDS.cc:1204
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition: DDS.cc:614
Holds a structure (aggregate) type.
Definition: Structure.h:83
Vars_riter var_rend()
Return a reverse iterator.
Definition: DDS.cc:823
string get_dataset_name() const
Definition: DDS.cc:357
int num_var()
Returns the number of variables in the DDS.
Definition: DDS.cc:879
bool mark(const string &name, bool state)
Mark the send_p flag of the named variable to state.
Definition: DDS.cc:1472
A class for software fault reporting.
Definition: InternalErr.h:64
void parse(string fname)
Parse a DDS from a file with the given d_name.
Definition: DDS.cc:948
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Returns a pointer to a member of a constructor class.
Definition: BaseType.cc:749
virtual bool is_vector_type() const
Returns true if the instance is a vector (i.e., array) type variable.
Definition: BaseType.cc:393
virtual void set_send_p(bool state)
Definition: BaseType.cc:559
virtual bool is_constructor_type() const
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable...
Definition: BaseType.cc:403
void mark_all(bool state)
Definition: DDS.cc:1519
void print_dmr(ostream &out, bool constrained)
Definition: DDS.cc:1337
virtual AttrTable & get_attr_table()
Definition: DDS.cc:373
BaseType * get_var_index(int i)
Get a variable.
Definition: DDS.cc:841
bool check_semantics(bool all=false)
Check the semantics of each of the variables represented in the DDS.
Definition: DDS.cc:1426
Structure * container()
Definition: DDS.cc:548
int get_dap_major() const
Get the DAP major version as sent by the client.
Definition: DDS.h:261
string get_request_xml_base() const
Get the URL that will return this DDS/DDX/DataThing.
Definition: DDS.h:279
string container_name()
Definition: DDS.cc:512
string get_error_message() const
Definition: Error.cc:276
virtual AttrTable * get_top_level_attributes()
Returns the top most set of attributes.
Definition: DAS.h:166
virtual void dump(ostream &strm) const
dumps information about this object
Definition: DDS.cc:1533
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:710
virtual string container_name() const
Returns the name of the current attribute container when multiple files used to build this DAS...
Definition: DAS.h:149
virtual BaseType * ptr_duplicate()=0
string get_namespace() const
Get the namespace associated with the DDS - likely set only by DDX responses.
Definition: DDS.h:285
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
Vars_iter var_end()
Return an iterator.
Definition: DDS.cc:817
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
Definition: DDS.cc:936
virtual AttrTable & get_attr_table()
Definition: BaseType.cc:573
void set_dap_minor(int p)
Definition: DDS.cc:424
void set_dataset_name(const string &n)
Definition: DDS.cc:364
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
libdap base object for common functionality of libdap objects
Definition: DapObj.h:55
Pass parameters by reference to a parser.
Definition: parser.h:68
void del_var(const string &n)
Removes a variable from the DDS.
Definition: DDS.cc:642
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
Vars_riter var_rbegin()
Return a reverse iterator.
Definition: DDS.cc:811
Vars_iter var_end()
Definition: Constructor.cc:364
Hold attribute data for a DAP2 dataset.
Definition: DAS.h:121
A class for error processing.
Definition: Error.h:90
int get_dap_minor() const
Get the DAP minor version as sent by the client.
Definition: DDS.h:263
void set_dap_major(int p)
Definition: DDS.cc:405
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.
Definition: DDS.cc:1103
void set_dap_version(const string &version_string="2.0")
Definition: DDS.cc:441
string id2www(string in, const string &allowable)
Definition: escaping.cc:153
void add_var(BaseType *bt)
Adds a copy of the variable to the DDS. Using the ptr_duplicate() method, perform a deep copy on the ...
Definition: DDS.cc:587