00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "config.h"
00035
00036 static char rcsid[] not_used = "$Id: AttrTable.cc 16726 2007-06-21 18:03:26Z jimg $";
00037
00038 #include <assert.h>
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
00055 string
00056 AttrType_to_String(const AttrType at)
00057 {
00058 switch (at) {
00059 case Attr_container: return "Container";
00060 case Attr_byte: return "Byte";
00061 case Attr_int16: return "Int16";
00062 case Attr_uint16: return "UInt16";
00063 case Attr_int32: return "Int32";
00064 case Attr_uint32: return "UInt32";
00065 case Attr_float32: return "Float32";
00066 case Attr_float64: return "Float64";
00067 case Attr_string: return "String";
00068 case Attr_url: return "Url";
00069 default: return "";
00070 }
00071 }
00072
00073 AttrType
00074 String_to_AttrType(const string &s)
00075 {
00076 string s2 = s;
00077 downcase(s2);
00078
00079 if (s2 == "container")
00080 return Attr_container;
00081 else if (s2 == "byte")
00082 return Attr_byte;
00083 else if (s2 == "int16")
00084 return Attr_int16;
00085 else if (s2 == "uint16")
00086 return Attr_uint16;
00087 else if (s2 == "int32")
00088 return Attr_int32;
00089 else if (s2 == "uint32")
00090 return Attr_uint32;
00091 else if (s2 == "float32")
00092 return Attr_float32;
00093 else if (s2 == "float64")
00094 return Attr_float64;
00095 else if (s2 == "string")
00096 return Attr_string;
00097 else if (s2 == "url")
00098 return Attr_url;
00099 else
00100 return Attr_unknown;
00101 }
00102
00105 void
00106 AttrTable::clone(const AttrTable &at)
00107 {
00108 d_name = at.d_name;
00109
00110 Attr_citer i = at.attr_map.begin() ;
00111 Attr_citer ie = at.attr_map.end() ;
00112 for (; i != ie; i++) {
00113 entry *e = new entry(*(*i)) ;
00114 attr_map.push_back(e) ;
00115 }
00116
00117 d_parent = at.d_parent;
00118 }
00119
00123 AttrTable::AttrTable() : d_name(""), d_parent(0)
00124 {}
00125
00126 AttrTable::AttrTable(const AttrTable &rhs) : DapObj()
00127 {
00128 clone(rhs);
00129 }
00130
00131
00132 void
00133 AttrTable::delete_attr_table()
00134 {
00135 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00136 delete *i; *i = 0;
00137 }
00138 }
00139
00140 AttrTable::~AttrTable()
00141 {
00142 DBG(cerr << "Entering ~AttrTable (" << this << ")" << endl);
00143 delete_attr_table();
00144 DBG(cerr << "Exiting ~AttrTable" << endl);
00145 }
00146
00147 AttrTable &
00148 AttrTable::operator=(const AttrTable &rhs)
00149 {
00150 if (this != &rhs) {
00151 delete_attr_table();
00152 clone(rhs);
00153 }
00154
00155 return *this;
00156 }
00158
00164 unsigned int
00165 AttrTable::get_size() const
00166 {
00167 return attr_map.size();
00168 }
00169
00172 string
00173 AttrTable::get_name() const
00174 {
00175 return d_name;
00176 }
00177
00180 void
00181 AttrTable::set_name(const string &n)
00182 {
00183 d_name = www2id(n);
00184 }
00185
00203 unsigned int
00204 AttrTable::append_attr(const string &name, const string &type,
00205 const string &attribute)
00206 {
00207 string lname = www2id(name);
00208
00209 Attr_iter iter = simple_find(lname) ;
00210
00211
00212
00213 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
00214 throw Error(string("An attribute called `") + name
00215 + string("' already exists but is of a different type"));
00216 if (iter != attr_map.end() && (get_type(iter) == "Container"))
00217 throw Error(string("An attribute called `") + name
00218 + string("' already exists but is a container."));
00219
00220 if (iter != attr_map.end()) {
00221 (*iter)->attr->push_back(attribute);
00222 return (*iter)->attr->size();
00223 }
00224 else {
00225 entry *e = new entry;
00226
00227 e->name = lname;
00228 e->is_alias = false;
00229 e->type = String_to_AttrType(type);
00230 e->attr = new vector<string>;
00231 e->attr->push_back(attribute);
00232
00233 attr_map.push_back(e);
00234
00235 return e->attr->size();
00236 }
00237 }
00238
00256 unsigned int
00257 AttrTable::append_attr(const string &name, const string &type,
00258 vector<string> *values)
00259 {
00260 string lname = www2id(name);
00261
00262 Attr_iter iter = simple_find(lname) ;
00263
00264
00265
00266 if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
00267 throw Error(string("An attribute called `") + name
00268 + string("' already exists but is of a different type"));
00269 if (iter != attr_map.end() && (get_type(iter) == "Container"))
00270 throw Error(string("An attribute called `") + name
00271 + string("' already exists but is a container."));
00272
00273 if (iter != attr_map.end()) {
00274 vector<string>::iterator i = values->begin();
00275 while (i != values->end())
00276 (*iter)->attr->push_back(*i++);
00277
00278 return (*iter)->attr->size();
00279 }
00280 else {
00281 entry *e = new entry;
00282
00283 e->name = lname;
00284 e->is_alias = false;
00285 e->type = String_to_AttrType(type);
00286 e->attr = new vector<string>(*values);
00287
00288 attr_map.push_back(e);
00289
00290 return e->attr->size();
00291 }
00292 }
00293
00302 AttrTable *
00303 AttrTable::append_container(const string &name)
00304 {
00305 AttrTable *new_at = new AttrTable ;
00306 AttrTable *ret = NULL ;
00307 try {
00308 ret = append_container(new_at, name) ;
00309 }
00310 catch (Error &e) {
00311
00312 delete new_at; new_at = 0;
00313 throw e;
00314 }
00315 return ret;
00316 }
00317
00330 AttrTable *
00331 AttrTable::append_container(AttrTable *at, const string &name)
00332 {
00333 string lname = www2id(name);
00334
00335 if (simple_find(name) != attr_end())
00336 throw Error(string("There already exists a container called `")
00337 + name + string("' in this attribute table."));
00338 DBG(cerr << "Setting appended attribute container name to: "
00339 << lname << endl);
00340 at->set_name(lname);
00341
00342 entry *e = new entry;
00343 e->name = lname;
00344 e->is_alias = false;
00345 e->type = Attr_container;
00346 e->attributes = at;
00347
00348 attr_map.push_back(e);
00349
00350 at->d_parent = this;
00351
00352 return e->attributes;
00353 }
00354
00369 void
00370 AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter)
00371 {
00372 string::size_type dotpos = target.rfind('.');
00373 if (dotpos != string::npos) {
00374 string container = target.substr(0, dotpos);
00375 string field = target.substr(dotpos + 1);
00376
00377 *at = find_container(container) ;
00378 if (*at) {
00379 *iter = (*at)->simple_find(field) ;
00380 }
00381 else {
00382 *iter = attr_map.end() ;
00383 }
00384 }
00385 else {
00386 #if 0
00387
00388
00389
00390 *at = this;
00391 *iter = simple_find(target);
00392 #endif
00393 *at = recurrsive_find(target, iter);
00394 }
00395 }
00396
00408 AttrTable *
00409 AttrTable::recurrsive_find(const string &target, Attr_iter *location)
00410 {
00411
00412 Attr_iter i = attr_begin();
00413 while (i != attr_end()) {
00414 if (target == (*i)->name) {
00415 *location = i;
00416 return this;
00417 }
00418 else if ((*i)->type == Attr_container) {
00419 AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
00420 if (at)
00421 return at;
00422 }
00423
00424 ++i;
00425 }
00426
00427 *location = i;
00428 return 0;
00429 }
00430
00431
00438 AttrTable::Attr_iter
00439 AttrTable::simple_find(const string &target)
00440 {
00441 Attr_iter i ;
00442 for (i = attr_map.begin(); i != attr_map.end(); i++) {
00443 if (target == (*i)->name) {
00444 break ;
00445 }
00446 }
00447 return i ;
00448 }
00449
00463 AttrTable *
00464 AttrTable::find_container(const string &target)
00465 {
00466 string::size_type dotpos = target.find('.');
00467 if (dotpos != string::npos) {
00468 string container = target.substr(0, dotpos);
00469 string field = target.substr(dotpos + 1);
00470
00471 AttrTable *at = simple_find_container(container);
00472 return (at) ? at->find_container(field) : 0;
00473 }
00474 else {
00475 return simple_find_container(target);
00476 }
00477 }
00478
00479
00480 AttrTable *
00481 AttrTable::simple_find_container(const string &target)
00482 {
00483 if (get_name() == target)
00484 return this;
00485
00486 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00487 if (is_container(i) && target == (*i)->name) {
00488 return (*i)->attributes;
00489 }
00490 }
00491
00492 return 0;
00493 }
00494
00502
00504 AttrTable *
00505 AttrTable::get_attr_table(const string &name)
00506 {
00507 return find_container(name);
00508 }
00509
00511 string
00512 AttrTable::get_type(const string &name)
00513 {
00514 Attr_iter p = simple_find(name);
00515 return (p != attr_map.end()) ? get_type(p) : (string)"";
00516 }
00517
00520 AttrType
00521 AttrTable::get_attr_type(const string &name)
00522 {
00523 Attr_iter p = simple_find(name);
00524 return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown;
00525 }
00526
00534 unsigned int
00535 AttrTable::get_attr_num(const string &name)
00536 {
00537 Attr_iter iter = simple_find(name);
00538 return (iter != attr_map.end()) ? get_attr_num(iter) : 0;
00539 }
00540
00553 vector<string> *
00554 AttrTable::get_attr_vector(const string &name)
00555 {
00556 Attr_iter p = simple_find(name);
00557 return (p != attr_map.end()) ? get_attr_vector(p) : 0;
00558 }
00559
00576 void
00577 AttrTable::del_attr(const string &name, int i)
00578 {
00579 string lname = www2id(name);
00580
00581 Attr_iter iter = simple_find(lname) ;
00582 if (iter != attr_map.end()) {
00583 if (i == -1) {
00584 entry *e = *iter ;
00585 attr_map.erase(iter) ;
00586 delete e ; e = 0;
00587 }
00588 else {
00589
00590
00591 if ((*iter)->type == Attr_container)
00592 return;
00593
00594 vector<string> *sxp = (*iter)->attr;
00595
00596 assert(i >= 0 && i < (int)sxp->size());
00597 sxp->erase(sxp->begin() + i);
00598 }
00599 }
00600 }
00601
00603
00608 AttrTable::Attr_iter
00609 AttrTable::attr_begin()
00610 {
00611 return attr_map.begin() ;
00612 }
00613
00617 AttrTable::Attr_iter
00618 AttrTable::attr_end()
00619 {
00620 return attr_map.end() ;
00621 }
00622
00631 AttrTable::Attr_iter
00632 AttrTable::get_attr_iter(int i)
00633 {
00634 return attr_map.begin() + i;
00635 }
00636
00638 string
00639 AttrTable::get_name(Attr_iter iter)
00640 {
00641 assert(iter != attr_map.end()) ;
00642
00643 return (*iter)->name ;
00644 }
00645
00647 bool
00648 AttrTable::is_container(Attr_iter i)
00649 {
00650 return (*i)->type == Attr_container ;
00651 }
00652
00658 AttrTable *
00659 AttrTable::get_attr_table(Attr_iter iter)
00660 {
00661 assert(iter != attr_map.end()) ;
00662 return (*iter)->type == Attr_container ? (*iter)->attributes : 0 ;
00663 }
00664
00672 AttrTable::Attr_iter
00673 AttrTable::del_attr_table(Attr_iter iter)
00674 {
00675 if ((*iter)->type != Attr_container)
00676 return ++iter;
00677
00678 return attr_map.erase(iter);
00679 }
00680
00684 string
00685 AttrTable::get_type(Attr_iter iter)
00686 {
00687 assert(iter != attr_map.end()) ;
00688 return AttrType_to_String((*iter)->type) ;
00689 }
00690
00694 AttrType
00695 AttrTable::get_attr_type(Attr_iter iter)
00696 {
00697 return (*iter)->type ;
00698 }
00699
00707 unsigned int
00708 AttrTable::get_attr_num(Attr_iter iter)
00709 {
00710 assert(iter != attr_map.end()) ;
00711 return ((*iter)->type == Attr_container)
00712 ? (*iter)->attributes->get_size()
00713 : (*iter)->attr->size() ;
00714 }
00715
00732 string
00733 AttrTable::get_attr(Attr_iter iter, unsigned int i)
00734 {
00735 assert(iter != attr_map.end());
00736 #if 1
00737 return (*iter)->type == Attr_container ? (string)"None" : (*(*iter)->attr)[i];
00738 #else
00739 if ((*iter)->type == Attr_container) {
00740 return "None";
00741 }
00742 else {
00743 cerr << "(*iter)->attr: " << (*iter)->attr << endl;
00744 cerr << "(*iter)->name: " << (*iter)->name << endl;
00745 cerr << "(*iter)->type: " << (*iter)->type << endl;
00746
00747 if ((*iter)->name == "SIS_ID")
00748 return "SIS_ID_value";
00749 else
00750 return (*(*iter)->attr)[i];
00751 }
00752 #endif
00753 }
00754
00755 string
00756 AttrTable::get_attr(const string &name, unsigned int i)
00757 {
00758 Attr_iter p = simple_find(name);
00759 return (p != attr_map.end()) ? get_attr(p, i) : (string)"";
00760 }
00761
00773 vector<string> *
00774 AttrTable::get_attr_vector(Attr_iter iter)
00775 {
00776 assert(iter != attr_map.end());
00777 return (*iter)->type != Attr_container ? (*iter)->attr : 0;
00778 }
00779
00781
00782
00788 void
00789 AttrTable::add_container_alias(const string &name, AttrTable *src)
00790 {
00791 string lname = www2id(name);
00792
00793 if (simple_find(lname) != attr_end())
00794 throw Error(string("There already exists a container called `")
00795 + name + string("in this attribute table."));
00796
00797 entry *e = new entry;
00798 e->name = lname;
00799 e->is_alias = true;
00800 e->aliased_to = src->get_name();
00801 e->type = Attr_container;
00802
00803 e->attributes = src;
00804
00805 attr_map.push_back(e);
00806 }
00807
00820 void
00821 AttrTable::add_value_alias(AttrTable *das, const string &name,
00822 const string &source)
00823 {
00824 string lname = www2id(name);
00825 string lsource = www2id(source);
00826
00827
00828
00829
00830 AttrTable *at;
00831 Attr_iter iter;
00832 das->find(lsource, &at, &iter);
00833
00834
00835
00836
00837
00838 if (!at || (iter == at->attr_end()) || !*iter) {
00839 find(lsource, &at, &iter);
00840 if (!at || (iter == at->attr_end()) || !*iter)
00841 throw Error(string("Could not find the attribute `")
00842 + source + string("' in the attribute object."));
00843 }
00844
00845
00846
00847 if (!at->is_container(iter) && this == das)
00848 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."));
00849
00850 if (simple_find(lname) != attr_end())
00851 throw Error(string("There already exists a container called `")
00852 + name + string("in this attribute table."));
00853
00854 entry *e = new entry;
00855 e->name = lname;
00856 e->is_alias = true;
00857 e->aliased_to = lsource;
00858 e->type = get_attr_type(iter);
00859 if (e->type == Attr_container)
00860 e->attributes = at->get_attr_table(iter);
00861 else
00862 e->attr = (*iter)->attr;
00863
00864 attr_map.push_back(e);
00865 }
00866
00867
00886 bool
00887 AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name)
00888 {
00889 add_value_alias(at, alias, name);
00890 return true;
00891 }
00892
00900 bool
00901 AttrTable::attr_alias(const string &alias, const string &name)
00902 {
00903 return attr_alias(alias, this, name);
00904 }
00905
00909 void
00910 AttrTable::erase()
00911 {
00912 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00913 delete *i; *i = 0;
00914 }
00915
00916 attr_map.erase(attr_map.begin(), attr_map.end());
00917
00918 d_name = "";
00919 }
00920
00921
00924 void
00925 AttrTable::simple_print(FILE *out, string pad, Attr_iter i,
00926 bool dereference)
00927 {
00928 switch ((*i)->type) {
00929 case Attr_container:
00930 fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str()) ;
00931
00932 (*i)->attributes->print(out, pad + " ", dereference);
00933
00934 fprintf(out, "%s}\n", pad.c_str()) ;
00935 break;
00936
00937 default: {
00938 fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(),
00939 id2www(get_name(i)).c_str()) ;
00940
00941 vector<string> *sxp = (*i)->attr;
00942
00943 vector<string>::iterator last = sxp->end() - 1;
00944 for (vector<string>::iterator i = sxp->begin(); i != last; ++i)
00945 fprintf(out, "%s, ", (*i).c_str()) ;
00946
00947 fprintf(out, "%s;\n", (*(sxp->end() - 1)).c_str()) ;
00948 }
00949 break;
00950 }
00951 }
00952
00963 void
00964 AttrTable::print(FILE *out, string pad, bool dereference)
00965 {
00966 for (Attr_iter i = attr_map.begin(); i != attr_map.end(); i++) {
00967 if ((*i)->is_alias) {
00968 if (dereference) {
00969 simple_print(out, pad, i, dereference);
00970 }
00971 else {
00972 fprintf(out, "%sAlias %s %s;\n",
00973 pad.c_str(),
00974 id2www(get_name(i)).c_str(),
00975 id2www((*i)->aliased_to).c_str()) ;
00976 }
00977 }
00978 else {
00979 simple_print(out, pad, i, dereference);
00980 }
00981 }
00982 }
00983
00989 void
00990 AttrTable::print_xml(FILE *out, string pad, bool constrained)
00991 {
00992
00993
00994
00995
00996
00997
00998
00999
01000 for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
01001
01002
01003
01004
01005
01006 if ((*i)->is_alias) {
01007 fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\">\n",
01008 pad.c_str(), id2xml(get_name(i)).c_str(),
01009 (*i)->aliased_to.c_str());
01010
01011 }
01012 else if (is_container(i)) {
01013 fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01014 pad.c_str(), id2xml(get_name(i)).c_str(),
01015 get_type(i).c_str());
01016
01017 get_attr_table(i)->print_xml(out, pad + " ", constrained);
01018
01019 fprintf(out, "%s</Attribute>\n", pad.c_str());
01020 }
01021 else {
01022 fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
01023 pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
01024
01025 string value_pad = pad + " ";
01026 for (unsigned j = 0; j < get_attr_num(i); ++j) {
01027 fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
01028 id2xml(get_attr(i, j)).c_str());
01029 }
01030
01031 fprintf(out, "%s</Attribute>\n", pad.c_str());
01032 }
01033 }
01034 }
01035
01043 void
01044 AttrTable::dump(ostream &strm) const
01045 {
01046 strm << DapIndent::LMarg << "AttrTable::dump - ("
01047 << (void *)this << ")" << endl ;
01048 DapIndent::Indent() ;
01049 strm << DapIndent::LMarg << "table name: " << d_name << endl ;
01050 if (attr_map.size()) {
01051 strm << DapIndent::LMarg << "attributes: " << endl ;
01052 DapIndent::Indent() ;
01053 Attr_citer i = attr_map.begin() ;
01054 Attr_citer ie = attr_map.end() ;
01055 for (; i != ie; i++) {
01056 entry *e = (*i) ;
01057 string type = AttrType_to_String(e->type) ;
01058 if (e->is_alias) {
01059 strm << DapIndent::LMarg << "alias: " << e->name
01060 << " aliased to: " << e->aliased_to
01061 << endl ;
01062 }
01063 else if (e->type == Attr_container) {
01064 strm << DapIndent::LMarg << "attr: " << e->name
01065 << " of type " << type
01066 << endl ;
01067 DapIndent::Indent() ;
01068 e->attributes->dump(strm) ;
01069 DapIndent::UnIndent() ;
01070 }
01071 else {
01072 strm << DapIndent::LMarg << "attr: " << e->name
01073 << " of type " << type
01074 << endl ;
01075 DapIndent::Indent() ;
01076 strm << DapIndent::LMarg ;
01077 vector<string>::const_iterator iter = e->attr->begin() ;
01078 vector<string>::const_iterator last = e->attr->end() - 1 ;
01079 for (; iter != last; iter++) {
01080 strm << (*iter) << ", " ;
01081 }
01082 strm << (*(e->attr->end() - 1)) << endl ;
01083 DapIndent::UnIndent() ;
01084 }
01085 }
01086 DapIndent::UnIndent() ;
01087 }
01088 else {
01089 strm << DapIndent::LMarg << "attributes: empty" << endl ;
01090 }
01091 if (d_parent) {
01092 strm << DapIndent::LMarg << "parent table:"
01093 << d_name << ":" << (void *)d_parent << endl ;
01094 }
01095 else {
01096 strm << DapIndent::LMarg << "parent table: none" << d_name << endl ;
01097 }
01098 DapIndent::UnIndent() ;
01099 }
01100