libdap Updated for version 3.18.1
D4Attributes.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//#define DODS_DEBUG
28
29#include "D4Attributes.h"
30#include "D4AttributeType.h"
31#include "InternalErr.h"
32
33#include "AttrTable.h"
34
35#include "util.h"
36#include "debug.h"
37
38namespace libdap {
39
43string D4AttributeTypeToString(D4AttributeType at)
44{
45 switch(at) {
46 case attr_null_c:
47 return "null";
48
49 case attr_byte_c:
50 return "Byte";
51
52 case attr_int16_c:
53 return "Int16";
54
55 case attr_uint16_c:
56 return "UInt16";
57
58 case attr_int32_c:
59 return "Int32";
60
61 case attr_uint32_c:
62 return "UInt32";
63
64 case attr_float32_c:
65 return "Float32";
66
67 case attr_float64_c:
68 return "Float64";
69
70 case attr_str_c:
71 return "String";
72
73 case attr_url_c:
74 return "Url";
75
76 // Added for DAP4
77 case attr_int8_c:
78 return "Int8";
79
80 case attr_uint8_c:
81 return "UInt8";
82
83 case attr_int64_c:
84 return "Int64";
85
86 case attr_uint64_c:
87 return "UInt64";
88
89 case attr_enum_c:
90 return "Enum";
91
92 case attr_opaque_c:
93 return "Opaque";
94
95 // These are specific to attributes while the other types are
96 // also supported by the variables. jhrg 4/17/13
97 case attr_container_c:
98 return "Container";
99
100 case attr_otherxml_c:
101 return "OtherXML";
102
103 default:
104 throw InternalErr(__FILE__, __LINE__, "Unsupported attribute type");
105 }
106}
107
108D4AttributeType StringToD4AttributeType(string s)
109{
110 downcase(s);
111
112 if (s == "container")
113 return attr_container_c;
114
115 else if (s == "byte")
116 return attr_byte_c;
117 else if (s == "int8")
118 return attr_int8_c;
119 else if (s == "uint8")
120 return attr_uint8_c;
121 else if (s == "int16")
122 return attr_int16_c;
123 else if (s == "uint16")
124 return attr_uint16_c;
125 else if (s == "int32")
126 return attr_int32_c;
127 else if (s == "uint32")
128 return attr_uint32_c;
129 else if (s == "int64")
130 return attr_int64_c;
131 else if (s == "uint64")
132 return attr_uint64_c;
133
134 else if (s == "float32")
135 return attr_float32_c;
136 else if (s == "float64")
137 return attr_float64_c;
138
139 else if (s == "string")
140 return attr_str_c;
141 else if (s == "url")
142 return attr_url_c;
143 else if (s == "otherxml")
144 return attr_otherxml_c;
145 else
146 return attr_null_c;
147}
148
149void
150D4Attribute::m_duplicate(const D4Attribute &src)
151{
152 d_name = src.d_name;
153 d_type = src.d_type;
154 d_values = src.d_values;
155 if (src.d_attributes)
156 d_attributes = new D4Attributes(*src.d_attributes);
157 else
158 d_attributes = 0;
159}
160
161D4Attribute::D4Attribute(const D4Attribute &src)
162{
163 m_duplicate(src);
164}
165
166D4Attribute::~D4Attribute()
167{
168 delete d_attributes;
169}
170
171D4Attribute &
172D4Attribute::operator=(const D4Attribute &rhs)
173{
174 if (this == &rhs) return *this;
175 m_duplicate(rhs);
176 return *this;
177}
178
179D4Attributes *
180D4Attribute::attributes()
181{
182 if (!d_attributes) d_attributes = new D4Attributes();
183 return d_attributes;
184}
185
193void
195{
196 // for every attribute in at, copy it to this.
197 for (AttrTable::Attr_iter i = at.attr_begin(), e = at.attr_end(); i != e; ++i) {
198 string name = at.get_name(i);
199 AttrType type = at.get_attr_type(i);
200
201 switch (type) {
202 case Attr_container: {
203 D4Attribute *a = new D4Attribute(name, attr_container_c);
204 D4Attributes *attributes = a->attributes(); // allocates a new object
205 attributes->transform_to_dap4(*at.get_attr_table(i));
206 add_attribute_nocopy(a);
207 break;
208 }
209 case Attr_byte: {
210 D4Attribute *a = new D4Attribute(name, attr_byte_c);
211 a->add_value_vector(*at.get_attr_vector(i));
212 add_attribute_nocopy(a);
213 break;
214 }
215 case Attr_int16: {
216 D4Attribute *a = new D4Attribute(name, attr_int16_c);
217 a->add_value_vector(*at.get_attr_vector(i));
218 add_attribute_nocopy(a);
219 break;
220 }
221 case Attr_uint16: {
222 D4Attribute *a = new D4Attribute(name, attr_uint16_c);
223 a->add_value_vector(*at.get_attr_vector(i));
224 add_attribute_nocopy(a);
225 break;
226 }
227 case Attr_int32: {
228 D4Attribute *a = new D4Attribute(name, attr_int32_c);
229 a->add_value_vector(*at.get_attr_vector(i));
230 add_attribute_nocopy(a);
231 break;
232 }
233 case Attr_uint32: {
234 D4Attribute *a = new D4Attribute(name, attr_uint32_c);
235 a->add_value_vector(*at.get_attr_vector(i));
236 add_attribute_nocopy(a);
237 break;
238 }
239 case Attr_float32: {
240 D4Attribute *a = new D4Attribute(name, attr_float32_c);
241 a->add_value_vector(*at.get_attr_vector(i));
242 add_attribute_nocopy(a);
243 break;
244 }
245 case Attr_float64: {
246 D4Attribute *a = new D4Attribute(name, attr_float64_c);
247 a->add_value_vector(*at.get_attr_vector(i));
248 add_attribute_nocopy(a);
249 break;
250 }
251 case Attr_string: {
252 D4Attribute *a = new D4Attribute(name, attr_str_c);
253 a->add_value_vector(*at.get_attr_vector(i));
254 add_attribute_nocopy(a);
255 break;
256 }
257 case Attr_url: {
258 D4Attribute *a = new D4Attribute(name, attr_url_c);
259 a->add_value_vector(*at.get_attr_vector(i));
260 add_attribute_nocopy(a);
261 break;
262 }
263 case Attr_other_xml: {
264 D4Attribute *a = new D4Attribute(name, attr_otherxml_c);
265 a->add_value_vector(*at.get_attr_vector(i));
266 add_attribute_nocopy(a);
267 break;
268 }
269 default:
270 throw InternalErr(__FILE__, __LINE__, "Unknown DAP2 attribute type in D4Attributes::copy_from_dap2()");
271 }
272 }
273}
274
276D4Attributes::find_depth_first(const string &name, D4AttributesIter i)
277{
278 if (i == attribute_end())
279 return 0;
280 else if ((*i)->name() == name)
281 return *i;
282 else if ((*i)->type() == attr_container_c)
283 return find_depth_first(name, (*i)->attributes()->attribute_begin());
284 else
285 return find_depth_first(name, ++i);
286}
287
288D4Attribute *
289D4Attributes::find(const string &name)
290{
291 return find_depth_first(name, attribute_begin());
292}
293
297D4Attribute *
298D4Attributes::get(const string &fqn)
299{
300 // name1.name2.name3
301 // name1
302 // name1.name2
303 size_t pos = fqn.find('.');
304 string part = fqn.substr(0, pos);
305 string rest= "";
306
307 if (pos != string::npos)
308 rest = fqn.substr(pos + 1);
309
310 DBG(cerr << "part: '" << part << "'; rest: '" << rest << "'" << endl);
311
312 if (!part.empty()) {
313 if (!rest.empty()) {
314 D4AttributesIter i = attribute_begin();
315 while (i != attribute_end()) {
316 if ((*i)->name() == part && (*i)->type() == attr_container_c)
317 return (*i)->attributes()->get(rest);
318 ++i;
319 }
320 }
321 else {
322 D4AttributesIter i = attribute_begin();
323 while (i != attribute_end()) {
324 if ((*i)->name() == part)
325 return (*i);
326 ++i;
327 }
328 }
329 }
330
331 return 0;
332}
333
334void
335D4Attribute::print_dap4(XMLWriter &xml) const
336{
337 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Attribute") < 0)
338 throw InternalErr(__FILE__, __LINE__, "Could not write Attribute element");
339 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
340 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
341 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "type", (const xmlChar*) D4AttributeTypeToString(type()).c_str()) < 0)
342 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for type");
343
344 switch (type()) {
345 case attr_container_c:
346 if (!d_attributes)
347 throw InternalErr(__FILE__, __LINE__, "Null Attribute container");
348 d_attributes->print_dap4(xml);
349 break;
350
351 case attr_otherxml_c:
352 if (num_values() != 1)
353 throw Error("OtherXML attributes cannot be vector-valued.");
354 if (xmlTextWriterWriteRaw(xml.get_writer(), (const xmlChar*) value(0).c_str()) < 0)
355 throw InternalErr(__FILE__, __LINE__, "Could not write OtherXML value");
356 break;
357
358 default: {
359 // Assume only valid types make it into instances
360 D4AttributeCIter i = d_values.begin();//value_begin();
361 while (i != d_values.end()) {
362 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Value") < 0)
363 throw InternalErr(__FILE__, __LINE__, "Could not write value element");
364
365 if (xmlTextWriterWriteString(xml.get_writer(), (const xmlChar*) (*i++).c_str()) < 0)
366 throw InternalErr(__FILE__, __LINE__, "Could not write attribute value");
367
368 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
369 throw InternalErr(__FILE__, __LINE__, "Could not end value element");
370 }
371
372 break;
373 }
374 }
375
376 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
377 throw InternalErr(__FILE__, __LINE__, "Could not end Attribute element");
378}
379
388void
389D4Attribute::dump(ostream &strm) const
390{
391 strm << DapIndent::LMarg << "D4Attribute::dump - (" << (void *)this << ")" << endl;
392
393 DapIndent::Indent() ;
394
395 XMLWriter xml;
396 print_dap4(xml);
397 strm << DapIndent::LMarg << xml.get_doc() << flush;
398
399 DapIndent::UnIndent() ;
400}
401
402
403void
404D4Attributes::print_dap4(XMLWriter &xml) const
405{
406 if (empty())
407 return;
408
409 D4AttributesCIter i = d_attrs.begin();
410 while (i != d_attrs.end()) {
411 (*i++)->print_dap4(xml);
412 }
413}
414
423void
424D4Attributes::dump(ostream &strm) const
425{
426 strm << DapIndent::LMarg << "D4Attributes::dump - (" << (void *)this << ")" << endl;
427
428 DapIndent::Indent() ;
429
430 XMLWriter xml;
431 print_dap4(xml);
432 strm << DapIndent::LMarg << xml.get_doc() << flush;
433
434 DapIndent::UnIndent() ;
435}
436
437
438} // namespace libdap
439
Contains the attributes for a dataset.
Definition: AttrTable.h:143
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
Definition: AttrTable.cc:606
virtual Attr_iter attr_end()
Definition: AttrTable.cc:718
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
Definition: AttrTable.cc:652
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:710
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:237
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
Definition: AttrTable.cc:620
virtual void dump(ostream &strm) const
dumps information about this object
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
D4Attribute * get(const string &fqn)
D4AttributesIter attribute_begin()
Get an iterator to the start of the enumerations.
Definition: D4Attributes.h:143
D4AttributesIter attribute_end()
Get an iterator to the end of the enumerations.
Definition: D4Attributes.h:146
virtual void dump(ostream &strm) const
dumps information about this object
A class for error processing.
Definition: Error.h:91
A class for software fault reporting.
Definition: InternalErr.h:65
void downcase(string &s)
Definition: util.cc:559
string D4AttributeTypeToString(D4AttributeType at)
Definition: D4Attributes.cc:43
AttrType
Definition: AttrTable.h:81