AttrTable.cc

Go to the documentation of this file.
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 
00025 // (c) COPYRIGHT URI/MIT 1994-1999
00026 // Please read the full copyright statement in the file COPYRIGHT_URI.
00027 //
00028 // Authors:
00029 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00030 
00031 // jhrg 7/29/94
00032 
00033 #include "config.h"
00034 
00035 // #define DODS_DEBUG
00036 
00037 static char rcsid[]not_used =
00038         "$Id: AttrTable.cc 22624 2010-04-30 16:55:58Z jimg $";
00039 
00040 #include <cassert>
00041 
00042 #include "AttrTable.h"
00043 
00044 #include "util.h"
00045 #include "escaping.h"
00046 
00047 #include "debug.h"
00048 
00049 using std::cerr;
00050 using std::string;
00051 using std::endl;
00052 using std::vector;
00053 
00054 namespace libdap {
00055 
00059 string AttrType_to_String(const AttrType at)
00060 {
00061     switch (at) {
00062         case Attr_container:
00063             return "Container";
00064         case Attr_byte:
00065             return "Byte";
00066         case Attr_int16:
00067             return "Int16";
00068         case Attr_uint16:
00069             return "UInt16";
00070         case Attr_int32:
00071             return "Int32";
00072         case Attr_uint32:
00073             return "UInt32";
00074         case Attr_float32:
00075             return "Float32";
00076         case Attr_float64:
00077             return "Float64";
00078         case Attr_string:
00079             return "String";
00080         case Attr_url:
00081             return "Url";
00082         case Attr_other_xml:
00083             return "OtherXML";
00084         default:
00085             return "";
00086     }
00087 }
00088 
00089 AttrType String_to_AttrType(const string &s)
00090 {
00091     string s2 = s;
00092     downcase(s2);
00093 
00094     if (s2 == "container")
00095         return Attr_container;
00096     else if (s2 == "byte")
00097         return Attr_byte;
00098     else if (s2 == "int16")
00099         return Attr_int16;
00100     else if (s2 == "uint16")
00101         return Attr_uint16;
00102     else if (s2 == "int32")
00103         return Attr_int32;
00104     else if (s2 == "uint32")
00105         return Attr_uint32;
00106     else if (s2 == "float32")
00107         return Attr_float32;
00108     else if (s2 == "float64")
00109         return Attr_float64;
00110     else if (s2 == "string")
00111         return Attr_string;
00112     else if (s2 == "url")
00113         return Attr_url;
00114     else if (s2 == "otherxml")
00115         return Attr_other_xml;
00116     else
00117         return Attr_unknown;
00118 }
00119 
00122 void AttrTable::clone(const AttrTable &at)
00123 {
00124     d_name = at.d_name;
00125     d_is_global_attribute = at.d_is_global_attribute;
00126 
00127     // Set the parent to null (no parent, not in container)
00128     // since using at.d_parent is semantically incorrect
00129     // and potentially dangerous.
00130     d_parent = 0;
00131 
00132     Attr_citer i = at.attr_map.begin();
00133     Attr_citer ie = at.attr_map.end();
00134     for (; i != ie; i++) {
00135         // this deep-copies containers recursively
00136         entry *e = new entry(*(*i));
00137         attr_map.push_back(e);
00138 
00139         // If the entry being added was a container,
00140         // set its parent to this to maintain invariant.
00141         if (e->type == Attr_container) {
00142           assert(e->attributes);
00143           e->attributes->d_parent = this;
00144         }
00145     }
00146 }
00147 
00151 AttrTable::AttrTable() :
00152     d_name(""), d_parent(0), d_is_global_attribute(true)
00153 {
00154 }
00155 
00156 AttrTable::AttrTable(const AttrTable &rhs) :
00157     DapObj()
00158 {
00159     clone(rhs);
00160 }
00161 
00162 // Private
00163 void AttrTable::delete_attr_table()
00164 {
00165     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00166         delete *i;
00167         *i = 0;
00168     }
00169 }
00170 
00171 AttrTable::~AttrTable()
00172 {
00173     DBG(cerr << "Entering ~AttrTable (" << this << ")" << endl);
00174     delete_attr_table();DBG(cerr << "Exiting ~AttrTable" << endl);
00175 }
00176 
00177 AttrTable &
00178 AttrTable::operator=(const AttrTable &rhs)
00179 {
00180     if (this != &rhs) {
00181         delete_attr_table();
00182         clone(rhs);
00183     }
00184 
00185     return *this;
00186 }
00188 
00194 unsigned int
00195 AttrTable::get_size() const
00196 {
00197     return attr_map.size();
00198 }
00199 
00202 string
00203 AttrTable::get_name() const
00204 {
00205     return d_name;
00206 }
00207 
00210 void
00211 AttrTable::set_name(const string &n)
00212 {
00213     d_name = www2id(n);
00214 }
00215 
00233 unsigned int
00234 AttrTable::append_attr(const string &name, const string &type,
00235         const string &attribute)
00236 {
00237     DBG(cerr << "Entering AttrTable::append_attr" << endl);
00238     string lname = www2id(name);
00239 
00240     Attr_iter iter = simple_find(lname);
00241 
00242     // If the types don't match OR this attribute is a container, calling
00243     // this mfunc is an error!
00244     if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
00245     throw Error(string("An attribute called `") + name
00246             + string("' already exists but is of a different type"));
00247     if (iter != attr_map.end() && (get_type(iter) == "Container"))
00248     throw Error(string("An attribute called `") + name
00249             + string("' already exists but is a container."));
00250 
00251     if (iter != attr_map.end()) { // Must be a new attribute value; add it.
00252         (*iter)->attr->push_back(attribute);
00253         return (*iter)->attr->size();
00254     }
00255     else { // Must be a completely new attribute; add it
00256         entry *e = new entry;
00257 
00258         e->name = lname;
00259         e->is_alias = false;
00260         e->type = String_to_AttrType(type); // Record type using standard names.
00261         e->attr = new vector<string>;
00262         e->attr->push_back(attribute);
00263 
00264         attr_map.push_back(e);
00265 
00266         return e->attr->size(); // return the length of the attr vector
00267     }
00268 }
00269 
00288 unsigned int
00289 AttrTable::append_attr(const string &name, const string &type,
00290         vector<string> *values)
00291 {
00292     DBG(cerr << "Entering AttrTable::append_attr(..., vector)" << endl);
00293     string lname = www2id(name);
00294 
00295     Attr_iter iter = simple_find(lname);
00296 
00297     // If the types don't match OR this attribute is a container, calling
00298     // this mfunc is an error!
00299     if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
00300     throw Error(string("An attribute called `") + name
00301             + string("' already exists but is of a different type"));
00302     if (iter != attr_map.end() && (get_type(iter) == "Container"))
00303     throw Error(string("An attribute called `") + name
00304             + string("' already exists but is a container."));
00305 
00306     if (iter != attr_map.end()) { // Must be new attribute values; add.
00307         vector<string>::iterator i = values->begin();
00308         while (i != values->end())
00309         (*iter)->attr->push_back(*i++);
00310 
00311         return (*iter)->attr->size();
00312     }
00313     else { // Must be a completely new attribute; add it
00314         entry *e = new entry;
00315 
00316         e->name = lname;
00317         e->is_alias = false;
00318         e->type = String_to_AttrType(type); // Record type using standard names.
00319         e->attr = new vector<string>(*values);
00320 
00321         attr_map.push_back(e);
00322 
00323         return e->attr->size(); // return the length of the attr vector
00324     }
00325 }
00326 
00335 AttrTable *
00336 AttrTable::append_container(const string &name)
00337 {
00338     AttrTable *new_at = new AttrTable;
00339     AttrTable *ret = NULL;
00340     try {
00341         ret = append_container(new_at, name);
00342     }
00343     catch (Error &e) {
00344         // an error occurred, attribute with that name already exists
00345         delete new_at; new_at = 0;
00346         throw e;
00347     }
00348     return ret;
00349 }
00350 
00363 AttrTable *
00364 AttrTable::append_container(AttrTable *at, const string &name)
00365 {
00366     string lname = www2id(name);
00367 
00368     if (simple_find(name) != attr_end())
00369     throw Error(string("There already exists a container called `")
00370             + name + string("' in this attribute table."));
00371     DBG(cerr << "Setting appended attribute container name to: "
00372             << lname << endl);
00373     at->set_name(lname);
00374 
00375     entry *e = new entry;
00376     e->name = lname;
00377     e->is_alias = false;
00378     e->type = Attr_container;
00379     e->attributes = at;
00380 
00381     attr_map.push_back(e);
00382 
00383     at->d_parent = this;
00384 
00385     return e->attributes;
00386 }
00387 
00402 void
00403 AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter)
00404 {
00405     string::size_type dotpos = target.rfind('.');
00406     if (dotpos != string::npos) {
00407         string container = target.substr(0, dotpos);
00408         string field = target.substr(dotpos + 1);
00409 
00410         *at = find_container(container);
00411         if (*at) {
00412             *iter = (*at)->simple_find(field);
00413         }
00414         else {
00415             *iter = attr_map.end();
00416         }
00417     }
00418     else {
00419         *at = recurrsive_find(target, iter);
00420     }
00421 }
00422 
00434 AttrTable *
00435 AttrTable::recurrsive_find(const string &target, Attr_iter *location)
00436 {
00437     //*location = attr_begin();
00438     Attr_iter i = attr_begin();
00439     while (i != attr_end()) {
00440         if (target == (*i)->name) {
00441             *location = i;
00442             return this;
00443         }
00444         else if ((*i)->type == Attr_container) {
00445             AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
00446             if (at)
00447             return at;
00448         }
00449 
00450         ++i;
00451     }
00452 
00453     *location = i;
00454     return 0;
00455 }
00456 
00457 // Made public for callers that want non-recursive find.  [mjohnson 6 oct 09]
00464 AttrTable::Attr_iter
00465 AttrTable::simple_find(const string &target)
00466 {
00467     Attr_iter i;
00468     for (i = attr_map.begin(); i != attr_map.end(); i++) {
00469         if (target == (*i)->name) {
00470             break;
00471         }
00472     }
00473     return i;
00474 }
00475 
00489 AttrTable *
00490 AttrTable::find_container(const string &target)
00491 {
00492     string::size_type dotpos = target.find('.');
00493     if (dotpos != string::npos) {
00494         string container = target.substr(0, dotpos);
00495         string field = target.substr(dotpos + 1);
00496 
00497         AttrTable *at = simple_find_container(container);
00498         return (at) ? at->find_container(field) : 0;
00499     }
00500     else {
00501         return simple_find_container(target);
00502     }
00503 }
00504 
00505 // Made public for callers that want non-recursive find.  [mjohnson 6 oct 09]
00506 AttrTable *
00507 AttrTable::simple_find_container(const string &target)
00508 {
00509     if (get_name() == target)
00510     return this;
00511 
00512     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00513         if (is_container(i) && target == (*i)->name) {
00514             return (*i)->attributes;
00515         }
00516     }
00517 
00518     return 0;
00519 }
00520 
00528 
00530 AttrTable *
00531 AttrTable::get_attr_table(const string &name)
00532 {
00533     return find_container(name);
00534 }
00535 
00537 string
00538 AttrTable::get_type(const string &name)
00539 {
00540     Attr_iter p = simple_find(name);
00541     return (p != attr_map.end()) ? get_type(p) : (string)"";
00542 }
00543 
00546 AttrType
00547 AttrTable::get_attr_type(const string &name)
00548 {
00549     Attr_iter p = simple_find(name);
00550     return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown;
00551 }
00552 
00560 unsigned int
00561 AttrTable::get_attr_num(const string &name)
00562 {
00563     Attr_iter iter = simple_find(name);
00564     return (iter != attr_map.end()) ? get_attr_num(iter) : 0;
00565 }
00566 
00579 vector<string> *
00580 AttrTable::get_attr_vector(const string &name)
00581 {
00582     Attr_iter p = simple_find(name);
00583     return (p != attr_map.end()) ? get_attr_vector(p) : 0;
00584 }
00585 
00602 void
00603 AttrTable::del_attr(const string &name, int i)
00604 {
00605     string lname = www2id(name);
00606 
00607     Attr_iter iter = simple_find(lname);
00608     if (iter != attr_map.end()) {
00609         if (i == -1) { // Delete the whole attribute
00610             entry *e = *iter;
00611             attr_map.erase(iter);
00612             delete e; e = 0;
00613         }
00614         else { // Delete one element from attribute array
00615             // Don't try to delete elements from the vector of values if the
00616             // map is a container!
00617             if ((*iter)->type == Attr_container)
00618             return;
00619 
00620             vector<string> *sxp = (*iter)->attr;
00621 
00622             assert(i >= 0 && i < (int)sxp->size());
00623             sxp->erase(sxp->begin() + i); // rm the element
00624         }
00625     }
00626 }
00627 
00629 
00634 AttrTable::Attr_iter
00635 AttrTable::attr_begin()
00636 {
00637     return attr_map.begin();
00638 }
00639 
00643 AttrTable::Attr_iter
00644 AttrTable::attr_end()
00645 {
00646     return attr_map.end();
00647 }
00648 
00657 AttrTable::Attr_iter
00658 AttrTable::get_attr_iter(int i)
00659 {
00660     return attr_map.begin() + i;
00661 }
00662 
00664 string
00665 AttrTable::get_name(Attr_iter iter)
00666 {
00667     assert(iter != attr_map.end());
00668 
00669     return (*iter)->name;
00670 }
00671 
00673 bool
00674 AttrTable::is_container(Attr_iter i)
00675 {
00676     return (*i)->type == Attr_container;
00677 }
00678 
00684 AttrTable *
00685 AttrTable::get_attr_table(Attr_iter iter)
00686 {
00687     assert(iter != attr_map.end());
00688     return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
00689 }
00690 
00699 AttrTable::Attr_iter
00700 AttrTable::del_attr_table(Attr_iter iter)
00701 {
00702     if ((*iter)->type != Attr_container)
00703     return ++iter;
00704 
00705     // the caller intends to delete/reuse the contained AttrTable,
00706     // so zero it out so it doesn't get deleted before we delete the entry
00707     // [mjohnson]
00708     struct entry* e = *iter;
00709     // container no longer has a parent.
00710     if (e->attributes) {
00711       e->attributes->d_parent = 0;
00712     }
00713     e->attributes = 0;
00714     delete e;
00715 
00716     return attr_map.erase(iter);
00717 }
00718 
00722 string
00723 AttrTable::get_type(Attr_iter iter)
00724 {
00725     assert(iter != attr_map.end());
00726     return AttrType_to_String((*iter)->type);
00727 }
00728 
00732 AttrType
00733 AttrTable::get_attr_type(Attr_iter iter)
00734 {
00735     return (*iter)->type;
00736 }
00737 
00745 unsigned int
00746 AttrTable::get_attr_num(Attr_iter iter)
00747 {
00748     assert(iter != attr_map.end());
00749     return ((*iter)->type == Attr_container)
00750     ? (*iter)->attributes->get_size()
00751     : (*iter)->attr->size();
00752 }
00753 
00770 string
00771 AttrTable::get_attr(Attr_iter iter, unsigned int i)
00772 {
00773     assert(iter != attr_map.end());
00774 #if 1
00775     return (*iter)->type == Attr_container ? (string)"None" : (*(*iter)->attr)[i];
00776 #else
00777     if ((*iter)->type == Attr_container) {
00778         return "None";
00779     }
00780     else {
00781         cerr << "(*iter)->attr: " << (*iter)->attr << endl;
00782         cerr << "(*iter)->name: " << (*iter)->name << endl;
00783         cerr << "(*iter)->type: " << (*iter)->type << endl;
00784         //cerr << "get_attr: return value: [" << i << "]: " << (*(*iter)->attr)[i]<< endl;
00785         if ((*iter)->name == "SIS_ID")
00786         return "SIS_ID_value";
00787         else
00788         return (*(*iter)->attr)[i];
00789     }
00790 #endif
00791 }
00792 
00793 string
00794 AttrTable::get_attr(const string &name, unsigned int i)
00795 {
00796     Attr_iter p = simple_find(name);
00797     return (p != attr_map.end()) ? get_attr(p, i) : (string)"";
00798 }
00799 
00811 vector<string> *
00812 AttrTable::get_attr_vector(Attr_iter iter)
00813 {
00814     assert(iter != attr_map.end());
00815     return (*iter)->type != Attr_container ? (*iter)->attr : 0;
00816 }
00817 
00818 bool
00819 AttrTable::is_global_attribute(Attr_iter iter)
00820 {
00821     assert(iter != attr_map.end());
00822     if ((*iter)->type == Attr_container)
00823         return (*iter)->attributes->is_global_attribute();
00824     else
00825         return (*iter)->is_global;
00826 }
00827 
00828 void
00829 AttrTable::set_is_global_attribute(Attr_iter iter, bool ga)
00830 {
00831     assert(iter != attr_map.end());
00832     if ((*iter)->type == Attr_container)
00833         (*iter)->attributes->set_is_global_attribute(ga);
00834     else
00835         (*iter)->is_global = ga;
00836 }
00837 
00839 
00840 // Alias an attribute table. The alias should be added to this object.
00846 void
00847 AttrTable::add_container_alias(const string &name, AttrTable *src)
00848 {
00849     string lname = www2id(name);
00850 
00851     if (simple_find(lname) != attr_end())
00852     throw Error(string("There already exists a container called `")
00853             + name + string("in this attribute table."));
00854 
00855     entry *e = new entry;
00856     e->name = lname;
00857     e->is_alias = true;
00858     e->aliased_to = src->get_name();
00859     e->type = Attr_container;
00860 
00861     e->attributes = src;
00862 
00863     attr_map.push_back(e);
00864 }
00865 
00878 void
00879 AttrTable::add_value_alias(AttrTable *das, const string &name,
00880         const string &source)
00881 {
00882     string lname = www2id(name);
00883     string lsource = www2id(source);
00884 
00885     // find the container that holds source and its (sources's) iterator
00886     // within that container. Search at the uppermost level of the attribute
00887     // object to find values defined `above' the current container.
00888     AttrTable *at;
00889     Attr_iter iter;
00890     das->find(lsource, &at, &iter);
00891 
00892     // If source is not found by looking at the topmost level, look in the
00893     // current table (i.e., alias z x where x is in the current container
00894     // won't be found by looking for `x' at the top level). See test case 26
00895     // in das-testsuite.
00896     if (!at || (iter == at->attr_end()) || !*iter) {
00897         find(lsource, &at, &iter);
00898         if (!at || (iter == at->attr_end()) || !*iter)
00899         throw Error(string("Could not find the attribute `")
00900                 + source + string("' in the attribute object."));
00901     }
00902 
00903     // If we've got a value to alias and it's being added at the top level of
00904     // the DAS, that's an error.
00905     if (at && !at->is_container(iter) && this == das)
00906     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."));
00907 
00908     if (simple_find(lname) != attr_end())
00909     throw Error(string("There already exists a container called `")
00910             + name + string("in this attribute table."));
00911 
00912     entry *e = new entry;
00913     e->name = lname;
00914     e->is_alias = true;
00915     e->aliased_to = lsource;
00916     e->type = get_attr_type(iter);
00917     if (at && e->type == Attr_container)
00918     e->attributes = at->get_attr_table(iter);
00919     else
00920     e->attr = (*iter)->attr;
00921 
00922     attr_map.push_back(e);
00923 }
00924 
00925 // Deprecated
00944 bool
00945 AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name)
00946 {
00947     add_value_alias(at, alias, name);
00948     return true;
00949 }
00950 
00958 bool
00959 AttrTable::attr_alias(const string &alias, const string &name)
00960 {
00961     return attr_alias(alias, this, name);
00962 }
00963 
00967 void
00968 AttrTable::erase()
00969 {
00970     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00971         delete *i; *i = 0;
00972     }
00973 
00974     attr_map.erase(attr_map.begin(), attr_map.end());
00975 
00976     d_name = "";
00977 }
00978 
00979 const string double_quote = "\"";
00980 
00981 // This is here as a result of the problem described in ticket #1163 where
00982 // the data handlers are adding quotes to string attributes so the DAS will
00983 // be printed correctly. But that has the affect of adding the quotes to the
00984 // attribute's _value_ not just it's print representation. As part of the fix
00985 // I made the code here add the quotes if the handlers are fixed (but not if
00986 // handlers are still adding them). The other part of 1163 is to fix all of
00987 // the handlers... What this fix means is that attributes whose values really
00988 // do contain bracketing quotes might be misunderstood, since we're assuming
00989 // those quotes were added by the handlers as a hack to get the output
00990 // formatting correct for the DAS. jhrg 7/30/08
00991 
00992 static void
00993 write_string_attribute_for_das(ostream &out, const string &value, const string &term)
00994 {
00995     if (is_quoted(value))
00996     out << value << term;
00997     else
00998     out << double_quote << value << double_quote << term;
00999 }
01000 
01001 static void
01002 write_string_attribute_for_das(FILE *out, const string &value, const string &term)
01003 {
01004     if (is_quoted(value))
01005     fprintf(out, "%s%s", value.c_str(), term.c_str());
01006     else
01007     fprintf(out, "\"%s\"%s", value.c_str(), term.c_str());
01008 }
01009 
01010 // Special treatment for XML: Make sure to escape double quotes when XML is
01011 // printed in a DAS.
01012 static void
01013 write_xml_attribute_for_das(ostream &out, const string &value, const string &term)
01014 {
01015     if (is_quoted(value))
01016     out << escape_double_quotes(value) << term;
01017     else
01018     out << double_quote << escape_double_quotes(value) << double_quote << term;
01019 }
01020 
01021 static void
01022 write_xml_attribute_for_das(FILE *out, const string &value, const string &term)
01023 {
01024     if (is_quoted(value))
01025     fprintf(out, "%s%s", escape_double_quotes(value).c_str(), term.c_str());
01026     else
01027     fprintf(out, "\"%s\"%s", escape_double_quotes(value).c_str(), term.c_str());
01028 }
01029 
01032 void
01033 AttrTable::simple_print(FILE *out, string pad, Attr_iter i,
01034         bool dereference)
01035 {
01036     switch ((*i)->type) {
01037         case Attr_container:
01038         fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str());
01039 
01040         (*i)->attributes->print(out, pad + "    ", dereference);
01041 
01042         fprintf(out, "%s}\n", pad.c_str());
01043         break;
01044 
01045         case Attr_string: {
01046             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
01047                     id2www(get_name(i)).c_str());
01048 
01049             vector<string> *sxp = (*i)->attr;
01050             vector<string>::iterator last = sxp->end() - 1;
01051             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01052                 write_string_attribute_for_das(out, *i, ", ");
01053             }
01054             write_string_attribute_for_das(out, *last, ";\n");
01055         }
01056         break;
01057 
01058         case Attr_other_xml: {
01059             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
01060                     id2www(get_name(i)).c_str());
01061 
01062             vector<string> *sxp = (*i)->attr;
01063             vector<string>::iterator last = sxp->end() - 1;
01064             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01065                 write_xml_attribute_for_das(out, *i, ", ");
01066             }
01067             write_xml_attribute_for_das(out, *last, ";\n");
01068         }
01069         break;
01070 
01071         default: {
01072             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
01073                     id2www(get_name(i)).c_str());
01074 
01075             vector<string> *sxp = (*i)->attr;
01076             vector<string>::iterator last = sxp->end() - 1;
01077             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01078                 fprintf(out, "%s%s", (*i).c_str(), ", ");
01079             }
01080             fprintf(out, "%s%s", (*last).c_str(), ";\n");
01081         }
01082         break;
01083     }
01084 }
01085 
01088 void
01089 AttrTable::simple_print(ostream &out, string pad, Attr_iter i,
01090         bool dereference)
01091 {
01092     switch ((*i)->type) {
01093         case Attr_container:
01094         out << pad << id2www(get_name(i)) << " {\n";
01095 
01096         (*i)->attributes->print(out, pad + "    ", dereference);
01097 
01098         out << pad << "}\n";
01099         break;
01100 
01101         case Attr_string: {
01102             out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
01103 
01104             vector<string> *sxp = (*i)->attr;
01105             vector<string>::iterator last = sxp->end() - 1;
01106             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01107                 write_string_attribute_for_das(out, *i, ", ");
01108             }
01109             write_string_attribute_for_das(out, *last, ";\n");
01110         }
01111         break;
01112 
01113         case Attr_other_xml: {
01114             out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
01115 
01116             vector<string> *sxp = (*i)->attr;
01117             vector<string>::iterator last = sxp->end() - 1;
01118             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01119                 write_xml_attribute_for_das(out, *i, ", ");
01120             }
01121             write_xml_attribute_for_das(out, *last, ";\n");
01122         }
01123         break;
01124 
01125         default: {
01126             out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
01127 
01128             vector<string> *sxp = (*i)->attr;
01129             vector<string>::iterator last = sxp->end() - 1;
01130             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01131                 out << *i <<", ";
01132             }
01133             out << *last << ";\n";
01134         }
01135         break;
01136     }
01137 }
01138 
01149 void
01150 AttrTable::print(FILE *out, string pad, bool dereference)
01151 {
01152     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
01153         if ((*i)->is_alias) {
01154             if (dereference) {
01155                 simple_print(out, pad, i, dereference);
01156             }
01157             else {
01158                 fprintf(out, "%sAlias %s %s;\n",
01159                         pad.c_str(),
01160                         id2www(get_name(i)).c_str(),
01161                         id2www((*i)->aliased_to).c_str());
01162             }
01163         }
01164         else {
01165             simple_print(out, pad, i, dereference);
01166         }
01167     }
01168 }
01169 
01180 void
01181 AttrTable::print(ostream &out, string pad, bool dereference)
01182 {
01183     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
01184         if ((*i)->is_alias) {
01185             if (dereference) {
01186                 simple_print(out, pad, i, dereference);
01187             }
01188             else {
01189                 out << pad << "Alias " << id2www(get_name(i))
01190                 << " " << id2www((*i)->aliased_to) << ";\n";
01191             }
01192         }
01193         else {
01194             simple_print(out, pad, i, dereference);
01195         }
01196     }
01197 }
01198 
01203 void
01204 AttrTable::print_xml(FILE *out, string pad, bool /*constrained*/)
01205 {
01206     // Why this works: AttrTable is really a hacked class that used to
01207     // implement a single-level set of attributes. Containers
01208     // were added several years later by dropping in the 'entry' structure.
01209     // It's not a class in its own right; instead accessors from AttrTable
01210     // are used to access information from entry. So... the loop below
01211     // actually iterates over the entries of *this* (which is an instance of
01212     // AttrTable). A container is an entry whose sole value is an AttrTable
01213     // instance. 05/19/03 jhrg
01214     for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01215         if ((*i)->is_alias) {
01216             fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
01217                     pad.c_str(), id2xml(get_name(i)).c_str(),
01218                     (*i)->aliased_to.c_str());
01219 
01220         }
01221         else if (is_container(i)) {
01222             fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01223                     pad.c_str(), id2xml(get_name(i)).c_str(),
01224                     get_type(i).c_str());
01225 
01226             get_attr_table(i)->print_xml(out, pad + "    "/*, constrained*/);
01227 
01228             fprintf(out, "%s</Attribute>\n", pad.c_str());
01229         }
01230         else {
01231             fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01232                     pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
01233 
01234             string value_pad = pad + "    ";
01235             // Special handling for the OtherXML attribute type - don't escape
01236             // the XML and don't include the <value> element. Note that there
01237             // cannot be an vector of XML things as can be with the other types.
01238             if (get_attr_type(i) == Attr_other_xml) {
01239                 if (get_attr_num(i) != 1)
01240                     throw Error("OtherXML attributes cannot be vector-valued.");
01241                 fprintf(out, "%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
01242             }
01243             else {
01244                 for (unsigned j = 0; j < get_attr_num(i); ++j) {
01245                     fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
01246                             id2xml(get_attr(i, j)).c_str());
01247                 }
01248             }
01249             fprintf(out, "%s</Attribute>\n", pad.c_str());
01250         }
01251     }
01252 }
01253 
01258 void
01259 AttrTable::print_xml(ostream &out, string pad, bool /*constrained*/)
01260 {
01261     for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01262         if ((*i)->is_alias) {
01263             out << pad << "<Alias name=\"" << id2xml(get_name(i))
01264             << "\" Attribute=\"" << (*i)->aliased_to << "\"/>\n";
01265 
01266         }
01267         else if (is_container(i)) {
01268             out << pad << "<Attribute name=\"" << id2xml(get_name(i))
01269             << "\" type=\"" << get_type(i) << "\">\n";
01270 
01271             get_attr_table(i)->print_xml(out, pad + "    "/*, constrained*/);
01272 
01273             out << pad << "</Attribute>\n";
01274         }
01275         else {
01276             out << pad << "<Attribute name=\"" << id2xml(get_name(i))
01277             << "\" type=\"" << get_type(i) << "\">\n";
01278 
01279             string value_pad = pad + "    ";
01280             if (get_attr_type(i) == Attr_other_xml) {
01281                 if (get_attr_num(i) != 1)
01282                     throw Error("OtherXML attributes cannot be vector-valued.");
01283                 out << value_pad << get_attr(i, 0) << "\n";
01284             }
01285             else {
01286                 string value_pad = pad + "    ";
01287                 for (unsigned j = 0; j < get_attr_num(i); ++j) {
01288                     out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n";
01289                 }
01290             }
01291             out << pad << "</Attribute>\n";
01292         }
01293     }
01294 }
01295 
01303 void
01304 AttrTable::dump(ostream &strm) const
01305 {
01306     strm << DapIndent::LMarg << "AttrTable::dump - ("
01307     << (void *)this << ")" << endl;
01308     DapIndent::Indent();
01309     strm << DapIndent::LMarg << "table name: " << d_name << endl;
01310     if (attr_map.size()) {
01311         strm << DapIndent::LMarg << "attributes: " << endl;
01312         DapIndent::Indent();
01313         Attr_citer i = attr_map.begin();
01314         Attr_citer ie = attr_map.end();
01315         for (; i != ie; i++) {
01316             entry *e = (*i);
01317             string type = AttrType_to_String(e->type);
01318             if (e->is_alias) {
01319                 strm << DapIndent::LMarg << "alias: " << e->name
01320                 << " aliased to: " << e->aliased_to
01321                 << endl;
01322             }
01323             else if (e->type == Attr_container) {
01324                 strm << DapIndent::LMarg << "attr: " << e->name
01325                 << " of type " << type
01326                 << endl;
01327                 DapIndent::Indent();
01328                 e->attributes->dump(strm);
01329                 DapIndent::UnIndent();
01330             }
01331             else {
01332                 strm << DapIndent::LMarg << "attr: " << e->name
01333                 << " of type " << type
01334                 << endl;
01335                 DapIndent::Indent();
01336                 strm << DapIndent::LMarg;
01337                 vector<string>::const_iterator iter = e->attr->begin();
01338                 vector<string>::const_iterator last = e->attr->end() - 1;
01339                 for (; iter != last; iter++) {
01340                     strm << (*iter) << ", ";
01341                 }
01342                 strm << (*(e->attr->end() - 1)) << endl;
01343                 DapIndent::UnIndent();
01344             }
01345         }
01346         DapIndent::UnIndent();
01347     }
01348     else {
01349         strm << DapIndent::LMarg << "attributes: empty" << endl;
01350     }
01351     if (d_parent) {
01352         strm << DapIndent::LMarg << "parent table:"
01353         << d_name << ":" << (void *)d_parent << endl;
01354     }
01355     else {
01356         strm << DapIndent::LMarg << "parent table: none" << d_name << endl;
01357     }
01358     DapIndent::UnIndent();
01359 }
01360 
01361 } // namespace libdap
01362 

Generated on Tue Jun 1 17:27:42 2010 for libdap++ by  doxygen 1.4.7