00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #define PERSIST_IN_LIBRARY_SOURCE
00012
00013 #include <iostream>
00014 #include <fstream>
00015 #include <unistd.h>
00016 #include <boost/lexical_cast.hpp>
00017 #include <boost/filesystem/path.hpp>
00018 #include <boost/filesystem/operations.hpp>
00019 #include <boost/bind.hpp>
00020 #include "parseobj.hpp"
00021 #include "../../common/object.hpp"
00022 #include "../../common/composition_object.hpp"
00023 #include "../../common/persistable_object.hpp"
00024 #include "../../common/outerable_object.hpp"
00025 #include "../../common/importable_object.hpp"
00026
00027 using namespace ph::persist;
00028
00029
00030 const xmlstring s_objtype = S("type");
00031 const xmlstring s_objname = S("name");
00032
00033
00034 const std::string efmt_bad_stack = S("Expected an entry on the object stack.");
00035 const std::string efmt_bad_tag = S("Unknown tag [%s].");
00036 const std::string efmt_fail_create = S("Couldn't create object [%s (%s)].");
00037 const std::string efmt_fail_create_root = S("Couldn't create root object [%s (%s)].");
00038 const std::string efmt_fail_create_delayed = S("Couldn't create delayed object [%s (%s)].");
00039 const std::string efmt_fail_not_importable = S("Object created was not importable.");
00040 const std::string efmt_prop_not_comp = S("Member is not composite object [%s(%s)].");
00041 const std::string efmt_bad_aggr_obj = S("Composite did not accept object (wrong type?) [%s(%s)].");
00042 const std::string efmt_bad_import = S("Could not import [%s].");
00043 const std::string efmt_bad_stream = S("Could not create URL stream for [%s].");
00044 const std::string efmt_bad_urlstream = S("Could not open URL stream for [%s].");
00045 const std::string efmt_bad_endimport = S("Bad place for an end import tag [%s].");
00046 const std::string efmt_bad_fragment = S("Bad place for a fragment tag [%s].");
00047 const std::string efmt_bad_endfragment = S("Bad place for an end fragment tag [%s].");
00048 const std::string efmt_bad_location = S("Location not found for a fragment tag [%s].");
00049 const std::string efmt_no_interface = S("Object has no %s interface [%s].");
00050 const std::string efmt_not_composite = S("Object is not composite [%s].");
00051 const std::string efmt_bad_data = S("Tried to set a member [%s] with bad data [%s].");
00052 const std::string efmt_bad_path = S("Bad pathvar encountered [%s] with [%s].");
00053 const std::string efmt_bad_ref_location = S("Location not found for a reference [%s].");
00054 const std::string efmt_end_stack = S("At the end, the stack still had elements. top: [%s]. "
00055 "Check for unbalanced tags.");
00056 const std::string efmt_import_is_root = S("An import is at the root of the file.");
00057
00058 xml::parseobj::parseobj(parseobj *outer, std::istream *stream, const boost::filesystem::path &streampath,
00059 ph::common::persistable_object_context *context,
00060 std::ostream *console, const boost::filesystem::path &rootpath, bool silent, unsigned int debug) :
00061 parse(console, silent)
00062 {
00063 _outer = outer;
00064 _stream = stream;
00065
00066
00067 _streampath = boost::filesystem::system_complete(streampath);
00068 _context = context;
00069 _rootpath = rootpath;
00070 _debug = debug;
00071
00072 _obj = 0;
00073 _root = 0;
00074 _rootouter = 0;
00075 _cdata = "";
00076 _comment = "";
00077 _abort = false;
00078 _inmember = false;
00079 _anonymousobjnum = 0;
00080 _import = 0;
00081 _rootname = "";
00082 _fragment = false;
00083 _delayed_obj = 0;
00084 }
00085
00086 static std::string obj_name(ph::common::object_base *obj)
00087 {
00088 std::string name;
00089 if (get_persistable_obj_name(obj, &name))
00090 return name;
00091 else
00092 return "No name for object";
00093 }
00094
00095 static std::string obj_type(ph::common::object_base *obj)
00096 {
00097 std::string type;
00098 if (get_persistable_obj_type(obj, &type))
00099 return type;
00100 else
00101 return "No type for object";
00102 }
00103
00104 void xml::parseobj::finish_handler()
00105 {
00106
00107
00108 if (!_abort && !_stack.empty())
00109 error(efmt_end_stack, obj_name(_stack.top()), true);
00110 }
00111
00112 void xml::parseobj::startelement_handler(const xmlstring &element, const std::vector<xmlstring> &atts)
00113 {
00114 if (_abort)
00115 return;
00116
00117 if (_debug & (PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00118 *_errorhandler << ">> startelement : [" << element << "]" << std::endl;
00119
00120 xmlstring arg = attr(atts, 0);
00121
00122 if (arg.empty())
00123 {
00124 if (_stack.empty())
00125 {
00126 error(efmt_bad_stack, true);
00127 _abort = true;
00128 return;
00129 }
00130
00131 ph::common::object_base *top = _stack.top();
00132 if (!test_persistable(top))
00133 return;
00134
00135 if (top->persistable()->has(element))
00136 {
00137
00138
00139 ph::common::object_base *c = top->persistable()->get_composite_object(element);
00140 if (c)
00141 {
00142 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00143 obj_out("pushing", c);
00144 _stack.push(c);
00145 }
00146 else
00147 {
00148
00149 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00150 element_out("in member", element);
00151 _inmember = true;
00152 }
00153 if (_debug & (PARSEOBJ_DATA_DEBUG | PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00154 *_errorhandler << ">> emptying cdata." << std::endl;
00155 _cdata = "";
00156 }
00157 else
00158 {
00159
00160 ph::common::object_base *obj = create_object(_stack.top(), element,
00161 S("_") + boost::lexical_cast<std::string>(_anonymousobjnum++));
00162 if (!obj)
00163 {
00164 error(efmt_bad_tag, element, true);
00165 _abort = true;
00166 return;
00167 }
00168
00169 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00170 {
00171 obj_out("composite (1)", _stack.top());
00172 obj_out("adding to composite (1)", obj);
00173 }
00174 if (!test_composition(_stack.top()))
00175 return;
00176 if (!_stack.top()->composition()->composite()->add(obj, true))
00177 {
00178 error(efmt_bad_aggr_obj, obj_name(_stack.top()), obj_type(_stack.top()), true);
00179 _abort = true;
00180 return;
00181 }
00182
00183 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00184 obj_out("pushing anonymous", obj);
00185 _stack.push(obj);
00186 }
00187 }
00188 else if (_import)
00189 {
00190
00191
00192
00193
00194
00195 if (element == "name")
00196 _import->_rootname = expectedattr(atts, "value");
00197 else if (element == "param")
00198 {
00199
00200 _import->add_param(
00201 dosubs(expectedattr(atts, "name")),
00202 dosubs(expectedattr(atts, "value")));
00203 }
00204 else if (element == "pathparam")
00205 {
00206
00207
00208
00209 std::string pathstr = dosubs(expectedattr(atts, "value"));
00210
00211 try
00212 {
00213 boost::filesystem::path p = pathstr;
00214 if (!p.is_complete())
00215 p = _streampath.branch_path() / p;
00216 _import->add_param(dosubs(expectedattr(atts, "name")), p.string());
00217 }
00218 catch (...)
00219 {
00220 error(efmt_bad_path, element, pathstr, true);
00221 _abort = true;
00222 return;
00223 }
00224 }
00225 }
00226 else if (_delayed_obj)
00227 {
00228
00229
00230
00231
00232
00233 if (element == "name")
00234 {
00235
00236 _delayed_obj->setname(expectedattr(atts, "value"));
00237 }
00238 else if (element == "param")
00239 {
00240
00241 _delayed_obj->addparam(
00242 dosubs(expectedattr(atts, "name")),
00243 dosubs(expectedattr(atts, "value")));
00244 }
00245 else if (element == "pathparam")
00246 {
00247
00248
00249
00250 std::string pathstr = dosubs(expectedattr(atts, "value"));
00251
00252 try
00253 {
00254 boost::filesystem::path p = pathstr;
00255 if (!p.is_complete())
00256 p = _streampath.branch_path() / p;
00257 _delayed_obj->addparam(dosubs(expectedattr(atts, "name")), p.string());
00258 }
00259 catch (...)
00260 {
00261 error(efmt_bad_path, element, pathstr, true);
00262 _abort = true;
00263 return;
00264 }
00265 }
00266 }
00267 else
00268 {
00269
00270
00271 if (element == S("import") || element == S("xi:include"))
00272 {
00273 xmlstring url = attr(atts, "href");
00274
00275 if (url.empty())
00276 url = expectedattr(atts, "url");
00277 xmlstring name = attr(atts, "name");
00278
00279
00280 url = dosubs(url);
00281 name = dosubs(name);
00282
00283 if (_context->delayed_import())
00284 {
00285
00286
00287 boost::filesystem::path p(url, boost::filesystem::no_check);
00288 if (!p.is_complete())
00289 p = _streampath.branch_path() / p;
00290
00291
00292 ph::common::object_base *obj = _context->create_delayed(_errorhandler,
00293 p, name, _debug);
00294 if (obj)
00295 {
00296
00297
00298 _delayed_obj = obj->importable();
00299 if (!_delayed_obj)
00300 {
00301 error(efmt_fail_not_importable, true);
00302 _abort = true;
00303 return;
00304 }
00305 }
00306 else
00307 {
00308 error(efmt_fail_create_delayed, url, name, true);
00309 _abort = true;
00310 return;
00311 }
00312
00313 if (_stack.empty())
00314 {
00315 error(efmt_import_is_root, true);
00316 _abort = true;
00317 return;
00318 }
00319 else
00320 {
00321
00322 if (!test_composition(_stack.top()))
00323 return;
00324 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00325 {
00326 obj_out("composite (2)", _stack.top());
00327 obj_out("adding to composite (2)", obj);
00328 }
00329 if (!_stack.top()->composition()->composite()->add(obj, true))
00330 {
00331 error(efmt_bad_aggr_obj, obj_name(_stack.top()), obj_type(_stack.top()), true);
00332 _abort = true;
00333 return;
00334 }
00335 }
00336 if (_debug & PARSEOBJ_DELAYED_DEBUG)
00337 *_errorhandler << ">> [" << p.string() << "] delaying." << std::endl;
00338 _stack.push(obj);
00339 }
00340 else
00341 {
00342 if (_import)
00343 {
00344 error(efmt_bad_import, url, true);
00345 _abort = true;
00346 return;
00347 }
00348
00349
00350
00351 boost::filesystem::path p(url, boost::filesystem::no_check);
00352 _importstreampath = p;
00353 if (!_importstreampath.is_complete())
00354 _importstreampath = _streampath.branch_path() / _importstreampath;
00355 _importstream = new std::ifstream(_importstreampath.native_file_string().c_str());
00356
00357
00358 _import = new parseobj(this, _importstream, _importstreampath, _context,
00359 _errorhandler, _rootpath, _silent, _debug);
00360
00361 if (name != "")
00362 _import->_rootname = name;
00363 }
00364 }
00365 else if (element == S("fragment"))
00366 {
00367 xmlstring location = expectedattr(atts, "location");
00368 if (_fragment)
00369 {
00370 error(efmt_bad_fragment, location, true);
00371 _abort = true;
00372 return;
00373 }
00374
00375 ph::common::object_base *c = _context->find_composite_object(_root, _root, location);
00376 if (!c)
00377 {
00378 error(efmt_bad_location, location, true);
00379 _abort = true;
00380 return;
00381 }
00382
00383 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00384 obj_out("pushing composite", c);
00385 _stack.push(c);
00386 _fragment = true;
00387 }
00388 else if (element == S("var"))
00389 {
00390
00391
00392 add_param(
00393 dosubs(expectedattr(atts, "name")),
00394 dosubs(expectedattr(atts, "value")));
00395 }
00396 else if (element == S("pathvar"))
00397 {
00398
00399
00400
00401 std::string pathstr = dosubs(expectedattr(atts, "value"));
00402
00403 try
00404 {
00405 boost::filesystem::path p = pathstr;
00406 if (!p.is_complete())
00407 p = _streampath.branch_path() / p;
00408 add_param(dosubs(expectedattr(atts, "name")), p.string());
00409 }
00410 catch (...)
00411 {
00412 error(efmt_bad_path, element, pathstr, true);
00413 _abort = true;
00414 return;
00415 }
00416 }
00417 else
00418 {
00419 if (arg == s_objname)
00420 {
00421 xmlstring val = attrval(atts, 0);
00422
00423
00424 ph::common::object_base *obj = 0;
00425
00426 if (_stack.empty())
00427 {
00428
00429
00430
00431
00432
00433
00434 if (_outer && !_outer->_stack.empty())
00435 obj = create_object(_outer->_stack.top(), element, val);
00436
00437 if (!obj)
00438 obj = _context->create(element, val);
00439
00440 if (!obj)
00441 {
00442 error(efmt_fail_create_root, element, val, true);
00443 _abort = true;
00444 return;
00445 }
00446
00447
00448 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00449 obj_out("stashing as root", obj);
00450
00451 _root = obj;
00452
00453
00454
00455 if (_rootouter)
00456 if (_root->outerable())
00457 _root->outerable()->outer(_rootouter);
00458
00459
00460 if (!test_persistable(_root))
00461 return;
00462 _root->persistable()->set_file_path(_streampath.string());
00463 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00464 obj_out("setting the path to [" + _streampath.string() + "]", obj);
00465 }
00466 else
00467 {
00468
00469 if (!test_composition(_stack.top()))
00470 return;
00471
00472
00473 obj = create_object(_stack.top(), element, val);
00474
00475
00476 if (!obj)
00477 {
00478 error(efmt_fail_create, element, val, true);
00479 _abort = true;
00480 return;
00481 }
00482
00483 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00484 {
00485 obj_out("composite (3)", _stack.top());
00486 obj_out("adding to composite (3)", obj);
00487 }
00488
00489 if (!_stack.top()->composition()->composite()->add(obj, true))
00490 {
00491 error(efmt_bad_aggr_obj, obj_name(_stack.top()), obj_type(_stack.top()), true);
00492 _abort = true;
00493 return;
00494 }
00495 }
00496
00497 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00498 obj_out("pushing obj with name", obj);
00499 _stack.push(obj);
00500 }
00501 else if (_stack.empty())
00502 {
00503 error(efmt_bad_stack, true);
00504 _abort = true;
00505 }
00506 else
00507 {
00508 error(efmt_bad_tag, element, true);
00509 _abort = true;
00510 }
00511 }
00512 }
00513 }
00514
00515 void xml::parseobj::cdata_handler(const xmlstring &s, int len)
00516 {
00517 if (_abort)
00518 return;
00519
00520 if (_debug & (PARSEOBJ_DATA_DEBUG | PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00521 *_errorhandler << ">> cdata : [" << s << "]" << std::endl;
00522
00523 _cdata += s;
00524 }
00525
00526 void xml::parseobj::comment_handler(const xmlstring &s)
00527 {
00528 if (_abort)
00529 return;
00530
00531 if (_debug & (PARSEOBJ_DATA_DEBUG | PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00532 *_errorhandler << ">> comment : [" << s << "]" << std::endl;
00533
00534 _comment = s;
00535 }
00536
00537 void xml::parseobj::endelement_handler(const xmlstring &element)
00538 {
00539 if (_abort)
00540 return;
00541
00542 if (_debug & (PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00543 *_errorhandler << ">> endelement : [" << element << "]" << std::endl;
00544
00545 if (_stack.empty())
00546 {
00547 error(efmt_bad_stack, true);
00548 _abort = true;
00549 return;
00550 }
00551
00552 if (element == S("import") || element == S("xi:include"))
00553 {
00554 if (_context->delayed_import())
00555 {
00556
00557 if (!_delayed_obj)
00558 {
00559 error(efmt_bad_endimport, element, true);
00560 _abort = true;
00561 return;
00562 }
00563 ph::common::object_base *obj = _stack.top();
00564 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00565 obj_out("popping because delayed", obj);
00566
00567 _stack.pop();
00568 _delayed_obj = 0;
00569 }
00570 else
00571 {
00572 if (!_import)
00573 {
00574 error(efmt_bad_endimport, element, true);
00575 _abort = true;
00576 return;
00577 }
00578
00579 if (!parse::parse_xml(_importstream, _importstreampath.string(), _import, 0))
00580 {
00581 error(efmt_bad_urlstream, element, true);
00582 _abort = true;
00583 return;
00584 }
00585
00586 ph::common::object_base *obj = _import->obj();
00587 if (!obj)
00588 {
00589 error(efmt_bad_import, _importstreampath.string(), true);
00590 _abort = true;
00591 return;
00592 }
00593
00594
00595 if (!_import->_rootname.empty())
00596 set_persistable_obj_name(obj, _import->_rootname);
00597
00598
00599 if (!test_persistable(obj))
00600 return;
00601 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00602 obj_out("setting the path to [" + _importstreampath.string() + "]", obj);
00603
00604 obj->persistable()->set_file_path(_importstreampath.string());
00605
00606
00607 if (!test_composition(_stack.top()))
00608 return;
00609
00610 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00611 {
00612 obj_out("composite (4)", _stack.top());
00613 obj_out("adding to composite (4)", obj);
00614 }
00615
00616 if (!_stack.top()->composition()->composite()->add(obj, true))
00617 {
00618 error(efmt_bad_aggr_obj, obj_name(_stack.top()), obj_type(_stack.top()), true);
00619 _abort = true;
00620 return;
00621 }
00622
00623
00624 delete _importstream;
00625 _importstream = 0;
00626 delete _import;
00627 _import = 0;
00628 }
00629 }
00630 else if (element == "param")
00631 {
00632
00633 }
00634 else if (element == "pathparam")
00635 {
00636
00637 }
00638 else if (element == "var")
00639 {
00640
00641 }
00642 else if (element == "pathvar")
00643 {
00644
00645 }
00646 else if (element == S("fragment"))
00647 {
00648 if (!_fragment)
00649 {
00650 error(efmt_bad_endfragment, element, true);
00651 _abort = true;
00652 return;
00653 }
00654
00655
00656 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00657 obj_out("popping", _stack.top());
00658 _stack.pop();
00659 _fragment = false;
00660 }
00661 else if (_inmember)
00662 {
00663 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00664 obj_out("setting member [" + element + "] of ", _stack.top());
00665 if (!test_persistable(_stack.top()))
00666 return;
00667
00668 try {
00669 _stack.top()->persistable()->set(element, dosubs(_cdata));
00670 }
00671 catch (...)
00672 {
00673 error(efmt_bad_data, element, _cdata, true);
00674 _abort = true;
00675 return;
00676 }
00677 if (_debug & (PARSEOBJ_DATA_DEBUG | PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00678 *_errorhandler << ">> emptying cdata." << std::endl;
00679 _cdata = "";
00680 _inmember = false;
00681 }
00682 else
00683 {
00684 ph::common::object_base *obj = _stack.top();
00685 if (obj_type(obj) == element)
00686 {
00687
00688 if (_cdata.find_first_not_of(" \t\n") != std::string::npos)
00689 *_errorhandler << ">> Ignoring cdata. [" << _cdata << "]" << std::endl;
00690
00691
00692 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00693 obj_out("closing out ", obj);
00694 _stack.pop();
00695
00696 if (_stack.empty())
00697 {
00698
00699 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00700 obj_out("stashing as _obj", obj);
00701 _obj = obj;
00702 }
00703 }
00704 else if (obj->composition() && obj->composition()->composite())
00705 {
00706 if (obj_name(obj) != element)
00707 {
00708 error(efmt_bad_tag, element, true);
00709 _abort = true;
00710 return;
00711 }
00712
00713 if (_cdata.find_first_not_of(" \t\n") != std::string::npos)
00714 {
00715 if (obj->composition()->composite()->singleton()
00716 && obj->composition()->composite()->count() == 0)
00717 {
00718
00719 ph::common::object_base *o = _context->find_object(_root, obj, _cdata);
00720 if (!o)
00721 {
00722 error(efmt_bad_ref_location, _cdata, true);
00723 _abort = true;
00724 return;
00725 }
00726
00727 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00728 {
00729 obj_out("composite (5)", obj);
00730 obj_out("adding to composite (5)", o);
00731 }
00732
00733
00734 if (!obj->composition()->composite()->add(o, false))
00735 {
00736 error(efmt_bad_aggr_obj, obj_name(obj), obj_type(obj), true);
00737 _abort = true;
00738 return;
00739 }
00740
00741
00742 if (_debug & (PARSEOBJ_DATA_DEBUG | PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00743 *_errorhandler << ">> emptying cdata." << std::endl;
00744 _cdata = "";
00745
00746 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00747 obj_out("popping because composite", obj);
00748
00749 _stack.pop();
00750 }
00751 else
00752 {
00753
00754
00755
00756
00757
00758
00759 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00760 obj_out("popping because composite (possible member?)", obj);
00761
00762 _stack.pop();
00763 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00764 obj_out("setting member [" + element + "] of ", _stack.top());
00765 if (!test_persistable(_stack.top()))
00766 return;
00767 try
00768 {
00769 _stack.top()->persistable()->set(element, dosubs(_cdata));
00770 }
00771 catch (...)
00772 {
00773 error(efmt_bad_data, element, _cdata, true);
00774 _abort = true;
00775 return;
00776 }
00777 if (_debug & (PARSEOBJ_DATA_DEBUG | PARSEOBJ_ELEMENT_DEBUG | PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00778 *_errorhandler << ">> emptying cdata." << std::endl;
00779 _cdata = "";
00780 }
00781 }
00782 else
00783 {
00784 if (_debug & (PARSEOBJ_STACK_DEBUG | PARSEOBJ_OBJECT_DEBUG))
00785 obj_out("popping because composite", obj);
00786
00787 _stack.pop();
00788 }
00789 }
00790 else
00791 {
00792 error(efmt_bad_tag, element, true);
00793 _abort = true;
00794 }
00795 }
00796 }
00797
00798 ph::common::object_base *xml::parseobj::create_object(ph::common::object_base *top, const xmlstring &type, const xmlstring &name)
00799 {
00800
00801
00802
00803 ph::common::object_base *topsearch = top;
00804 if (top->composition() && top->composition()->composite())
00805 {
00806 if (!test_outerable(top))
00807 return 0;
00808 topsearch = top->outerable()->outer();
00809 }
00810
00811 if (_debug & PARSEOBJ_OBJECT_DEBUG)
00812 *_errorhandler << ">> create_object type: [" << type
00813 << "] name: [" << name
00814 << "] top->name: [" << obj_name(top) << "]" << std::endl;
00815
00816
00817 if (!test_persistable(top))
00818 return 0;
00819 ph::common::object_base *obj = topsearch->persistable()->create(type, name, _context);
00820
00821
00822 if (!obj)
00823 obj = _context->create(type, name);
00824
00825 if (obj)
00826 {
00827
00828
00829 if (obj->outerable())
00830 obj->outerable()->outer(top);
00831 }
00832
00833 return obj;
00834 }
00835
00836 xmlstring xml::parseobj::dosubs(const xmlstring &s)
00837
00838
00839
00840
00841
00842 {
00843 xmlstring remain = s;
00844 xmlstring news = S("");
00845 int loc = remain.find(S("$("));
00846 if (loc >= 0)
00847 {
00848 while (loc >= 0)
00849 {
00850 news += remain.substr(0, loc);
00851 remain = remain.substr(loc);
00852 loc = remain.find(L')');
00853 if (loc >= 0)
00854 {
00855 xmlstring token = remain.substr(2, loc-2);
00856 remain = remain.substr(loc+1);
00857
00858 std::string value;
00859 if (find_param(token, &value))
00860 news += value;
00861 else
00862 news += S("$(") + token + S(")");
00863 }
00864 loc = remain.find(S("$("));
00865 }
00866 news += remain;
00867 }
00868
00869 if (news.empty())
00870 return s;
00871 else
00872 return news;
00873 }
00874
00875 void xml::parseobj::add_params(const std::map<std::string, std::string> ¶ms)
00876 {
00877
00878 std::for_each(params.begin(), params.end(),
00879 boost::bind(&add_param_1,
00880 &_params,
00881 boost::bind(&std::map<std::string, std::string>::value_type::first, _1),
00882 boost::bind(&std::map<std::string, std::string>::value_type::second, _1)));
00883 }
00884
00885 void xml::parseobj::add_param_1(std::map<std::string, std::string> *params,
00886 const std::string &name, const std::string &val)
00887 {
00888 (*params)[name] = val;
00889 }
00890
00891 void xml::parseobj::add_param(const std::string &name, const std::string &val)
00892 {
00893 add_param_1(&_params, name, val);
00894 }
00895
00896 bool xml::parseobj::find_param(const std::string &name, std::string *value)
00897 {
00898 std::map<std::string, std::string>::iterator i = _params.find(name);
00899 if (i == _params.end())
00900 return false;
00901 *value = i->second;
00902 return true;
00903 }
00904
00905 bool xml::parseobj::test_outerable(ph::common::object_base *obj)
00906 {
00907 if (!obj->outerable())
00908 {
00909 error(efmt_no_interface, "outerable", obj_name(obj), true);
00910 _abort = true;
00911 return false;
00912 }
00913 return true;
00914 }
00915
00916 bool xml::parseobj::test_persistable(ph::common::object_base *obj)
00917 {
00918 if (!obj->persistable())
00919 {
00920 error(efmt_no_interface, "persistable", obj_name(obj), true);
00921 _abort = true;
00922 return false;
00923 }
00924 return true;
00925 }
00926
00927 bool xml::parseobj::test_composition(ph::common::object_base *obj)
00928 {
00929 if (!obj->composition())
00930 {
00931 error(efmt_no_interface, "composition", obj_name(obj), true);
00932 _abort = true;
00933 return false;
00934 }
00935 if (!obj->composition()->composite())
00936 {
00937 error(efmt_not_composite, obj_name(obj), true);
00938 _abort = true;
00939 return false;
00940 }
00941 return true;
00942 }
00943
00944 void xml::parseobj::obj_out(const std::string &msg, ph::common::object_base *obj)
00945 {
00946 *_errorhandler << ">> " << msg << " [" << obj_type(obj) << ", " << obj_name(obj) << "]" << std::endl;
00947 }
00948
00949 void xml::parseobj::element_out(const std::string &msg, const xmlstring &element)
00950 {
00951 *_errorhandler << ">> " << msg << " [" << element << "]" << std::endl;
00952 }
00953
00954
00955 xmlstring xml::parseobj::getdecodedattrval(const std::vector<xmlstring> &atts, int index)
00956 {
00957 xmlstring val = attrval(atts, index);
00958 xmlstring news;
00959 if (decodexmldata(val, &news))
00960 return news;
00961 else
00962 return val;
00963 }
00964
00965 xmlstring xml::parseobj::getdecodedexpectedattr(const std::vector<xmlstring> &atts, const xmlstring &token)
00966 {
00967 xmlstring val = expectedattr(atts, token);
00968 xmlstring news;
00969 if (decodexmldata(val, &news))
00970 return news;
00971 else
00972 return val;
00973 }
00974
00975 xmlstring xml::parseobj::getdecodedattr(const std::vector<xmlstring> &atts, const xmlstring &token)
00976 {
00977 xmlstring val = attr(atts, token);
00978 xmlstring news;
00979 if (decodexmldata(val, &news))
00980 return news;
00981 else
00982 return val;
00983 }