libdap++  Updated for version 3.13.1
DDS.cc
Go to the documentation of this file.
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 
85 const string c_xml_xsi = "http://www.w3.org/2001/XMLSchema-instance";
86 const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
87 
88 const string grddl_transformation_dap32 = "http://xml.opendap.org/transforms/ddxToRdfTriples.xsl";
89 
90 const string c_default_dap20_schema_location = "http://xml.opendap.org/dap/dap2.xsd";
91 const string c_default_dap32_schema_location = "http://xml.opendap.org/dap/dap3.2.xsd";
92 const string c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
93 
94 const string c_dap20_namespace = "http://xml.opendap.org/ns/DAP2";
95 const string c_dap32_namespace = "http://xml.opendap.org/ns/DAP/3.2#";
96 const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
97 
101 
102 using namespace std;
103 
104 int ddsparse(libdap::parser_arg *arg);
105 
106 // Glue for the DDS parser defined in dds.lex
107 void dds_switch_to_buffer(void *new_buffer);
108 void dds_delete_buffer(void * buffer);
109 void *dds_buffer(FILE *fp);
110 
111 namespace libdap {
112 
113 void
114 DDS::duplicate(const DDS &dds)
115 {
116  DBG(cerr << "Entering DDS::duplicate... " <<endl);
117 #if 0
118  BaseTypeFactory *d_factory;
119 
120  string d_name; // The dataset d_name
121  string d_filename; // File d_name (or other OS identifier) for
122  string d_container_name; // d_name of container structure
123  Structure *d_container; // current container for container d_name
124  // dataset or part of dataset.
125 
126  int d_dap_major; // The protocol major version number
127  int d_dap_minor; // ... and minor version number
128  string d_dap_version; // String version of the protocol
129  string d_request_xml_base;
130  string d_namespace;
131 
132  AttrTable d_attr; // Global attributes.
133 
134  vector<BaseType *> vars; // Variables at the top level
135 
136  int d_timeout; // alarm time in seconds. If greater than
137  // zero, raise the alarm signal if more than
138  // d_timeout seconds are spent reading data.
139  Keywords d_keywords; // Holds keywords parsed from the CE
140 
141  long d_max_response_size; // In bytes
142 #endif
143 
144  d_factory = dds.d_factory;
145 
146  d_name = dds.d_name;
147  d_filename = dds.d_filename;
148  d_container_name = dds.d_container_name;
149  d_container = dds.d_container;
150 
151  d_dap_major = dds.d_dap_major;
152  d_dap_minor = dds.d_dap_minor;
153 
154  d_dap_version = dds.d_dap_version; // String version of the protocol
155  d_request_xml_base = dds.d_request_xml_base;
156  d_namespace = dds.d_namespace;
157 
158  d_attr = dds.d_attr;
159 
160  DDS &dds_tmp = const_cast<DDS &>(dds);
161 
162  // copy the things pointed to by the list, not just the pointers
163  for (Vars_iter i = dds_tmp.var_begin(); i != dds_tmp.var_end(); i++) {
164  add_var(*i); // add_var() dups the BaseType.
165  }
166 
167  d_timeout = dds.d_timeout;
168 
169  d_keywords = dds.d_keywords; // value copy; Keywords contains no pointers
170 
171  d_max_response_size = dds.d_max_response_size;
172 }
173 
174 //FIXME says 3.2 when it's 2.0
187 DDS::DDS(BaseTypeFactory *factory, const string &name)
188  : d_factory(factory), d_name(name), d_container_name(""), d_container(0),
189  d_request_xml_base(""),
190  d_timeout(0), d_keywords(), d_max_response_size(0)
191 {
192  DBG(cerr << "Building a DDS for the default version (3.2)" << endl);
193 
194  // This method sets a number of values, including those returned by
195  // get_protocol_major(), ..., get_namespace().
196  set_dap_version("2.0");
197 }
198 
214 DDS::DDS(BaseTypeFactory *factory, const string &name, const string &version)
215  : d_factory(factory), d_name(name), d_container_name(""), d_container(0),
216  d_request_xml_base(""),
217  d_timeout(0), d_keywords(), d_max_response_size(0)
218 {
219  DBG(cerr << "Building a DDS for version: " << version << endl);
220 
221  // This method sets a number of values, including those returned by
222  // get_protocol_major(), ..., get_namespace().
223  set_dap_version(version);
224 }
225 
227 DDS::DDS(const DDS &rhs) : DapObj()
228 {
229  DBG(cerr << "Entering DDS(const DDS &rhs) ..." << endl);
230  duplicate(rhs);
231  DBG(cerr << " bye." << endl);
232 }
233 
235 {
236  // delete all the variables in this DDS
237  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
238  BaseType *btp = *i ;
239  delete btp ; btp = 0;
240  }
241 }
242 
243 DDS &
244 DDS::operator=(const DDS &rhs)
245 {
246  DBG(cerr << "Entering DDS::operator= ..." << endl);
247  if (this == &rhs)
248  return *this;
249 
250  duplicate(rhs);
251 
252  DBG(cerr << " bye." << endl);
253  return *this;
254 }
255 
270  // If there is a container set in the DDS then get the container from
271  // the DAS. If they are not the same container, then throw an exception
272  // (should be working on the same container). If the container does not
273  // exist in the DAS, then throw an exception
274  if (d_container) {
275  if (das->container_name() != d_container_name)
276  throw InternalErr(__FILE__, __LINE__,
277  "Error transferring attributes: working on a container in dds, but not das");
278  }
279 
280  // Give each variable a chance to claim its attributes.
281  AttrTable *top_level = das->get_top_level_attributes();
282 
283  Vars_iter var = var_begin();
284  while (var != var_end()) {
285  try {
286  DBG(cerr << "Processing the attributes for: " << (*var)->d_name() << " a " << (*var)->type_name() << endl);
287  (*var)->transfer_attributes(top_level);
288  var++;
289  } catch (Error &e) {
290  DBG(cerr << "Got this exception: " << e.get_error_message() << endl);
291  var++;
292  throw e;
293  }
294  }
295 
296  // Now we transfer all of the attributes still marked as global to the
297  // global container in the DDS.
298 
299  AttrTable::Attr_iter at_cont_p = top_level->attr_begin();
300  while (at_cont_p != top_level->attr_end()) {
301  // In truth, all of the top level attributes should be containers, but
302  // this test handles the abnormal case where somehow someone makes a
303  // top level attribute that is not a container by silently dropping it.
304  if ((*at_cont_p)->type == Attr_container && (*at_cont_p)->attributes->is_global_attribute()) {
305  DBG(cerr << (*at_cont_p)->d_name << " is a global attribute." << endl);
306  // copy the source container so that the DAS passed in can be
307  // deleted after calling this method.
308  AttrTable *at = new AttrTable(*(*at_cont_p)->attributes);
309  d_attr.append_container(at, at->get_name());
310  }
311 
312  at_cont_p++;
313  }
314 }
315 
323 
325 string
327 {
328  return d_name;
329 }
330 
332 void
333 DDS::set_dataset_name(const string &n)
334 {
335  d_name = n;
336 }
337 
339 
341 AttrTable &
343 {
344  return d_attr;
345 }
346 
356 string
358 {
359  return d_filename;
360 }
361 
363 void
364 DDS::filename(const string &fn)
365 {
366  d_filename = fn;
367 }
369 
373 void
375 {
376  d_dap_major = p;
377 
378  // This works because regardless of the order set_dap_major and set_dap_minor
379  // are called, once they both are called, the value in the string is
380  // correct. I protect against negative numbers because that would be
381  // nonsensical.
382  if (d_dap_minor >= 0) {
383  ostringstream oss;
384  oss << d_dap_major << "." << d_dap_minor;
385  d_dap_version = oss.str();
386  }
387 }
388 
392 void
394 {
395  d_dap_minor = p;
396 
397  if (d_dap_major >= 0) {
398  ostringstream oss;
399  oss << d_dap_major << "." << d_dap_minor;
400  d_dap_version = oss.str();
401  }
402 }
403 
409 void
410 DDS::set_dap_version(const string &v /* = "2.0" */)
411 {
412  istringstream iss(v);
413 
414  int major = -1, minor = -1;
415  char dot;
416  if (!iss.eof() && !iss.fail())
417  iss >> major;
418  if (!iss.eof() && !iss.fail())
419  iss >> dot;
420  if (!iss.eof() && !iss.fail())
421  iss >> minor;
422 
423  if (major == -1 || minor == -1 or dot != '.')
424  throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
425 
426  d_dap_version = v;
427 
428  d_dap_major = major;
429  d_dap_minor = minor;
430 
431  // Now set the related XML constants. These might be overwritten if
432  // the DDS instance is being built from a document parse, but if it's
433  // being constructed by a server the code to generate the XML document
434  // needs these values to match the DAP version information.
435  switch (d_dap_major) {
436  case 2:
437  d_namespace = c_dap20_namespace;
438  break;
439  case 3:
440  d_namespace = c_dap32_namespace;
441  break;
442  case 4:
443  d_namespace = c_dap40_namespace;
444  break;
445  default:
446  throw InternalErr(__FILE__, __LINE__, "Unknown DAP version.");
447  }
448 }
449 
457 void
459 {
460  int major = floor(d);
461  int minor = (d-major)*10;
462 
463  DBG(cerr << "Major: " << major << ", Minor: " << minor << endl);
464 
465  ostringstream oss;
466  oss << major << "." << minor;
467 
468  set_dap_version(oss.str());
469 }
470 
480 string
482 {
483  return d_container_name;
484 }
485 
488 void
489 DDS::container_name(const string &cn)
490 {
491  // we want to search the DDS for the top level structure with the given
492  // d_name. Set the container to null so that we don't search some previous
493  // container.
494  d_container = 0 ;
495  if( !cn.empty() )
496  {
497  d_container = dynamic_cast<Structure *>( var( cn ) ) ;
498  if( !d_container )
499  {
500  // create a structure for this container. Calling add_var
501  // while_container is null will add the new structure to DDS and
502  // not some sub structure. Adding the new structure makes a copy
503  // of it. So after adding it, go get it and set d_container.
504  Structure *s = new Structure( cn ) ;
505  add_var( s ) ;
506  delete s ;
507  s = 0 ;
508  d_container = dynamic_cast<Structure *>( var( cn ) ) ;
509  }
510  }
511  d_container_name = cn;
512 
513 }
514 
516 Structure *
518 {
519  return d_container ;
520 }
521 
523 
534 int
535 DDS::get_request_size(bool constrained)
536 {
537  int w = 0;
538  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
539  if (constrained) {
540  if ((*i)->send_p())
541  w += (*i)->width(constrained);
542  }
543  else {
544  w += (*i)->width(constrained);
545  }
546  }
547 
548  return w;
549 }
550 
557  if (!bt)
558  throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
559 #if 0
560  if (bt->is_dap4_only_type())
561  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
562 #endif
563  DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
564 
565  BaseType *btp = bt->ptr_duplicate();
566  DBG2(cerr << "In DDS::add_var(), btp's address is: " << btp << endl);
567  if (d_container) {
568  // Mem leak fix [mjohnson nov 2009]
569  // Structure::add_var() creates ANOTHER copy.
570  d_container->add_var(bt);
571  // So we need to delete btp or else it leaks
572  delete btp;
573  btp = 0;
574  }
575  else {
576  vars.push_back(btp);
577  }
578 }
579 
582 void
584 {
585  if (!bt)
586  throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
587 #if 0
588  //FIXME There's no longer a DAP2 and DAP4 DDS
589  if (bt->is_dap4_only_type())
590  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
591 #endif
592 
593  DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
594 
595  if (d_container) {
596  d_container->add_var_nocopy(bt);
597  }
598  else {
599  vars.push_back(bt);
600  }
601 }
602 
603 
610 void
611 DDS::del_var(const string &n)
612 {
613  if( d_container )
614  {
615  d_container->del_var( n ) ;
616  return ;
617  }
618 
619  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
620  if ((*i)->name() == n) {
621  BaseType *bt = *i ;
622  vars.erase(i) ;
623  delete bt ; bt = 0;
624  return;
625  }
626  }
627 }
628 
633 void
635 {
636  if (i != vars.end()) {
637  BaseType *bt = *i ;
638  vars.erase(i) ;
639  delete bt ; bt = 0;
640  }
641 }
642 
649 void
651 {
652  for (Vars_iter i_tmp = i1; i_tmp != i2; i_tmp++) {
653  BaseType *bt = *i_tmp ;
654  delete bt ; bt = 0;
655  }
656  vars.erase(i1, i2) ;
657 }
658 
666 BaseType *
667 DDS::var(const string &n, BaseType::btp_stack &s)
668 {
669  return var(n, &s);
670 }
690 BaseType *
691 DDS::var(const string &n, BaseType::btp_stack *s)
692 {
693  string name = www2id(n);
694  if( d_container )
695  return d_container->var( name, false, s ) ;
696 
697  BaseType *v = exact_match(name, s);
698  if (v)
699  return v;
700 
701  return leaf_match(name, s);
702 }
703 
704 BaseType *
706 {
707  DBG(cerr << "DDS::leaf_match: Looking for " << n << endl);
708 
709  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
710  BaseType *btp = *i;
711  DBG(cerr << "DDS::leaf_match: Looking for " << n << " in: " << btp->d_name() << endl);
712  // Look for the d_name in the dataset's top-level
713  if (btp->name() == n) {
714  DBG(cerr << "Found " << n << " in: " << btp->d_name() << endl);
715  return btp;
716  }
717 
718  if (btp->is_constructor_type()) {
719  BaseType *found = btp->var(n, false, s);
720  if (found) {
721  DBG(cerr << "Found " << n << " in: " << btp->d_name() << endl);
722  return found;
723  }
724  }
725 #if STRUCTURE_ARRAY_SYNTAX_OLD
726  if (btp->is_vector_type() && btp->var()->is_constructor_type()) {
727  s->push(btp);
728  BaseType *found = btp->var()->var(n, false, s);
729  if (found) {
730  DBG(cerr << "Found " << n << " in: " << btp->var()->d_name() << endl);
731  return found;
732  }
733  }
734 #endif
735  }
736 
737  return 0; // It is not here.
738 }
739 
740 BaseType *
741 DDS::exact_match(const string &name, BaseType::btp_stack *s)
742 {
743  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
744  BaseType *btp = *i;
745  DBG2(cerr << "Looking for " << d_name << " in: " << btp << endl);
746  // Look for the d_name in the current ctor type or the top level
747  if (btp->name() == name) {
748  DBG2(cerr << "Found " << d_name << " in: " << btp << endl);
749  return btp;
750  }
751  }
752 
753  string::size_type dot_pos = name.find(".");
754  if (dot_pos != string::npos) {
755  string aggregate = name.substr(0, dot_pos);
756  string field = name.substr(dot_pos + 1);
757 
758  BaseType *agg_ptr = var(aggregate, s);
759  if (agg_ptr) {
760  DBG2(cerr << "Descending into " << agg_ptr->name() << endl);
761  return agg_ptr->var(field, true, s);
762  }
763  else
764  return 0; // qualified names must be *fully* qualified
765  }
766 
767  return 0; // It is not here.
768 }
769 
770 
775 {
776  return vars.begin();
777 }
778 
781 {
782  return vars.rbegin();
783 }
784 
787 {
788  return vars.end() ;
789 }
790 
793 {
794  return vars.rend() ;
795 }
796 
802 {
803  return vars.begin() + i;
804 }
805 
809 BaseType *
811 {
812  return *(vars.begin() + i);
813 }
814 
819 void
821 {
822 #if 0
823  if (ptr->is_dap4_only_type())
824  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
825 #endif
826  vars.insert(i, ptr->ptr_duplicate());
827 }
828 
836 void
838 {
839 #if 0
840  if (ptr->is_dap4_only_type())
841  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 DDS.");
842 #endif
843  vars.insert(i, ptr);
844 }
845 
847 int
849 {
850  return vars.size();
851 }
852 
853 void
855 {
856 #ifndef WIN32
857  alarm(d_timeout);
858 #endif
859 }
860 
861 void
863 {
864 #ifndef WIN32
865  d_timeout = alarm(0);
866 #endif
867 }
868 
869 void
871 {
872  // Has no effect under win32
873  d_timeout = t;
874 }
875 
876 int
878 {
879  // Has to effect under win32
880  return d_timeout;
881 }
882 
884 void
886 {
887  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
888  if ((*i)->type() == dods_sequence_c)
889  dynamic_cast<Sequence&>(**i).set_leaf_sequence();
890  else if ((*i)->type() == dods_structure_c)
891  dynamic_cast<Structure&>(**i).set_leaf_sequence();
892  }
893 }
894 
896 void
897 DDS::parse(string fname)
898 {
899  FILE *in = fopen(fname.c_str(), "r");
900 
901  if (!in) {
902  throw Error(cannot_read_file, "Could not open: " + fname);
903  }
904 
905  try {
906  parse(in);
907  fclose(in);
908  }
909  catch (Error &e) {
910  fclose(in);
911  throw ;
912  }
913 }
914 
915 
917 void
918 DDS::parse(int fd)
919 {
920 #ifdef WIN32
921  FILE *in = fdopen(_dup(fd), "r");
922 #else
923  FILE *in = fdopen(dup(fd), "r");
924 #endif
925 
926  if (!in) {
927  throw InternalErr(__FILE__, __LINE__, "Could not access file.");
928  }
929 
930  try {
931  parse(in);
932  fclose(in);
933  }
934  catch (Error &e) {
935  fclose(in);
936  throw ;
937  }
938 }
939 
946 void
947 DDS::parse(FILE *in)
948 {
949  if (!in) {
950  throw InternalErr(__FILE__, __LINE__, "Null input stream.");
951  }
952 
953  void *buffer = dds_buffer(in);
954  dds_switch_to_buffer(buffer);
955 
956  parser_arg arg(this);
957 
958  bool status = ddsparse(&arg) == 0;
959 
960  dds_delete_buffer(buffer);
961 
962  DBG2(cout << "Status from parser: " << status << endl);
963 
964  // STATUS is the result of the parser function; if a recoverable error
965  // was found it will be true but arg.status() will be false.
966  if (!status || !arg.status()) {// Check parse result
967  if (arg.error())
968  throw *arg.error();
969  }
970 }
971 
973 void
974 DDS::print(FILE *out)
975 {
976  ostringstream oss;
977  print(oss);
978  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
979 }
980 
982 void
983 DDS::print(ostream &out)
984 {
985  out << "Dataset {\n" ;
986 
987  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
988  (*i)->print_decl(out) ;
989  }
990 
991  out << "} " << id2www(d_name) << ";\n" ;
992 
993  return ;
994 }
995 
1005 void
1006 DDS::print_das(ostream &out)
1007 {
1008  out << "Attributes {\n" ;
1009 
1010  d_attr.print(out, " ");
1011  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1012  (*i)->get_attr_table().print(out, " ");
1013  }
1014 
1015  out << "}\n" ;
1016 }
1017 
1028 void
1030 {
1031  ostringstream oss;
1032  print_constrained(oss);
1033  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1034 }
1035 
1046 void
1048 {
1049  out << "Dataset {\n" ;
1050 
1051  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1052  // for each variable, indent with four spaces, print a trailing
1053  // semicolon, do not print debugging information, print only
1054  // variables in the current projection.
1055  (*i)->print_decl(out, " ", true, false, true) ;
1056  }
1057 
1058  out << "} " << id2www(d_name) << ";\n" ;
1059 
1060  return;
1061 }
1062 
1074 void
1075 DDS::print_xml(FILE *out, bool constrained, const string &blob)
1076 {
1077  ostringstream oss;
1078  print_xml_writer(oss, constrained, blob);
1079  fwrite(oss.str().data(), 1, oss.str().length(), out);
1080 }
1081 
1093 void
1094 DDS::print_xml(ostream &out, bool constrained, const string &blob)
1095 {
1096  print_xml_writer(out, constrained, blob);
1097 }
1098 
1099 class VariablePrintXMLWriter : public unary_function<BaseType *, void>
1100 {
1101  XMLWriter &d_xml;
1102  bool d_constrained;
1103 public:
1104  VariablePrintXMLWriter(XMLWriter &xml, bool constrained)
1105  : d_xml(xml), d_constrained(constrained)
1106  {}
1107  void operator()(BaseType *bt)
1108  {
1109  bt->print_xml_writer(d_xml, d_constrained);
1110  }
1111 };
1112 
1129 void
1130 DDS::print_xml_writer(ostream &out, bool constrained, const string &blob)
1131 {
1132  XMLWriter xml(" ");
1133 
1134  // Stamp and repeat for these sections; trying to economize is makes it
1135  // even more confusing
1136  if (get_dap_major() >= 4) {
1137  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
1138  throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
1139  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1140  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1141 
1142  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)get_dap_version().c_str()) < 0)
1143  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1144 
1145  if (!get_request_xml_base().empty()) {
1146  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
1147  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1148 
1149  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
1150  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1151  }
1152  if (!get_namespace().empty()) {
1153  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)get_namespace().c_str()) < 0)
1154  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1155  }
1156  }
1157  else if (get_dap_major() == 3 && get_dap_minor() >= 2) {
1158  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
1159  throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
1160  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1161  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1162  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
1163  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1164 
1165  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_32_n_sl.c_str()) < 0)
1166  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1167 
1168  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:grddl", (const xmlChar*)"http://www.w3.org/2003/g/data-view#") < 0)
1169  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:grddl");
1170 
1171  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "grddl:transformation", (const xmlChar*)grddl_transformation_dap32.c_str()) < 0)
1172  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:transformation");
1173 
1174  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
1175  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1176  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:dap", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
1177  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:dap");
1178 
1179  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)"3.2") < 0)
1180  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1181 
1182  if (!get_request_xml_base().empty()) {
1183  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
1184  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1185 
1186  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
1187  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1188  }
1189  }
1190  else { // dap2
1191  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
1192  throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
1193  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1194  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1195  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
1196  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1197 
1198  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap20_namespace.c_str()) < 0)
1199  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1200 
1201  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_20_n_sl.c_str()) < 0)
1202  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1203  }
1204 
1205  // Print the global attributes
1206  d_attr.print_xml_writer(xml);
1207 
1208  // Print each variable
1209  for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
1210 
1211  // For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
1212  // the CID of the MIME part that holds the data. For DAP2 (which includes
1213  // 3.0 and 3.1), the blob is an href. For DAP4, only write the CID if it's
1214  // given.
1215  if (get_dap_major() >= 4) {
1216  if (!blob.empty()) {
1217  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1218  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1219  string cid = "cid:" + blob;
1220  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1221  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1222  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1223  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1224  }
1225  }
1226  else if (get_dap_major() == 3 && get_dap_minor() >= 2) {
1227  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1228  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1229  string cid = "cid:" + blob;
1230  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1231  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1232  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1233  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1234  }
1235  else { // dap2
1236  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "dataBLOB") < 0)
1237  throw InternalErr(__FILE__, __LINE__, "Could not write dataBLOB element");
1238  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) "") < 0)
1239  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1240  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1241  throw InternalErr(__FILE__, __LINE__, "Could not end dataBLOB element");
1242  }
1243 
1244  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1245  throw InternalErr(__FILE__, __LINE__, "Could not end Dataset element");
1246 
1247  out << xml.get_doc();// << ends;// << endl;
1248 }
1249 
1262 void
1263 DDS::print_dmr(ostream &out, bool constrained)
1264 {
1265  if (get_dap_major() < 4)
1266  throw InternalErr(__FILE__, __LINE__, "Tried to print a DMR with DAP major version less than 4");
1267 
1268  XMLWriter xml(" ");
1269 
1270  // DAP4 wraps a dataset in a top-level Group element.
1271  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
1272  throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
1273 
1274  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml",
1275  (const xmlChar*) c_xml_namespace.c_str()) < 0)
1276  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1277 
1278  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*) c_xml_xsi.c_str())
1279  < 0)
1280  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1281 
1282  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation",
1283  (const xmlChar*) c_dap_40_n_sl.c_str()) < 0)
1284  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1285 
1286  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns",
1287  (const xmlChar*) get_namespace().c_str()) < 0)
1288  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1289 
1290  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion",
1291  (const xmlChar*) get_dap_version().c_str()) < 0)
1292  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1293 
1294  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*) get_dmr_version().c_str()) < 0)
1295  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1296 
1297  if (!get_request_xml_base().empty()) {
1298  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
1299  (const xmlChar*) get_request_xml_base().c_str()) < 0)
1300  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1301  }
1302 
1303  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) d_name.c_str()) < 0)
1304  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1305 
1306  // Print the global attributes
1307  d_attr.print_xml_writer(xml);
1308 
1309  // Print each variable
1310  for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
1311 
1312 #if 0
1313  // For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
1314  // the CID of the MIME part that holds the data. For DAP2 (which includes
1315  // 3.0 and 3.1), the blob is an href. For DAP4, only write the CID if it's
1316  // given.
1317  if (get_dap_major() >= 4) {
1318  if (!blob.empty()) {
1319  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1320  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1321  string cid = "cid:" + blob;
1322  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1323  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1324  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1325  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1326  }
1327  }
1328 #endif
1329 
1330  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1331  throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
1332 
1333  out << xml.get_doc();
1334 }
1335 
1336 // Used by DDS::send() when returning data from a function call.
1351 bool
1353 {
1354  // The dataset must have a d_name
1355  if (d_name == "") {
1356  cerr << "A dataset must have a d_name" << endl;
1357  return false;
1358  }
1359 
1360  string msg;
1361  if (!unique_names(vars, d_name, "Dataset", msg))
1362  return false;
1363 
1364  if (all)
1365  for (Vars_iter i = vars.begin(); i != vars.end(); i++)
1366  if (!(*i)->check_semantics(msg, true))
1367  return false;
1368 
1369  return true;
1370 }
1371 
1397 bool
1398 DDS::mark(const string &n, bool state)
1399 {
1400  // TODO use auto_ptr
1402 
1403  DBG2(cerr << "DDS::mark: Looking for " << n << endl);
1404 
1405  BaseType *variable = var(n, s);
1406  if (!variable) {
1407  DBG2(cerr << "Could not find variable " << n << endl);
1408  delete s; s = 0;
1409  return false;
1410  }
1411  variable->set_send_p(state);
1412 
1413  DBG2(cerr << "DDS::mark: Set variable " << variable->d_name()
1414  << " (a " << variable->type_name() << ")" << endl);
1415 
1416  // Now check the btp_stack and run BaseType::set_send_p for every
1417  // BaseType pointer on the stack. Using BaseType::set_send_p() will
1418  // set the property for a Constructor but not its contained variables
1419  // which preserves the semantics of projecting just one field.
1420  while (!s->empty()) {
1421  s->top()->BaseType::set_send_p(state);
1422 
1423  DBG2(cerr << "DDS::mark: Set variable " << s->top()->d_name()
1424  << " (a " << s->top()->type_name() << ")" << endl);
1425  // FIXME get_parent() hosed?
1426 #if 1
1427  string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
1428  string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
1429  DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
1430 #endif
1431  s->pop();
1432  }
1433 
1434  delete s ; s = 0;
1435 
1436  return true;
1437 }
1438 
1444 void
1445 DDS::mark_all(bool state)
1446 {
1447  for (Vars_iter i = vars.begin(); i != vars.end(); i++)
1448  (*i)->set_send_p(state);
1449 }
1450 
1458 void
1459 DDS::dump(ostream &strm) const
1460 {
1461  strm << DapIndent::LMarg << "DDS::dump - ("
1462  << (void *)this << ")" << endl ;
1463  DapIndent::Indent() ;
1464  strm << DapIndent::LMarg << "d_name: " << d_name << endl ;
1465  strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
1466  strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
1467  strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
1468  strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
1469 
1470  strm << DapIndent::LMarg << "global attributes:" << endl ;
1471  DapIndent::Indent() ;
1472  d_attr.dump(strm) ;
1474 
1475  if (vars.size()) {
1476  strm << DapIndent::LMarg << "vars:" << endl ;
1477  DapIndent::Indent() ;
1478  Vars_citer i = vars.begin() ;
1479  Vars_citer ie = vars.end() ;
1480  for (; i != ie; i++) {
1481  (*i)->dump(strm) ;
1482  }
1484  }
1485  else {
1486  strm << DapIndent::LMarg << "vars: none" << endl ;
1487  }
1488 
1490 }
1491 
1492 } // namespace libdap
std::vector< entry * >::iterator Attr_iter
Definition: AttrTable.h:237
const string c_dap32_namespace
Definition: DDS.cc:95
static void UnIndent()
Definition: DapIndent.cc:51
void print(FILE *out)
Print the entire DDS to the specified file.
Definition: DDS.cc:974
const string c_dap_32_n_sl
Definition: DDS.cc:99
xmlTextWriterPtr get_writer()
Definition: XMLWriter.h:60
virtual Attr_iter attr_end()
Definition: AttrTable.cc:724
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:183
void insert_var_nocopy(Vars_iter i, BaseType *ptr)
Definition: DDS.cc:837
const string c_dap20_namespace
Definition: DDS.cc:94
Contains the attributes for a dataset.
Definition: AttrTable.h:150
string get_dmr_version() const
Definition: DDS.h:269
void dds_delete_buffer(void *buffer)
Vars_iter get_vars_iter(int i)
Get an iterator.
Definition: DDS.cc:801
string get_error_message() const
Definition: Error.cc:279
const string c_default_dap32_schema_location
Definition: DDS.cc:91
BaseType * leaf_match(const string &name, BaseType::btp_stack *s=0)
Definition: DDS.cc:705
void insert_var(Vars_iter i, BaseType *ptr)
Insert a variable before the referenced element.
Definition: DDS.cc:820
Vars_iter var_begin()
Return an iterator to the first variable.
Definition: DDS.cc:774
const string c_default_dap40_schema_location
Definition: DDS.cc:92
string get_request_xml_base() const
Get the URL that will return this DDS/DDX/DataThing.
Definition: DDS.h:281
int ddsparse(libdap::parser_arg *arg)
void set_timeout(int t)
Definition: DDS.cc:870
DDS(BaseTypeFactory *factory, const string &name="")
Definition: DDS.cc:187
int get_request_size(bool constrained)
Get the estimated response size.
Definition: DDS.cc:535
BaseType * var(const string &n, BaseType::btp_stack &s)
Definition: DDS.cc:667
virtual void transfer_attributes(DAS *das)
Definition: DDS.cc:269
void print_xml(FILE *out, bool constrained, const string &blob="")
Definition: DDS.cc:1075
void print_xml_writer(XMLWriter &xml)
Definition: AttrTable.cc:1415
virtual void add_var_nocopy(BaseType *bt, Part part=nil)
Definition: Constructor.cc:346
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
Definition: AttrTable.cc:1233
std::vector< BaseType * >::const_iterator Vars_citer
Definition: DDS.h:218
void timeout_off()
Definition: DDS.cc:862
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
Definition: DDS.cc:1130
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition: DDS.cc:583
Holds a structure (aggregate) type.
Definition: Structure.h:85
Vars_riter var_rend()
Return a reverse iterator.
Definition: DDS.cc:792
virtual void add_var(BaseType *bt, Part part=nil)
Definition: Constructor.cc:321
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:242
#define DBG2(x)
Definition: debug.h:73
int num_var()
Returns the number of variables in the DDS.
Definition: DDS.cc:848
std::vector< BaseType * >::reverse_iterator Vars_riter
Definition: DDS.h:220
stack< BaseType * > btp_stack
Definition: BaseType.h:233
bool mark(const string &name, bool state)
Mark the send_p flag of the named variable to state.
Definition: DDS.cc:1398
A class for software fault reporting.
Definition: InternalErr.h:64
virtual bool is_vector_type()
Returns true if the instance is a vector (i.e., array) type variable.
Definition: BaseType.cc:402
void parse(string fname)
Parse a DDS from a file with the given d_name.
Definition: DDS.cc:897
DDS & operator=(const DDS &rhs)
Definition: DDS.cc:244
const string c_dap40_namespace
Definition: DDS.cc:96
virtual bool is_constructor_type()
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable...
Definition: BaseType.cc:449
const char * version
Definition: getdap.cc:60
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:795
#define DBG(x)
Definition: debug.h:58
string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:296
string get_namespace() const
Get the namespace associated with the DDS - likely set only by DDX responses.
Definition: DDS.h:287
virtual ~DDS()
Definition: DDS.cc:234
string get_dap_version() const
Definition: DDS.h:268
int get_dap_major() const
Get the DAP major version as sent by the client.
Definition: DDS.h:263
virtual void set_send_p(bool state)
Definition: BaseType.cc:652
void mark_all(bool state)
Definition: DDS.cc:1445
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition: AttrTable.cc:414
const char * get_doc()
Definition: XMLWriter.cc:105
static void Indent()
Definition: DapIndent.cc:45
#define cannot_read_file
Definition: Error.h:66
const string c_xml_namespace
Definition: DDS.cc:86
std::vector< BaseType * >::iterator Vars_iter
Definition: DDS.h:219
void print_das(ostream &out)
Definition: DDS.cc:1006
const string c_dap_40_n_sl
Definition: DDS.cc:100
void print_dmr(ostream &out, bool constrained)
Definition: DDS.cc:1263
virtual AttrTable & get_attr_table()
Definition: DDS.cc:342
BaseType * get_var_index(int i)
Get a variable.
Definition: DDS.cc:810
bool check_semantics(bool all=false)
Check the semantics of each of the variables represented in the DDS.
Definition: DDS.cc:1352
void * dds_buffer(FILE *fp)
Structure * container()
Definition: DDS.cc:517
Error * error()
Definition: parser.h:93
string container_name()
Definition: DDS.cc:481
void dds_switch_to_buffer(void *new_buffer)
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:254
virtual AttrTable * get_top_level_attributes()
Returns the top most set of attributes.
Definition: DAS.h:143
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:220
void timeout_on()
Definition: DDS.cc:854
Vars_iter var_end()
Return an iterator.
Definition: DDS.cc:786
BaseType * exact_match(const string &name, BaseType::btp_stack *s=0)
Definition: DDS.cc:741
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
Definition: DDS.cc:885
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:80
const string c_default_dap20_schema_location
Definition: DDS.cc:90
void set_dap_minor(int p)
Definition: DDS.cc:393
void set_dataset_name(const string &n)
Definition: DDS.cc:333
The basic data type for the DODS DAP types.
Definition: BaseType.h:199
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:611
bool unique_names(vector< BaseType * > l, const string &var_name, const string &type_name, string &msg)
Definition: util.cc:338
virtual void dump(ostream &strm) const
dumps information about this object
Definition: AttrTable.cc:1489
Vars_riter var_rbegin()
Return a reverse iterator.
Definition: DDS.cc:780
Hold attribute data for a DAP2 dataset.
Definition: DAS.h:121
const string grddl_transformation_dap32
Definition: DDS.cc:88
int get_dap_minor() const
Get the DAP minor version as sent by the client.
Definition: DDS.h:265
A class for error processing.
Definition: Error.h:90
string get_dataset_name() const
Definition: DDS.cc:326
void duplicate(const DDS &dds)
Definition: DDS.cc:114
void set_dap_major(int p)
Definition: DDS.cc:374
virtual void del_var(const string &name)
Definition: Constructor.cc:362
string filename()
Definition: DDS.cc:357
int get_timeout()
Definition: DDS.cc:877
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.
Definition: DDS.cc:1029
virtual void dump(ostream &strm) const
dumps information about this object
Definition: DDS.cc:1459
virtual string container_name()
Returns the name of the current attribute container when multiple files used to build this DAS...
Definition: DAS.cc:98
void set_dap_version(const string &version_string="2.0")
Definition: DDS.cc:410
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:556
const string c_dap_20_n_sl
Definition: DDS.cc:98
const string c_xml_xsi
Definition: DDS.cc:85