libdap++  Updated for version 3.14.0
DMR.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) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 #ifdef WIN32
28 #include <io.h>
29 #include <process.h>
30 #include <fstream>
31 #else
32 #include <unistd.h> // for alarm and dup
33 #include <sys/wait.h>
34 #endif
35 
36 #include <cassert>
37 
38 #include <iostream>
39 #include <sstream>
40 
41 //#define DODS_DEBUG
42 //#define DODS_DEBUG2
43 
44 #include "D4Group.h"
45 #include "BaseType.h"
46 #include "Array.h"
47 #include "DMR.h"
48 #include "XMLWriter.h"
49 #include "D4BaseTypeFactory.h"
50 #include "D4Attributes.h"
51 
52 #include "DDS.h" // Included so DMRs can be built using a DDS for 'legacy' handlers
53 
54 #include "debug.h"
55 
56 
62 const string c_xml_xsi = "http://www.w3.org/2001/XMLSchema-instance";
63 const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
64 
65 const string c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
66 
67 const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
68 
70 
71 using namespace std;
72 
73 namespace libdap {
74 
75 void
76 DMR::m_duplicate(const DMR &dmr)
77 {
78  // This is needed because we use the factory to make a new instance of the root group
79  assert(dmr.OK());
80 
81  d_factory = dmr.d_factory; // Shallow copy here
82 
83  d_name = dmr.d_name;
84  d_filename = dmr.d_filename;
85 
86  d_dap_major = dmr.d_dap_major;
87  d_dap_minor = dmr.d_dap_minor;
88  d_dap_version = dmr.d_dap_version; // String version of the protocol
89 
90  d_dmr_version = dmr.d_dmr_version;
91 
92  d_request_xml_base = dmr.d_request_xml_base;
93 
94  d_namespace = dmr.d_namespace;
95 
96  d_max_response_size = dmr.d_max_response_size;
97 
98  // Deep copy, using ptr_duplicate()
99  d_root = dmr.d_root->ptr_duplicate();
100  DBG(cerr << "dmr.d_root: " << dmr.d_root << endl);
101  DBG(cerr << "d_root (from ptr_dup(): " << d_root << endl);
102 
103  //d_root = static_cast<D4Group*>(dmr.d_factory->NewVariable(dods_group_c, dmr.d_root->name()));
104 }
105 
118 DMR::DMR(D4BaseTypeFactory *factory, const string &name)
119  : d_factory(factory), d_name(name), d_filename(""),
120  d_dap_major(4), d_dap_minor(0),
121  d_dmr_version("1.0"), d_request_xml_base(""),
122  d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
123 {
124  // sets d_dap_version string and the two integer fields too
125  set_dap_version("4.0");
126 }
127 
149  : d_factory(factory), d_name(dds.get_dataset_name()),
150  d_filename(dds.filename()), d_dap_major(4), d_dap_minor(0),
151  d_dmr_version("1.0"), d_request_xml_base(""),
152  d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
153 {
154  // sets d_dap_version string and the two integer fields too
155  set_dap_version("4.0");
156 
157  build_using_dds(dds);
158 #if 0
159  for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
160  BaseType *new_var = (*i)->transform_to_dap4(root() /*group*/, root() /*container*/);
161  // If the variable being transformed is a Grid,
162  // then Grid::transform_to_dap4() will add all the arrays to the
163  // container (root() in this case) and return null, indicating that
164  // this code does not need to do anything to add the transformed variable.
165  if (new_var)
166  root()->add_var_nocopy(new_var);
167  }
168 
169  // Now copy the global attributes
171 #endif
172 }
173 
181  : d_factory(0), d_name(""), d_filename(""), d_dap_major(4), d_dap_minor(0),
182  d_dap_version("4.0"), d_dmr_version("1.0"), d_request_xml_base(""),
183  d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
184 {
185  // sets d_dap_version string and the two integer fields too
186  set_dap_version("4.0");
187 }
188 
190 DMR::DMR(const DMR &rhs) : DapObj()
191 {
192  m_duplicate(rhs);
193 }
194 
199 {
200 #if 1
201  delete d_root;
202 #endif
203 }
204 
205 DMR &
206 DMR::operator=(const DMR &rhs)
207 {
208  if (this == &rhs)
209  return *this;
210 
211  m_duplicate(rhs);
212 
213  return *this;
214 }
215 
225 {
226  set_name(dds.get_dataset_name());
227  set_filename(dds.filename());
228 
229  for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
230  BaseType *new_var = (*i)->transform_to_dap4(root() /*group*/, root() /*container*/);
231  // If the variable being transformed is a Grid,
232  // then Grid::transform_to_dap4() will add all the arrays to the
233  // container (root() in this case) and return null, indicating that
234  // this code does not need to do anything to add the transformed variable.
235  if (new_var) root()->add_var_nocopy(new_var);
236  }
237 
238  // Now copy the global attributes
240 }
241 
242 D4Group *
244 {
245  if (!d_root) d_root = static_cast<D4Group*>(d_factory->NewVariable(dods_group_c, "/"));
246  return d_root;
247 }
248 
254 void
255 DMR::set_dap_version(const string &v)
256 {
257  istringstream iss(v);
258 
259  int major = -1, minor = -1;
260  char dot;
261  if (!iss.eof() && !iss.fail())
262  iss >> major;
263  if (!iss.eof() && !iss.fail())
264  iss >> dot;
265  if (!iss.eof() && !iss.fail())
266  iss >> minor;
267 
268  if (major == -1 || minor == -1 or dot != '.')
269  throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
270 
271  d_dap_version = v;
272 
273  d_dap_major = major;
274  d_dap_minor = minor;
275 
276  // Now set the related XML constants. These might be overwritten if
277  // the DMR instance is being built from a document parse, but if it's
278  // being constructed by a server the code to generate the XML document
279  // needs these values to match the DAP version information.
280  switch (d_dap_major) {
281  case 4:
282  d_namespace = c_dap40_namespace;
283  break;
284  default:
285  d_namespace = "";
286  break;
287  }
288 }
289 
300 long
301 DMR::request_size(bool constrained)
302 {
303  return d_root->request_size(constrained);
304 }
305 
313 void
314 DMR::print_dap4(XMLWriter &xml, bool constrained)
315 {
316  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
317  throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
318 
319 #if 0
320  // Reintroduce these if they are really useful. jhrg 4/15/13
321  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml",
322  (const xmlChar*) c_xml_namespace.c_str()) < 0)
323  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
324 
325  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*) c_xml_xsi.c_str())
326  < 0)
327  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
328 
329  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation",
330  (const xmlChar*) c_dap_40_n_sl.c_str()) < 0)
331  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
332 #endif
333 
334  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*) get_namespace().c_str()) < 0)
335  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
336 
337  if (!request_xml_base().empty()) {
338  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
339  (const xmlChar*)request_xml_base().c_str()) < 0)
340  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
341  }
342 
343  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)dap_version().c_str()) < 0)
344  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
345 
346  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*)dmr_version().c_str()) < 0)
347  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
348 
349  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
350  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
351 
352  root()->print_dap4(xml, constrained);
353 
354  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
355  throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
356 }
357 
358 
366 void
367 DMR::dump(ostream &strm) const
368 {
369  strm << DapIndent::LMarg << "DMR::dump - ("
370  << (void *)this << ")" << endl ;
372  strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
373  strm << DapIndent::LMarg << "name: " << d_name << endl ;
374  strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
375  strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
376  strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
377 
379 }
380 
381 } // namespace libdap
string dap_version() const
Definition: DMR.h:140
static void UnIndent()
Definition: DapIndent.cc:51
xmlTextWriterPtr get_writer()
Definition: XMLWriter.h:56
string filename() const
Definition: DDS.cc:389
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition: DMR.cc:314
D4Group * root()
Definition: DMR.cc:243
Vars_iter var_begin()
Return an iterator to the first variable.
Definition: DDS.cc:806
string dmr_version() const
Definition: DMR.h:145
virtual void add_var_nocopy(BaseType *bt, Part part=nil)
Definition: Constructor.cc:407
string name() const
Definition: DMR.h:117
virtual ~DMR()
Definition: DMR.cc:198
virtual void dump(ostream &strm) const
dumps information about this object
Definition: DMR.cc:367
const string c_default_dap40_schema_location
Definition: DMR.cc:65
string request_xml_base() const
Get the URL that will return this DMR/DDX/DataThing.
Definition: DMR.h:149
A class for software fault reporting.
Definition: InternalErr.h:64
DMR & operator=(const DMR &rhs)
Definition: DMR.cc:206
#define DBG(x)
Definition: debug.h:58
const string c_dap_40_n_sl
Definition: DMR.cc:69
bool OK() const
Definition: DMR.h:109
long request_size(bool constrained)
Definition: D4Group.cc:377
static void Indent()
Definition: DapIndent.cc:45
std::vector< BaseType * >::iterator Vars_iter
Definition: DDS.h:219
long request_size(bool constrained)
Get the estimated response size, in kilo bytes.
Definition: DMR.cc:301
virtual D4Attributes * attributes()
Definition: BaseType.cc:529
virtual AttrTable & get_attr_table()
Definition: DDS.cc:374
virtual void build_using_dds(DDS &dds)
Definition: DMR.cc:224
Vars_iter var_end()
Return an iterator.
Definition: DDS.cc:818
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:80
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
string get_namespace() const
Get the namespace associated with the DDS - likely set only by DDX responses.
Definition: DMR.h:155
void m_duplicate(const DMR &dmr)
Definition: DMR.cc:76
void set_dap_version(const string &version_string)
Definition: DMR.cc:255
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition: D4Group.cc:524
const string c_xml_xsi
Definition: DMR.cc:62
const string c_dap40_namespace
Definition: DMR.cc:67
virtual D4Group * ptr_duplicate()
Definition: D4Group.cc:128
string get_dataset_name() const
Definition: DDS.cc:358
void set_name(const string &n)
Definition: DMR.h:118
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
void set_filename(const string &fn)
Definition: DMR.h:137
virtual BaseType * NewVariable(Type t, const string &name) const
const string c_xml_namespace
Definition: DMR.cc:63
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
DAP2 to DAP4 transform.
Definition: BaseType.cc:216