51#define NEW_DEL_ATTR_TABLE_BEHAVIOR 0
63 string::size_type pos = s.find(
"%20");
64 if (pos != string::npos) {
67 n.replace(pos, 3,
" ");
69 }
while (pos != string::npos);
80 string::size_type pos = s.find(
" ");
81 if (pos != string::npos) {
84 n.replace(pos, 1,
"%20");
86 }
while (pos != string::npos);
127AttrType String_to_AttrType(
const string &s)
132 if (s2 ==
"container")
133 return Attr_container;
134 else if (s2 ==
"byte")
136 else if (s2 ==
"int16")
138 else if (s2 ==
"uint16")
140 else if (s2 ==
"int32")
142 else if (s2 ==
"uint32")
144 else if (s2 ==
"float32")
146 else if (s2 ==
"float64")
148 else if (s2 ==
"string")
150 else if (s2 ==
"url")
152 else if (s2 ==
"otherxml")
153 return Attr_other_xml;
163 d_is_global_attribute = at.d_is_global_attribute;
170 Attr_citer i = at.attr_map.begin();
171 Attr_citer ie = at.attr_map.end();
172 for (; i != ie; ++i) {
175 attr_map.push_back(e);
179 if (e->type == Attr_container) {
180 assert(e->attributes);
181 e->attributes->d_parent =
this;
189AttrTable::AttrTable() :
190 DapObj(), d_name(
""), d_parent(0), attr_map(), d_is_global_attribute(true)
194AttrTable::AttrTable(
const AttrTable &rhs) :
201void AttrTable::delete_attr_table()
203 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
209AttrTable::~AttrTable()
215AttrTable::operator=(
const AttrTable &rhs)
233 return attr_map.size();
258static void add_bad_attribute(
AttrTable *attr,
const string &type,
const string &name,
const string &value,
269 if (attr->
get_name().find(
"_dods_errors") != string::npos) {
274 string error_cont_name = attr->
get_name() +
"_dods_errors";
281#ifndef ATTR_STRING_QUOTE_FIX
282 error_cont->append_attr(name +
"_dap_explanation",
"String",
"\"" + msg +
"\"");
284 error_cont->append_attr(name +
"_dap_explanation",
"String", msg);
309 DBG(cerr <<
"Entering AttrTable::append_attr" << endl);
311 string lname =
www2id(name);
320 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
321 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
322 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
323 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
325 if (iter != attr_map.end()) {
326 (*iter)->attr->push_back(value);
327 return (*iter)->attr->size();
334 e->type = String_to_AttrType(type);
335 e->attr =
new vector<string> ;
336 e->attr->push_back(value);
338 attr_map.push_back(e);
340 return e->attr->size();
364 DBG(cerr <<
"Entering AttrTable::append_attr(..., vector)" << endl);
366 string lname =
www2id(name);
374 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
375 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
376 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
377 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
379 if (iter != attr_map.end()) {
380 vector<string>::iterator i = values->begin();
381 while (i != values->end())
382 (*iter)->attr->push_back(*i++);
384 return (*iter)->attr->size();
391 e->type = String_to_AttrType(type);
392 e->attr =
new vector<string> (*values);
394 attr_map.push_back(e);
396 return e->attr->size();
443 string lname =
www2id(name);
449 throw Error(
"There already exists a container called '" + name +
"' in this attribute table (" + at->
get_name() +
"). (1)");
451 DBG(cerr <<
"Setting appended attribute container name to: " << lname << endl);
457 e->type = Attr_container;
460 attr_map.push_back(e);
464 return e->attributes;
483 string::size_type dotpos = target.rfind(
'.');
484 if (dotpos != string::npos) {
485 string container = target.substr(0, dotpos);
486 string field = target.substr(dotpos + 1);
490 *iter = (*at)->simple_find(field);
493 *iter = attr_map.end();
517 if (target == (*i)->name) {
521 else if ((*i)->type == Attr_container) {
544 for (i = attr_map.begin(); i != attr_map.end(); ++i) {
545 if (target == (*i)->name) {
568 string::size_type dotpos = target.
find(
'.');
569 if (dotpos != string::npos) {
570 string container = target.substr(0, dotpos);
571 string field = target.substr(dotpos + 1);
573 AttrTable *at = simple_find_container(container);
577 return simple_find_container(target);
583AttrTable::simple_find_container(
const string &target)
588 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
590 return (*i)->attributes;
616 return (p != attr_map.end()) ?
get_type(p) : (string)
"";
624 return (p != attr_map.end()) ?
get_attr_type(p) : Attr_unknown;
637 return (iter != attr_map.end()) ?
get_attr_num(iter) : 0;
678 string lname =
www2id(name);
684 if (iter != attr_map.end()) {
687 attr_map.erase(iter);
694 if ((*iter)->type == Attr_container)
697 vector<string> *sxp = (*iter)->attr;
699 assert(i >= 0 && i < (
int) sxp->size());
700 sxp->erase(sxp->begin() + i);
713 return attr_map.begin();
721 return attr_map.end();
734 return attr_map.begin() + i;
740 assert(iter != attr_map.end());
742 return (*iter)->name;
748 return (*i)->type == Attr_container;
759 assert(iter != attr_map.end());
760 return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
783 if ((*iter)->type != Attr_container)
789 struct entry *e = *iter;
792 e->attributes->d_parent = 0;
794#if NEW_DEL_ATTR_TABLE_BEHAVIOR
795 delete e->attributes;
802 return attr_map.erase(iter);
810 assert(iter != attr_map.end());
819 return (*iter)->type;
831 assert(iter != attr_map.end());
832 return ((*iter)->type == Attr_container) ? (*iter)->attributes->get_size() : (*iter)->attr->size();
851string AttrTable::get_attr(Attr_iter iter,
unsigned int i)
853 assert(iter != attr_map.end());
855 return (*iter)->type == Attr_container ? (
string)
"None" : (*(*iter)->attr)[i];
858string AttrTable::get_attr(
const string &name,
unsigned int i)
861 return (p != attr_map.end()) ? get_attr(p, i) : (string)
"";
878 assert(iter != attr_map.end());
879 return (*iter)->type != Attr_container ? (*iter)->attr : 0;
882bool AttrTable::is_global_attribute(Attr_iter iter)
884 assert(iter != attr_map.end());
885 if ((*iter)->type == Attr_container)
886 return (*iter)->attributes->is_global_attribute();
888 return (*iter)->is_global;
891void AttrTable::set_is_global_attribute(Attr_iter iter,
bool ga)
893 assert(iter != attr_map.end());
894 if ((*iter)->type == Attr_container)
895 (*iter)->attributes->set_is_global_attribute(ga);
897 (*iter)->is_global = ga;
911 string lname =
www2id(name);
917 throw Error(
string(
"There already exists a container called `") + name +
string(
"in this attribute table. (2)"));
923 e->type = Attr_container;
927 attr_map.push_back(e);
945 string lname =
www2id(name);
951 string lsource =
www2id(source);
961 das->
find(lsource, &at, &iter);
967 if (!at || (iter == at->
attr_end()) || !*iter) {
968 find(lsource, &at, &iter);
969 if (!at || (iter == at->
attr_end()) || !*iter)
970 throw Error(
string(
"Could not find the attribute `") + source +
string(
"' in the attribute object."));
978 "A value cannot be aliased to the top level of the DAS;\nOnly containers may be present at that level of the DAS."));
981 throw Error(
string(
"There already exists a container called `") + name +
string(
"in this attribute table. (3)"));
986 e->aliased_to = lsource;
988 if (at && e->type == Attr_container)
991 e->attr = (*iter)->attr;
993 attr_map.push_back(e);
1038 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1043 attr_map.erase(attr_map.begin(), attr_map.end());
1048const string double_quote =
"\"";
1061static void write_string_attribute_for_das(ostream &out,
const string &value,
const string &term)
1064 out << value << term;
1066 out << double_quote << value << double_quote << term;
1071write_string_attribute_for_das(FILE *out,
const string &value,
const string &term)
1074 fprintf(out,
"%s%s", value.c_str(), term.c_str());
1076 fprintf(out,
"\"%s\"%s", value.c_str(), term.c_str());
1082static void write_xml_attribute_for_das(ostream &out,
const string &value,
const string &term)
1092write_xml_attribute_for_das(FILE *out,
const string &value,
const string &term)
1107 fwrite(oss.str().data(), 1, oss.str().length(), out);
1110 switch ((*i)->type) {
1111 case Attr_container:
1113 fprintf(out,
"%s%s {\n", pad.c_str(),
id2www(
get_name(i)).c_str());
1115 fprintf(out,
"%s%s {\n", pad.c_str(),
get_name(i).c_str());
1117 (*i)->attributes->print(out, pad +
" ", dereference);
1119 fprintf(out,
"%s}\n", pad.c_str());
1126 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1128 vector<string> *sxp = (*i)->attr;
1129 vector<string>::iterator last = sxp->end() - 1;
1130 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1131 write_string_attribute_for_das(out, *i,
", ");
1133 write_string_attribute_for_das(out, *last,
";\n");
1137 case Attr_other_xml: {
1141 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1143 vector<string> *sxp = (*i)->attr;
1144 vector<string>::iterator last = sxp->end() - 1;
1145 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1146 write_xml_attribute_for_das(out, *i,
", ");
1148 write_xml_attribute_for_das(out, *last,
";\n");
1156 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1159 vector<string> *sxp = (*i)->attr;
1160 vector<string>::iterator last = sxp->end() - 1;
1161 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1162 fprintf(out,
"%s%s", (*i).c_str(),
", ");
1164 fprintf(out,
"%s%s", (*last).c_str(),
";\n");
1175 switch ((*i)->type) {
1176 case Attr_container:
1182 (*i)->attributes->print(out, pad +
" ", dereference);
1183 out << pad <<
"}\n";
1192 vector<string> *sxp = (*i)->attr;
1193 vector<string>::iterator last = sxp->end() - 1;
1194 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1195 write_string_attribute_for_das(out, *i,
", ");
1197 write_string_attribute_for_das(out, *last,
";\n");
1201 case Attr_other_xml: {
1207 vector<string> *sxp = (*i)->attr;
1208 vector<string>::iterator last = sxp->end() - 1;
1209 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1210 write_xml_attribute_for_das(out, *i,
", ");
1212 write_xml_attribute_for_das(out, *last,
";\n");
1222 vector<string> *sxp = (*i)->attr;
1223 vector<string>::iterator last = sxp->end() - 1;
1224 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1227 out << *last <<
";\n";
1246 print(oss, pad, dereference);
1247 fwrite(oss.str().data(), 1, oss.str().length(), out);
1250 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1251 if ((*i)->is_alias) {
1257 fprintf(out,
"%sAlias %s %s;\n",
1260 id2www((*i)->aliased_to).c_str());
1262 fprintf(out,
"%sAlias %s %s;\n",
1287 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1288 if ((*i)->is_alias) {
1295 <<
" " <<
id2www((*i)->aliased_to) <<
";\n";
1317 fwrite(xml.get_doc(),
sizeof(
char), xml.get_doc_size(), out);
1322 fwrite(oss.str().data(), 1, oss.str().length(), out);
1335 if ((*i)->is_alias) {
1336 fprintf(out,
"%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
1338 (*i)->aliased_to.c_str());
1342 fprintf(out,
"%s<Attribute name=\"%s\" type=\"%s\">\n",
1348 fprintf(out,
"%s</Attribute>\n", pad.c_str());
1351 fprintf(out,
"%s<Attribute name=\"%s\" type=\"%s\">\n",
1354 string value_pad = pad +
" ";
1360 throw Error(
"OtherXML attributes cannot be vector-valued.");
1361 fprintf(out,
"%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
1365 fprintf(out,
"%s<value>%s</value>\n", value_pad.c_str(),
1366 id2xml(get_attr(i, j)).c_str());
1369 fprintf(out,
"%s</Attribute>\n", pad.c_str());
1382 out << xml.get_doc();
1386 if ((*i)->is_alias) {
1388 <<
"\" Attribute=\"" << (*i)->aliased_to <<
"\"/>\n";
1393 <<
"\" type=\"" <<
get_type(i) <<
"\">\n";
1397 out << pad <<
"</Attribute>\n";
1401 <<
"\" type=\"" <<
get_type(i) <<
"\">\n";
1403 string value_pad = pad +
" ";
1406 throw Error(
"OtherXML attributes cannot be vector-valued.");
1407 out << value_pad << get_attr(i, 0) <<
"\n";
1410 string value_pad = pad +
" ";
1412 out << value_pad <<
"<value>" <<
id2xml(get_attr(i, j)) <<
"</value>\n";
1415 out << pad <<
"</Attribute>\n";
1428 if ((*i)->is_alias) {
1429 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Alias") < 0)
1430 throw InternalErr(__FILE__, __LINE__,
"Could not write Alias element");
1431 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name",
1432 (
const xmlChar*)
get_name(i).c_str()) < 0)
1433 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1434 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"Attribute",
1435 (
const xmlChar*) (*i)->aliased_to.c_str()) < 0)
1436 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1437 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1438 throw InternalErr(__FILE__, __LINE__,
"Could not end Alias element");
1441 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Attribute") < 0)
1442 throw InternalErr(__FILE__, __LINE__,
"Could not write Attribute element");
1443 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name",
1444 (
const xmlChar*)
get_name(i).c_str()) < 0)
1445 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1446 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"type",
1447 (
const xmlChar*)
get_type(i).c_str()) < 0)
1448 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1452 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1453 throw InternalErr(__FILE__, __LINE__,
"Could not end Attribute element");
1456 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Attribute") < 0)
1457 throw InternalErr(__FILE__, __LINE__,
"Could not write Attribute element");
1458 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name",
1459 (
const xmlChar*)
get_name(i).c_str()) < 0)
1460 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1461 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"type",
1462 (
const xmlChar*)
get_type(i).c_str()) < 0)
1463 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1467 throw Error(
"OtherXML attributes cannot be vector-valued.");
1471 if (xmlTextWriterWriteRaw(xml.get_writer(), (
const xmlChar*) get_attr(i, 0).c_str()) < 0)
1472 throw InternalErr(__FILE__, __LINE__,
"Could not write OtherXML value");
1476 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"value") < 0)
1477 throw InternalErr(__FILE__, __LINE__,
"Could not write value element");
1479 if (xmlTextWriterWriteString(xml.get_writer(), (
const xmlChar*) get_attr(i, j).c_str()) < 0)
1480 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute value");
1482 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1483 throw InternalErr(__FILE__, __LINE__,
"Could not end value element");
1486 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1487 throw InternalErr(__FILE__, __LINE__,
"Could not end Attribute element");
1512 strm << DapIndent::LMarg <<
"AttrTable::dump - (" << (
void *)
this <<
")" << endl;
1513 DapIndent::Indent();
1514 strm << DapIndent::LMarg <<
"table name: " << d_name << endl;
1515 if (attr_map.size()) {
1516 strm << DapIndent::LMarg <<
"attributes: " << endl;
1517 DapIndent::Indent();
1518 Attr_citer i = attr_map.begin();
1519 Attr_citer ie = attr_map.end();
1520 for (; i != ie; ++i) {
1524 strm << DapIndent::LMarg <<
"alias: " << e->name <<
" aliased to: " << e->aliased_to << endl;
1526 else if (e->type == Attr_container) {
1527 strm << DapIndent::LMarg <<
"attr: " << e->name <<
" of type " << type << endl;
1528 DapIndent::Indent();
1529 e->attributes->
dump(strm);
1530 DapIndent::UnIndent();
1533 strm << DapIndent::LMarg <<
"attr: " << e->name <<
" of type " << type << endl;
1534 DapIndent::Indent();
1535 strm << DapIndent::LMarg;
1536 vector<string>::const_iterator iter = e->attr->begin();
1537 vector<string>::const_iterator last = e->attr->end() - 1;
1538 for (; iter != last; ++iter) {
1539 strm << (*iter) <<
", ";
1541 strm << (*(e->attr->end() - 1)) << endl;
1542 DapIndent::UnIndent();
1545 DapIndent::UnIndent();
1548 strm << DapIndent::LMarg <<
"attributes: empty" << endl;
1551 strm << DapIndent::LMarg <<
"parent table:" << d_name <<
":" << (
void *) d_parent << endl;
1554 strm << DapIndent::LMarg <<
"parent table: none" << d_name << endl;
1556 DapIndent::UnIndent();
Contains the attributes for a dataset.
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
void simple_print(FILE *out, string pad, Attr_iter i, bool dereference)
virtual unsigned int get_attr_num(const string &name)
Get the number of attributes in this container.
virtual bool attr_alias(const string &alias, AttrTable *at, const string &name)
Adds an alias to the set of attributes.
virtual bool is_container(Attr_iter iter)
virtual void find(const string &target, AttrTable **at, Attr_iter *iter)
virtual void set_name(const string &n)
Set the name of this attribute table.
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
void clone(const AttrTable &at)
virtual Attr_iter attr_end()
virtual void print_xml(FILE *out, string pad=" ", bool constrained=false)
virtual string get_type(const string &name)
Get the type name of an attribute within this attribute table.
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
virtual void add_value_alias(AttrTable *at, const string &name, const string &source)
Add an alias for an attribute.
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
virtual Attr_iter attr_begin()
virtual Attr_iter get_attr_iter(int i)
void print_dap4(XMLWriter &xml)
virtual void del_attr(const string &name, int i=-1)
Deletes an attribute.
virtual string get_name() const
Get the name of this attribute table.
virtual void erase()
Erase the attribute table.
void print_xml_writer(XMLWriter &xml)
virtual Attr_iter del_attr_table(Attr_iter iter)
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
virtual void add_container_alias(const string &name, AttrTable *src)
Add an alias to a container held by this attribute table.
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
virtual void dump(ostream &strm) const
dumps information about this object
virtual AttrTable * find_container(const string &target)
Find an attribute with a given name.
Attr_iter simple_find(const string &target)
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
virtual AttrTable * recurrsive_find(const string &target, Attr_iter *location)
libdap base object for common functionality of libdap objects
A class for error processing.
A class for software fault reporting.
top level DAP object to house generic methods
string www2id(const string &in, const string &escape, const string &except)
string id2xml(string in, const string ¬_allowed)
string add_space_encoding(const string &s)
string AttrType_to_String(const AttrType at)
string escape_double_quotes(string source)
string remove_space_encoding(const string &s)
bool is_quoted(const string &s)
string id2www(string in, const string &allowable)