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 23473 2010-09-01 20:33:22Z mjohnson $";
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 
340 AttrTable *
341 AttrTable::append_container(const string &name)
342 {
343  AttrTable *new_at = new AttrTable;
344  AttrTable *ret = NULL;
345  try {
346  ret = append_container(new_at, name);
347  }
348  catch (Error &e) {
349  // an error occurred, attribute with that name already exists
350  delete new_at; new_at = 0;
351  throw e;
352  }
353  return ret;
354 }
355 
368 AttrTable *
369 AttrTable::append_container(AttrTable *at, const string &name)
370 {
371  string lname = www2id(name);
372 
373  if (simple_find(name) != attr_end())
374  throw Error(string("There already exists a container called `")
375  + name + string("' in this attribute table."));
376  DBG(cerr << "Setting appended attribute container name to: "
377  << lname << endl);
378  at->set_name(lname);
379 
380  entry *e = new entry;
381  e->name = lname;
382  e->is_alias = false;
383  e->type = Attr_container;
384  e->attributes = at;
385 
386  attr_map.push_back(e);
387 
388  at->d_parent = this;
389 
390  return e->attributes;
391 }
392 
407 void
408 AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter)
409 {
410  string::size_type dotpos = target.rfind('.');
411  if (dotpos != string::npos) {
412  string container = target.substr(0, dotpos);
413  string field = target.substr(dotpos + 1);
414 
415  *at = find_container(container);
416  if (*at) {
417  *iter = (*at)->simple_find(field);
418  }
419  else {
420  *iter = attr_map.end();
421  }
422  }
423  else {
424  *at = recurrsive_find(target, iter);
425  }
426 }
427 
439 AttrTable *
440 AttrTable::recurrsive_find(const string &target, Attr_iter *location)
441 {
442  //*location = attr_begin();
443  Attr_iter i = attr_begin();
444  while (i != attr_end()) {
445  if (target == (*i)->name) {
446  *location = i;
447  return this;
448  }
449  else if ((*i)->type == Attr_container) {
450  AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
451  if (at)
452  return at;
453  }
454 
455  ++i;
456  }
457 
458  *location = i;
459  return 0;
460 }
461 
462 // Made public for callers that want non-recursive find. [mjohnson 6 oct 09]
470 AttrTable::simple_find(const string &target)
471 {
472  Attr_iter i;
473  for (i = attr_map.begin(); i != attr_map.end(); ++i) {
474  if (target == (*i)->name) {
475  break;
476  }
477  }
478  return i;
479 }
480 
494 AttrTable *
495 AttrTable::find_container(const string &target)
496 {
497  string::size_type dotpos = target.find('.');
498  if (dotpos != string::npos) {
499  string container = target.substr(0, dotpos);
500  string field = target.substr(dotpos + 1);
501 
502  AttrTable *at = simple_find_container(container);
503  return (at) ? at->find_container(field) : 0;
504  }
505  else {
506  return simple_find_container(target);
507  }
508 }
509 
510 // Made public for callers that want non-recursive find. [mjohnson 6 oct 09]
511 AttrTable *
512 AttrTable::simple_find_container(const string &target)
513 {
514  if (get_name() == target)
515  return this;
516 
517  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
518  if (is_container(i) && target == (*i)->name) {
519  return (*i)->attributes;
520  }
521  }
522 
523  return 0;
524 }
525 
533 
535 AttrTable *
536 AttrTable::get_attr_table(const string &name)
537 {
538  return find_container(name);
539 }
540 
542 string
543 AttrTable::get_type(const string &name)
544 {
545  Attr_iter p = simple_find(name);
546  return (p != attr_map.end()) ? get_type(p) : (string)"";
547 }
548 
551 AttrType
552 AttrTable::get_attr_type(const string &name)
553 {
554  Attr_iter p = simple_find(name);
555  return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown;
556 }
557 
565 unsigned int
566 AttrTable::get_attr_num(const string &name)
567 {
568  Attr_iter iter = simple_find(name);
569  return (iter != attr_map.end()) ? get_attr_num(iter) : 0;
570 }
571 
584 vector<string> *
585 AttrTable::get_attr_vector(const string &name)
586 {
587  Attr_iter p = simple_find(name);
588  return (p != attr_map.end()) ? get_attr_vector(p) : 0;
589 }
590 
607 void
608 AttrTable::del_attr(const string &name, int i)
609 {
610  string lname = www2id(name);
611 
612  Attr_iter iter = simple_find(lname);
613  if (iter != attr_map.end()) {
614  if (i == -1) { // Delete the whole attribute
615  entry *e = *iter;
616  attr_map.erase(iter);
617  delete e; e = 0;
618  }
619  else { // Delete one element from attribute array
620  // Don't try to delete elements from the vector of values if the
621  // map is a container!
622  if ((*iter)->type == Attr_container)
623  return;
624 
625  vector<string> *sxp = (*iter)->attr;
626 
627  assert(i >= 0 && i < (int)sxp->size());
628  sxp->erase(sxp->begin() + i); // rm the element
629  }
630  }
631 }
632 
634 
641 {
642  return attr_map.begin();
643 }
644 
650 {
651  return attr_map.end();
652 }
653 
664 {
665  return attr_map.begin() + i;
666 }
667 
669 string
671 {
672  assert(iter != attr_map.end());
673 
674  return (*iter)->name;
675 }
676 
678 bool
680 {
681  return (*i)->type == Attr_container;
682 }
683 
689 AttrTable *
691 {
692  assert(iter != attr_map.end());
693  return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
694 }
695 
706 {
707  if ((*iter)->type != Attr_container)
708  return ++iter;
709 
710  // the caller intends to delete/reuse the contained AttrTable,
711  // so zero it out so it doesn't get deleted before we delete the entry
712  // [mjohnson]
713  struct entry* e = *iter;
714  // container no longer has a parent.
715  if (e->attributes) {
716  e->attributes->d_parent = 0;
717  }
718  e->attributes = 0;
719  delete e;
720 
721  return attr_map.erase(iter);
722 }
723 
727 string
729 {
730  assert(iter != attr_map.end());
731  return AttrType_to_String((*iter)->type);
732 }
733 
737 AttrType
739 {
740  return (*iter)->type;
741 }
742 
750 unsigned int
752 {
753  assert(iter != attr_map.end());
754  return ((*iter)->type == Attr_container)
755  ? (*iter)->attributes->get_size()
756  : (*iter)->attr->size();
757 }
758 
775 string
776 AttrTable::get_attr(Attr_iter iter, unsigned int i)
777 {
778  assert(iter != attr_map.end());
779 #if 1
780  return (*iter)->type == Attr_container ? (string)"None" : (*(*iter)->attr)[i];
781 #else
782  if ((*iter)->type == Attr_container) {
783  return "None";
784  }
785  else {
786  cerr << "(*iter)->attr: " << (*iter)->attr << endl;
787  cerr << "(*iter)->name: " << (*iter)->name << endl;
788  cerr << "(*iter)->type: " << (*iter)->type << endl;
789  //cerr << "get_attr: return value: [" << i << "]: " << (*(*iter)->attr)[i]<< endl;
790  if ((*iter)->name == "SIS_ID")
791  return "SIS_ID_value";
792  else
793  return (*(*iter)->attr)[i];
794  }
795 #endif
796 }
797 
798 string
799 AttrTable::get_attr(const string &name, unsigned int i)
800 {
801  Attr_iter p = simple_find(name);
802  return (p != attr_map.end()) ? get_attr(p, i) : (string)"";
803 }
804 
816 vector<string> *
818 {
819  assert(iter != attr_map.end());
820  return (*iter)->type != Attr_container ? (*iter)->attr : 0;
821 }
822 
823 bool
825 {
826  assert(iter != attr_map.end());
827  if ((*iter)->type == Attr_container)
828  return (*iter)->attributes->is_global_attribute();
829  else
830  return (*iter)->is_global;
831 }
832 
833 void
835 {
836  assert(iter != attr_map.end());
837  if ((*iter)->type == Attr_container)
838  (*iter)->attributes->set_is_global_attribute(ga);
839  else
840  (*iter)->is_global = ga;
841 }
842 
844 
845 // Alias an attribute table. The alias should be added to this object.
851 void
852 AttrTable::add_container_alias(const string &name, AttrTable *src)
853 {
854  string lname = www2id(name);
855 
856  if (simple_find(lname) != attr_end())
857  throw Error(string("There already exists a container called `")
858  + name + string("in this attribute table."));
859 
860  entry *e = new entry;
861  e->name = lname;
862  e->is_alias = true;
863  e->aliased_to = src->get_name();
864  e->type = Attr_container;
865 
866  e->attributes = src;
867 
868  attr_map.push_back(e);
869 }
870 
883 void
884 AttrTable::add_value_alias(AttrTable *das, const string &name,
885  const string &source)
886 {
887  string lname = www2id(name);
888  string lsource = www2id(source);
889 
890  // find the container that holds source and its (sources's) iterator
891  // within that container. Search at the uppermost level of the attribute
892  // object to find values defined `above' the current container.
893  AttrTable *at;
894  Attr_iter iter;
895  das->find(lsource, &at, &iter);
896 
897  // If source is not found by looking at the topmost level, look in the
898  // current table (i.e., alias z x where x is in the current container
899  // won't be found by looking for `x' at the top level). See test case 26
900  // in das-testsuite.
901  if (!at || (iter == at->attr_end()) || !*iter) {
902  find(lsource, &at, &iter);
903  if (!at || (iter == at->attr_end()) || !*iter)
904  throw Error(string("Could not find the attribute `")
905  + source + string("' in the attribute object."));
906  }
907 
908  // If we've got a value to alias and it's being added at the top level of
909  // the DAS, that's an error.
910  if (at && !at->is_container(iter) && this == das)
911  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."));
912 
913  if (simple_find(lname) != attr_end())
914  throw Error(string("There already exists a container called `")
915  + name + string("in this attribute table."));
916 
917  entry *e = new entry;
918  e->name = lname;
919  e->is_alias = true;
920  e->aliased_to = lsource;
921  e->type = get_attr_type(iter);
922  if (at && e->type == Attr_container)
923  e->attributes = at->get_attr_table(iter);
924  else
925  e->attr = (*iter)->attr;
926 
927  attr_map.push_back(e);
928 }
929 
930 // Deprecated
949 bool
950 AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name)
951 {
952  add_value_alias(at, alias, name);
953  return true;
954 }
955 
963 bool
964 AttrTable::attr_alias(const string &alias, const string &name)
965 {
966  return attr_alias(alias, this, name);
967 }
968 
972 void
974 {
975  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
976  delete *i; *i = 0;
977  }
978 
979  attr_map.erase(attr_map.begin(), attr_map.end());
980 
981  d_name = "";
982 }
983 
984 const string double_quote = "\"";
985 
986 // This is here as a result of the problem described in ticket #1163 where
987 // the data handlers are adding quotes to string attributes so the DAS will
988 // be printed correctly. But that has the affect of adding the quotes to the
989 // attribute's _value_ not just it's print representation. As part of the fix
990 // I made the code here add the quotes if the handlers are fixed (but not if
991 // handlers are still adding them). The other part of 1163 is to fix all of
992 // the handlers... What this fix means is that attributes whose values really
993 // do contain bracketing quotes might be misunderstood, since we're assuming
994 // those quotes were added by the handlers as a hack to get the output
995 // formatting correct for the DAS. jhrg 7/30/08
996 
997 static void
998 write_string_attribute_for_das(ostream &out, const string &value, const string &term)
999 {
1000  if (is_quoted(value))
1001  out << value << term;
1002  else
1003  out << double_quote << value << double_quote << term;
1004 }
1005 
1006 static void
1007 write_string_attribute_for_das(FILE *out, const string &value, const string &term)
1008 {
1009  if (is_quoted(value))
1010  fprintf(out, "%s%s", value.c_str(), term.c_str());
1011  else
1012  fprintf(out, "\"%s\"%s", value.c_str(), term.c_str());
1013 }
1014 
1015 // Special treatment for XML: Make sure to escape double quotes when XML is
1016 // printed in a DAS.
1017 static void
1018 write_xml_attribute_for_das(ostream &out, const string &value, const string &term)
1019 {
1020  if (is_quoted(value))
1021  out << escape_double_quotes(value) << term;
1022  else
1023  out << double_quote << escape_double_quotes(value) << double_quote << term;
1024 }
1025 
1026 static void
1027 write_xml_attribute_for_das(FILE *out, const string &value, const string &term)
1028 {
1029  if (is_quoted(value))
1030  fprintf(out, "%s%s", escape_double_quotes(value).c_str(), term.c_str());
1031  else
1032  fprintf(out, "\"%s\"%s", escape_double_quotes(value).c_str(), term.c_str());
1033 }
1034 
1037 void
1038 AttrTable::simple_print(FILE *out, string pad, Attr_iter i,
1039  bool dereference)
1040 {
1041  switch ((*i)->type) {
1042  case Attr_container:
1043  fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str());
1044 
1045  (*i)->attributes->print(out, pad + " ", dereference);
1046 
1047  fprintf(out, "%s}\n", pad.c_str());
1048  break;
1049 
1050  case Attr_string: {
1051  fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
1052  id2www(get_name(i)).c_str());
1053 
1054  vector<string> *sxp = (*i)->attr;
1055  vector<string>::iterator last = sxp->end() - 1;
1056  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1057  write_string_attribute_for_das(out, *i, ", ");
1058  }
1059  write_string_attribute_for_das(out, *last, ";\n");
1060  }
1061  break;
1062 
1063  case Attr_other_xml: {
1064  fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
1065  id2www(get_name(i)).c_str());
1066 
1067  vector<string> *sxp = (*i)->attr;
1068  vector<string>::iterator last = sxp->end() - 1;
1069  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1070  write_xml_attribute_for_das(out, *i, ", ");
1071  }
1072  write_xml_attribute_for_das(out, *last, ";\n");
1073  }
1074  break;
1075 
1076  default: {
1077  fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
1078  id2www(get_name(i)).c_str());
1079 
1080  vector<string> *sxp = (*i)->attr;
1081  vector<string>::iterator last = sxp->end() - 1;
1082  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1083  fprintf(out, "%s%s", (*i).c_str(), ", ");
1084  }
1085  fprintf(out, "%s%s", (*last).c_str(), ";\n");
1086  }
1087  break;
1088  }
1089 }
1090 
1093 void
1094 AttrTable::simple_print(ostream &out, string pad, Attr_iter i,
1095  bool dereference)
1096 {
1097  switch ((*i)->type) {
1098  case Attr_container:
1099  out << pad << id2www(get_name(i)) << " {\n";
1100 
1101  (*i)->attributes->print(out, pad + " ", dereference);
1102 
1103  out << pad << "}\n";
1104  break;
1105 
1106  case Attr_string: {
1107  out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
1108 
1109  vector<string> *sxp = (*i)->attr;
1110  vector<string>::iterator last = sxp->end() - 1;
1111  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1112  write_string_attribute_for_das(out, *i, ", ");
1113  }
1114  write_string_attribute_for_das(out, *last, ";\n");
1115  }
1116  break;
1117 
1118  case Attr_other_xml: {
1119  out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
1120 
1121  vector<string> *sxp = (*i)->attr;
1122  vector<string>::iterator last = sxp->end() - 1;
1123  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1124  write_xml_attribute_for_das(out, *i, ", ");
1125  }
1126  write_xml_attribute_for_das(out, *last, ";\n");
1127  }
1128  break;
1129 
1130  default: {
1131  out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
1132 
1133  vector<string> *sxp = (*i)->attr;
1134  vector<string>::iterator last = sxp->end() - 1;
1135  for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
1136  out << *i <<", ";
1137  }
1138  out << *last << ";\n";
1139  }
1140  break;
1141  }
1142 }
1143 
1154 void
1155 AttrTable::print(FILE *out, string pad, bool dereference)
1156 {
1157  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1158  if ((*i)->is_alias) {
1159  if (dereference) {
1160  simple_print(out, pad, i, dereference);
1161  }
1162  else {
1163  fprintf(out, "%sAlias %s %s;\n",
1164  pad.c_str(),
1165  id2www(get_name(i)).c_str(),
1166  id2www((*i)->aliased_to).c_str());
1167  }
1168  }
1169  else {
1170  simple_print(out, pad, i, dereference);
1171  }
1172  }
1173 }
1174 
1185 void
1186 AttrTable::print(ostream &out, string pad, bool dereference)
1187 {
1188  for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1189  if ((*i)->is_alias) {
1190  if (dereference) {
1191  simple_print(out, pad, i, dereference);
1192  }
1193  else {
1194  out << pad << "Alias " << id2www(get_name(i))
1195  << " " << id2www((*i)->aliased_to) << ";\n";
1196  }
1197  }
1198  else {
1199  simple_print(out, pad, i, dereference);
1200  }
1201  }
1202 }
1203 
1208 void
1209 AttrTable::print_xml(FILE *out, string pad, bool /*constrained*/)
1210 {
1211  // Why this works: AttrTable is really a hacked class that used to
1212  // implement a single-level set of attributes. Containers
1213  // were added several years later by dropping in the 'entry' structure.
1214  // It's not a class in its own right; instead accessors from AttrTable
1215  // are used to access information from entry. So... the loop below
1216  // actually iterates over the entries of *this* (which is an instance of
1217  // AttrTable). A container is an entry whose sole value is an AttrTable
1218  // instance. 05/19/03 jhrg
1219  for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
1220  if ((*i)->is_alias) {
1221  fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
1222  pad.c_str(), id2xml(get_name(i)).c_str(),
1223  (*i)->aliased_to.c_str());
1224 
1225  }
1226  else if (is_container(i)) {
1227  fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
1228  pad.c_str(), id2xml(get_name(i)).c_str(),
1229  get_type(i).c_str());
1230 
1231  get_attr_table(i)->print_xml(out, pad + " "/*, constrained*/);
1232 
1233  fprintf(out, "%s</Attribute>\n", pad.c_str());
1234  }
1235  else {
1236  fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
1237  pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
1238 
1239  string value_pad = pad + " ";
1240  // Special handling for the OtherXML attribute type - don't escape
1241  // the XML and don't include the <value> element. Note that there
1242  // cannot be an vector of XML things as can be with the other types.
1243  if (get_attr_type(i) == Attr_other_xml) {
1244  if (get_attr_num(i) != 1)
1245  throw Error("OtherXML attributes cannot be vector-valued.");
1246  fprintf(out, "%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
1247  }
1248  else {
1249  for (unsigned j = 0; j < get_attr_num(i); ++j) {
1250  fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
1251  id2xml(get_attr(i, j)).c_str());
1252  }
1253  }
1254  fprintf(out, "%s</Attribute>\n", pad.c_str());
1255  }
1256  }
1257 }
1258 
1263 void
1264 AttrTable::print_xml(ostream &out, string pad, bool /*constrained*/)
1265 {
1266  for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
1267  if ((*i)->is_alias) {
1268  out << pad << "<Alias name=\"" << id2xml(get_name(i))
1269  << "\" Attribute=\"" << (*i)->aliased_to << "\"/>\n";
1270 
1271  }
1272  else if (is_container(i)) {
1273  out << pad << "<Attribute name=\"" << id2xml(get_name(i))
1274  << "\" type=\"" << get_type(i) << "\">\n";
1275 
1276  get_attr_table(i)->print_xml(out, pad + " "/*, constrained*/);
1277 
1278  out << pad << "</Attribute>\n";
1279  }
1280  else {
1281  out << pad << "<Attribute name=\"" << id2xml(get_name(i))
1282  << "\" type=\"" << get_type(i) << "\">\n";
1283 
1284  string value_pad = pad + " ";
1285  if (get_attr_type(i) == Attr_other_xml) {
1286  if (get_attr_num(i) != 1)
1287  throw Error("OtherXML attributes cannot be vector-valued.");
1288  out << value_pad << get_attr(i, 0) << "\n";
1289  }
1290  else {
1291  string value_pad = pad + " ";
1292  for (unsigned j = 0; j < get_attr_num(i); ++j) {
1293  out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n";
1294  }
1295  }
1296  out << pad << "</Attribute>\n";
1297  }
1298  }
1299 }
1300 
1308 void
1309 AttrTable::dump(ostream &strm) const
1310 {
1311  strm << DapIndent::LMarg << "AttrTable::dump - ("
1312  << (void *)this << ")" << endl;
1314  strm << DapIndent::LMarg << "table name: " << d_name << endl;
1315  if (attr_map.size()) {
1316  strm << DapIndent::LMarg << "attributes: " << endl;
1318  Attr_citer i = attr_map.begin();
1319  Attr_citer ie = attr_map.end();
1320  for (; i != ie; ++i) {
1321  entry *e = (*i);
1322  string type = AttrType_to_String(e->type);
1323  if (e->is_alias) {
1324  strm << DapIndent::LMarg << "alias: " << e->name
1325  << " aliased to: " << e->aliased_to
1326  << endl;
1327  }
1328  else if (e->type == Attr_container) {
1329  strm << DapIndent::LMarg << "attr: " << e->name
1330  << " of type " << type
1331  << endl;
1333  e->attributes->dump(strm);
1335  }
1336  else {
1337  strm << DapIndent::LMarg << "attr: " << e->name
1338  << " of type " << type
1339  << endl;
1341  strm << DapIndent::LMarg;
1342  vector<string>::const_iterator iter = e->attr->begin();
1343  vector<string>::const_iterator last = e->attr->end() - 1;
1344  for (; iter != last; iter++) {
1345  strm << (*iter) << ", ";
1346  }
1347  strm << (*(e->attr->end() - 1)) << endl;
1349  }
1350  }
1352  }
1353  else {
1354  strm << DapIndent::LMarg << "attributes: empty" << endl;
1355  }
1356  if (d_parent) {
1357  strm << DapIndent::LMarg << "parent table:"
1358  << d_name << ":" << (void *)d_parent << endl;
1359  }
1360  else {
1361  strm << DapIndent::LMarg << "parent table: none" << d_name << endl;
1362  }
1364 }
1365 
1366 } // namespace libdap
1367 
std::vector< entry * >::iterator Attr_iter
Definition: AttrTable.h:233
static void UnIndent()
Definition: DapIndent.cc:49
virtual bool is_global_attribute() const
Definition: AttrTable.h:280
virtual Attr_iter attr_end()
Definition: AttrTable.cc:649
void downcase(string &s)
Definition: util.cc:367
Contains the attributes for a dataset.
Definition: AttrTable.h:146
#define not_used
Definition: config.h:521
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:543
void clone(const AttrTable &at)
Definition: AttrTable.cc:122
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:208
virtual void add_container_alias(const string &name, AttrTable *src)
Add an alias to a container held by this attribute table.
Definition: AttrTable.cc:852
virtual void print_xml(FILE *out, string pad=" ", bool constrained=false)
Definition: AttrTable.cc:1209
virtual ~AttrTable()
Definition: AttrTable.cc:176
string id2xml(string in, const string &not_allowed)
Definition: escaping.cc:266
virtual string get_attr(const string &name, unsigned int i=0)
Definition: AttrTable.cc:799
virtual void del_attr(const string &name, int i=-1)
Deletes an attribute.
Definition: AttrTable.cc:608
string escape_double_quotes(string source)
Definition: escaping.cc:464
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:440
const string double_quote
Definition: AttrTable.cc:984
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
Definition: AttrTable.cc:1155
virtual AttrTable * find_container(const string &target)
Find an attribute with a given name.
Definition: AttrTable.cc:495
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:663
#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:884
virtual bool is_container(Attr_iter iter)
Definition: AttrTable.cc:679
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:341
static void Indent()
Definition: DapIndent.cc:43
AttrTable * simple_find_container(const string &target)
Definition: AttrTable.cc:512
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
Definition: AttrTable.cc:536
virtual void erase()
Erase the attribute table.
Definition: AttrTable.cc:973
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:950
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:640
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:214
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:566
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:1038
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
Definition: AttrTable.cc:552
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
Definition: AttrTable.cc:585
A class for error processing.
Definition: Error.h:90
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
Definition: AttrTable.cc:200
virtual void set_name(const string &n)
Set the name of this attribute table.
Definition: AttrTable.cc:216
virtual void dump(ostream &strm) const
dumps information about this object
Definition: AttrTable.cc:1309
std::vector< string > * attr
Definition: AttrTable.h:168
virtual Attr_iter del_attr_table(Attr_iter iter)
Definition: AttrTable.cc:705
virtual void find(const string &target, AttrTable **at, Attr_iter *iter)
Definition: AttrTable.cc:408
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:470