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 static char rcsid[]not_used =
00036         "$Id: AttrTable.cc 21699 2009-11-05 00:06:01Z 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 AttrType_to_String(const AttrType at)
00058 {
00059     switch (at) {
00060         case Attr_container:
00061             return "Container";
00062         case Attr_byte:
00063             return "Byte";
00064         case Attr_int16:
00065             return "Int16";
00066         case Attr_uint16:
00067             return "UInt16";
00068         case Attr_int32:
00069             return "Int32";
00070         case Attr_uint32:
00071             return "UInt32";
00072         case Attr_float32:
00073             return "Float32";
00074         case Attr_float64:
00075             return "Float64";
00076         case Attr_string:
00077             return "String";
00078         case Attr_url:
00079             return "Url";
00080         case Attr_other_xml:
00081             return "OtherXML";
00082         default:
00083             return "";
00084     }
00085 }
00086 
00087 AttrType String_to_AttrType(const string &s)
00088 {
00089     string s2 = s;
00090     downcase(s2);
00091 
00092     if (s2 == "container")
00093         return Attr_container;
00094     else if (s2 == "byte")
00095         return Attr_byte;
00096     else if (s2 == "int16")
00097         return Attr_int16;
00098     else if (s2 == "uint16")
00099         return Attr_uint16;
00100     else if (s2 == "int32")
00101         return Attr_int32;
00102     else if (s2 == "uint32")
00103         return Attr_uint32;
00104     else if (s2 == "float32")
00105         return Attr_float32;
00106     else if (s2 == "float64")
00107         return Attr_float64;
00108     else if (s2 == "string")
00109         return Attr_string;
00110     else if (s2 == "url")
00111         return Attr_url;
00112     else if (s2 == "otherxml")
00113         return Attr_other_xml;
00114     else
00115         return Attr_unknown;
00116 }
00117 
00120 void AttrTable::clone(const AttrTable &at)
00121 {
00122     d_name = at.d_name;
00123 
00124     Attr_citer i = at.attr_map.begin();
00125     Attr_citer ie = at.attr_map.end();
00126     for (; i != ie; i++) {
00127         entry *e = new entry(*(*i));
00128         attr_map.push_back(e);
00129     }
00130 
00131     d_parent = at.d_parent;
00132 }
00133 
00137 AttrTable::AttrTable() :
00138     d_name(""), d_parent(0)
00139 {
00140 }
00141 
00142 AttrTable::AttrTable(const AttrTable &rhs) :
00143     DapObj()
00144 {
00145     clone(rhs);
00146 }
00147 
00148 // Private
00149 void AttrTable::delete_attr_table()
00150 {
00151     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00152         delete *i;
00153         *i = 0;
00154     }
00155 }
00156 
00157 AttrTable::~AttrTable()
00158 {
00159     DBG(cerr << "Entering ~AttrTable (" << this << ")" << endl);
00160     delete_attr_table();DBG(cerr << "Exiting ~AttrTable" << endl);
00161 }
00162 
00163 AttrTable &
00164 AttrTable::operator=(const AttrTable &rhs)
00165 {
00166     if (this != &rhs) {
00167         delete_attr_table();
00168         clone(rhs);
00169     }
00170 
00171     return *this;
00172 }
00174 
00180 unsigned int
00181 AttrTable::get_size() const
00182 {
00183     return attr_map.size();
00184 }
00185 
00188 string
00189 AttrTable::get_name() const
00190 {
00191     return d_name;
00192 }
00193 
00196 void
00197 AttrTable::set_name(const string &n)
00198 {
00199     d_name = www2id(n);
00200 }
00201 
00219 unsigned int
00220 AttrTable::append_attr(const string &name, const string &type,
00221         const string &attribute)
00222 {
00223     string lname = www2id(name);
00224 
00225     Attr_iter iter = simple_find(lname);
00226 
00227     // If the types don't match OR this attribute is a container, calling
00228     // this mfunc is an error!
00229     if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
00230     throw Error(string("An attribute called `") + name
00231             + string("' already exists but is of a different type"));
00232     if (iter != attr_map.end() && (get_type(iter) == "Container"))
00233     throw Error(string("An attribute called `") + name
00234             + string("' already exists but is a container."));
00235 
00236     if (iter != attr_map.end()) { // Must be a new attribute value; add it.
00237         (*iter)->attr->push_back(attribute);
00238         return (*iter)->attr->size();
00239     }
00240     else { // Must be a completely new attribute; add it
00241         entry *e = new entry;
00242 
00243         e->name = lname;
00244         e->is_alias = false;
00245         e->type = String_to_AttrType(type); // Record type using standard names.
00246         e->attr = new vector<string>;
00247         e->attr->push_back(attribute);
00248 
00249         attr_map.push_back(e);
00250 
00251         return e->attr->size(); // return the length of the attr vector
00252     }
00253 }
00254 
00273 unsigned int
00274 AttrTable::append_attr(const string &name, const string &type,
00275         vector<string> *values)
00276 {
00277     string lname = www2id(name);
00278 
00279     Attr_iter iter = simple_find(lname);
00280 
00281     // If the types don't match OR this attribute is a container, calling
00282     // this mfunc is an error!
00283     if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
00284     throw Error(string("An attribute called `") + name
00285             + string("' already exists but is of a different type"));
00286     if (iter != attr_map.end() && (get_type(iter) == "Container"))
00287     throw Error(string("An attribute called `") + name
00288             + string("' already exists but is a container."));
00289 
00290     if (iter != attr_map.end()) { // Must be new attribute values; add.
00291         vector<string>::iterator i = values->begin();
00292         while (i != values->end())
00293         (*iter)->attr->push_back(*i++);
00294 
00295         return (*iter)->attr->size();
00296     }
00297     else { // Must be a completely new attribute; add it
00298         entry *e = new entry;
00299 
00300         e->name = lname;
00301         e->is_alias = false;
00302         e->type = String_to_AttrType(type); // Record type using standard names.
00303         e->attr = new vector<string>(*values);
00304 
00305         attr_map.push_back(e);
00306 
00307         return e->attr->size(); // return the length of the attr vector
00308     }
00309 }
00310 
00319 AttrTable *
00320 AttrTable::append_container(const string &name)
00321 {
00322     AttrTable *new_at = new AttrTable;
00323     AttrTable *ret = NULL;
00324     try {
00325         ret = append_container(new_at, name);
00326     }
00327     catch (Error &e) {
00328         // an error occurred, attribute with that name already exists
00329         delete new_at; new_at = 0;
00330         throw e;
00331     }
00332     return ret;
00333 }
00334 
00347 AttrTable *
00348 AttrTable::append_container(AttrTable *at, const string &name)
00349 {
00350     string lname = www2id(name);
00351 
00352     if (simple_find(name) != attr_end())
00353     throw Error(string("There already exists a container called `")
00354             + name + string("' in this attribute table."));
00355     DBG(cerr << "Setting appended attribute container name to: "
00356             << lname << endl);
00357     at->set_name(lname);
00358 
00359     entry *e = new entry;
00360     e->name = lname;
00361     e->is_alias = false;
00362     e->type = Attr_container;
00363     e->attributes = at;
00364 
00365     attr_map.push_back(e);
00366 
00367     at->d_parent = this;
00368 
00369     return e->attributes;
00370 }
00371 
00386 void
00387 AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter)
00388 {
00389     string::size_type dotpos = target.rfind('.');
00390     if (dotpos != string::npos) {
00391         string container = target.substr(0, dotpos);
00392         string field = target.substr(dotpos + 1);
00393 
00394         *at = find_container(container);
00395         if (*at) {
00396             *iter = (*at)->simple_find(field);
00397         }
00398         else {
00399             *iter = attr_map.end();
00400         }
00401     }
00402     else {
00403         *at = recurrsive_find(target, iter);
00404     }
00405 }
00406 
00418 AttrTable *
00419 AttrTable::recurrsive_find(const string &target, Attr_iter *location)
00420 {
00421     //*location = attr_begin();
00422     Attr_iter i = attr_begin();
00423     while (i != attr_end()) {
00424         if (target == (*i)->name) {
00425             *location = i;
00426             return this;
00427         }
00428         else if ((*i)->type == Attr_container) {
00429             AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
00430             if (at)
00431             return at;
00432         }
00433 
00434         ++i;
00435     }
00436 
00437     *location = i;
00438     return 0;
00439 }
00440 
00441 // Made public for callers that want non-recursive find.  [mjohnson 6 oct 09]
00448 AttrTable::Attr_iter
00449 AttrTable::simple_find(const string &target)
00450 {
00451     Attr_iter i;
00452     for (i = attr_map.begin(); i != attr_map.end(); i++) {
00453         if (target == (*i)->name) {
00454             break;
00455         }
00456     }
00457     return i;
00458 }
00459 
00473 AttrTable *
00474 AttrTable::find_container(const string &target)
00475 {
00476     string::size_type dotpos = target.find('.');
00477     if (dotpos != string::npos) {
00478         string container = target.substr(0, dotpos);
00479         string field = target.substr(dotpos + 1);
00480 
00481         AttrTable *at = simple_find_container(container);
00482         return (at) ? at->find_container(field) : 0;
00483     }
00484     else {
00485         return simple_find_container(target);
00486     }
00487 }
00488 
00489 // Made public for callers that want non-recursive find.  [mjohnson 6 oct 09]
00490 AttrTable *
00491 AttrTable::simple_find_container(const string &target)
00492 {
00493     if (get_name() == target)
00494     return this;
00495 
00496     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00497         if (is_container(i) && target == (*i)->name) {
00498             return (*i)->attributes;
00499         }
00500     }
00501 
00502     return 0;
00503 }
00504 
00512 
00514 AttrTable *
00515 AttrTable::get_attr_table(const string &name)
00516 {
00517     return find_container(name);
00518 }
00519 
00521 string
00522 AttrTable::get_type(const string &name)
00523 {
00524     Attr_iter p = simple_find(name);
00525     return (p != attr_map.end()) ? get_type(p) : (string)"";
00526 }
00527 
00530 AttrType
00531 AttrTable::get_attr_type(const string &name)
00532 {
00533     Attr_iter p = simple_find(name);
00534     return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown;
00535 }
00536 
00544 unsigned int
00545 AttrTable::get_attr_num(const string &name)
00546 {
00547     Attr_iter iter = simple_find(name);
00548     return (iter != attr_map.end()) ? get_attr_num(iter) : 0;
00549 }
00550 
00563 vector<string> *
00564 AttrTable::get_attr_vector(const string &name)
00565 {
00566     Attr_iter p = simple_find(name);
00567     return (p != attr_map.end()) ? get_attr_vector(p) : 0;
00568 }
00569 
00586 void
00587 AttrTable::del_attr(const string &name, int i)
00588 {
00589     string lname = www2id(name);
00590 
00591     Attr_iter iter = simple_find(lname);
00592     if (iter != attr_map.end()) {
00593         if (i == -1) { // Delete the whole attribute
00594             entry *e = *iter;
00595             attr_map.erase(iter);
00596             delete e; e = 0;
00597         }
00598         else { // Delete one element from attribute array
00599             // Don't try to delete elements from the vector of values if the
00600             // map is a container!
00601             if ((*iter)->type == Attr_container)
00602             return;
00603 
00604             vector<string> *sxp = (*iter)->attr;
00605 
00606             assert(i >= 0 && i < (int)sxp->size());
00607             sxp->erase(sxp->begin() + i); // rm the element
00608         }
00609     }
00610 }
00611 
00613 
00618 AttrTable::Attr_iter
00619 AttrTable::attr_begin()
00620 {
00621     return attr_map.begin();
00622 }
00623 
00627 AttrTable::Attr_iter
00628 AttrTable::attr_end()
00629 {
00630     return attr_map.end();
00631 }
00632 
00641 AttrTable::Attr_iter
00642 AttrTable::get_attr_iter(int i)
00643 {
00644     return attr_map.begin() + i;
00645 }
00646 
00648 string
00649 AttrTable::get_name(Attr_iter iter)
00650 {
00651     assert(iter != attr_map.end());
00652 
00653     return (*iter)->name;
00654 }
00655 
00657 bool
00658 AttrTable::is_container(Attr_iter i)
00659 {
00660     return (*i)->type == Attr_container;
00661 }
00662 
00668 AttrTable *
00669 AttrTable::get_attr_table(Attr_iter iter)
00670 {
00671     assert(iter != attr_map.end());
00672     return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
00673 }
00674 
00683 AttrTable::Attr_iter
00684 AttrTable::del_attr_table(Attr_iter iter)
00685 {
00686     if ((*iter)->type != Attr_container)
00687     return ++iter;
00688 
00689     // the caller intends to delete/reuse the contained AttrTable,
00690     // so zero it out so it doesn't get deleted before we delete the entry
00691     // [mjohnson]
00692     struct entry* e = *iter;
00693     // container no longer has a parent.
00694     if (e->attributes) {
00695       e->attributes->d_parent = 0;
00696     }
00697     e->attributes = 0;
00698     delete e;
00699 
00700     return attr_map.erase(iter);
00701 }
00702 
00706 string
00707 AttrTable::get_type(Attr_iter iter)
00708 {
00709     assert(iter != attr_map.end());
00710     return AttrType_to_String((*iter)->type);
00711 }
00712 
00716 AttrType
00717 AttrTable::get_attr_type(Attr_iter iter)
00718 {
00719     return (*iter)->type;
00720 }
00721 
00729 unsigned int
00730 AttrTable::get_attr_num(Attr_iter iter)
00731 {
00732     assert(iter != attr_map.end());
00733     return ((*iter)->type == Attr_container)
00734     ? (*iter)->attributes->get_size()
00735     : (*iter)->attr->size();
00736 }
00737 
00754 string
00755 AttrTable::get_attr(Attr_iter iter, unsigned int i)
00756 {
00757     assert(iter != attr_map.end());
00758 #if 1
00759     return (*iter)->type == Attr_container ? (string)"None" : (*(*iter)->attr)[i];
00760 #else
00761     if ((*iter)->type == Attr_container) {
00762         return "None";
00763     }
00764     else {
00765         cerr << "(*iter)->attr: " << (*iter)->attr << endl;
00766         cerr << "(*iter)->name: " << (*iter)->name << endl;
00767         cerr << "(*iter)->type: " << (*iter)->type << endl;
00768         //cerr << "get_attr: return value: [" << i << "]: " << (*(*iter)->attr)[i]<< endl;
00769         if ((*iter)->name == "SIS_ID")
00770         return "SIS_ID_value";
00771         else
00772         return (*(*iter)->attr)[i];
00773     }
00774 #endif
00775 }
00776 
00777 string
00778 AttrTable::get_attr(const string &name, unsigned int i)
00779 {
00780     Attr_iter p = simple_find(name);
00781     return (p != attr_map.end()) ? get_attr(p, i) : (string)"";
00782 }
00783 
00795 vector<string> *
00796 AttrTable::get_attr_vector(Attr_iter iter)
00797 {
00798     assert(iter != attr_map.end());
00799     return (*iter)->type != Attr_container ? (*iter)->attr : 0;
00800 }
00801 
00803 
00804 // Alias an attribute table. The alias should be added to this object.
00810 void
00811 AttrTable::add_container_alias(const string &name, AttrTable *src)
00812 {
00813     string lname = www2id(name);
00814 
00815     if (simple_find(lname) != attr_end())
00816     throw Error(string("There already exists a container called `")
00817             + name + string("in this attribute table."));
00818 
00819     entry *e = new entry;
00820     e->name = lname;
00821     e->is_alias = true;
00822     e->aliased_to = src->get_name();
00823     e->type = Attr_container;
00824 
00825     e->attributes = src;
00826 
00827     attr_map.push_back(e);
00828 }
00829 
00842 void
00843 AttrTable::add_value_alias(AttrTable *das, const string &name,
00844         const string &source)
00845 {
00846     string lname = www2id(name);
00847     string lsource = www2id(source);
00848 
00849     // find the container that holds source and its (sources's) iterator
00850     // within that container. Search at the uppermost level of the attribute
00851     // object to find values defined `above' the current container.
00852     AttrTable *at;
00853     Attr_iter iter;
00854     das->find(lsource, &at, &iter);
00855 
00856     // If source is not found by looking at the topmost level, look in the
00857     // current table (i.e., alias z x where x is in the current container
00858     // won't be found by looking for `x' at the top level). See test case 26
00859     // in das-testsuite.
00860     if (!at || (iter == at->attr_end()) || !*iter) {
00861         find(lsource, &at, &iter);
00862         if (!at || (iter == at->attr_end()) || !*iter)
00863         throw Error(string("Could not find the attribute `")
00864                 + source + string("' in the attribute object."));
00865     }
00866 
00867     // If we've got a value to alias and it's being added at the top level of
00868     // the DAS, that's an error.
00869     if (at && !at->is_container(iter) && this == das)
00870     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."));
00871 
00872     if (simple_find(lname) != attr_end())
00873     throw Error(string("There already exists a container called `")
00874             + name + string("in this attribute table."));
00875 
00876     entry *e = new entry;
00877     e->name = lname;
00878     e->is_alias = true;
00879     e->aliased_to = lsource;
00880     e->type = get_attr_type(iter);
00881     if (at && e->type == Attr_container)
00882     e->attributes = at->get_attr_table(iter);
00883     else
00884     e->attr = (*iter)->attr;
00885 
00886     attr_map.push_back(e);
00887 }
00888 
00889 // Deprecated
00908 bool
00909 AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name)
00910 {
00911     add_value_alias(at, alias, name);
00912     return true;
00913 }
00914 
00922 bool
00923 AttrTable::attr_alias(const string &alias, const string &name)
00924 {
00925     return attr_alias(alias, this, name);
00926 }
00927 
00931 void
00932 AttrTable::erase()
00933 {
00934     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00935         delete *i; *i = 0;
00936     }
00937 
00938     attr_map.erase(attr_map.begin(), attr_map.end());
00939 
00940     d_name = "";
00941 }
00942 
00943 const string double_quote = "\"";
00944 
00945 // This is here as a result of the problem described in ticket #1163 where
00946 // the data handlers are adding quotes to string attributes so the DAS will
00947 // be printed correctly. But that has the affect of adding the quotes to the
00948 // attribute's _value_ not just it's print representation. As part of the fix
00949 // I made the code here add the quotes if the handlers are fixed (but not if
00950 // handlers are still adding them). The other part of 1163 is to fix all of
00951 // the handlers... What this fix means is that attributes whose values really
00952 // do contain bracketing quotes might be misunderstood, since we're assuming
00953 // those quotes were added by the handlers as a hack to get the output
00954 // formatting correct for the DAS. jhrg 7/30/08
00955 
00956 static void
00957 write_string_attribute_for_das(ostream &out, const string &value, const string &term)
00958 {
00959     if (is_quoted(value))
00960     out << value << term;
00961     else
00962     out << double_quote << value << double_quote << term;
00963 }
00964 
00965 static void
00966 write_string_attribute_for_das(FILE *out, const string &value, const string &term)
00967 {
00968     if (is_quoted(value))
00969     fprintf(out, "%s%s", value.c_str(), term.c_str());
00970     else
00971     fprintf(out, "\"%s\"%s", value.c_str(), term.c_str());
00972 }
00973 
00974 // Special treatment for XML: Make sure to escape double quotes when XML is
00975 // printed in a DAS.
00976 static void
00977 write_xml_attribute_for_das(ostream &out, const string &value, const string &term)
00978 {
00979     if (is_quoted(value))
00980     out << escape_double_quotes(value) << term;
00981     else
00982     out << double_quote << escape_double_quotes(value) << double_quote << term;
00983 }
00984 
00985 static void
00986 write_xml_attribute_for_das(FILE *out, const string &value, const string &term)
00987 {
00988     if (is_quoted(value))
00989     fprintf(out, "%s%s", escape_double_quotes(value).c_str(), term.c_str());
00990     else
00991     fprintf(out, "\"%s\"%s", escape_double_quotes(value).c_str(), term.c_str());
00992 }
00993 
00996 void
00997 AttrTable::simple_print(FILE *out, string pad, Attr_iter i,
00998         bool dereference)
00999 {
01000     switch ((*i)->type) {
01001         case Attr_container:
01002         fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str());
01003 
01004         (*i)->attributes->print(out, pad + "    ", dereference);
01005 
01006         fprintf(out, "%s}\n", pad.c_str());
01007         break;
01008 
01009         case Attr_string: {
01010             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
01011                     id2www(get_name(i)).c_str());
01012 
01013             vector<string> *sxp = (*i)->attr;
01014             vector<string>::iterator last = sxp->end() - 1;
01015             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01016                 write_string_attribute_for_das(out, *i, ", ");
01017             }
01018             write_string_attribute_for_das(out, *last, ";\n");
01019         }
01020         break;
01021 
01022         case Attr_other_xml: {
01023             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
01024                     id2www(get_name(i)).c_str());
01025 
01026             vector<string> *sxp = (*i)->attr;
01027             vector<string>::iterator last = sxp->end() - 1;
01028             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01029                 write_xml_attribute_for_das(out, *i, ", ");
01030             }
01031             write_xml_attribute_for_das(out, *last, ";\n");
01032         }
01033         break;
01034 
01035         default: {
01036             fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
01037                     id2www(get_name(i)).c_str());
01038 
01039             vector<string> *sxp = (*i)->attr;
01040             vector<string>::iterator last = sxp->end() - 1;
01041             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01042                 fprintf(out, "%s%s", (*i).c_str(), ", ");
01043             }
01044             fprintf(out, "%s%s", (*last).c_str(), ";\n");
01045         }
01046         break;
01047     }
01048 }
01049 
01052 void
01053 AttrTable::simple_print(ostream &out, string pad, Attr_iter i,
01054         bool dereference)
01055 {
01056     switch ((*i)->type) {
01057         case Attr_container:
01058         out << pad << id2www(get_name(i)) << " {\n";
01059 
01060         (*i)->attributes->print(out, pad + "    ", dereference);
01061 
01062         out << pad << "}\n";
01063         break;
01064 
01065         case Attr_string: {
01066             out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
01067 
01068             vector<string> *sxp = (*i)->attr;
01069             vector<string>::iterator last = sxp->end() - 1;
01070             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01071                 write_string_attribute_for_das(out, *i, ", ");
01072             }
01073             write_string_attribute_for_das(out, *last, ";\n");
01074         }
01075         break;
01076 
01077         case Attr_other_xml: {
01078             out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
01079 
01080             vector<string> *sxp = (*i)->attr;
01081             vector<string>::iterator last = sxp->end() - 1;
01082             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01083                 write_xml_attribute_for_das(out, *i, ", ");
01084             }
01085             write_xml_attribute_for_das(out, *last, ";\n");
01086         }
01087         break;
01088 
01089         default: {
01090             out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
01091 
01092             vector<string> *sxp = (*i)->attr;
01093             vector<string>::iterator last = sxp->end() - 1;
01094             for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
01095                 out << *i <<", ";
01096             }
01097             out << *last << ";\n";
01098         }
01099         break;
01100     }
01101 }
01102 
01113 void
01114 AttrTable::print(FILE *out, string pad, bool dereference)
01115 {
01116     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
01117         if ((*i)->is_alias) {
01118             if (dereference) {
01119                 simple_print(out, pad, i, dereference);
01120             }
01121             else {
01122                 fprintf(out, "%sAlias %s %s;\n",
01123                         pad.c_str(),
01124                         id2www(get_name(i)).c_str(),
01125                         id2www((*i)->aliased_to).c_str());
01126             }
01127         }
01128         else {
01129             simple_print(out, pad, i, dereference);
01130         }
01131     }
01132 }
01133 
01144 void
01145 AttrTable::print(ostream &out, string pad, bool dereference)
01146 {
01147     for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
01148         if ((*i)->is_alias) {
01149             if (dereference) {
01150                 simple_print(out, pad, i, dereference);
01151             }
01152             else {
01153                 out << pad << "Alias " << id2www(get_name(i))
01154                 << " " << id2www((*i)->aliased_to) << ";\n";
01155             }
01156         }
01157         else {
01158             simple_print(out, pad, i, dereference);
01159         }
01160     }
01161 }
01162 
01167 void
01168 AttrTable::print_xml(FILE *out, string pad, bool /*constrained*/)
01169 {
01170     // Why this works: AttrTable is really a hacked class that used to
01171     // implement a single-level set of attributes. Containers
01172     // were added several years later by dropping in the 'entry' structure.
01173     // It's not a class in its own right; instead accessors from AttrTable
01174     // are used to access information from entry. So... the loop below
01175     // actually iterates over the entries of *this* (which is an instance of
01176     // AttrTable). A container is an entry whose sole value is an AttrTable
01177     // instance. 05/19/03 jhrg
01178     for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01179         if ((*i)->is_alias) {
01180             fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
01181                     pad.c_str(), id2xml(get_name(i)).c_str(),
01182                     (*i)->aliased_to.c_str());
01183 
01184         }
01185         else if (is_container(i)) {
01186             fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01187                     pad.c_str(), id2xml(get_name(i)).c_str(),
01188                     get_type(i).c_str());
01189 
01190             get_attr_table(i)->print_xml(out, pad + "    "/*, constrained*/);
01191 
01192             fprintf(out, "%s</Attribute>\n", pad.c_str());
01193         }
01194         else {
01195             fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01196                     pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
01197 
01198             string value_pad = pad + "    ";
01199             // Special handling for the OtherXML attribute type - don't escape
01200             // the XML and don't include the <value> element. Note that there
01201             // cannot be an vector of XML things as can be with the other types.
01202             if (get_attr_type(i) == Attr_other_xml) {
01203                 if (get_attr_num(i) != 1)
01204                     throw Error("OtherXML attributes cannot be vector-valued.");
01205                 fprintf(out, "%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
01206             }
01207             else {
01208                 for (unsigned j = 0; j < get_attr_num(i); ++j) {
01209                     fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
01210                             id2xml(get_attr(i, j)).c_str());
01211                 }
01212             }
01213             fprintf(out, "%s</Attribute>\n", pad.c_str());
01214         }
01215     }
01216 }
01217 
01222 void
01223 AttrTable::print_xml(ostream &out, string pad, bool /*constrained*/)
01224 {
01225     for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01226         if ((*i)->is_alias) {
01227             out << pad << "<Alias name=\"" << id2xml(get_name(i))
01228             << "\" Attribute=\"" << (*i)->aliased_to << "\"/>\n";
01229 
01230         }
01231         else if (is_container(i)) {
01232             out << pad << "<Attribute name=\"" << id2xml(get_name(i))
01233             << "\" type=\"" << get_type(i) << "\">\n";
01234 
01235             get_attr_table(i)->print_xml(out, pad + "    "/*, constrained*/);
01236 
01237             out << pad << "</Attribute>\n";
01238         }
01239         else {
01240             out << pad << "<Attribute name=\"" << id2xml(get_name(i))
01241             << "\" type=\"" << get_type(i) << "\">\n";
01242 
01243             string value_pad = pad + "    ";
01244             if (get_attr_type(i) == Attr_other_xml) {
01245                 if (get_attr_num(i) != 1)
01246                     throw Error("OtherXML attributes cannot be vector-valued.");
01247                 out << value_pad << get_attr(i, 0) << "\n";
01248             }
01249             else {
01250                 string value_pad = pad + "    ";
01251                 for (unsigned j = 0; j < get_attr_num(i); ++j) {
01252                     out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n";
01253                 }
01254             }
01255             out << pad << "</Attribute>\n";
01256         }
01257     }
01258 }
01259 
01267 void
01268 AttrTable::dump(ostream &strm) const
01269 {
01270     strm << DapIndent::LMarg << "AttrTable::dump - ("
01271     << (void *)this << ")" << endl;
01272     DapIndent::Indent();
01273     strm << DapIndent::LMarg << "table name: " << d_name << endl;
01274     if (attr_map.size()) {
01275         strm << DapIndent::LMarg << "attributes: " << endl;
01276         DapIndent::Indent();
01277         Attr_citer i = attr_map.begin();
01278         Attr_citer ie = attr_map.end();
01279         for (; i != ie; i++) {
01280             entry *e = (*i);
01281             string type = AttrType_to_String(e->type);
01282             if (e->is_alias) {
01283                 strm << DapIndent::LMarg << "alias: " << e->name
01284                 << " aliased to: " << e->aliased_to
01285                 << endl;
01286             }
01287             else if (e->type == Attr_container) {
01288                 strm << DapIndent::LMarg << "attr: " << e->name
01289                 << " of type " << type
01290                 << endl;
01291                 DapIndent::Indent();
01292                 e->attributes->dump(strm);
01293                 DapIndent::UnIndent();
01294             }
01295             else {
01296                 strm << DapIndent::LMarg << "attr: " << e->name
01297                 << " of type " << type
01298                 << endl;
01299                 DapIndent::Indent();
01300                 strm << DapIndent::LMarg;
01301                 vector<string>::const_iterator iter = e->attr->begin();
01302                 vector<string>::const_iterator last = e->attr->end() - 1;
01303                 for (; iter != last; iter++) {
01304                     strm << (*iter) << ", ";
01305                 }
01306                 strm << (*(e->attr->end() - 1)) << endl;
01307                 DapIndent::UnIndent();
01308             }
01309         }
01310         DapIndent::UnIndent();
01311     }
01312     else {
01313         strm << DapIndent::LMarg << "attributes: empty" << endl;
01314     }
01315     if (d_parent) {
01316         strm << DapIndent::LMarg << "parent table:"
01317         << d_name << ":" << (void *)d_parent << endl;
01318     }
01319     else {
01320         strm << DapIndent::LMarg << "parent table: none" << d_name << endl;
01321     }
01322     DapIndent::UnIndent();
01323 }
01324 
01325 } // namespace libdap
01326 

Generated on Wed Feb 10 16:08:01 2010 for libdap++ by  doxygen 1.4.7