libdap
Updated for version 3.17.0
|
00001 // -*- mode: c++; c-basic-offset:4 -*- 00002 00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00004 // Access Protocol. 00005 00006 // Copyright (c) 2013 OPeNDAP, Inc. 00007 // Author: James Gallagher <jgallagher@opendap.org> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00024 00025 #include "config.h" 00026 00027 //#define DODS_DEBUG 00028 00029 #include "D4Attributes.h" 00030 #include "D4AttributeType.h" 00031 #include "InternalErr.h" 00032 00033 #include "AttrTable.h" 00034 00035 #include "util.h" 00036 #include "debug.h" 00037 00038 namespace libdap { 00039 00043 string D4AttributeTypeToString(D4AttributeType at) 00044 { 00045 switch(at) { 00046 case attr_null_c: 00047 return "null"; 00048 00049 case attr_byte_c: 00050 return "Byte"; 00051 00052 case attr_int16_c: 00053 return "Int16"; 00054 00055 case attr_uint16_c: 00056 return "UInt16"; 00057 00058 case attr_int32_c: 00059 return "Int32"; 00060 00061 case attr_uint32_c: 00062 return "UInt32"; 00063 00064 case attr_float32_c: 00065 return "Float32"; 00066 00067 case attr_float64_c: 00068 return "Float64"; 00069 00070 case attr_str_c: 00071 return "String"; 00072 00073 case attr_url_c: 00074 return "Url"; 00075 00076 // Added for DAP4 00077 case attr_int8_c: 00078 return "Int8"; 00079 00080 case attr_uint8_c: 00081 return "UInt8"; 00082 00083 case attr_int64_c: 00084 return "Int64"; 00085 00086 case attr_uint64_c: 00087 return "UInt64"; 00088 00089 case attr_enum_c: 00090 return "Enum"; 00091 00092 case attr_opaque_c: 00093 return "Opaque"; 00094 00095 // These are specific to attributes while the other types are 00096 // also supported by the variables. jhrg 4/17/13 00097 case attr_container_c: 00098 return "Container"; 00099 00100 case attr_otherxml_c: 00101 return "OtherXML"; 00102 00103 default: 00104 throw InternalErr(__FILE__, __LINE__, "Unsupported attribute type"); 00105 } 00106 } 00107 00108 D4AttributeType StringToD4AttributeType(string s) 00109 { 00110 downcase(s); 00111 00112 if (s == "container") 00113 return attr_container_c; 00114 00115 else if (s == "byte") 00116 return attr_byte_c; 00117 else if (s == "int8") 00118 return attr_int8_c; 00119 else if (s == "uint8") 00120 return attr_uint8_c; 00121 else if (s == "int16") 00122 return attr_int16_c; 00123 else if (s == "uint16") 00124 return attr_uint16_c; 00125 else if (s == "int32") 00126 return attr_int32_c; 00127 else if (s == "uint32") 00128 return attr_uint32_c; 00129 else if (s == "int64") 00130 return attr_int64_c; 00131 else if (s == "uint64") 00132 return attr_uint64_c; 00133 00134 else if (s == "float32") 00135 return attr_float32_c; 00136 else if (s == "float64") 00137 return attr_float64_c; 00138 00139 else if (s == "string") 00140 return attr_str_c; 00141 else if (s == "url") 00142 return attr_url_c; 00143 else if (s == "otherxml") 00144 return attr_otherxml_c; 00145 else 00146 return attr_null_c; 00147 } 00148 00149 void 00150 D4Attribute::m_duplicate(const D4Attribute &src) 00151 { 00152 d_name = src.d_name; 00153 d_type = src.d_type; 00154 d_values = src.d_values; 00155 if (src.d_attributes) 00156 d_attributes = new D4Attributes(*src.d_attributes); 00157 else 00158 d_attributes = 0; 00159 } 00160 00161 D4Attribute::D4Attribute(const D4Attribute &src) 00162 { 00163 m_duplicate(src); 00164 } 00165 00166 D4Attribute::~D4Attribute() 00167 { 00168 delete d_attributes; 00169 } 00170 00171 D4Attribute & 00172 D4Attribute::operator=(const D4Attribute &rhs) 00173 { 00174 if (this == &rhs) return *this; 00175 m_duplicate(rhs); 00176 return *this; 00177 } 00178 00179 D4Attributes * 00180 D4Attribute::attributes() 00181 { 00182 if (!d_attributes) d_attributes = new D4Attributes(); 00183 return d_attributes; 00184 } 00185 00193 void 00194 D4Attributes::transform_to_dap4(AttrTable &at) 00195 { 00196 // for every attribute in at, copy it to this. 00197 for (AttrTable::Attr_iter i = at.attr_begin(), e = at.attr_end(); i != e; ++i) { 00198 string name = at.get_name(i); 00199 AttrType type = at.get_attr_type(i); 00200 00201 switch (type) { 00202 case Attr_container: { 00203 D4Attribute *a = new D4Attribute(name, attr_container_c); 00204 D4Attributes *attributes = a->attributes(); // allocates a new object 00205 attributes->transform_to_dap4(*at.get_attr_table(i)); 00206 add_attribute_nocopy(a); 00207 break; 00208 } 00209 case Attr_byte: { 00210 D4Attribute *a = new D4Attribute(name, attr_byte_c); 00211 a->add_value_vector(*at.get_attr_vector(i)); 00212 add_attribute_nocopy(a); 00213 break; 00214 } 00215 case Attr_int16: { 00216 D4Attribute *a = new D4Attribute(name, attr_int16_c); 00217 a->add_value_vector(*at.get_attr_vector(i)); 00218 add_attribute_nocopy(a); 00219 break; 00220 } 00221 case Attr_uint16: { 00222 D4Attribute *a = new D4Attribute(name, attr_uint16_c); 00223 a->add_value_vector(*at.get_attr_vector(i)); 00224 add_attribute_nocopy(a); 00225 break; 00226 } 00227 case Attr_int32: { 00228 D4Attribute *a = new D4Attribute(name, attr_int32_c); 00229 a->add_value_vector(*at.get_attr_vector(i)); 00230 add_attribute_nocopy(a); 00231 break; 00232 } 00233 case Attr_uint32: { 00234 D4Attribute *a = new D4Attribute(name, attr_uint32_c); 00235 a->add_value_vector(*at.get_attr_vector(i)); 00236 add_attribute_nocopy(a); 00237 break; 00238 } 00239 case Attr_float32: { 00240 D4Attribute *a = new D4Attribute(name, attr_float32_c); 00241 a->add_value_vector(*at.get_attr_vector(i)); 00242 add_attribute_nocopy(a); 00243 break; 00244 } 00245 case Attr_float64: { 00246 D4Attribute *a = new D4Attribute(name, attr_float64_c); 00247 a->add_value_vector(*at.get_attr_vector(i)); 00248 add_attribute_nocopy(a); 00249 break; 00250 } 00251 case Attr_string: { 00252 D4Attribute *a = new D4Attribute(name, attr_str_c); 00253 a->add_value_vector(*at.get_attr_vector(i)); 00254 add_attribute_nocopy(a); 00255 break; 00256 } 00257 case Attr_url: { 00258 D4Attribute *a = new D4Attribute(name, attr_url_c); 00259 a->add_value_vector(*at.get_attr_vector(i)); 00260 add_attribute_nocopy(a); 00261 break; 00262 } 00263 case Attr_other_xml: { 00264 D4Attribute *a = new D4Attribute(name, attr_otherxml_c); 00265 a->add_value_vector(*at.get_attr_vector(i)); 00266 add_attribute_nocopy(a); 00267 break; 00268 } 00269 default: 00270 throw InternalErr(__FILE__, __LINE__, "Unknown DAP2 attribute type in D4Attributes::copy_from_dap2()"); 00271 } 00272 } 00273 } 00274 00275 D4Attribute * 00276 D4Attributes::find_depth_first(const string &name, D4AttributesIter i) 00277 { 00278 if (i == attribute_end()) 00279 return 0; 00280 else if ((*i)->name() == name) 00281 return *i; 00282 else if ((*i)->type() == attr_container_c) 00283 return find_depth_first(name, (*i)->attributes()->attribute_begin()); 00284 else 00285 return find_depth_first(name, ++i); 00286 } 00287 00288 D4Attribute * 00289 D4Attributes::find(const string &name) 00290 { 00291 return find_depth_first(name, attribute_begin()); 00292 } 00293 00297 D4Attribute * 00298 D4Attributes::get(const string &fqn) 00299 { 00300 // name1.name2.name3 00301 // name1 00302 // name1.name2 00303 size_t pos = fqn.find('.'); 00304 string part = fqn.substr(0, pos); 00305 string rest= ""; 00306 00307 if (pos != string::npos) 00308 rest = fqn.substr(pos + 1); 00309 00310 DBG(cerr << "part: '" << part << "'; rest: '" << rest << "'" << endl); 00311 00312 if (!part.empty()) { 00313 if (!rest.empty()) { 00314 D4AttributesIter i = attribute_begin(); 00315 while (i != attribute_end()) { 00316 if ((*i)->name() == part && (*i)->type() == attr_container_c) 00317 return (*i)->attributes()->get(rest); 00318 ++i; 00319 } 00320 } 00321 else { 00322 D4AttributesIter i = attribute_begin(); 00323 while (i != attribute_end()) { 00324 if ((*i)->name() == part) 00325 return (*i); 00326 ++i; 00327 } 00328 } 00329 } 00330 00331 return 0; 00332 } 00333 00334 void 00335 D4Attribute::print_dap4(XMLWriter &xml) const 00336 { 00337 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Attribute") < 0) 00338 throw InternalErr(__FILE__, __LINE__, "Could not write Attribute element"); 00339 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0) 00340 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name"); 00341 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "type", (const xmlChar*) D4AttributeTypeToString(type()).c_str()) < 0) 00342 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for type"); 00343 00344 switch (type()) { 00345 case attr_container_c: 00346 if (!d_attributes) 00347 throw InternalErr(__FILE__, __LINE__, "Null Attribute container"); 00348 d_attributes->print_dap4(xml); 00349 break; 00350 00351 case attr_otherxml_c: 00352 if (num_values() != 1) 00353 throw Error("OtherXML attributes cannot be vector-valued."); 00354 if (xmlTextWriterWriteRaw(xml.get_writer(), (const xmlChar*) value(0).c_str()) < 0) 00355 throw InternalErr(__FILE__, __LINE__, "Could not write OtherXML value"); 00356 break; 00357 00358 default: { 00359 // Assume only valid types make it into instances 00360 D4AttributeCIter i = d_values.begin();//value_begin(); 00361 while (i != d_values.end()) { 00362 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Value") < 0) 00363 throw InternalErr(__FILE__, __LINE__, "Could not write value element"); 00364 00365 if (xmlTextWriterWriteString(xml.get_writer(), (const xmlChar*) (*i++).c_str()) < 0) 00366 throw InternalErr(__FILE__, __LINE__, "Could not write attribute value"); 00367 00368 if (xmlTextWriterEndElement(xml.get_writer()) < 0) 00369 throw InternalErr(__FILE__, __LINE__, "Could not end value element"); 00370 } 00371 00372 break; 00373 } 00374 } 00375 00376 if (xmlTextWriterEndElement(xml.get_writer()) < 0) 00377 throw InternalErr(__FILE__, __LINE__, "Could not end Attribute element"); 00378 } 00379 00380 void 00381 D4Attributes::print_dap4(XMLWriter &xml) const 00382 { 00383 if (empty()) 00384 return; 00385 00386 D4AttributesCIter i = d_attrs.begin(); 00387 while (i != d_attrs.end()) { 00388 (*i++)->print_dap4(xml); 00389 } 00390 } 00391 00392 } // namespace libdap 00393