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 18315 2008-03-03 20:14:44Z 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 
00926 void
00927 AttrTable::simple_print(FILE *out, string pad, Attr_iter i,
00928                         bool dereference)
00929 {
00930     switch ((*i)->type) {
00931     case Attr_container:
00932         fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str()) ;
00933 
00934         (*i)->attributes->print(out, pad + "    ", dereference);
00935 
00936         fprintf(out, "%s}\n", pad.c_str()) ;
00937         break;
00938 
00939     default: {
00940             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
00941                     id2www(get_name(i)).c_str()) ;
00942 
00943             vector<string> *sxp = (*i)->attr;
00944 
00945             vector<string>::iterator last = sxp->end() - 1;
00946             for (vector<string>::iterator i = sxp->begin(); i != last; ++i)
00947                 fprintf(out, "%s, ", (*i).c_str()) ;
00948 
00949             fprintf(out, "%s;\n", (*(sxp->end() - 1)).c_str()) ;
00950         }
00951         break;
00952     }
00953 }
00954 
00957 void
00958 AttrTable::simple_print(ostream &out, string pad, Attr_iter i,
00959                         bool dereference)
00960 {
00961     switch ((*i)->type) {
00962     case Attr_container:
00963         out << pad << id2www(get_name(i)) << " {\n" ;
00964 
00965         (*i)->attributes->print(out, pad + "    ", dereference);
00966 
00967         out << pad << "}\n" ;
00968         break;
00969 
00970     default: {
00971             out << pad << get_type(i) << " " << id2www(get_name(i)) << " " ;
00972 
00973             vector<string> *sxp = (*i)->attr;
00974 
00975             vector<string>::iterator last = sxp->end() - 1;
00976             for (vector<string>::iterator i = sxp->begin(); i != last; ++i)
00977                 out << (*i) << ", " ;
00978 
00979             out << (*(sxp->end() - 1)) << ";\n" ;
00980         }
00981         break;
00982     }
00983 }
00984 
00995 void
00996 AttrTable::print(FILE *out, string pad, bool dereference)
00997 {
00998     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00999         if ((*i)->is_alias) {
01000             if (dereference) {
01001                 simple_print(out, pad, i, dereference);
01002             }
01003             else {
01004                 fprintf(out, "%sAlias %s %s;\n",
01005                         pad.c_str(),
01006                         id2www(get_name(i)).c_str(),
01007                         id2www((*i)->aliased_to).c_str()) ;
01008             }
01009         }
01010         else {
01011             simple_print(out, pad, i, dereference);
01012         }
01013     }
01014 }
01015 
01026 void
01027 AttrTable::print(ostream &out, string pad, bool dereference)
01028 {
01029     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
01030         if ((*i)->is_alias) {
01031             if (dereference) {
01032                 simple_print(out, pad, i, dereference);
01033             }
01034             else {
01035                 out << pad << "Alias " << id2www(get_name(i))
01036                     << " " << id2www((*i)->aliased_to) << ";\n" ;
01037             }
01038         }
01039         else {
01040             simple_print(out, pad, i, dereference);
01041         }
01042     }
01043 }
01044 
01050 void
01051 AttrTable::print_xml(FILE *out, string pad, bool constrained)
01052 {
01053     // Why this works: AttrTable is really a hacked class that used to
01054     // implement a single level, not nested, set of attributes. Containers
01055     // were added several years later by dropping in the 'entry' structure.
01056     // It's not a class in its own right; instead accessors from AttrTable
01057     // are used to access information from entry. So... the loop below
01058     // actually iterates over the entries of *this* (which is an instance of
01059     // AttrTable). A container is an entry whose sole value is an AttrTable
01060     // instance. 05/19/03 jhrg
01061     for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01062         // To handle aliases, if constrained, check to see if the aliased
01063         // variable is part of the current projection. If so, then the
01064         // target is going to be sent so just write out the <Alias ...> tag.
01065         // If not, don't write the alias (we should write out the complete
01066         // target AttrTable, but that's not what the Java code does)
01067         if ((*i)->is_alias) {
01068             fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\">\n",
01069                     pad.c_str(), id2xml(get_name(i)).c_str(),
01070                     (*i)->aliased_to.c_str());
01071 
01072         }
01073         else if (is_container(i)) {
01074             fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01075                     pad.c_str(), id2xml(get_name(i)).c_str(),
01076                     get_type(i).c_str());
01077 
01078             get_attr_table(i)->print_xml(out, pad + "    ", constrained);
01079 
01080             fprintf(out, "%s</Attribute>\n", pad.c_str());
01081         }
01082         else {
01083             fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01084                     pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
01085 
01086             string value_pad = pad + "    ";
01087             for (unsigned j = 0; j < get_attr_num(i); ++j) {
01088                 fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
01089                         id2xml(get_attr(i, j)).c_str());
01090             }
01091 
01092             fprintf(out, "%s</Attribute>\n", pad.c_str());
01093         }
01094     }
01095 }
01096 
01102 void
01103 AttrTable::print_xml(ostream &out, string pad, bool constrained)
01104 {
01105     // Why this works: AttrTable is really a hacked class that used to
01106     // implement a single level, not nested, set of attributes. Containers
01107     // were added several years later by dropping in the 'entry' structure.
01108     // It's not a class in its own right; instead accessors from AttrTable
01109     // are used to access information from entry. So... the loop below
01110     // actually iterates over the entries of *this* (which is an instance of
01111     // AttrTable). A container is an entry whose sole value is an AttrTable
01112     // instance. 05/19/03 jhrg
01113     for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01114         // To handle aliases, if constrained, check to see if the aliased
01115         // variable is part of the current projection. If so, then the
01116         // target is going to be sent so just write out the <Alias ...> tag.
01117         // If not, don't write the alias (we should write out the complete
01118         // target AttrTable, but that's not what the Java code does)
01119         if ((*i)->is_alias) {
01120             out << pad << "<Alias name=\"" << id2xml(get_name(i))
01121                 << "\" Attribute=\"" << (*i)->aliased_to << "\">\n" ;
01122 
01123         }
01124         else if (is_container(i)) {
01125             out << pad << "<Attribute name=\"" << id2xml(get_name(i))
01126                 << "\" type=\"" << get_type(i) << "\">\n" ;
01127 
01128             get_attr_table(i)->print_xml(out, pad + "    ", constrained);
01129 
01130             out << pad << "</Attribute>\n" ;
01131         }
01132         else {
01133             out << pad << "<Attribute name=\"" << id2xml(get_name(i))
01134                 << "\" type=\"" << get_type(i) << "\">\n" ;
01135 
01136             string value_pad = pad + "    ";
01137             for (unsigned j = 0; j < get_attr_num(i); ++j) {
01138                 out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n" ;
01139             }
01140 
01141             out << pad << "</Attribute>\n" ;
01142         }
01143     }
01144 }
01145 
01153 void
01154 AttrTable::dump(ostream &strm) const
01155 {
01156     strm << DapIndent::LMarg << "AttrTable::dump - ("
01157     << (void *)this << ")" << endl ;
01158     DapIndent::Indent() ;
01159     strm << DapIndent::LMarg << "table name: " << d_name << endl ;
01160     if (attr_map.size()) {
01161         strm << DapIndent::LMarg << "attributes: " << endl ;
01162         DapIndent::Indent() ;
01163         Attr_citer i = attr_map.begin() ;
01164         Attr_citer ie = attr_map.end() ;
01165         for (; i != ie; i++) {
01166             entry *e = (*i) ;
01167             string type = AttrType_to_String(e->type) ;
01168             if (e->is_alias) {
01169                 strm << DapIndent::LMarg << "alias: " << e->name
01170                 << " aliased to: " << e->aliased_to
01171                 << endl ;
01172             }
01173             else if (e->type == Attr_container) {
01174                 strm << DapIndent::LMarg << "attr: " << e->name
01175                 << " of type " << type
01176                 << endl ;
01177                 DapIndent::Indent() ;
01178                 e->attributes->dump(strm) ;
01179                 DapIndent::UnIndent() ;
01180             }
01181             else {
01182                 strm << DapIndent::LMarg << "attr: " << e->name
01183                 << " of type " << type
01184                 << endl ;
01185                 DapIndent::Indent() ;
01186                 strm << DapIndent::LMarg ;
01187                 vector<string>::const_iterator iter = e->attr->begin() ;
01188                 vector<string>::const_iterator last = e->attr->end() - 1 ;
01189                 for (; iter != last; iter++) {
01190                     strm << (*iter) << ", " ;
01191                 }
01192                 strm << (*(e->attr->end() - 1)) << endl ;
01193                 DapIndent::UnIndent() ;
01194             }
01195         }
01196         DapIndent::UnIndent() ;
01197     }
01198     else {
01199         strm << DapIndent::LMarg << "attributes: empty" << endl ;
01200     }
01201     if (d_parent) {
01202         strm << DapIndent::LMarg << "parent table:"
01203         << d_name << ":" << (void *)d_parent << endl ;
01204     }
01205     else {
01206         strm << DapIndent::LMarg << "parent table: none" << d_name << endl ;
01207     }
01208     DapIndent::UnIndent() ;
01209 }
01210 
01211 } // namespace libdap
01212 

Generated on Tue Mar 4 18:01:54 2008 for libdap++ by  doxygen 1.5.1