libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1994-1999 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 // jhrg 7/29/94 00033 00034 #include "config.h" 00035 00036 static char rcsid[] not_used = "$Id: AttrTable.cc 19707 2008-10-08 18:29:21Z jimg $"; 00037 00038 #include <cassert> 00039 00040 #include "AttrTable.h" 00041 00042 #include "util.h" 00043 #include "escaping.h" 00044 00045 #include "debug.h" 00046 00047 using std::cerr; 00048 using std::string; 00049 using std::endl; 00050 using std::vector; 00051 00052 namespace libdap { 00053 00057 string 00058 AttrType_to_String(const AttrType at) 00059 { 00060 switch (at) { 00061 case Attr_container: return "Container"; 00062 case Attr_byte: return "Byte"; 00063 case Attr_int16: return "Int16"; 00064 case Attr_uint16: return "UInt16"; 00065 case Attr_int32: return "Int32"; 00066 case Attr_uint32: return "UInt32"; 00067 case Attr_float32: return "Float32"; 00068 case Attr_float64: return "Float64"; 00069 case Attr_string: return "String"; 00070 case Attr_url: return "Url"; 00071 default: return ""; 00072 } 00073 } 00074 00075 AttrType 00076 String_to_AttrType(const string &s) 00077 { 00078 string s2 = s; 00079 downcase(s2); 00080 00081 if (s2 == "container") 00082 return Attr_container; 00083 else if (s2 == "byte") 00084 return Attr_byte; 00085 else if (s2 == "int16") 00086 return Attr_int16; 00087 else if (s2 == "uint16") 00088 return Attr_uint16; 00089 else if (s2 == "int32") 00090 return Attr_int32; 00091 else if (s2 == "uint32") 00092 return Attr_uint32; 00093 else if (s2 == "float32") 00094 return Attr_float32; 00095 else if (s2 == "float64") 00096 return Attr_float64; 00097 else if (s2 == "string") 00098 return Attr_string; 00099 else if (s2 == "url") 00100 return Attr_url; 00101 else 00102 return Attr_unknown; 00103 } 00104 00107 void 00108 AttrTable::clone(const AttrTable &at) 00109 { 00110 d_name = at.d_name; 00111 00112 Attr_citer i = at.attr_map.begin() ; 00113 Attr_citer ie = at.attr_map.end() ; 00114 for (; i != ie; i++) { 00115 entry *e = new entry(*(*i)) ; 00116 attr_map.push_back(e) ; 00117 } 00118 00119 d_parent = at.d_parent; 00120 } 00121 00125 AttrTable::AttrTable() : d_name(""), d_parent(0) 00126 {} 00127 00128 AttrTable::AttrTable(const AttrTable &rhs) : DapObj() 00129 { 00130 clone(rhs); 00131 } 00132 00133 // Private 00134 void 00135 AttrTable::delete_attr_table() 00136 { 00137 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) { 00138 delete *i; *i = 0; 00139 } 00140 } 00141 00142 AttrTable::~AttrTable() 00143 { 00144 DBG(cerr << "Entering ~AttrTable (" << this << ")" << endl); 00145 delete_attr_table(); 00146 DBG(cerr << "Exiting ~AttrTable" << endl); 00147 } 00148 00149 AttrTable & 00150 AttrTable::operator=(const AttrTable &rhs) 00151 { 00152 if (this != &rhs) { 00153 delete_attr_table(); 00154 clone(rhs); 00155 } 00156 00157 return *this; 00158 } 00160 00166 unsigned int 00167 AttrTable::get_size() const 00168 { 00169 return attr_map.size(); 00170 } 00171 00174 string 00175 AttrTable::get_name() const 00176 { 00177 return d_name; 00178 } 00179 00182 void 00183 AttrTable::set_name(const string &n) 00184 { 00185 d_name = www2id(n); 00186 } 00187 00205 unsigned int 00206 AttrTable::append_attr(const string &name, const string &type, 00207 const string &attribute) 00208 { 00209 string lname = www2id(name); 00210 00211 Attr_iter iter = simple_find(lname) ; 00212 00213 // If the types don't match OR this attribute is a container, calling 00214 // this mfunc is an error! 00215 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type))) 00216 throw Error(string("An attribute called `") + name 00217 + string("' already exists but is of a different type")); 00218 if (iter != attr_map.end() && (get_type(iter) == "Container")) 00219 throw Error(string("An attribute called `") + name 00220 + string("' already exists but is a container.")); 00221 00222 if (iter != attr_map.end()) { // Must be a new attribute value; add it. 00223 (*iter)->attr->push_back(attribute); 00224 return (*iter)->attr->size(); 00225 } 00226 else { // Must be a completely new attribute; add it 00227 entry *e = new entry; 00228 00229 e->name = lname; 00230 e->is_alias = false; 00231 e->type = String_to_AttrType(type); // Record type using standard names. 00232 e->attr = new vector<string>; 00233 e->attr->push_back(attribute); 00234 00235 attr_map.push_back(e); 00236 00237 return e->attr->size(); // return the length of the attr vector 00238 } 00239 } 00240 00258 unsigned int 00259 AttrTable::append_attr(const string &name, const string &type, 00260 vector<string> *values) 00261 { 00262 string lname = www2id(name); 00263 00264 Attr_iter iter = simple_find(lname) ; 00265 00266 // If the types don't match OR this attribute is a container, calling 00267 // this mfunc is an error! 00268 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type))) 00269 throw Error(string("An attribute called `") + name 00270 + string("' already exists but is of a different type")); 00271 if (iter != attr_map.end() && (get_type(iter) == "Container")) 00272 throw Error(string("An attribute called `") + name 00273 + string("' already exists but is a container.")); 00274 00275 if (iter != attr_map.end()) { // Must be new attribute values; add. 00276 vector<string>::iterator i = values->begin(); 00277 while (i != values->end()) 00278 (*iter)->attr->push_back(*i++); 00279 00280 return (*iter)->attr->size(); 00281 } 00282 else { // Must be a completely new attribute; add it 00283 entry *e = new entry; 00284 00285 e->name = lname; 00286 e->is_alias = false; 00287 e->type = String_to_AttrType(type); // Record type using standard names. 00288 e->attr = new vector<string>(*values); 00289 00290 attr_map.push_back(e); 00291 00292 return e->attr->size(); // return the length of the attr vector 00293 } 00294 } 00295 00304 AttrTable * 00305 AttrTable::append_container(const string &name) 00306 { 00307 AttrTable *new_at = new AttrTable ; 00308 AttrTable *ret = NULL ; 00309 try { 00310 ret = append_container(new_at, name) ; 00311 } 00312 catch (Error &e) { 00313 // an error occurred, attribute with that name already exists 00314 delete new_at; new_at = 0; 00315 throw e; 00316 } 00317 return ret; 00318 } 00319 00332 AttrTable * 00333 AttrTable::append_container(AttrTable *at, const string &name) 00334 { 00335 string lname = www2id(name); 00336 00337 if (simple_find(name) != attr_end()) 00338 throw Error(string("There already exists a container called `") 00339 + name + string("' in this attribute table.")); 00340 DBG(cerr << "Setting appended attribute container name to: " 00341 << lname << endl); 00342 at->set_name(lname); 00343 00344 entry *e = new entry; 00345 e->name = lname; 00346 e->is_alias = false; 00347 e->type = Attr_container; 00348 e->attributes = at; 00349 00350 attr_map.push_back(e); 00351 00352 at->d_parent = this; 00353 00354 return e->attributes; 00355 } 00356 00371 void 00372 AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter) 00373 { 00374 string::size_type dotpos = target.rfind('.'); 00375 if (dotpos != string::npos) { 00376 string container = target.substr(0, dotpos); 00377 string field = target.substr(dotpos + 1); 00378 00379 *at = find_container(container) ; 00380 if (*at) { 00381 *iter = (*at)->simple_find(field) ; 00382 } 00383 else { 00384 *iter = attr_map.end() ; 00385 } 00386 } 00387 else { 00388 #if 0 00389 // Replaced this call to simple_find with the call to recursive_find 00390 // so that older code that assumes that attribute names will not need 00391 // to be FQNs works. jhrg 2/9/06 00392 *at = this; 00393 *iter = simple_find(target); 00394 #endif 00395 *at = recurrsive_find(target, iter); 00396 } 00397 } 00398 00410 AttrTable * 00411 AttrTable::recurrsive_find(const string &target, Attr_iter *location) 00412 { 00413 //*location = attr_begin(); 00414 Attr_iter i = attr_begin(); 00415 while (i != attr_end()) { 00416 if (target == (*i)->name) { 00417 *location = i; 00418 return this; 00419 } 00420 else if ((*i)->type == Attr_container) { 00421 AttrTable *at = (*i)->attributes->recurrsive_find(target, location); 00422 if (at) 00423 return at; 00424 } 00425 00426 ++i; 00427 } 00428 00429 *location = i; 00430 return 0; 00431 } 00432 00433 // Private 00440 AttrTable::Attr_iter 00441 AttrTable::simple_find(const string &target) 00442 { 00443 Attr_iter i ; 00444 for (i = attr_map.begin(); i != attr_map.end(); i++) { 00445 if (target == (*i)->name) { 00446 break ; 00447 } 00448 } 00449 return i ; 00450 } 00451 00465 AttrTable * 00466 AttrTable::find_container(const string &target) 00467 { 00468 string::size_type dotpos = target.find('.'); 00469 if (dotpos != string::npos) { 00470 string container = target.substr(0, dotpos); 00471 string field = target.substr(dotpos + 1); 00472 00473 AttrTable *at = simple_find_container(container); 00474 return (at) ? at->find_container(field) : 0; 00475 } 00476 else { 00477 return simple_find_container(target); 00478 } 00479 } 00480 00481 // Private 00482 AttrTable * 00483 AttrTable::simple_find_container(const string &target) 00484 { 00485 if (get_name() == target) 00486 return this; 00487 00488 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) { 00489 if (is_container(i) && target == (*i)->name) { 00490 return (*i)->attributes; 00491 } 00492 } 00493 00494 return 0; 00495 } 00496 00504 00506 AttrTable * 00507 AttrTable::get_attr_table(const string &name) 00508 { 00509 return find_container(name); 00510 } 00511 00513 string 00514 AttrTable::get_type(const string &name) 00515 { 00516 Attr_iter p = simple_find(name); 00517 return (p != attr_map.end()) ? get_type(p) : (string)""; 00518 } 00519 00522 AttrType 00523 AttrTable::get_attr_type(const string &name) 00524 { 00525 Attr_iter p = simple_find(name); 00526 return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown; 00527 } 00528 00536 unsigned int 00537 AttrTable::get_attr_num(const string &name) 00538 { 00539 Attr_iter iter = simple_find(name); 00540 return (iter != attr_map.end()) ? get_attr_num(iter) : 0; 00541 } 00542 00555 vector<string> * 00556 AttrTable::get_attr_vector(const string &name) 00557 { 00558 Attr_iter p = simple_find(name); 00559 return (p != attr_map.end()) ? get_attr_vector(p) : 0; 00560 } 00561 00578 void 00579 AttrTable::del_attr(const string &name, int i) 00580 { 00581 string lname = www2id(name); 00582 00583 Attr_iter iter = simple_find(lname) ; 00584 if (iter != attr_map.end()) { 00585 if (i == -1) { // Delete the whole attribute 00586 entry *e = *iter ; 00587 attr_map.erase(iter) ; 00588 delete e ; e = 0; 00589 } 00590 else { // Delete one element from attribute array 00591 // Don't try to delete elements from the vector of values if the 00592 // map is a container! 00593 if ((*iter)->type == Attr_container) 00594 return; 00595 00596 vector<string> *sxp = (*iter)->attr; 00597 00598 assert(i >= 0 && i < (int)sxp->size()); 00599 sxp->erase(sxp->begin() + i); // rm the element 00600 } 00601 } 00602 } 00603 00605 00610 AttrTable::Attr_iter 00611 AttrTable::attr_begin() 00612 { 00613 return attr_map.begin() ; 00614 } 00615 00619 AttrTable::Attr_iter 00620 AttrTable::attr_end() 00621 { 00622 return attr_map.end() ; 00623 } 00624 00633 AttrTable::Attr_iter 00634 AttrTable::get_attr_iter(int i) 00635 { 00636 return attr_map.begin() + i; 00637 } 00638 00640 string 00641 AttrTable::get_name(Attr_iter iter) 00642 { 00643 assert(iter != attr_map.end()) ; 00644 00645 return (*iter)->name ; 00646 } 00647 00649 bool 00650 AttrTable::is_container(Attr_iter i) 00651 { 00652 return (*i)->type == Attr_container ; 00653 } 00654 00660 AttrTable * 00661 AttrTable::get_attr_table(Attr_iter iter) 00662 { 00663 assert(iter != attr_map.end()) ; 00664 return (*iter)->type == Attr_container ? (*iter)->attributes : 0 ; 00665 } 00666 00674 AttrTable::Attr_iter 00675 AttrTable::del_attr_table(Attr_iter iter) 00676 { 00677 if ((*iter)->type != Attr_container) 00678 return ++iter; 00679 00680 return attr_map.erase(iter); 00681 } 00682 00686 string 00687 AttrTable::get_type(Attr_iter iter) 00688 { 00689 assert(iter != attr_map.end()) ; 00690 return AttrType_to_String((*iter)->type) ; 00691 } 00692 00696 AttrType 00697 AttrTable::get_attr_type(Attr_iter iter) 00698 { 00699 return (*iter)->type ; 00700 } 00701 00709 unsigned int 00710 AttrTable::get_attr_num(Attr_iter iter) 00711 { 00712 assert(iter != attr_map.end()) ; 00713 return ((*iter)->type == Attr_container) 00714 ? (*iter)->attributes->get_size() 00715 : (*iter)->attr->size() ; 00716 } 00717 00734 string 00735 AttrTable::get_attr(Attr_iter iter, unsigned int i) 00736 { 00737 assert(iter != attr_map.end()); 00738 #if 1 00739 return (*iter)->type == Attr_container ? (string)"None" : (*(*iter)->attr)[i]; 00740 #else 00741 if ((*iter)->type == Attr_container) { 00742 return "None"; 00743 } 00744 else { 00745 cerr << "(*iter)->attr: " << (*iter)->attr << endl; 00746 cerr << "(*iter)->name: " << (*iter)->name << endl; 00747 cerr << "(*iter)->type: " << (*iter)->type << endl; 00748 //cerr << "get_attr: return value: [" << i << "]: " << (*(*iter)->attr)[i]<< endl; 00749 if ((*iter)->name == "SIS_ID") 00750 return "SIS_ID_value"; 00751 else 00752 return (*(*iter)->attr)[i]; 00753 } 00754 #endif 00755 } 00756 00757 string 00758 AttrTable::get_attr(const string &name, unsigned int i) 00759 { 00760 Attr_iter p = simple_find(name); 00761 return (p != attr_map.end()) ? get_attr(p, i) : (string)""; 00762 } 00763 00775 vector<string> * 00776 AttrTable::get_attr_vector(Attr_iter iter) 00777 { 00778 assert(iter != attr_map.end()); 00779 return (*iter)->type != Attr_container ? (*iter)->attr : 0; 00780 } 00781 00783 00784 // Alias an attribute table. The alias should be added to this object. 00790 void 00791 AttrTable::add_container_alias(const string &name, AttrTable *src) 00792 { 00793 string lname = www2id(name); 00794 00795 if (simple_find(lname) != attr_end()) 00796 throw Error(string("There already exists a container called `") 00797 + name + string("in this attribute table.")); 00798 00799 entry *e = new entry; 00800 e->name = lname; 00801 e->is_alias = true; 00802 e->aliased_to = src->get_name(); 00803 e->type = Attr_container; 00804 00805 e->attributes = src; 00806 00807 attr_map.push_back(e); 00808 } 00809 00822 void 00823 AttrTable::add_value_alias(AttrTable *das, const string &name, 00824 const string &source) 00825 { 00826 string lname = www2id(name); 00827 string lsource = www2id(source); 00828 00829 // find the container that holds source and its (sources's) iterator 00830 // within that container. Search at the uppermost level of the attribute 00831 // object to find values defined `above' the current container. 00832 AttrTable *at; 00833 Attr_iter iter; 00834 das->find(lsource, &at, &iter); 00835 00836 // If source is not found by looking at the topmost level, look in the 00837 // current table (i.e., alias z x where x is in the current container 00838 // won't be found by looking for `x' at the top level). See test case 26 00839 // in das-testsuite. 00840 if (!at || (iter == at->attr_end()) || !*iter) { 00841 find(lsource, &at, &iter); 00842 if (!at || (iter == at->attr_end()) || !*iter) 00843 throw Error(string("Could not find the attribute `") 00844 + source + string("' in the attribute object.")); 00845 } 00846 00847 // If we've got a value to alias and it's being added at the top level of 00848 // the DAS, that's an error. 00849 if (at && !at->is_container(iter) && this == das) 00850 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.")); 00851 00852 if (simple_find(lname) != attr_end()) 00853 throw Error(string("There already exists a container called `") 00854 + name + string("in this attribute table.")); 00855 00856 entry *e = new entry; 00857 e->name = lname; 00858 e->is_alias = true; 00859 e->aliased_to = lsource; 00860 e->type = get_attr_type(iter); 00861 if (at && e->type == Attr_container) 00862 e->attributes = at->get_attr_table(iter); 00863 else 00864 e->attr = (*iter)->attr; 00865 00866 attr_map.push_back(e); 00867 } 00868 00869 // Deprecated 00888 bool 00889 AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name) 00890 { 00891 add_value_alias(at, alias, name); 00892 return true; 00893 } 00894 00902 bool 00903 AttrTable::attr_alias(const string &alias, const string &name) 00904 { 00905 return attr_alias(alias, this, name); 00906 } 00907 00911 void 00912 AttrTable::erase() 00913 { 00914 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) { 00915 delete *i; *i = 0; 00916 } 00917 00918 attr_map.erase(attr_map.begin(), attr_map.end()); 00919 00920 d_name = ""; 00921 } 00922 00923 00924 const string double_quote = "\""; 00925 00926 // This is here as a result of the problem described in ticket #1163 where 00927 // the data handlers are adding quotes to string attributes so the DAS will 00928 // be printed correctly. But that has the affect of adding the quoted to the 00929 // attribute's _value_ not just it's print representation. As part of the fix 00930 // I made the code here add the quotes if the handlers are fixed (but not if 00931 // handlers are still adding them). The other part of 1163 is to fix all of 00932 // the handlers... What this fix means is that attributes whose values really 00933 // do contain bracketing quotes might be misunderstood, since we're assuming 00934 // those quotes were added by the handlers as a hack to get the output 00935 // formatting correct for the DAS. jhrg 7/30/08 00936 static void 00937 write_string_attribute_for_das(ostream &out, const string &value, const string &term) 00938 { 00939 if (is_quoted(value)) 00940 out << value << term; 00941 else 00942 out << double_quote << value << double_quote << term; 00943 } 00944 00945 static void 00946 write_string_attribute_for_das(FILE *out, const string &value, const string &term) 00947 { 00948 if (is_quoted(value)) 00949 fprintf(out, "%s%s", value.c_str(), term.c_str()); 00950 else 00951 fprintf(out, "\"%s\"%s", value.c_str(), term.c_str()); 00952 } 00953 00954 00957 void 00958 AttrTable::simple_print(FILE *out, string pad, Attr_iter i, 00959 bool dereference) 00960 { 00961 switch ((*i)->type) { 00962 case Attr_container: 00963 fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str()); 00964 00965 (*i)->attributes->print(out, pad + " ", dereference); 00966 00967 fprintf(out, "%s}\n", pad.c_str()); 00968 break; 00969 00970 case Attr_string: { 00971 fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), 00972 id2www(get_name(i)).c_str()); 00973 00974 vector<string> *sxp = (*i)->attr; 00975 vector<string>::iterator last = sxp->end() - 1; 00976 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) { 00977 write_string_attribute_for_das(out, *i, ", "); 00978 } 00979 write_string_attribute_for_das(out, *last, ";\n"); 00980 } 00981 break; 00982 00983 default: { 00984 fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), 00985 id2www(get_name(i)).c_str()); 00986 00987 vector<string> *sxp = (*i)->attr; 00988 vector<string>::iterator last = sxp->end() - 1; 00989 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) { 00990 fprintf(out, "%s%s", (*i).c_str(), ", "); 00991 } 00992 fprintf(out, "%s%s", (*last).c_str(), ";\n"); 00993 } 00994 break; 00995 } 00996 } 00997 01000 void 01001 AttrTable::simple_print(ostream &out, string pad, Attr_iter i, 01002 bool dereference) 01003 { 01004 switch ((*i)->type) { 01005 case Attr_container: 01006 out << pad << id2www(get_name(i)) << " {\n"; 01007 01008 (*i)->attributes->print(out, pad + " ", dereference); 01009 01010 out << pad << "}\n"; 01011 break; 01012 01013 case Attr_string: { 01014 out << pad << get_type(i) << " " << id2www(get_name(i)) << " "; 01015 01016 vector<string> *sxp = (*i)->attr; 01017 vector<string>::iterator last = sxp->end() - 1; 01018 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) { 01019 write_string_attribute_for_das(out, *i, ", "); 01020 } 01021 write_string_attribute_for_das(out, *last, ";\n"); 01022 } 01023 break; 01024 01025 default: { 01026 out << pad << get_type(i) << " " << id2www(get_name(i)) << " "; 01027 01028 vector<string> *sxp = (*i)->attr; 01029 vector<string>::iterator last = sxp->end() - 1; 01030 for (vector<string>::iterator i = sxp->begin(); i != last; ++i) { 01031 out << *i <<", "; 01032 } 01033 out << *last << ";\n"; 01034 } 01035 break; 01036 } 01037 } 01038 01049 void 01050 AttrTable::print(FILE *out, string pad, bool dereference) 01051 { 01052 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) { 01053 if ((*i)->is_alias) { 01054 if (dereference) { 01055 simple_print(out, pad, i, dereference); 01056 } 01057 else { 01058 fprintf(out, "%sAlias %s %s;\n", 01059 pad.c_str(), 01060 id2www(get_name(i)).c_str(), 01061 id2www((*i)->aliased_to).c_str()) ; 01062 } 01063 } 01064 else { 01065 simple_print(out, pad, i, dereference); 01066 } 01067 } 01068 } 01069 01080 void 01081 AttrTable::print(ostream &out, string pad, bool dereference) 01082 { 01083 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) { 01084 if ((*i)->is_alias) { 01085 if (dereference) { 01086 simple_print(out, pad, i, dereference); 01087 } 01088 else { 01089 out << pad << "Alias " << id2www(get_name(i)) 01090 << " " << id2www((*i)->aliased_to) << ";\n"; 01091 } 01092 } 01093 else { 01094 simple_print(out, pad, i, dereference); 01095 } 01096 } 01097 } 01098 01104 void 01105 AttrTable::print_xml(FILE *out, string pad, bool constrained) 01106 { 01107 // Why this works: AttrTable is really a hacked class that used to 01108 // implement a single level, not nested, set of attributes. Containers 01109 // were added several years later by dropping in the 'entry' structure. 01110 // It's not a class in its own right; instead accessors from AttrTable 01111 // are used to access information from entry. So... the loop below 01112 // actually iterates over the entries of *this* (which is an instance of 01113 // AttrTable). A container is an entry whose sole value is an AttrTable 01114 // instance. 05/19/03 jhrg 01115 for (Attr_iter i = attr_begin(); i != attr_end(); ++i) { 01116 // To handle aliases, if constrained, check to see if the aliased 01117 // variable is part of the current projection. If so, then the 01118 // target is going to be sent so just write out the <Alias ...> tag. 01119 // If not, don't write the alias (we should write out the complete 01120 // target AttrTable, but that's not what the Java code does) 01121 if ((*i)->is_alias) { 01122 fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\"/>\n", 01123 pad.c_str(), id2xml(get_name(i)).c_str(), 01124 (*i)->aliased_to.c_str()); 01125 01126 } 01127 else if (is_container(i)) { 01128 fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n", 01129 pad.c_str(), id2xml(get_name(i)).c_str(), 01130 get_type(i).c_str()); 01131 01132 get_attr_table(i)->print_xml(out, pad + " ", constrained); 01133 01134 fprintf(out, "%s</Attribute>\n", pad.c_str()); 01135 } 01136 else { 01137 fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n", 01138 pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str()); 01139 01140 string value_pad = pad + " "; 01141 for (unsigned j = 0; j < get_attr_num(i); ++j) { 01142 fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(), 01143 id2xml(get_attr(i, j)).c_str()); 01144 } 01145 01146 fprintf(out, "%s</Attribute>\n", pad.c_str()); 01147 } 01148 } 01149 } 01150 01156 void 01157 AttrTable::print_xml(ostream &out, string pad, bool constrained) 01158 { 01159 // Why this works: AttrTable is really a hacked class that used to 01160 // implement a single level, not nested, set of attributes. Containers 01161 // were added several years later by dropping in the 'entry' structure. 01162 // It's not a class in its own right; instead accessors from AttrTable 01163 // are used to access information from entry. So... the loop below 01164 // actually iterates over the entries of *this* (which is an instance of 01165 // AttrTable). A container is an entry whose sole value is an AttrTable 01166 // instance. 05/19/03 jhrg 01167 for (Attr_iter i = attr_begin(); i != attr_end(); ++i) { 01168 // To handle aliases, if constrained, check to see if the aliased 01169 // variable is part of the current projection. If so, then the 01170 // target is going to be sent so just write out the <Alias ...> tag. 01171 // If not, don't write the alias (we should write out the complete 01172 // target AttrTable, but that's not what the Java code does) 01173 if ((*i)->is_alias) { 01174 out << pad << "<Alias name=\"" << id2xml(get_name(i)) 01175 << "\" Attribute=\"" << (*i)->aliased_to << "\"/>\n" ; 01176 01177 } 01178 else if (is_container(i)) { 01179 out << pad << "<Attribute name=\"" << id2xml(get_name(i)) 01180 << "\" type=\"" << get_type(i) << "\">\n" ; 01181 01182 get_attr_table(i)->print_xml(out, pad + " ", constrained); 01183 01184 out << pad << "</Attribute>\n" ; 01185 } 01186 else { 01187 out << pad << "<Attribute name=\"" << id2xml(get_name(i)) 01188 << "\" type=\"" << get_type(i) << "\">\n" ; 01189 01190 string value_pad = pad + " "; 01191 for (unsigned j = 0; j < get_attr_num(i); ++j) { 01192 out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n" ; 01193 } 01194 01195 out << pad << "</Attribute>\n" ; 01196 } 01197 } 01198 } 01199 01207 void 01208 AttrTable::dump(ostream &strm) const 01209 { 01210 strm << DapIndent::LMarg << "AttrTable::dump - (" 01211 << (void *)this << ")" << endl ; 01212 DapIndent::Indent() ; 01213 strm << DapIndent::LMarg << "table name: " << d_name << endl ; 01214 if (attr_map.size()) { 01215 strm << DapIndent::LMarg << "attributes: " << endl ; 01216 DapIndent::Indent() ; 01217 Attr_citer i = attr_map.begin() ; 01218 Attr_citer ie = attr_map.end() ; 01219 for (; i != ie; i++) { 01220 entry *e = (*i) ; 01221 string type = AttrType_to_String(e->type) ; 01222 if (e->is_alias) { 01223 strm << DapIndent::LMarg << "alias: " << e->name 01224 << " aliased to: " << e->aliased_to 01225 << endl ; 01226 } 01227 else if (e->type == Attr_container) { 01228 strm << DapIndent::LMarg << "attr: " << e->name 01229 << " of type " << type 01230 << endl ; 01231 DapIndent::Indent() ; 01232 e->attributes->dump(strm) ; 01233 DapIndent::UnIndent() ; 01234 } 01235 else { 01236 strm << DapIndent::LMarg << "attr: " << e->name 01237 << " of type " << type 01238 << endl ; 01239 DapIndent::Indent() ; 01240 strm << DapIndent::LMarg ; 01241 vector<string>::const_iterator iter = e->attr->begin() ; 01242 vector<string>::const_iterator last = e->attr->end() - 1 ; 01243 for (; iter != last; iter++) { 01244 strm << (*iter) << ", " ; 01245 } 01246 strm << (*(e->attr->end() - 1)) << endl ; 01247 DapIndent::UnIndent() ; 01248 } 01249 } 01250 DapIndent::UnIndent() ; 01251 } 01252 else { 01253 strm << DapIndent::LMarg << "attributes: empty" << endl ; 01254 } 01255 if (d_parent) { 01256 strm << DapIndent::LMarg << "parent table:" 01257 << d_name << ":" << (void *)d_parent << endl ; 01258 } 01259 else { 01260 strm << DapIndent::LMarg << "parent table: none" << d_name << endl ; 01261 } 01262 DapIndent::UnIndent() ; 01263 } 01264 01265 } // namespace libdap 01266