libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
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 <fstream>
29#include <io.h>
30#include <process.h>
31#endif
32
33#include <iostream>
34#include <memory>
35#include <sstream>
36
37#include "Array.h"
38#include "BaseType.h"
39#include "D4Attributes.h"
40#include "D4BaseTypeFactory.h"
41#include "D4Group.h"
42#include "DMR.h"
43#include "Grid.h"
44#include "XMLWriter.h"
45
46#include "DDS.h" // Included so DMRs can be built using a DDS for 'legacy' handlers
47
48#include "DapIndent.h"
49#include "debug.h"
50
51using namespace std;
52
53namespace libdap {
54
60void DMR::m_duplicate(const DMR &dmr) {
61 d_factory = dmr.d_factory; // Shallow copy here
62
63 d_name = dmr.d_name;
64 d_filename = dmr.d_filename;
65
66 d_dap_major = dmr.d_dap_major;
67 d_dap_minor = dmr.d_dap_minor;
68 d_dap_version = dmr.d_dap_version; // String version of the protocol
69
70 d_dmr_version = dmr.d_dmr_version;
71
72 d_request_xml_base = dmr.d_request_xml_base;
73
74 d_namespace = dmr.d_namespace;
75
76 d_max_response_size_kb = dmr.d_max_response_size_kb;
77
78 d_ce_empty = dmr.d_ce_empty;
79
80 // Deep copy, using ptr_duplicate()
81 // d_root can only be a D4Group, so the thing returned by ptr_duplicate() must be a D4Group.
82 d_root = static_cast<D4Group *>(dmr.d_root->ptr_duplicate());
83 DBG(cerr << "dmr.d_root: " << dmr.d_root << endl);
84 DBG(cerr << "d_root (from ptr_dup(): " << d_root << endl);
85}
86
99DMR::DMR(D4BaseTypeFactory *factory, const string &name) : d_factory(factory), d_name(name) {}
100
122 : d_factory(factory), d_name(dds.get_dataset_name()), d_filename(dds.filename()) {
123 build_using_dds(dds);
124}
125
127DMR::DMR(const DMR &rhs) : DapObj() { m_duplicate(rhs); }
128
132DMR::~DMR() { delete d_root; }
133
134DMR &DMR::operator=(const DMR &rhs) {
135 if (this == &rhs)
136 return *this;
137
138 m_duplicate(rhs);
139
140 return *this;
141}
142
153 set_filename(dds.filename());
154
155 D4Group *root_grp = root();
156 for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
157 BaseType *d4_var = root()->var((*i)->name());
158 // Don't add duplicate variables. We have to make this check
159 // because some of the child variables may add arrays
160 // to the root object. For example, this happens in
161 // Grid with the Map Arrays - ndp - 05/08/17
162 if (!d4_var) {
163 // no variable of this name is in the root group at this point. Add it.
164 DBG(cerr << __func__ << "() - Transforming top level variable: " << " (" << (*i)->type_name() << ":'"
165 << (*i)->name() << "':" << (void *)(*i) << ") (root:" << root_grp << ")" << endl;);
166 (*i)->transform_to_dap4(root_grp, root_grp);
167 DBG(cerr << __func__ << "() - top level variable: '" << (*i)->name() << "' (type:" << (*i)->type_name()
168 << ") Transformed" << endl;);
169 } else {
170 DBG(cerr << __func__ << "() - Skipping variable: " << d4_var->type_name() << " " << d4_var->name()
171 << " because a variable with" << " this name already exists in the root group." << endl;);
172 }
173 }
174
175 // Now copy the global attributes
177}
178
195 DBG(cerr << __func__ << "() - BEGIN" << endl);
196
197 BaseTypeFactory btf;
198 DDS *dds = new DDS(&btf, name());
199 dds->filename(filename());
200
201 // Now copy the global attributes
202 // TODO Make this a unique_ptr<> and let the compiler delete it. jhrg 6/17/19
203 // change made jhrg 2/4/22
204#if 1
205 unique_ptr<vector<BaseType *>> top_vars(root()->transform_to_dap2(&(dds->get_attr_table()) /*, true*/));
206 for (vector<BaseType *>::iterator i = top_vars->begin(), e = top_vars->end(); i != e; i++) {
207 dds->add_var_nocopy(*i);
208 }
209#else
210 vector<BaseType *> *top_vars = root()->transform_to_dap2(&(dds->get_attr_table()) /*, true*/);
211 for (vector<BaseType *>::iterator i = top_vars->begin(), e = top_vars->end(); i != e; i++) {
212 dds->add_var_nocopy(*i);
213 }
214 delete top_vars;
215#endif
216 DBG(cerr << __func__ << "() - END" << endl);
217
218 dds->set_factory(0);
219 return dds;
220}
221
229 if (!d_root)
230 d_root = static_cast<D4Group *>(d_factory->NewVariable(dods_group_c, "/"));
231 return d_root;
232}
233
239void DMR::set_dap_version(const string &v) {
240 istringstream iss(v);
241
242 int major = -1, minor = -1;
243 char dot;
244 if (!iss.eof() && !iss.fail())
245 iss >> major;
246 if (!iss.eof() && !iss.fail())
247 iss >> dot;
248 if (!iss.eof() && !iss.fail())
249 iss >> minor;
250
251 if (major == -1 || minor == -1 or dot != '.')
252 throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
253
254 d_dap_version = v;
255
256 d_dap_major = major;
257 d_dap_minor = minor;
258
259 // Now set the related XML constants. These might be overwritten if
260 // the DMR instance is being built from a document parse, but if it's
261 // being constructed by a server the code to generate the XML document
262 // needs these values to match the DAP version information.
263 switch (d_dap_major) {
264 case 4:
265 d_namespace = c_dap40_namespace;
266 break;
267 default:
268 d_namespace = "";
269 break;
270 }
271}
272
284//[[deprecated("Use DMR::request_size_kb()")]]
285long DMR::request_size(bool constrained) { return d_root->request_size(constrained); }
286
297uint64_t DMR::request_size_kb(bool constrained) { return d_root->request_size_kb(constrained); }
298
306void DMR::print_dap4(XMLWriter &xml, bool constrained) {
307 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar *)"Dataset") < 0)
308 throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
309
310 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"xmlns",
311 (const xmlChar *)get_namespace().c_str()) < 0)
312 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
313
314 if (!request_xml_base().empty()) {
315 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"xml:base",
316 (const xmlChar *)request_xml_base().c_str()) < 0)
317 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
318 }
319
320 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"dapVersion",
321 (const xmlChar *)dap_version().c_str()) < 0)
322 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
323
324 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"dmrVersion",
325 (const xmlChar *)dmr_version().c_str()) < 0)
326 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
327
328 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar *)"name", (const xmlChar *)name().c_str()) < 0)
329 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
330
331 root()->print_dap4(xml, constrained);
332
333 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
334 throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
335}
336
343bool DMR::is_dap4_projected(std::vector<string> &inventory) {
344 bool has_dap4 = root()->attributes()->has_dap4_types(root()->FQN(), inventory);
345
346 for (const auto var : root()->variables()) {
347 has_dap4 |= var->is_dap4_projected(inventory);
348 }
349 for (const auto grp : root()->groups()) {
350 has_dap4 |= grp->is_dap4_projected(inventory);
351 }
352 return has_dap4;
353}
354
362void DMR::dump(ostream &strm) const {
363 strm << DapIndent::LMarg << "DMR::dump - (" << (void *)this << ")" << endl;
365 strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl;
366 strm << DapIndent::LMarg << "name: " << d_name << endl;
367 strm << DapIndent::LMarg << "filename: " << d_filename << endl;
368 strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
369 strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
370
372}
373
374} // namespace libdap
The basic data type for the DODS DAP types.
Definition BaseType.h:118
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:335
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:296
virtual D4Attributes * attributes()
Definition BaseType.cc:507
BaseType * var(const string &name, bool exact_match=true, btp_stack *s=nullptr) override
btp_stack no longer needed; use back pointers (BaseType::get_parent())
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
bool has_dap4_types(const std::string &path, std::vector< std::string > &inventory) const
void print_dap4(XMLWriter &xml, bool constrained=false) override
Definition D4Group.cc:566
BaseType * ptr_duplicate() override
Definition D4Group.cc:139
std::vector< BaseType * > * transform_to_dap2(AttrTable *parent_attr_table) override
Transform the D4Group's variables to DAP2 variables.
Definition D4Group.cc:723
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition DDS.cc:504
string filename() const
Definition DDS.cc:287
virtual AttrTable & get_attr_table()
Definition DDS.cc:276
BaseTypeFactory * set_factory(BaseTypeFactory *factory)
Definition DDS.h:239
string get_dataset_name() const
Definition DDS.cc:268
Vars_iter var_begin()
Definition DDS.h:336
Vars_iter var_end()
Return an iterator.
Definition DDS.h:341
std::vector< BaseType * >::iterator Vars_iter
Definition DDS.h:211
void dump(std::ostream &strm) const override
dumps information about this object
Definition DMR.cc:362
virtual DDS * getDDS()
Build a DDS from a DMR.
Definition DMR.cc:194
~DMR() override
Definition DMR.cc:132
void m_duplicate(const DMR &dmr)
Copy the contents of the given DMR into this one. This is defined because the we perform a deep copy ...
Definition DMR.cc:60
std::string name() const
Definition DMR.h:125
DMR()=default
void set_dap_version(const std::string &version_string)
Definition DMR.cc:239
std::string get_namespace() const
Get the namespace associated with the DMR.
Definition DMR.h:161
std::string dap_version() const
Definition DMR.h:146
std::string request_xml_base() const
Get the URL that will return this DMR.
Definition DMR.h:155
DMR & operator=(const DMR &rhs)
Definition DMR.cc:134
void set_name(const std::string &n)
Definition DMR.h:126
virtual bool is_dap4_projected(std::vector< string > &inventory)
Scans the inventory of projected variables and their attributes for projected DAP4 types....
Definition DMR.cc:343
virtual void build_using_dds(DDS &dds)
Definition DMR.cc:151
D4Group * root()
Definition DMR.cc:228
long request_size(bool constrained)
Get the estimated response size, in kilobytes.
Definition DMR.cc:285
uint64_t request_size_kb(bool constrained)
Compute the estimated response size, in kilobytes.
Definition DMR.cc:297
void set_filename(const std::string &fn)
Definition DMR.h:143
std::string filename() const
Definition DMR.h:142
virtual D4BaseTypeFactory * factory()
Definition DMR.h:133
std::string dmr_version() const
Definition DMR.h:151
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition DMR.cc:306
static ostream & LMarg(ostream &strm)
Definition DapIndent.cc:61
static void Indent()
Definition DapIndent.cc:44
static void UnIndent()
Definition DapIndent.cc:46
libdap base object for common functionality of libdap objects
Definition DapObj.h:49
A class for software fault reporting.
Definition InternalErr.h:61
xmlTextWriterPtr get_writer() const
Definition XMLWriter.h:55
STL iterator class.
#define DBG(x)
Definition debug.h:58
top level DAP object to house generic methods
Definition AISConnect.cc:30
@ dods_group_c
Definition Type.h:122
const string c_dap40_namespace
Definition DMR.h:40