libdap++  Updated for version 3.8.2
AttrTable.cc
Go to the documentation of this file.
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) 2002,2003 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 // (c) COPYRIGHT URI/MIT 1994-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 // Authors:
29 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30 
31 // jhrg 7/29/94
32 
33 #include "config.h"
34 
35 // #define DODS_DEBUG
36 
37 static char rcsid[]not_used =
38  "$Id: AttrTable.cc 24370 2011-03-28 16:21:32Z jimg $";
39 
40 #include <cassert>
41 
42 #include "AttrTable.h"
43 
44 #include "util.h"
45 #include "escaping.h"
46 
47 #include "debug.h"
48 
49 using std::cerr;
50 using std::string;
51 using std::endl;
52 using std::vector;
53 
54 namespace libdap {
55 
59 string AttrType_to_String(const AttrType at)
60 {
61  switch (at) {
62  case Attr_container:
63  return "Container";
64  case Attr_byte:
65  return "Byte";
66  case Attr_int16:
67  return "Int16";
68  case Attr_uint16:
69  return "UInt16";
70  case Attr_int32:
71  return "Int32";
72  case Attr_uint32:
73  return "UInt32";
74  case Attr_float32:
75  return "Float32";
76  case Attr_float64:
77  return "Float64";
78  case Attr_string:
79  return "String";
80  case Attr_url:
81  return "Url";
82  case Attr_other_xml:
83  return "OtherXML";
84  default:
85  return "";
86  }
87 }
88 
89 AttrType String_to_AttrType(const string &s)
90 {
91  string s2 = s;
92  downcase(s2);
93 
94  if (s2 == "container")
95  return Attr_container;
96  else if (s2 == "byte")
97  return Attr_byte;
98  else if (s2 == "int16")
99  return Attr_int16;
100  else if (s2 == "uint16")
101  return Attr_uint16;
102  else if (s2 == "int32")
103  return Attr_int32;
104  else if (s2 == "uint32")
105  return Attr_uint32;
106  else if (s2 == "float32")
107  return Attr_float32;
108  else if (s2 == "float64")
109  return Attr_float64;
110  else if (s2 == "string")
111  return Attr_string;
112  else if (s2 == "url")
113  return Attr_url;
114  else if (s2 == "otherxml")
115  return Attr_other_xml;
116  else
117  return Attr_unknown;
118 }
119 
123 {
124  d_name = at.d_name;
125  d_is_global_attribute = at.d_is_global_attribute;
126 
127  // Set the parent to null (no parent, not in container)
128  // since using at.d_parent is semantically incorrect
129  // and potentially dangerous.
130  d_parent = 0;
131 
132  Attr_citer i = at.attr_map.begin();
133  Attr_citer ie = at.attr_map.end();
134  for (; i != ie; ++i) {
135  // this deep-copies containers recursively
136  entry *e = new entry(*(*i));
137  attr_map.push_back(e);
138 
139  // If the entry being added was a container,
140  // set its parent to this to maintain invariant.
141  if (e->type == Attr_container) {
142  assert(e->attributes);
143  e->attributes->d_parent = this;
144  }
145  }
146 }
147 
152  : DapObj()
153  , d_name("")
154  , d_parent(0)
155  , attr_map()
156  , d_is_global_attribute(true)
157 {
158 }
159 
161 : DapObj()
162 {
163  clone(rhs);
164 }
165 
166 // Private
167 void AttrTable::delete_attr_table()
168 {
169  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
170  delete *i;
171  *i = 0;
172  }
173  attr_map.clear();
174 }
175 
177 {
178  DBG(cerr << "Entering ~AttrTable (" << this << ")" << endl);
179  delete_attr_table();DBG(cerr << "Exiting ~AttrTable" << endl);
180 }
181 
182 AttrTable &
184 {
185  if (this != &rhs) {
186  delete_attr_table();
187  clone(rhs);
188  }
189 
190  return *this;
191 }
193 
199 unsigned int
201 {
202  return attr_map.size();
203 }
204 
207 string
209 {
210  return d_name;
211 }
212 
215 void
216 AttrTable::set_name(const string &n)
217 {
218  d_name = www2id(n);
219 }
220 
238 unsigned int
239 AttrTable::append_attr(const string &name, const string &type,
240  const string &attribute)
241 {
242  DBG(cerr << "Entering AttrTable::append_attr" << endl);
243  string lname = www2id(name);
244 
245  Attr_iter iter = simple_find(lname);
246 
247  // If the types don't match OR this attribute is a container, calling
248  // this mfunc is an error!
249  if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
250  throw Error(string("An attribute called `") + name
251  + string("' already exists but is of a different type"));
252  if (iter != attr_map.end() && (get_type(iter) == "Container"))
253  throw Error(string("An attribute called `") + name
254  + string("' already exists but is a container."));
255 
256  if (iter != attr_map.end()) { // Must be a new attribute value; add it.
257  (*iter)->attr->push_back(attribute);
258  return (*iter)->attr->size();
259  }
260  else { // Must be a completely new attribute; add it
261  entry *e = new entry;
262 
263  e->name = lname;
264  e->is_alias = false;
265  e->type = String_to_AttrType(type); // Record type using standard names.
266  e->attr = new vector<string>;
267  e->attr->push_back(attribute);
268 
269  attr_map.push_back(e);
270 
271  return e->attr->size(); // return the length of the attr vector
272  }
273 }
274 
293 unsigned int
294 AttrTable::append_attr(const string &name, const string &type,
295  vector<string> *values)
296 {
297  DBG(cerr << "Entering AttrTable::append_attr(..., vector)" << endl);
298  string lname = www2id(name);
299 
300  Attr_iter iter = simple_find(lname);
301 
302  // If the types don't match OR this attribute is a container, calling
303  // this mfunc is an error!
304  if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
305  throw Error(string("An attribute called `") + name
306  + string("' already exists but is of a different type"));
307  if (iter != attr_map.end() && (get_type(iter) == "Container"))
308  throw Error(string("An attribute called `") + name
309  + string("' already exists but is a container."));
310 
311  if (iter != attr_map.end()) { // Must be new attribute values; add.
312  vector<string>::iterator i = values->begin();
313  while (i != values->end())
314  (*iter)->attr->push_back(*i++);
315 
316  return (*iter)->attr->size();
317  }
318  else { // Must be a completely new attribute; add it
319  entry *e = new entry;
320 
321  e->name = lname;
322  e->is_alias = false;
323  e->type = String_to_AttrType(type); // Record type using standard names.
324  e->attr = new vector<string>(*values);
325 
326  attr_map.push_back(e);
327 
328  return e->attr->size(); // return the length of the attr vector
329  }
330 }
331 
341 AttrTable *
342 AttrTable::append_container(const string &name)
343 {
344  AttrTable *new_at = new AttrTable;
345  AttrTable *ret = NULL;
346  try {
347  ret = append_container(new_at, name);
348  }
349  catch (Error &e) {
350  // an error occurred, attribute with that name already exists
351  delete new_at; new_at = 0;
352  throw ;
353  }
354  return ret;
355 }
356 
371 AttrTable *
372 AttrTable::append_container(AttrTable *at, const string &name)
373 {
374  string lname = www2id(name);
375 
376  if (simple_find(name) != attr_end())
377  throw Error(string("There already exists a container called `")
378  + name + string("' in this attribute table."));
379  DBG(cerr << "Setting appended attribute container name to: "
380  << lname << endl);
381  at->set_name(lname);
382 
383  entry *e = new entry;
384  e->name = lname;
385  e->is_alias = false;
386  e->type = Attr_container;
387  e->attributes = at;
388 
389  attr_map.push_back(e);
390 
391  at->d_parent = this;
392 
393  return e->attributes;
394 }
395 
410 void
411 AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter)
412 {
413  string::size_type dotpos = target.rfind('.');
414  if (dotpos != string::npos) {
415  string container = target.substr(0, dotpos);
416  string field = target.substr(dotpos + 1);
417 
418  *at = find_container(container);
419  if (*at) {
420  *iter = (*at)->simple_find(field);
421  }
422  else {
423  *iter = attr_map.end();
424  }
425  }
426  else {
427  *at = recurrsive_find(target, iter);
428  }
429 }
430 
442 AttrTable *
443 AttrTable::recurrsive_find(const string &target, Attr_iter *location)
444 {
445  //*location = attr_begin();
446  Attr_iter i = attr_begin();
447  while (i != attr_end()) {
448  if (target == (*i)->name) {
449  *location = i;
450  return this;
451  }
452  else if ((*i)->type == Attr_container) {
453  AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
454  if (at)
455  return at;
456  }
457 
458  ++i;
459  }
460 
461  *location = i;
462  return 0;
463 }
464 
465 // Made public for callers that want non-recursive find. [mjohnson 6 oct 09]
473 AttrTable::simple_find(const string &target)
474 {
475  Attr_iter i;
476  for (i = attr_map.begin(); i != attr_map.end(); ++i) {
477  if (target == (*i)->name) {
478  break;
479  }
480  }
481  return i;
482 }
483 
497 AttrTable *
498 AttrTable::find_container(const string &target)
499 {
500  string::size_type dotpos = target.find('.');
501  if (dotpos != string::npos) {
502  string container = target.substr(0, dotpos);
503  string field = target.substr(dotpos + 1);
504 
505  AttrTable *at = simple_find_container(container);
506  return (at) ? at->find_container(field) : 0;
507  }
508  else {
509  return simple_find_container(target);
510  }
511 }
512 
513 // Made public for callers that want non-recursive find. [mjohnson 6 oct 09]
514 AttrTable *
515 AttrTable::simple_find_container(const string &target)
516 {
517  if (get_name() == target)
518  return this;
519 
520  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
521  if (is_container(i) && target == (*i)->name) {
522  return (*i)->attributes;
523  }
524  }
525 
526  return 0;
527 }
528 
536 
538 AttrTable *
539 AttrTable::get_attr_table(const string &name)
540 {
541  return find_container(name);
542 }
543 
545 string
546 AttrTable::get_type(const string &name)
547 {
548  Attr_iter p = simple_find(name);
549  return (p != attr_map.end()) ? get_type(p) : (string)"";
550 }
551 
554 AttrType
555 AttrTable::get_attr_type(const string &name)
556 {
557  Attr_iter p = simple_find(name);
558  return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown;
559 }
560 
568 unsigned int
569 AttrTable::get_attr_num(const string &name)
570 {
571  Attr_iter iter = simple_find(name);
572  return (iter != attr_map.end()) ? get_attr_num(iter) : 0;
573 }
574 
587 vector<string> *
588 AttrTable::get_attr_vector(const string &name)
589 {
590  Attr_iter p = simple_find(name);
591  return (p != attr_map.end()) ? get_attr_vector(p) : 0;
592 }
593 
610 void
611 AttrTable::del_attr(const string &name, int i)
612 {
613  string lname = www2id(name);
614 
615  Attr_iter iter = simple_find(lname);
616  if (iter != attr_map.end()) {
617  if (i == -1) { // Delete the whole attribute
618  entry *e = *iter;
619  attr_map.erase(iter);
620  delete e; e = 0;
621  }
622  else { // Delete one element from attribute array
623  // Don't try to delete elements from the vector of values if the
624  // map is a container!
625  if ((*iter)->type == Attr_container)
626  return;
627 
628  vector<string> *sxp = (*iter)->attr;
629 
630  assert(i >= 0 && i < (int)sxp->size());
631  sxp->erase(sxp->begin() + i); // rm the element
632  }
633  }
634 }
635 
637 
644 {
645  return attr_map.begin();
646 }
647 
653 {
654  return attr_map.end();
655 }
656 
667 {
668  return attr_map.begin() + i;
669 }
670 
672 string
674 {
675  assert(iter != attr_map.end());
676 
677  return (*iter)->name;
678 }
679 
681 bool
683 {
684  return (*i)->type == Attr_container;
685 }
686 
692 AttrTable *
694 {
695  assert(iter != attr_map.end());
696  return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
697 }
698 
709 {
710  if ((*iter)->type != Attr_container)
711  return ++iter;
712 
713  // the caller intends to delete/reuse the contained AttrTable,
714  // so zero it out so it doesn't get deleted before we delete the entry
715  // [mjohnson]
716  struct entry* e = *iter;
717  // container no longer has a parent.
718  if (e->attributes) {
719  e->attributes->d_parent = 0;
720  }
721  e->attributes = 0;
722  delete e;
723 
724  return attr_map.erase(iter);
725 }
726 
730 string
732 {
733  assert(iter != attr_map.end());
734  return AttrType_to_String((*iter)->type);
735 }
736 
740 AttrType
742 {
743  return (*iter)->type;
744 }
745 
753 unsigned int
755 {
756  assert(iter != attr_map.end());
757  return ((*iter)->type == Attr_container)
758  ? (*iter)->attributes->get_size()
759  : (*iter)->attr->size();
760 }
761 
778 string
779 AttrTable::get_attr(Attr_iter iter, unsigned int i)
780 {
781  assert(iter != attr_map.end());
782 #if 1
783  return (*iter)->type == Attr_container ? (string)"None" : (*(*iter)->attr)[i];
784 #else
785  if ((*iter)->type == Attr_container) {
786  return "None";
787  }
788  else {
789  cerr << "(*iter)->attr: " << (*iter)->attr << endl;
790  cerr << "(*iter)->name: " << (*iter)->name << endl;
791  cerr << "(*iter)->type: " << (*iter)->type << endl;
792  //cerr << "get_attr: return value: [" << i << "]: " << (*(*iter)->attr)[i]<< endl;
793  if ((*iter)->name == "SIS_ID")
794  return "SIS_ID_value";
795  else
796  return (*(*iter)->attr)[i];
797  }
798 #endif
799 }
800 
801 string
802 AttrTable::get_attr(const string &name, unsigned int i)
803 {
804  Attr_iter p = simple_find(name);
805  return (p != attr_map.end()) ? get_attr(p, i) : (string)"";
806 }
807 
819 vector<string> *
821 {
822  assert(iter != attr_map.end());
823  return (*iter)->type != Attr_container ? (*iter)->attr : 0;
824 }
825 
826 bool
828 {
829  assert(iter != attr_map.end());
830  if ((*iter)->type == Attr_container)
831  return (*iter)->attributes->is_global_attribute();
832  else
833  return (*iter)->is_global;
834 }
835 
836 void
838 {
839  assert(iter != attr_map.end());
840  if ((*iter)->type == Attr_container)
841  (*iter)->attributes->set_is_global_attribute(ga);
842  else
843  (*iter)->is_global = ga;
844 }
845 
847 
848 // Alias an attribute table. The alias should be added to this object.
854 void
855 AttrTable::add_container_alias(const string &name, AttrTable *src)
856 {
857  string lname = www2id(name);
858 
859  if (simple_find(lname) != attr_end())
860  throw Error(string("There already exists a container called `")
861  + name + string("in this attribute table."));
862 
863  entry *e = new entry;
864  e->name = lname;
865  e->is_alias = true;
866  e->aliased_to = src->get_name();
867  e->type = Attr_container;
868 
869  e->attributes = src;
870 
871  attr_map.push_back(e);
872 }
873 
886 void
887 AttrTable::add_value_alias(AttrTable *das, const string &name,
888  const string &source)
889 {
890  string lname = www2id(name);
891  string lsource = www2id(source);
892 
893  // find the container that holds source and its (sources's) iterator
894  // within that container. Search at the uppermost level of the attribute
895  // object to find values defined `above' the current container.
896  AttrTable *at;
897  Attr_iter iter;
898  das->find(lsource, &at, &iter);
899 
900  // If source is not found by looking at the topmost level, look in the
901  // current table (i.e., alias z x where x is in the current container
902  // won't be found by looking for `x' at the top level). See test case 26
903  // in das-testsuite.
904  if (!at || (iter == at->attr_end()) || !*iter) {
905  find(lsource, &at, &iter);
906  if (!at || (iter == at->attr_end()) || !*iter)
907  throw Error(string("Could not find the attribute `")
908  + source + string("' in the attribute object."));
909  }
910 
911  // If we've got a value to alias and it's being added at the top level of
912  // the DAS, that's an error.
913  if (at && !at->is_container(iter) && this == das)
914  throw Error(string("A value cannot be aliased to the top level of the DAS;\nOnly containers may be present at that level of the DAS."));
915 
916  if (simple_find(lname) != attr_end())
917  throw Error(string("There already exists a container called `")
918  + name + string("in this attribute table."));
919 
920  entry *e = new entry;
921  e->name = lname;
922  e->is_alias = true;
923  e->aliased_to = lsource;
924  e->type = get_attr_type(iter);
925  if (at && e->type == Attr_container)
926  e->attributes = at->get_attr_table(iter);
927  else
928  e->attr = (*iter)->attr;
929 
930  attr_map.push_back(e);
931 }
932 
933 // Deprecated
952 bool
953 AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name)
954 {
955  add_value_alias(at, alias, name);
956  return true;
957 }
958 
966 bool
967 AttrTable::attr_alias(const string &alias, const string &name)
968 {
969  return attr_alias(alias, this, name);
970 }
971 
975 void
977 {
978  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
979  delete *i; *i = 0;
980  }
981 
982  attr_map.erase(attr_map.begin(), attr_map.end());
983 
984  d_name = "";
985 }
986 
987 const string double_quote = "\"";
988 
989 // This is here as a result of the problem described in ticket #1163 where
990 // the data handlers are adding quotes to string attributes so the DAS will
991 // be printed correctly. But that has the affect of adding the quotes to the
992 // attribute's _value_ not just it's print representation. As part of the fix
993 // I made the code here add the quotes if the handlers are fixed (but not if
994 // handlers are still adding them). The other part of 1163 is to fix all of
995 // the handlers... What this fix means is that attributes whose values really
996 // do contain bracketing quotes might be misunderstood, since we're assuming
997 // those quotes were added by the handlers as a hack to get the output
998 // formatting correct for the DAS. jhrg 7/30/08
999 
1000 static void
1001 write_string_attribute_for_das(ostream &out, const string &value, const string &term)
1002 {
1003  if (is_quoted(value))
1004  out << value << term;
1005  else
1006  out << double_quote << value << double_quote << term;
1007 }
1008 
1009 static void
1010 write_string_attribute_for_das(FILE *out, const string &value, const string &term)
1011 {
1012  if (is_quoted(value))
1013  fprintf(out, "%s%s", value.c_str(), term.c_str());
1014  else
1015  fprintf(out, "\"%s\"%s", value.c_str(), term.c_str());
1016 }
1017 
1018 // Special treatment for XML: Make sure to escape double quotes when XML is
1019 // printed in a DAS.
1020 static void
1021 write_xml_attribute_for_das(ostream &out, const string &value, const string &term)
1022 {
1023  if (is_quoted(value))
1024  out << escape_double_quotes(value) << term;
1025  else
1026  out << double_quote << escape_double_quotes(value) << double_quote << term;
1027 }
1028 
1029 static void
1030 write_xml_attribute_for_das(FILE *out, const string &value, const string &term)
1031 {
1032  if (is_quoted(value))
1033  fprintf(out, "%s%s", escape_double_quotes(value).c_str(), term.c_str());
1034  else
1035  fprintf(out, "\"%s\"%s", escape_double_quotes(value).c_str(), term.c_str());
1036 }
1037 
1040 void
1041 AttrTable::simple_print(FILE *out, string pad, Attr_iter i,
1042  bool dereference)
1043 {
1044  switch ((*i)->type) {
1045  case Attr_container:
1046  fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str());
1047 
1048  (*i)->attributes->print(out, pad + " ", dereference);
1049 
1050  fprintf(out, "%s}\n", pad.c_str());
1051  break;
1052 
1053  case Attr_string: {
1054  fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
1055  id2www(get_name(i)).c_str());
1056 
1057  vector<string> *sxp = (*i)->attr;
1058  vector<string>::iterator last = sxp->end() - 1;
1059  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1060  write_string_attribute_for_das(out, *i, ", ");
1061  }
1062  write_string_attribute_for_das(out, *last, ";\n");
1063  }
1064  break;
1065 
1066  case Attr_other_xml: {
1067  fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
1068  id2www(get_name(i)).c_str());
1069 
1070  vector<string> *sxp = (*i)->attr;
1071  vector<string>::iterator last = sxp->end() - 1;
1072  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1073  write_xml_attribute_for_das(out, *i, ", ");
1074  }
1075  write_xml_attribute_for_das(out, *last, ";\n");
1076  }
1077  break;
1078 
1079  default: {
1080  fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
1081  id2www(get_name(i)).c_str());
1082 
1083  vector<string> *sxp = (*i)->attr;
1084  vector<string>::iterator last = sxp->end() - 1;
1085  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1086  fprintf(out, "%s%s", (*i).c_str(), ", ");
1087  }
1088  fprintf(out, "%s%s", (*last).c_str(), ";\n");
1089  }
1090  break;
1091  }
1092 }
1093 
1096 void
1097 AttrTable::simple_print(ostream &out, string pad, Attr_iter i,
1098  bool dereference)
1099 {
1100  switch ((*i)->type) {
1101  case Attr_container:
1102  out << pad << id2www(get_name(i)) << " {\n";
1103 
1104  (*i)->attributes->print(out, pad + " ", dereference);
1105 
1106  out << pad << "}\n";
1107  break;
1108 
1109  case Attr_string: {
1110  out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
1111 
1112  vector<string> *sxp = (*i)->attr;
1113  vector<string>::iterator last = sxp->end() - 1;
1114  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1115  write_string_attribute_for_das(out, *i, ", ");
1116  }
1117  write_string_attribute_for_das(out, *last, ";\n");
1118  }
1119  break;
1120 
1121  case Attr_other_xml: {
1122  out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
1123 
1124  vector<string> *sxp = (*i)->attr;
1125  vector<string>::iterator last = sxp->end() - 1;
1126  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1127  write_xml_attribute_for_das(out, *i, ", ");
1128  }
1129  write_xml_attribute_for_das(out, *last, ";\n");
1130  }
1131  break;
1132 
1133  default: {
1134  out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
1135 
1136  vector<string> *sxp = (*i)->attr;
1137  vector<string>::iterator last = sxp->end() - 1;
1138  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1139  out << *i <<", ";
1140  }
1141  out << *last << ";\n";
1142  }
1143  break;
1144  }
1145 }
1146 
1157 void
1158 AttrTable::print(FILE *out, string pad, bool dereference)
1159 {
1160  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1161  if ((*i)->is_alias) {
1162  if (dereference) {
1163  simple_print(out, pad, i, dereference);
1164  }
1165  else {
1166  fprintf(out, "%sAlias %s %s;\n",
1167  pad.c_str(),
1168  id2www(get_name(i)).c_str(),
1169  id2www((*i)->aliased_to).c_str());
1170  }
1171  }
1172  else {
1173  simple_print(out, pad, i, dereference);
1174  }
1175  }
1176 }
1177 
1188 void
1189 AttrTable::print(ostream &out, string pad, bool dereference)
1190 {
1191  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1192  if ((*i)->is_alias) {
1193  if (dereference) {
1194  simple_print(out, pad, i, dereference);
1195  }
1196  else {
1197  out << pad << "Alias " << id2www(get_name(i))
1198  << " " << id2www((*i)->aliased_to) << ";\n";
1199  }
1200  }
1201  else {
1202  simple_print(out, pad, i, dereference);
1203  }
1204  }
1205 }
1206 
1211 void
1212 AttrTable::print_xml(FILE *out, string pad, bool /*constrained*/)
1213 {
1214  // Why this works: AttrTable is really a hacked class that used to
1215  // implement a single-level set of attributes. Containers
1216  // were added several years later by dropping in the 'entry' structure.
1217  // It's not a class in its own right; instead accessors from AttrTable
1218  // are used to access information from entry. So... the loop below
1219  // actually iterates over the entries of *this* (which is an instance of
1220  // AttrTable). A container is an entry whose sole value is an AttrTable
1221  // instance. 05/19/03 jhrg
1222  for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
1223  if ((*i)->is_alias) {
1224  fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
1225  pad.c_str(), id2xml(get_name(i)).c_str(),
1226  (*i)->aliased_to.c_str());
1227 
1228  }
1229  else if (is_container(i)) {
1230  fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
1231  pad.c_str(), id2xml(get_name(i)).c_str(),
1232  get_type(i).c_str());
1233 
1234  get_attr_table(i)->print_xml(out, pad + " "/*, constrained*/);
1235 
1236  fprintf(out, "%s</Attribute>\n", pad.c_str());
1237  }
1238  else {
1239  fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
1240  pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
1241 
1242  string value_pad = pad + " ";
1243  // Special handling for the OtherXML attribute type - don't escape
1244  // the XML and don't include the <value> element. Note that there
1245  // cannot be an vector of XML things as can be with the other types.
1246  if (get_attr_type(i) == Attr_other_xml) {
1247  if (get_attr_num(i) != 1)
1248  throw Error("OtherXML attributes cannot be vector-valued.");
1249  fprintf(out, "%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
1250  }
1251  else {
1252  for (unsigned j = 0; j < get_attr_num(i); ++j) {
1253  fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
1254  id2xml(get_attr(i, j)).c_str());
1255  }
1256  }
1257  fprintf(out, "%s</Attribute>\n", pad.c_str());
1258  }
1259  }
1260 }
1261 
1266 void
1267 AttrTable::print_xml(ostream &out, string pad, bool /*constrained*/)
1268 {
1269  for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
1270  if ((*i)->is_alias) {
1271  out << pad << "<Alias name=\"" << id2xml(get_name(i))
1272  << "\" Attribute=\"" << (*i)->aliased_to << "\"/>\n";
1273 
1274  }
1275  else if (is_container(i)) {
1276  out << pad << "<Attribute name=\"" << id2xml(get_name(i))
1277  << "\" type=\"" << get_type(i) << "\">\n";
1278 
1279  get_attr_table(i)->print_xml(out, pad + " "/*, constrained*/);
1280 
1281  out << pad << "</Attribute>\n";
1282  }
1283  else {
1284  out << pad << "<Attribute name=\"" << id2xml(get_name(i))
1285  << "\" type=\"" << get_type(i) << "\">\n";
1286 
1287  string value_pad = pad + " ";
1288  if (get_attr_type(i) == Attr_other_xml) {
1289  if (get_attr_num(i) != 1)
1290  throw Error("OtherXML attributes cannot be vector-valued.");
1291  out << value_pad << get_attr(i, 0) << "\n";
1292  }
1293  else {
1294  string value_pad = pad + " ";
1295  for (unsigned j = 0; j < get_attr_num(i); ++j) {
1296  out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n";
1297  }
1298  }
1299  out << pad << "</Attribute>\n";
1300  }
1301  }
1302 }
1303 
1311 void
1312 AttrTable::dump(ostream &strm) const
1313 {
1314  strm << DapIndent::LMarg << "AttrTable::dump - ("
1315  << (void *)this << ")" << endl;
1317  strm << DapIndent::LMarg << "table name: " << d_name << endl;
1318  if (attr_map.size()) {
1319  strm << DapIndent::LMarg << "attributes: " << endl;
1321  Attr_citer i = attr_map.begin();
1322  Attr_citer ie = attr_map.end();
1323  for (; i != ie; ++i) {
1324  entry *e = (*i);
1325  string type = AttrType_to_String(e->type);
1326  if (e->is_alias) {
1327  strm << DapIndent::LMarg << "alias: " << e->name
1328  << " aliased to: " << e->aliased_to
1329  << endl;
1330  }
1331  else if (e->type == Attr_container) {
1332  strm << DapIndent::LMarg << "attr: " << e->name
1333  << " of type " << type
1334  << endl;
1336  e->attributes->dump(strm);
1338  }
1339  else {
1340  strm << DapIndent::LMarg << "attr: " << e->name
1341  << " of type " << type
1342  << endl;
1344  strm << DapIndent::LMarg;
1345  vector<string>::const_iterator iter = e->attr->begin();
1346  vector<string>::const_iterator last = e->attr->end() - 1;
1347  for (; iter != last; ++iter) {
1348  strm << (*iter) << ", ";
1349  }
1350  strm << (*(e->attr->end() - 1)) << endl;
1352  }
1353  }
1355  }
1356  else {
1357  strm << DapIndent::LMarg << "attributes: empty" << endl;
1358  }
1359  if (d_parent) {
1360  strm << DapIndent::LMarg << "parent table:"
1361  << d_name << ":" << (void *)d_parent << endl;
1362  }
1363  else {
1364  strm << DapIndent::LMarg << "parent table: none" << d_name << endl;
1365  }
1367 }
1368 
1369 } // namespace libdap
1370 
std::vector< entry * >::iterator Attr_iter
Definition: AttrTable.h:233
static void UnIndent()
Definition: DapIndent.cc:49
virtual Attr_iter attr_end()
Definition: AttrTable.cc:652
void downcase(string &s)
Definition: util.cc:367
Contains the attributes for a dataset.
Definition: AttrTable.h:146
#define not_used
Definition: config.h:850
string AttrType_to_String(const AttrType at)
Definition: AttrTable.cc:59
virtual string get_type(const string &name)
Get the type name of an attribute within this attribute table.
Definition: AttrTable.cc:546
void clone(const AttrTable &at)
Definition: AttrTable.cc:122
virtual void add_container_alias(const string &name, AttrTable *src)
Add an alias to a container held by this attribute table.
Definition: AttrTable.cc:855
virtual void print_xml(FILE *out, string pad=" ", bool constrained=false)
Definition: AttrTable.cc:1212
virtual ~AttrTable()
Definition: AttrTable.cc:176
virtual bool is_global_attribute() const
Definition: AttrTable.h:280
string id2xml(string in, const string &not_allowed)
Definition: escaping.cc:270
virtual string get_attr(const string &name, unsigned int i=0)
Definition: AttrTable.cc:802
virtual void del_attr(const string &name, int i=-1)
Deletes an attribute.
Definition: AttrTable.cc:611
string escape_double_quotes(string source)
Definition: escaping.cc:468
virtual void set_is_global_attribute(bool ga)
Definition: AttrTable.h:281
virtual AttrTable * recurrsive_find(const string &target, Attr_iter *location)
Definition: AttrTable.cc:443
const string double_quote
Definition: AttrTable.cc:987
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
Definition: AttrTable.cc:1158
virtual AttrTable * find_container(const string &target)
Find an attribute with a given name.
Definition: AttrTable.cc:498
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:208
AttrTable & operator=(const AttrTable &rhs)
Definition: AttrTable.cc:183
AttrTable * attributes
Definition: AttrTable.h:167
virtual Attr_iter get_attr_iter(int i)
Definition: AttrTable.cc:666
#define DBG(x)
Definition: debug.h:58
virtual void add_value_alias(AttrTable *at, const string &name, const string &source)
Add an alias for an attribute.
Definition: AttrTable.cc:887
virtual bool is_container(Attr_iter iter)
Definition: AttrTable.cc:682
AttrType String_to_AttrType(const string &s)
Definition: AttrTable.cc:89
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition: AttrTable.cc:342
static void Indent()
Definition: DapIndent.cc:43
AttrTable * simple_find_container(const string &target)
Definition: AttrTable.cc:515
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
Definition: AttrTable.cc:539
virtual void erase()
Erase the attribute table.
Definition: AttrTable.cc:976
bool is_quoted(const string &s)
Definition: util.cc:374
virtual bool attr_alias(const string &alias, AttrTable *at, const string &name)
Adds an alias to the set of attributes.
Definition: AttrTable.cc:953
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:643
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:218
std::vector< entry * >::const_iterator Attr_citer
Definition: AttrTable.h:232
virtual unsigned int get_attr_num(const string &name)
Get the number of attributes in this container.
Definition: AttrTable.cc:569
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
Definition: AttrTable.cc:239
libdap base object for common functionality of libdap objects
Definition: DapObj.h:55
void simple_print(FILE *out, string pad, Attr_iter i, bool dereference)
Definition: AttrTable.cc:1041
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
Definition: AttrTable.cc:555
virtual void dump(ostream &strm) const
dumps information about this object
Definition: AttrTable.cc:1312
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
Definition: AttrTable.cc:588
A class for error processing.
Definition: Error.h:90
virtual void set_name(const string &n)
Set the name of this attribute table.
Definition: AttrTable.cc:216
std::vector< string > * attr
Definition: AttrTable.h:168
virtual Attr_iter del_attr_table(Attr_iter iter)
Definition: AttrTable.cc:708
virtual void find(const string &target, AttrTable **at, Attr_iter *iter)
Definition: AttrTable.cc:411
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
Definition: AttrTable.cc:200
AttrType
Definition: AttrTable.h:77
string id2www(string in, const string &allowable)
Definition: escaping.cc:151
Attr_iter simple_find(const string &target)
Definition: AttrTable.cc:473