libdap Updated for version 3.18.1
DMR.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2013 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 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
61const string c_xml_xsi = "http://www.w3.org/2001/XMLSchema-instance";
62const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
63
64const string c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
65
66const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
67
68const string c_dap_40_n_sl = c_dap40_namespace + " " + c_default_dap40_schema_location;
69
70using namespace std;
71
72namespace libdap {
73
74void
75DMR::m_duplicate(const DMR &dmr)
76{
77 // This is needed because we use the factory to make a new instance of the root group
78 assert(dmr.OK());
79
80 d_factory = dmr.d_factory; // Shallow copy here
81
82 d_name = dmr.d_name;
83 d_filename = dmr.d_filename;
84
85 d_dap_major = dmr.d_dap_major;
86 d_dap_minor = dmr.d_dap_minor;
87 d_dap_version = dmr.d_dap_version; // String version of the protocol
88
89 d_dmr_version = dmr.d_dmr_version;
90
91 d_request_xml_base = dmr.d_request_xml_base;
92
93 d_namespace = dmr.d_namespace;
94
95 d_max_response_size = dmr.d_max_response_size;
96
97 // Deep copy, using ptr_duplicate()
98 d_root = dmr.d_root->ptr_duplicate();
99 DBG(cerr << "dmr.d_root: " << dmr.d_root << endl);
100 DBG(cerr << "d_root (from ptr_dup(): " << d_root << endl);
101
102 //d_root = static_cast<D4Group*>(dmr.d_factory->NewVariable(dods_group_c, dmr.d_root->name()));
103}
104
117DMR::DMR(D4BaseTypeFactory *factory, const string &name)
118 : d_factory(factory), d_name(name), d_filename(""),
119 d_dap_major(4), d_dap_minor(0),
120 d_dmr_version("1.0"), d_request_xml_base(""),
121 d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
122{
123 // sets d_dap_version string and the two integer fields too
124 set_dap_version("4.0");
125}
126
148 : d_factory(factory), d_name(dds.get_dataset_name()),
149 d_filename(dds.filename()), d_dap_major(4), d_dap_minor(0),
150 d_dmr_version("1.0"), d_request_xml_base(""),
151 d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
152{
153 // sets d_dap_version string and the two integer fields too
154 set_dap_version("4.0");
155
156 build_using_dds(dds);
157#if 0
158 for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
159 BaseType *new_var = (*i)->transform_to_dap4(root() /*group*/, root() /*container*/);
160 // If the variable being transformed is a Grid,
161 // then Grid::transform_to_dap4() will add all the arrays to the
162 // container (root() in this case) and return null, indicating that
163 // this code does not need to do anything to add the transformed variable.
164 if (new_var)
165 root()->add_var_nocopy(new_var);
166 }
167
168 // Now copy the global attributes
170#endif
171}
172
180 : d_factory(0), d_name(""), d_filename(""), d_dap_major(4), d_dap_minor(0),
181 d_dap_version("4.0"), d_dmr_version("1.0"), d_request_xml_base(""),
182 d_namespace(c_dap40_namespace), d_max_response_size(0), d_root(0)
183{
184 // sets d_dap_version string and the two integer fields too
185 set_dap_version("4.0");
186}
187
189DMR::DMR(const DMR &rhs) : DapObj()
190{
191 m_duplicate(rhs);
192}
193
198{
199#if 1
200 delete d_root;
201#endif
202}
203
204DMR &
205DMR::operator=(const DMR &rhs)
206{
207 if (this == &rhs)
208 return *this;
209
210 m_duplicate(rhs);
211
212 return *this;
213}
214
224{
225 set_name(dds.get_dataset_name());
226 set_filename(dds.filename());
227
228 for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
229 BaseType *new_var = (*i)->transform_to_dap4(root() /*group*/, root() /*container*/);
230 // If the variable being transformed is a Grid,
231 // then Grid::transform_to_dap4() will add all the arrays to the
232 // container (root() in this case) and return null, indicating that
233 // this code does not need to do anything to add the transformed variable.
234 if (new_var) root()->add_var_nocopy(new_var);
235 }
236
237 // Now copy the global attributes
239}
240
241D4Group *
243{
244 if (!d_root) d_root = static_cast<D4Group*>(d_factory->NewVariable(dods_group_c, "/"));
245 return d_root;
246}
247
253void
254DMR::set_dap_version(const string &v)
255{
256 istringstream iss(v);
257
258 int major = -1, minor = -1;
259 char dot;
260 if (!iss.eof() && !iss.fail())
261 iss >> major;
262 if (!iss.eof() && !iss.fail())
263 iss >> dot;
264 if (!iss.eof() && !iss.fail())
265 iss >> minor;
266
267 if (major == -1 || minor == -1 or dot != '.')
268 throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
269
270 d_dap_version = v;
271
272 d_dap_major = major;
273 d_dap_minor = minor;
274
275 // Now set the related XML constants. These might be overwritten if
276 // the DMR instance is being built from a document parse, but if it's
277 // being constructed by a server the code to generate the XML document
278 // needs these values to match the DAP version information.
279 switch (d_dap_major) {
280 case 4:
281 d_namespace = c_dap40_namespace;
282 break;
283 default:
284 d_namespace = "";
285 break;
286 }
287}
288
299long
300DMR::request_size(bool constrained)
301{
302 return d_root->request_size(constrained);
303}
304
312void
313DMR::print_dap4(XMLWriter &xml, bool constrained)
314{
315 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
316 throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
317
318#if 0
319 // Reintroduce these if they are really useful. jhrg 4/15/13
320 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml",
321 (const xmlChar*) c_xml_namespace.c_str()) < 0)
322 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
323
324 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*) c_xml_xsi.c_str())
325 < 0)
326 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
327
328 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation",
329 (const xmlChar*) c_dap_40_n_sl.c_str()) < 0)
330 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
331#endif
332
333 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*) get_namespace().c_str()) < 0)
334 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
335
336 if (!request_xml_base().empty()) {
337 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
338 (const xmlChar*)request_xml_base().c_str()) < 0)
339 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
340 }
341
342 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)dap_version().c_str()) < 0)
343 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
344
345 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*)dmr_version().c_str()) < 0)
346 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
347
348 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
349 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
350
351 root()->print_dap4(xml, constrained);
352
353 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
354 throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
355}
356
357
365void
366DMR::dump(ostream &strm) const
367{
368 strm << DapIndent::LMarg << "DMR::dump - ("
369 << (void *)this << ")" << endl ;
370 DapIndent::Indent() ;
371 strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
372 strm << DapIndent::LMarg << "name: " << d_name << endl ;
373 strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
374 strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
375 strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
376
377 DapIndent::UnIndent() ;
378}
379
380} // namespace libdap
The basic data type for the DODS DAP types.
Definition: BaseType.h:118
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
DAP2 to DAP4 transform.
Definition: BaseType.cc:215
virtual D4Attributes * attributes()
Definition: BaseType.cc:544
virtual void add_var_nocopy(BaseType *bt, Part part=nil)
Definition: Constructor.cc:407
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
virtual BaseType * NewVariable(Type t, const string &name) const
long request_size(bool constrained)
Definition: D4Group.cc:400
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition: D4Group.cc:565
virtual D4Group * ptr_duplicate()
Definition: D4Group.cc:151
string filename() const
Definition: DDS.cc:388
virtual AttrTable & get_attr_table()
Definition: DDS.cc:373
string get_dataset_name() const
Definition: DDS.cc:357
Vars_iter var_begin()
Return an iterator to the first variable.
Definition: DDS.cc:805
Vars_iter var_end()
Return an iterator.
Definition: DDS.cc:817
string request_xml_base() const
Get the URL that will return this DMR/DDX/DataThing.
Definition: DMR.h:149
virtual void dump(ostream &strm) const
dumps information about this object
Definition: DMR.cc:366
void set_dap_version(const string &version_string)
Definition: DMR.cc:254
virtual ~DMR()
Definition: DMR.cc:197
string get_namespace() const
Get the namespace associated with the DDS - likely set only by DDX responses.
Definition: DMR.h:155
virtual void build_using_dds(DDS &dds)
Definition: DMR.cc:223
D4Group * root()
Definition: DMR.cc:242
long request_size(bool constrained)
Get the estimated response size, in kilo bytes.
Definition: DMR.cc:300
string name() const
Definition: DMR.h:117
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition: DMR.cc:313
libdap base object for common functionality of libdap objects
Definition: DapObj.h:56
A class for software fault reporting.
Definition: InternalErr.h:65