libdap++ Updated for version 3.8.2

AttrTable.cc

Go to the documentation of this file.
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