libdap  Updated for version 3.18.3
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 
38 namespace libdap {
39 
43 string 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 
108 D4AttributeType 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 
149 void
150 D4Attribute::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 
161 D4Attribute::D4Attribute(const D4Attribute &src)
162 {
163  m_duplicate(src);
164 }
165 
166 D4Attribute::~D4Attribute()
167 {
168  delete d_attributes;
169 }
170 
171 D4Attribute &
172 D4Attribute::operator=(const D4Attribute &rhs)
173 {
174  if (this == &rhs) return *this;
175  m_duplicate(rhs);
176  return *this;
177 }
178 
179 D4Attributes *
180 D4Attribute::attributes()
181 {
182  if (!d_attributes) d_attributes = new D4Attributes();
183  return d_attributes;
184 }
185 
193 void
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 
275 D4Attribute *
276 D4Attributes::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 
288 D4Attribute *
289 D4Attributes::find(const string &name)
290 {
291  return find_depth_first(name, attribute_begin());
292 }
293 
297 D4Attribute *
298 D4Attributes::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 
334 void
335 D4Attribute::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 
388 void
389 D4Attribute::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 
403 void
404 D4Attributes::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 
423 void
424 D4Attributes::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 
virtual void dump(ostream &strm) const
dumps information about this object
virtual Attr_iter attr_end()
Definition: AttrTable.cc:718
void downcase(string &s)
Definition: util.cc:562
D4AttributesIter attribute_begin()
Get an iterator to the start of the enumerations.
Definition: D4Attributes.h:143
Contains the attributes for a dataset.
Definition: AttrTable.h:142
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:237
A class for software fault reporting.
Definition: InternalErr.h:64
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
Definition: AttrTable.cc:606
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:710
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
Definition: AttrTable.cc:620
D4AttributesIter attribute_end()
Get an iterator to the end of the enumerations.
Definition: D4Attributes.h:146
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
Definition: AttrTable.cc:652
D4Attribute * get(const string &fqn)
A class for error processing.
Definition: Error.h:90
string D4AttributeTypeToString(D4AttributeType at)
Definition: D4Attributes.cc:43
void transform_to_dap4(AttrTable &at)
copy attributes from DAP2 to DAP4
AttrType
Definition: AttrTable.h:81
virtual void dump(ostream &strm) const
dumps information about this object