libdap Updated for version 3.21.0
libdap4 is an implementation of OPeNDAP's DAP protocol.
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#endif
32
33#include <iostream>
34#include <sstream>
35#include <memory>
36
37#include "D4Group.h"
38#include "BaseType.h"
39#include "Array.h"
40#include "Grid.h"
41#include "DMR.h"
42#include "XMLWriter.h"
43#include "D4BaseTypeFactory.h"
44#include "D4Attributes.h"
45
46#include "DDS.h" // Included so DMRs can be built using a DDS for 'legacy' handlers
47
48#include "debug.h"
49#include "DapIndent.h"
50
51using namespace std;
52
53namespace libdap {
54
60void
62{
63 d_factory = dmr.d_factory; // Shallow copy here
64
65 d_name = dmr.d_name;
66 d_filename = dmr.d_filename;
67
68 d_dap_major = dmr.d_dap_major;
69 d_dap_minor = dmr.d_dap_minor;
70 d_dap_version = dmr.d_dap_version; // String version of the protocol
71
72 d_dmr_version = dmr.d_dmr_version;
73
74 d_request_xml_base = dmr.d_request_xml_base;
75
76 d_namespace = dmr.d_namespace;
77
78 d_max_response_size_kb = dmr.d_max_response_size_kb;
79
80 d_ce_empty = dmr.d_ce_empty;
81
82 // Deep copy, using ptr_duplicate()
83 // d_root can only be a D4Group, so the thing returned by ptr_duplicate() must be a D4Group.
84 d_root = static_cast<D4Group*>(dmr.d_root->ptr_duplicate());
85 DBG(cerr << "dmr.d_root: " << dmr.d_root << endl);
86 DBG(cerr << "d_root (from ptr_dup(): " << d_root << endl);
87}
88
101DMR::DMR(D4BaseTypeFactory *factory, const string &name)
102 : d_factory(factory), d_name(name)
103{
104}
105
126DMR::DMR(D4BaseTypeFactory *factory, DDS &dds)
127 : d_factory(factory), d_name(dds.get_dataset_name()), d_filename(dds.filename())
128{
129 build_using_dds(dds);
130}
131
133DMR::DMR(const DMR &rhs) : DapObj()
134{
135 m_duplicate(rhs);
136}
137
142{
143 delete d_root;
144}
145
146DMR &
147DMR::operator=(const DMR &rhs)
148{
149 if (this == &rhs)
150 return *this;
151
152 m_duplicate(rhs);
153
154 return *this;
155}
156
166{
167 set_name(dds.get_dataset_name());
168 set_filename(dds.filename());
169
170 D4Group *root_grp = root();
171 for (DDS::Vars_iter i = dds.var_begin(), e = dds.var_end(); i != e; ++i) {
172 BaseType *d4_var = root()->var((*i)->name());
173 // Don't add duplicate variables. We have to make this check
174 // because some of the child variables may add arrays
175 // to the root object. For example, this happens in
176 // Grid with the Map Arrays - ndp - 05/08/17
177 if(!d4_var){
178 // no variable of this name is in the root group at this point. Add it.
179 DBG(cerr << __func__ << "() - Transforming top level variable: " <<
180 " (" << (*i)->type_name() << ":'" << (*i)->name() << "':"<<(void *)(*i) <<
181 ") (root:"<< root_grp << ")"<< endl; );
182 (*i)->transform_to_dap4(root_grp, root_grp);
183 DBG(cerr << __func__ << "() - top level variable: '" <<
184 (*i)->name() << "' (type:" << (*i)->type_name() << ") Transformed"<< endl; );
185 }
186 else {
187 DBG(cerr << __func__ << "() - Skipping variable: " <<
188 d4_var->type_name() << " " << d4_var->name() << " because a variable with" <<
189 " this name already exists in the root group." << endl; );
190 }
191 }
192
193 // Now copy the global attributes
195}
196
212DDS *
214{
215 DBG( cerr << __func__ << "() - BEGIN" << endl);
216
217 BaseTypeFactory btf;
218 DDS *dds = new DDS(&btf, name());
219 dds->filename(filename());
220
221 // Now copy the global attributes
222 // TODO Make this a unique_ptr<> and let the compiler delete it. jhrg 6/17/19
223 // change made jhrg 2/4/22
224#if 1
225 unique_ptr< vector<BaseType *>> top_vars(root()->transform_to_dap2(&(dds->get_attr_table())/*, true*/));
226 for (vector<BaseType *>::iterator i = top_vars->begin(), e = top_vars->end(); i != e; i++) {
227 dds->add_var_nocopy(*i);
228 }
229#else
230 vector<BaseType *> *top_vars = root()->transform_to_dap2(&(dds->get_attr_table())/*, true*/);
231 for (vector<BaseType *>::iterator i = top_vars->begin(), e = top_vars->end(); i != e; i++) {
232 dds->add_var_nocopy(*i);
233 }
234 delete top_vars;
235#endif
236 DBG( cerr << __func__ << "() - END" << endl);
237
238 dds->set_factory(0);
239 return dds;
240}
241
248D4Group *
250{
251 if (!d_root) d_root = static_cast<D4Group*>(d_factory->NewVariable(dods_group_c, "/"));
252 return d_root;
253}
254
260void
261DMR::set_dap_version(const string &v)
262{
263 istringstream iss(v);
264
265 int major = -1, minor = -1;
266 char dot;
267 if (!iss.eof() && !iss.fail())
268 iss >> major;
269 if (!iss.eof() && !iss.fail())
270 iss >> dot;
271 if (!iss.eof() && !iss.fail())
272 iss >> minor;
273
274 if (major == -1 || minor == -1 or dot != '.')
275 throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
276
277 d_dap_version = v;
278
279 d_dap_major = major;
280 d_dap_minor = minor;
281
282 // Now set the related XML constants. These might be overwritten if
283 // the DMR instance is being built from a document parse, but if it's
284 // being constructed by a server the code to generate the XML document
285 // needs these values to match the DAP version information.
286 switch (d_dap_major) {
287 case 4:
288 d_namespace = c_dap40_namespace;
289 break;
290 default:
291 d_namespace = "";
292 break;
293 }
294}
295
307//[[deprecated("Use DMR::request_size_kb()")]]
308long DMR::request_size(bool constrained)
309{
310 return d_root->request_size(constrained);
311}
312
323uint64_t DMR::request_size_kb(bool constrained)
324{
325 return d_root->request_size_kb(constrained);
326}
327
328
329
330
338void
339DMR::print_dap4(XMLWriter &xml, bool constrained)
340{
341 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
342 throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
343
344 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*) get_namespace().c_str()) < 0)
345 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
346
347 if (!request_xml_base().empty()) {
348 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
349 (const xmlChar*)request_xml_base().c_str()) < 0)
350 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
351 }
352
353 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)dap_version().c_str()) < 0)
354 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
355
356 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*)dmr_version().c_str()) < 0)
357 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
358
359 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
360 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
361
362 root()->print_dap4(xml, constrained);
363
364 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
365 throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
366}
367
368
375bool DMR::is_dap4_projected(std::vector<string> &inventory)
376{
377 bool has_dap4 = root()->attributes()->has_dap4_types(root()->FQN(),inventory);
378
379 for(const auto var : root()->variables()){
380 has_dap4 |= var->is_dap4_projected(inventory);
381 }
382 for(const auto grp: root()->groups()){
383 has_dap4 |= grp->is_dap4_projected(inventory);
384 }
385 return has_dap4;
386
387}
388
396void
397DMR::dump(ostream &strm) const
398{
399 strm << DapIndent::LMarg << "DMR::dump - ("
400 << (void *)this << ")" << endl ;
401 DapIndent::Indent() ;
402 strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
403 strm << DapIndent::LMarg << "name: " << d_name << endl ;
404 strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
405 strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
406 strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
407
408 DapIndent::UnIndent() ;
409}
410
411} // namespace libdap
The basic data type for the DODS DAP types.
Definition: BaseType.h:120
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:376
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:317
virtual D4Attributes * attributes()
Definition: BaseType.cc:596
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())
Definition: Constructor.cc:210
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
virtual BaseType * NewVariable(Type t, const string &name) const
void print_dap4(XMLWriter &xml, bool constrained=false) override
Definition: D4Group.cc:630
uint64_t request_size_kb(bool constrained)
Get the estimated size of a response in kilobytes.
Definition: D4Group.cc:467
BaseType * ptr_duplicate() override
Definition: D4Group.cc:165
long request_size(bool constrained)
Definition: D4Group.cc:448
std::vector< BaseType * > * transform_to_dap2(AttrTable *parent_attr_table) override
Transform the D4Group's variables to DAP2 variables.
Definition: D4Group.cc:797
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition: DDS.cc:568
string filename() const
Definition: DDS.cc:316
virtual AttrTable & get_attr_table()
Definition: DDS.cc:301
BaseTypeFactory * set_factory(BaseTypeFactory *factory)
Definition: DDS.h:244
string get_dataset_name() const
Definition: DDS.cc:285
Vars_iter var_begin()
Definition: DDS.h:344
Vars_iter var_end()
Return an iterator.
Definition: DDS.h:349
void dump(std::ostream &strm) const override
dumps information about this object
Definition: DMR.cc:397
virtual DDS * getDDS()
Build a DDS from a DMR.
Definition: DMR.cc:213
~DMR() override
Definition: DMR.cc:141
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:61
std::string name() const
Definition: DMR.h:125
void set_dap_version(const std::string &version_string)
Definition: DMR.cc:261
std::string get_namespace() const
Get the namespace associated with the DMR.
Definition: DMR.h:161
std::string request_xml_base() const
Get the URL that will return this DMR.
Definition: DMR.h:155
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:375
virtual void build_using_dds(DDS &dds)
Definition: DMR.cc:165
D4Group * root()
Definition: DMR.cc:249
long request_size(bool constrained)
Get the estimated response size, in kilobytes.
Definition: DMR.cc:308
uint64_t request_size_kb(bool constrained)
Compute the estimated response size, in kilobytes.
Definition: DMR.cc:323
std::string filename() const
Definition: DMR.h:142
void print_dap4(XMLWriter &xml, bool constrained=false)
Definition: DMR.cc:339
libdap base object for common functionality of libdap objects
Definition: DapObj.h:51
A class for software fault reporting.
Definition: InternalErr.h:65
top level DAP object to house generic methods
Definition: AlarmHandler.h:36