38 #include "AttrTable.h"
47 #define WWW_ENCODING 0
50 #define NEW_DEL_ATTR_TABLE_BEHAVIOR 0
62 string::size_type pos = s.find(
"%20");
63 if (pos != string::npos) {
66 n.replace(pos, 3,
" ");
68 }
while (pos != string::npos);
79 string::size_type pos = s.find(
" ");
80 if (pos != string::npos) {
83 n.replace(pos, 1,
"%20");
85 }
while (pos != string::npos);
126 AttrType String_to_AttrType(
const string &s)
131 if (s2 ==
"container")
132 return Attr_container;
133 else if (s2 ==
"byte")
135 else if (s2 ==
"int16")
137 else if (s2 ==
"uint16")
139 else if (s2 ==
"int32")
141 else if (s2 ==
"uint32")
143 else if (s2 ==
"float32")
145 else if (s2 ==
"float64")
147 else if (s2 ==
"string")
149 else if (s2 ==
"url")
151 else if (s2 ==
"otherxml")
152 return Attr_other_xml;
162 d_is_global_attribute = at.d_is_global_attribute;
169 Attr_citer i = at.attr_map.begin();
170 Attr_citer ie = at.attr_map.end();
171 for (; i != ie; ++i) {
174 attr_map.push_back(e);
178 if (e->type == Attr_container) {
179 assert(e->attributes);
180 e->attributes->d_parent =
this;
188 AttrTable::AttrTable() :
189 DapObj(), d_name(
""), d_parent(0), attr_map(), d_is_global_attribute(true)
193 AttrTable::AttrTable(
const AttrTable &rhs) :
200 void AttrTable::delete_attr_table()
202 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
208 AttrTable::~AttrTable()
214 AttrTable::operator=(
const AttrTable &rhs)
232 return attr_map.size();
257 static void add_bad_attribute(
AttrTable *attr,
const string &type,
const string &name,
const string &value,
268 if (attr->
get_name().find(
"_dods_errors") != string::npos) {
273 string error_cont_name = attr->
get_name() +
"_dods_errors";
280 #ifndef ATTR_STRING_QUOTE_FIX
281 error_cont->append_attr(name +
"_dap_explanation",
"String",
"\"" + msg +
"\"");
283 error_cont->append_attr(name +
"_dap_explanation",
"String", msg);
308 DBG(cerr <<
"Entering AttrTable::append_attr" << endl);
310 string lname =
www2id(name);
319 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
320 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
321 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
322 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
324 if (iter != attr_map.end()) {
325 (*iter)->attr->push_back(value);
326 return (*iter)->attr->size();
333 e->type = String_to_AttrType(type);
334 e->attr =
new vector<string> ;
335 e->attr->push_back(value);
337 attr_map.push_back(e);
339 return e->attr->size();
363 DBG(cerr <<
"Entering AttrTable::append_attr(..., vector)" << endl);
365 string lname =
www2id(name);
373 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
374 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
375 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
376 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
378 if (iter != attr_map.end()) {
379 vector<string>::iterator i = values->begin();
380 while (i != values->end())
381 (*iter)->attr->push_back(*i++);
383 return (*iter)->attr->size();
390 e->type = String_to_AttrType(type);
391 e->attr =
new vector<string> (*values);
393 attr_map.push_back(e);
395 return e->attr->size();
442 string lname =
www2id(name);
448 throw Error(
"There already exists a container called '" + name +
"' in this attribute table (" + at->
get_name() +
"). (1)");
450 DBG(cerr <<
"Setting appended attribute container name to: " << lname << endl);
456 e->type = Attr_container;
459 attr_map.push_back(e);
463 return e->attributes;
482 string::size_type dotpos = target.rfind(
'.');
483 if (dotpos != string::npos) {
484 string container = target.substr(0, dotpos);
485 string field = target.substr(dotpos + 1);
489 *iter = (*at)->simple_find(field);
492 *iter = attr_map.end();
516 if (target == (*i)->name) {
520 else if ((*i)->type == Attr_container) {
543 for (i = attr_map.begin(); i != attr_map.end(); ++i) {
544 if (target == (*i)->name) {
567 string::size_type dotpos = target.
find(
'.');
568 if (dotpos != string::npos) {
569 string container = target.substr(0, dotpos);
570 string field = target.substr(dotpos + 1);
572 AttrTable *at = simple_find_container(container);
576 return simple_find_container(target);
582 AttrTable::simple_find_container(
const string &target)
587 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
589 return (*i)->attributes;
615 return (p != attr_map.end()) ?
get_type(p) : (string)
"";
623 return (p != attr_map.end()) ?
get_attr_type(p) : Attr_unknown;
636 return (iter != attr_map.end()) ?
get_attr_num(iter) : 0;
677 string lname =
www2id(name);
683 if (iter != attr_map.end()) {
686 attr_map.erase(iter);
693 if ((*iter)->type == Attr_container)
696 vector<string> *sxp = (*iter)->attr;
698 assert(i >= 0 && i < (
int) sxp->size());
699 sxp->erase(sxp->begin() + i);
712 return attr_map.begin();
720 return attr_map.end();
733 return attr_map.begin() + i;
739 assert(iter != attr_map.end());
741 return (*iter)->name;
747 return (*i)->type == Attr_container;
758 assert(iter != attr_map.end());
759 return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
782 if ((*iter)->type != Attr_container)
788 struct entry *e = *iter;
791 e->attributes->d_parent = 0;
793 #if NEW_DEL_ATTR_TABLE_BEHAVIOR
794 delete e->attributes;
801 return attr_map.erase(iter);
809 assert(iter != attr_map.end());
818 return (*iter)->type;
830 assert(iter != attr_map.end());
831 return ((*iter)->type == Attr_container) ? (*iter)->attributes->get_size() : (*iter)->attr->size();
850 string AttrTable::get_attr(Attr_iter iter,
unsigned int i)
852 assert(iter != attr_map.end());
854 return (*iter)->type == Attr_container ? (
string)
"None" : (*(*iter)->attr)[i];
857 string AttrTable::get_attr(
const string &name,
unsigned int i)
860 return (p != attr_map.end()) ? get_attr(p, i) : (string)
"";
877 assert(iter != attr_map.end());
878 return (*iter)->type != Attr_container ? (*iter)->attr : 0;
881 bool AttrTable::is_global_attribute(Attr_iter iter)
883 assert(iter != attr_map.end());
884 if ((*iter)->type == Attr_container)
885 return (*iter)->attributes->is_global_attribute();
887 return (*iter)->is_global;
890 void AttrTable::set_is_global_attribute(Attr_iter iter,
bool ga)
892 assert(iter != attr_map.end());
893 if ((*iter)->type == Attr_container)
894 (*iter)->attributes->set_is_global_attribute(ga);
896 (*iter)->is_global = ga;
910 string lname =
www2id(name);
916 throw Error(
string(
"There already exists a container called `") + name +
string(
"in this attribute table. (2)"));
922 e->type = Attr_container;
926 attr_map.push_back(e);
944 string lname =
www2id(name);
950 string lsource =
www2id(source);
960 das->
find(lsource, &at, &iter);
966 if (!at || (iter == at->
attr_end()) || !*iter) {
967 find(lsource, &at, &iter);
968 if (!at || (iter == at->
attr_end()) || !*iter)
969 throw Error(
string(
"Could not find the attribute `") + source +
string(
"' in the attribute object."));
977 "A value cannot be aliased to the top level of the DAS;\nOnly containers may be present at that level of the DAS."));
980 throw Error(
string(
"There already exists a container called `") + name +
string(
"in this attribute table. (3)"));
985 e->aliased_to = lsource;
987 if (at && e->type == Attr_container)
990 e->attr = (*iter)->attr;
992 attr_map.push_back(e);
1037 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1042 attr_map.erase(attr_map.begin(), attr_map.end());
1047 const string double_quote =
"\"";
1060 static void write_string_attribute_for_das(ostream &out,
const string &value,
const string &term)
1063 out << value << term;
1065 out << double_quote << value << double_quote << term;
1070 write_string_attribute_for_das(FILE *out,
const string &value,
const string &term)
1073 fprintf(out,
"%s%s", value.c_str(), term.c_str());
1075 fprintf(out,
"\"%s\"%s", value.c_str(), term.c_str());
1081 static void write_xml_attribute_for_das(ostream &out,
const string &value,
const string &term)
1091 write_xml_attribute_for_das(FILE *out,
const string &value,
const string &term)
1106 fwrite(oss.str().data(), 1, oss.str().length(), out);
1109 switch ((*i)->type) {
1110 case Attr_container:
1112 fprintf(out,
"%s%s {\n", pad.c_str(),
id2www(
get_name(i)).c_str());
1114 fprintf(out,
"%s%s {\n", pad.c_str(),
get_name(i).c_str());
1116 (*i)->attributes->print(out, pad +
" ", dereference);
1118 fprintf(out,
"%s}\n", pad.c_str());
1125 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1127 vector<string> *sxp = (*i)->attr;
1128 vector<string>::iterator last = sxp->end() - 1;
1129 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1130 write_string_attribute_for_das(out, *i,
", ");
1132 write_string_attribute_for_das(out, *last,
";\n");
1136 case Attr_other_xml: {
1140 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1142 vector<string> *sxp = (*i)->attr;
1143 vector<string>::iterator last = sxp->end() - 1;
1144 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1145 write_xml_attribute_for_das(out, *i,
", ");
1147 write_xml_attribute_for_das(out, *last,
";\n");
1155 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1158 vector<string> *sxp = (*i)->attr;
1159 vector<string>::iterator last = sxp->end() - 1;
1160 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1161 fprintf(out,
"%s%s", (*i).c_str(),
", ");
1163 fprintf(out,
"%s%s", (*last).c_str(),
";\n");
1174 switch ((*i)->type) {
1175 case Attr_container:
1181 (*i)->attributes->print(out, pad +
" ", dereference);
1182 out << pad <<
"}\n";
1191 vector<string> *sxp = (*i)->attr;
1192 vector<string>::iterator last = sxp->end() - 1;
1193 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1194 write_string_attribute_for_das(out, *i,
", ");
1196 write_string_attribute_for_das(out, *last,
";\n");
1200 case Attr_other_xml: {
1206 vector<string> *sxp = (*i)->attr;
1207 vector<string>::iterator last = sxp->end() - 1;
1208 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1209 write_xml_attribute_for_das(out, *i,
", ");
1211 write_xml_attribute_for_das(out, *last,
";\n");
1221 vector<string> *sxp = (*i)->attr;
1222 vector<string>::iterator last = sxp->end() - 1;
1223 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1226 out << *last <<
";\n";
1245 print(oss, pad, dereference);
1246 fwrite(oss.str().data(), 1, oss.str().length(), out);
1249 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1250 if ((*i)->is_alias) {
1256 fprintf(out,
"%sAlias %s %s;\n",
1259 id2www((*i)->aliased_to).c_str());
1261 fprintf(out,
"%sAlias %s %s;\n",
1286 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1287 if ((*i)->is_alias) {
1294 <<
" " <<
id2www((*i)->aliased_to) <<
";\n";
1316 fwrite(xml.get_doc(),
sizeof(
char), xml.get_doc_size(), out);
1318 #if OLD_XML_MOETHODS
1321 fwrite(oss.str().data(), 1, oss.str().length(), out);
1334 if ((*i)->is_alias) {
1335 fprintf(out,
"%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
1337 (*i)->aliased_to.c_str());
1341 fprintf(out,
"%s<Attribute name=\"%s\" type=\"%s\">\n",
1347 fprintf(out,
"%s</Attribute>\n", pad.c_str());
1350 fprintf(out,
"%s<Attribute name=\"%s\" type=\"%s\">\n",
1353 string value_pad = pad +
" ";
1359 throw Error(
"OtherXML attributes cannot be vector-valued.");
1360 fprintf(out,
"%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
1364 fprintf(out,
"%s<value>%s</value>\n", value_pad.c_str(),
1365 id2xml(get_attr(i, j)).c_str());
1368 fprintf(out,
"%s</Attribute>\n", pad.c_str());
1381 out << xml.get_doc();
1385 if ((*i)->is_alias) {
1387 <<
"\" Attribute=\"" << (*i)->aliased_to <<
"\"/>\n";
1392 <<
"\" type=\"" <<
get_type(i) <<
"\">\n";
1396 out << pad <<
"</Attribute>\n";
1400 <<
"\" type=\"" <<
get_type(i) <<
"\">\n";
1402 string value_pad = pad +
" ";
1405 throw Error(
"OtherXML attributes cannot be vector-valued.");
1406 out << value_pad << get_attr(i, 0) <<
"\n";
1409 string value_pad = pad +
" ";
1411 out << value_pad <<
"<value>" <<
id2xml(get_attr(i, j)) <<
"</value>\n";
1414 out << pad <<
"</Attribute>\n";
1427 if ((*i)->is_alias) {
1428 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Alias") < 0)
1429 throw InternalErr(__FILE__, __LINE__,
"Could not write Alias element");
1430 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name",
1431 (
const xmlChar*)
get_name(i).c_str()) < 0)
1432 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1433 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"Attribute",
1434 (
const xmlChar*) (*i)->aliased_to.c_str()) < 0)
1435 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1436 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1437 throw InternalErr(__FILE__, __LINE__,
"Could not end Alias element");
1440 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Attribute") < 0)
1441 throw InternalErr(__FILE__, __LINE__,
"Could not write Attribute element");
1442 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name",
1443 (
const xmlChar*)
get_name(i).c_str()) < 0)
1444 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1445 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"type",
1446 (
const xmlChar*)
get_type(i).c_str()) < 0)
1447 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1451 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1452 throw InternalErr(__FILE__, __LINE__,
"Could not end Attribute element");
1455 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Attribute") < 0)
1456 throw InternalErr(__FILE__, __LINE__,
"Could not write Attribute element");
1457 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name",
1458 (
const xmlChar*)
get_name(i).c_str()) < 0)
1459 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1460 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"type",
1461 (
const xmlChar*)
get_type(i).c_str()) < 0)
1462 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1466 throw Error(
"OtherXML attributes cannot be vector-valued.");
1470 if (xmlTextWriterWriteRaw(xml.get_writer(), (
const xmlChar*) get_attr(i, 0).c_str()) < 0)
1471 throw InternalErr(__FILE__, __LINE__,
"Could not write OtherXML value");
1475 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"value") < 0)
1476 throw InternalErr(__FILE__, __LINE__,
"Could not write value element");
1478 if (xmlTextWriterWriteString(xml.get_writer(), (
const xmlChar*) get_attr(i, j).c_str()) < 0)
1479 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute value");
1481 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1482 throw InternalErr(__FILE__, __LINE__,
"Could not end value element");
1485 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1486 throw InternalErr(__FILE__, __LINE__,
"Could not end Attribute element");
1511 strm << DapIndent::LMarg <<
"AttrTable::dump - (" << (
void *)
this <<
")" << endl;
1512 DapIndent::Indent();
1513 strm << DapIndent::LMarg <<
"table name: " << d_name << endl;
1514 if (attr_map.size()) {
1515 strm << DapIndent::LMarg <<
"attributes: " << endl;
1516 DapIndent::Indent();
1517 Attr_citer i = attr_map.begin();
1518 Attr_citer ie = attr_map.end();
1519 for (; i != ie; ++i) {
1523 strm << DapIndent::LMarg <<
"alias: " << e->name <<
" aliased to: " << e->aliased_to << endl;
1525 else if (e->type == Attr_container) {
1526 strm << DapIndent::LMarg <<
"attr: " << e->name <<
" of type " << type << endl;
1527 DapIndent::Indent();
1528 e->attributes->
dump(strm);
1529 DapIndent::UnIndent();
1532 strm << DapIndent::LMarg <<
"attr: " << e->name <<
" of type " << type << endl;
1533 DapIndent::Indent();
1534 strm << DapIndent::LMarg;
1535 vector<string>::const_iterator iter = e->attr->begin();
1536 vector<string>::const_iterator last = e->attr->end() - 1;
1537 for (; iter != last; ++iter) {
1538 strm << (*iter) <<
", ";
1540 strm << (*(e->attr->end() - 1)) << endl;
1541 DapIndent::UnIndent();
1544 DapIndent::UnIndent();
1547 strm << DapIndent::LMarg <<
"attributes: empty" << endl;
1550 strm << DapIndent::LMarg <<
"parent table:" << d_name <<
":" << (
void *) d_parent << endl;
1553 strm << DapIndent::LMarg <<
"parent table: none" << d_name << endl;
1555 DapIndent::UnIndent();