diff options
author | randomdan <randomdan@localhost> | 2011-12-14 21:42:31 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2011-12-14 21:42:31 +0000 |
commit | 8a7980bff41ccb8dc42b18eb1edd4b3938977fc3 (patch) | |
tree | 4b0a3414ba881a3118630c41ca24129d23f996df | |
parent | Don't write JSON numbers in scientific notation, use native C++ boolalpha for... (diff) | |
download | project2-8a7980bff41ccb8dc42b18eb1edd4b3938977fc3.tar.bz2 project2-8a7980bff41ccb8dc42b18eb1edd4b3938977fc3.tar.xz project2-8a7980bff41ccb8dc42b18eb1edd4b3938977fc3.zip |
Pluggable script engines
XML script parser moved to XML module
Script parsing object multiple instantiation bug fix
Scripts changed to match new standardized format and layout
159 files changed, 1219 insertions, 928 deletions
diff --git a/project2/cgi/Jamfile.jam b/project2/cgi/Jamfile.jam index 48225cb..017dd11 100644 --- a/project2/cgi/Jamfile.jam +++ b/project2/cgi/Jamfile.jam @@ -1,6 +1,7 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib boost_filesystem : : <name>boost_filesystem ; lib cgicc : : <name>cgicc ; lib fcgi : : <name>fcgi ; @@ -9,7 +10,7 @@ lib fcgi++ : : <name>fcgi++ ; cpp-pch pch : pch.hpp : <include>../../libmisc <library>cgicc - <library>libxmlpp + <library>glibmm <library>../common//p2common <library>boost_filesystem <library>../xml//p2xml @@ -20,7 +21,7 @@ lib p2web : : <include>../libmisc <library>cgicc - <library>libxmlpp + <library>glibmm <library>../common//p2common <library>boost_filesystem <library>../xml//p2xml diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 7fd7c33..4d91069 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -56,15 +56,15 @@ CgiApplicationEngine::process() const currentStage = currentStage.get<0>()->run(); } catch (const CheckHost::CheckFailure & cf) { - currentStage = NextStage(new PresentStage(_env, _env->resolveScript(_env->presentRoot, cf.failedCheck->present()))); + currentStage = NextStage(new PresentStage(_env, _env->resolveScript(_env->presentRoot, cf.failedCheck->present(), false))); } - catch (const XmlScriptParser::NotFound & nf) { + catch (const ScriptNotFound & nf) { if (_env->notFoundPresent.empty() || triedNotFound) { currentStage = NextStage(new DefaultNotFoundStage(_env, nf)); } else { triedNotFound = true; - currentStage = NextStage(new CustomNotFoundStage(_env, nf)); + currentStage = NextStage(new CustomNotFoundStage(_env, nf, _env->resolveScript(_env->errorPresentRoot, _env->notFoundPresent, false))); } } catch (const std::exception & ex) { @@ -73,7 +73,7 @@ CgiApplicationEngine::process() const } else { triedNotFound = true; - currentStage = NextStage(new CustomErrorStage(_env, ex)); + currentStage = NextStage(new CustomErrorStage(_env, ex, _env->resolveScript(_env->errorPresentRoot, _env->onErrorPresent, false))); } } } while (currentStage.get<0>()); diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index 25d3b93..f4b3896 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -88,7 +88,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Stage to process POST requests class RequestStage : public ResponseStage, TaskHost { public: - RequestStage(const CgiEnvironment *, const boost::filesystem::path & path); + RequestStage(const CgiEnvironment *, ScriptReaderPtr); virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; @@ -99,7 +99,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Stage to process GET requests and follow up RequestStages class PresentStage : public virtual ResponseStage, ViewHost { public: - PresentStage(const CgiEnvironment * e, const boost::filesystem::path & path); + PresentStage(const CgiEnvironment * e, ScriptReaderPtr); virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; @@ -108,19 +108,19 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// The built-in fail-safe not found stage class DefaultNotFoundStage : public virtual ResponseStage { public: - DefaultNotFoundStage(const CgiEnvironment *, const XmlScriptParser::NotFound &); + DefaultNotFoundStage(const CgiEnvironment *, const ScriptNotFound &); virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; private: - const XmlScriptParser::NotFound nf; + const ScriptNotFound nf; XmlPresenterPtr pres; }; /// Custom not found handling stage class CustomNotFoundStage : public DefaultNotFoundStage, public PresentStage { public: - CustomNotFoundStage(const CgiEnvironment *, const ::XmlScriptParser::NotFound &); + CustomNotFoundStage(const CgiEnvironment *, const ScriptNotFound &, ScriptReaderPtr); virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; }; @@ -142,7 +142,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Custom unhandled error handling stage class CustomErrorStage : public DefaultErrorStage, public PresentStage { public: - CustomErrorStage(const CgiEnvironment *, const std::exception &); + CustomErrorStage(const CgiEnvironment *, const std::exception &, ScriptReaderPtr); virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; }; diff --git a/project2/cgi/cgiOutputOptions.cpp b/project2/cgi/cgiOutputOptions.cpp index add1671..f9a6d86 100644 --- a/project2/cgi/cgiOutputOptions.cpp +++ b/project2/cgi/cgiOutputOptions.cpp @@ -1,4 +1,5 @@ #include "cgiOutputOptions.h" +#include "scripts.h" bool OutputOptions::core; bool OutputOptions::session; @@ -7,13 +8,13 @@ bool OutputOptions::environment; bool OutputOptions::url; bool OutputOptions::parameters; -OutputOptions::OutputOptions(const xmlpp::Element * p) : - Core(p, "core", false, core), - Session(p, "session", false, session), - Timing(p, "timing", false, timing), - Environment(p, "environment", false, environment), - URL(p, "url", false, url), - Parameters(p, "parameters", false, parameters) +OutputOptions::OutputOptions(ScriptNodePtr p) : + Core(p, "core", core), + Session(p, "session", session), + Timing(p, "timing", timing), + Environment(p, "environment", environment), + URL(p, "url", url), + Parameters(p, "parameters", parameters) { } @@ -31,7 +32,7 @@ OutputOptionsLoader::OutputOptionsLoader() : } OutputOptionsPtr -OutputOptionsLoader::createFrom(const xmlpp::Element * e) const { +OutputOptionsLoader::createFrom(ScriptNodePtr e) const { return new OutputOptions(e); } diff --git a/project2/cgi/cgiOutputOptions.h b/project2/cgi/cgiOutputOptions.h index a1ff62d..07b7598 100644 --- a/project2/cgi/cgiOutputOptions.h +++ b/project2/cgi/cgiOutputOptions.h @@ -11,7 +11,7 @@ namespace xmlpp { class OutputOptions : public IntrusivePtrBase { public: - OutputOptions(const xmlpp::Element *); + OutputOptions(ScriptNodePtr); const Variable Core; const Variable Session; @@ -35,7 +35,7 @@ typedef boost::intrusive_ptr<OutputOptions> OutputOptionsPtr; class OutputOptionsLoader : public ComponentLoader { public: OutputOptionsLoader(); - OutputOptionsPtr createFrom(const xmlpp::Element * e) const; + OutputOptionsPtr createFrom(ScriptNodePtr e) const; const Options * options() const; private: diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp index 8b4b347..82fc6a1 100644 --- a/project2/cgi/cgiStageCustomError.cpp +++ b/project2/cgi/cgiStageCustomError.cpp @@ -4,12 +4,12 @@ #include "cgiHttpHeader.h" #include "logger.h" -CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const CgiEnvironment * env, const std::exception & ex) : +CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const CgiEnvironment * env, const std::exception & ex, ScriptReaderPtr s) : CgiApplicationEngine::ResponseStage(env), - ::XmlScriptParser(e->resolveScript(env->errorPresentRoot, env->onErrorPresent), false), - ::CheckHost(e->resolveScript(env->errorPresentRoot, env->onErrorPresent)), + ::CommonObjects(s), + ::CheckHost(s), CgiApplicationEngine::DefaultErrorStage(env, ex), - CgiApplicationEngine::PresentStage(env, e->resolveScript(env->errorPresentRoot, env->onErrorPresent)) + CgiApplicationEngine::PresentStage(env, s) { } diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp index fc49804..8a224fa 100644 --- a/project2/cgi/cgiStageCustomNotFound.cpp +++ b/project2/cgi/cgiStageCustomNotFound.cpp @@ -4,12 +4,12 @@ #include "cgiHttpHeader.h" #include "logger.h" -CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const ::XmlScriptParser::NotFound & notfound) : +CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const ScriptNotFound & notfound, ScriptReaderPtr s) : CgiApplicationEngine::ResponseStage(env), - ::XmlScriptParser(e->resolveScript(env->errorPresentRoot, env->notFoundPresent), false), - ::CheckHost(e->resolveScript(env->errorPresentRoot, env->notFoundPresent)), + ::CommonObjects(s), + ::CheckHost(s), CgiApplicationEngine::DefaultNotFoundStage(env, notfound), - CgiApplicationEngine::PresentStage(env, e->resolveScript(env->errorPresentRoot, env->notFoundPresent)) + CgiApplicationEngine::PresentStage(env, s) { } diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp index 38cc395..d05c92b 100644 --- a/project2/cgi/cgiStageDefaultNotFound.cpp +++ b/project2/cgi/cgiStageDefaultNotFound.cpp @@ -6,7 +6,7 @@ static const Glib::ustring DefaultNotFoundStageResp("notfound"); -CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnvironment * env, const XmlScriptParser::NotFound & notfound) : +CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnvironment * env, const ScriptNotFound & notfound) : CgiApplicationEngine::ResponseStage(env), nf(notfound), pres(new XmlPresenter(DefaultNotFoundStageResp, e->errorTransformStyle, e->errorContentType)) diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp index 87aba66..62de295 100644 --- a/project2/cgi/cgiStageFail.cpp +++ b/project2/cgi/cgiStageFail.cpp @@ -31,11 +31,11 @@ namespace CgiApplicationExtras { class CgiFail : public View { public: - CgiFail(const xmlpp::Element * e) : + CgiFail(ScriptNodePtr e) : SourceObject(e), View(e), - code(e, "code", false, 500), - message(e, "message", false, "Application error") { + code(e, "code", 500), + message(e, "message", "Application error") { } void execute(const MultiRowSetPresenter *) const { throw CgiApplicationEngine::ResponseStagePtr( diff --git a/project2/cgi/cgiStageInitial.cpp b/project2/cgi/cgiStageInitial.cpp index b263110..0fe81d4 100644 --- a/project2/cgi/cgiStageInitial.cpp +++ b/project2/cgi/cgiStageInitial.cpp @@ -17,12 +17,10 @@ CgiApplicationEngine::InitialStage::run() if (e->elems.empty()) { throw EmptyRequestURL(); } - return NextStage(new RequestStage(e, e->resolveScript(e->requestRoot, - e->getRedirectURL()))); + return NextStage(new RequestStage(e, e->resolveScript(e->requestRoot, e->getRedirectURL(), false))); } else { - return NextStage(new PresentStage(e, e->resolveScript(e->presentRoot, - e->elems.empty() ? e->defaultPresent : e->getRedirectURL()))); + return NextStage(new PresentStage(e, e->resolveScript(e->presentRoot, e->elems.empty() ? e->defaultPresent : e->getRedirectURL(), false))); } } diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp index 54b0e02..8eb0487 100644 --- a/project2/cgi/cgiStagePresent.cpp +++ b/project2/cgi/cgiStagePresent.cpp @@ -5,13 +5,13 @@ #include <boost/foreach.hpp> #include <boost/bind.hpp> -CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, const boost::filesystem::path & path) : +CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, ScriptReaderPtr s) : CgiApplicationEngine::ResponseStage(e), - XmlScriptParser(path, false), - CheckHost(path), - ViewHost(path) + CommonObjects(s), + CheckHost(s), + ViewHost(s) { - loader.supportedStorers.insert(Storer::into<OutputOptionsLoader>(&outputOptions)); + s->loader.addLoadTarget(s->root(), Storer::into<OutputOptionsLoader>(&outputOptions)); } CgiApplicationEngine::NextStage diff --git a/project2/cgi/cgiStageRedirect.cpp b/project2/cgi/cgiStageRedirect.cpp index f72e986..8c918f1 100644 --- a/project2/cgi/cgiStageRedirect.cpp +++ b/project2/cgi/cgiStageRedirect.cpp @@ -29,10 +29,10 @@ namespace CgiApplicationExtras { class CgiRedirect : public View { public: - CgiRedirect(const xmlpp::Element * e) : + CgiRedirect(ScriptNodePtr e) : SourceObject(e), View(e), - url(e, "url", true) { + url(e, "url") { } void execute(const MultiRowSetPresenter *) const { throw CgiApplicationEngine::ResponseStagePtr( diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp index 4831a71..99ca956 100644 --- a/project2/cgi/cgiStageRequest.cpp +++ b/project2/cgi/cgiStageRequest.cpp @@ -5,13 +5,13 @@ #include "xmlObjectLoader.h" #include <boost/foreach.hpp> -CgiApplicationEngine::RequestStage::RequestStage(const CgiEnvironment * e, const boost::filesystem::path & path) : - XmlScriptParser(path, false), - SourceObject(get_document()->get_root_node()), - ::CheckHost(path), +CgiApplicationEngine::RequestStage::RequestStage(const CgiEnvironment * e, ScriptReaderPtr s) : + SourceObject(s->root()), + CommonObjects(s), + ::CheckHost(s), CgiApplicationEngine::ResponseStage(e), - ::TaskHost(path), - present(get_document()->get_root_node()->get_attribute_value("present")) + ::TaskHost(s), + present(s->root()->value("present","").as<std::string>()) { } @@ -20,7 +20,7 @@ CgiApplicationEngine::RequestStage::run() { runChecks(); execute(); - return NextStage(present.empty() ? NULL : new PresentStage(e, e->resolveScript(e->presentRoot, present)), this); + return NextStage(present.empty() ? NULL : new PresentStage(e, e->resolveScript(e->presentRoot, present, false)), this); } const std::string contentType = "text/plain"; diff --git a/project2/common/Jamfile.jam b/project2/common/Jamfile.jam index 4964ea1..5c6cfc7 100644 --- a/project2/common/Jamfile.jam +++ b/project2/common/Jamfile.jam @@ -1,6 +1,7 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib dl : : <name>dl ; lib boost_system : : <name>boost_system ; lib boost_filesystem : : <name>boost_filesystem ; @@ -8,7 +9,7 @@ lib boost_date_time : : <name>boost_date_time ; cpp-pch pch : pch.hpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm ; lib p2common : pch @@ -18,7 +19,7 @@ lib p2common : ../../libmisc/misc.cpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>dl <library>boost_system <library>boost_filesystem diff --git a/project2/common/cache.cpp b/project2/common/cache.cpp index 7ad4053..f5edc43 100644 --- a/project2/common/cache.cpp +++ b/project2/common/cache.cpp @@ -5,10 +5,10 @@ #include "logger.h" #include <boost/foreach.hpp> -Cache::Cache(const xmlpp::Element * p) : +Cache::Cache(ScriptNodePtr p) : IHaveParameters(p), SourceObject(p), - inherit(p->get_attribute_value("inherit") != "false") + inherit(p->value("inherit", true).as<bool>()) { } diff --git a/project2/common/cache.h b/project2/common/cache.h index eff24b0..2c438b8 100644 --- a/project2/common/cache.h +++ b/project2/common/cache.h @@ -12,7 +12,7 @@ typedef boost::intrusive_ptr<const RowSet> RowSetCPtr; class Cache : public IHaveParameters, public SourceObject { public: - Cache(const xmlpp::Element * p); + Cache(ScriptNodePtr p); bool checkAndExecute(const Glib::ustring &, const Glib::ustring &, const RowProcessor *); virtual RowSetPresenterPtr openFor(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; diff --git a/project2/common/checkHost.cpp b/project2/common/checkHost.cpp index 343b255..4f2ab44 100644 --- a/project2/common/checkHost.cpp +++ b/project2/common/checkHost.cpp @@ -3,10 +3,10 @@ #include "appEngine.h" #include <boost/foreach.hpp> -CheckHost::CheckHost(const boost::filesystem::path & file) : - XmlScriptParser(file, false) +CheckHost::CheckHost(ScriptReaderPtr s) : + CommonObjects(s) { - loader.supportedStorers.insert(Storer::into<ElementLoader>(¶meterChecks)); + s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(¶meterChecks)); } CheckHost::~CheckHost() @@ -16,7 +16,7 @@ CheckHost::~CheckHost() void CheckHost::runChecks() const { - parseDocument(); + loadScriptComponents(); BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks) { if (!pc->performCheck()) { ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message()); diff --git a/project2/common/checkHost.h b/project2/common/checkHost.h index 54fc96d..9a87aea 100644 --- a/project2/common/checkHost.h +++ b/project2/common/checkHost.h @@ -1,13 +1,13 @@ #ifndef CHECKHOST_H #define CHECKHOST_H -#include "xmlScriptParser.h" #include "paramChecker.h" #include "xmlStorage.h" #include <set> #include <boost/function.hpp> +#include "commonObjects.h" -class CheckHost : public virtual XmlScriptParser { +class CheckHost : virtual public CommonObjects { public: class CheckFailure : std::exception { public: @@ -15,7 +15,7 @@ class CheckHost : public virtual XmlScriptParser { ~CheckFailure() throw(); const ParamCheckerCPtr failedCheck; }; - CheckHost(const boost::filesystem::path & file); + CheckHost(ScriptReaderPtr script); ~CheckHost(); void runChecks() const; diff --git a/project2/common/columns.cpp b/project2/common/columns.cpp index e64a9f8..268a59d 100644 --- a/project2/common/columns.cpp +++ b/project2/common/columns.cpp @@ -1,11 +1,10 @@ #include <pch.hpp> #include "columns.h" -#include <libxml++/nodes/textnode.h> -Column::Column(unsigned int i, const xmlpp::Element * p) : +Column::Column(unsigned int i, ScriptNodePtr p) : idx(i), - name(p->get_attribute("name") ? p->get_attribute_value("name") : p->get_child_text()->get_content()), - defValue(p, "default", false) + name(p->get_name()), + defValue(p, "default", Null()) { } @@ -17,7 +16,7 @@ Column::Column(unsigned int i, const Glib::ustring & n, const Variable & v) : } Column * -Column::make(unsigned int idx, const xmlpp::Element * p) +Column::make(unsigned int idx, ScriptNodePtr p) { return new Column(idx, p); } diff --git a/project2/common/columns.h b/project2/common/columns.h index 8b9b9b3..d0b62d9 100644 --- a/project2/common/columns.h +++ b/project2/common/columns.h @@ -1,7 +1,6 @@ #ifndef COLUMNS_H #define COLUMNS_H -#include <libxml++/nodes/element.h> #include "variables.h" #include <boost/multi_index_container.hpp> #include <boost/multi_index/member.hpp> @@ -9,10 +8,10 @@ class Column : public IntrusivePtrBase { public: - Column(unsigned int idx, const xmlpp::Element * p); + Column(unsigned int idx, ScriptNodePtr p); Column(unsigned int i, const Glib::ustring & n, const Variable & v = Variable(Null())); - static Column * make(unsigned int idx, const xmlpp::Element * p); + static Column * make(unsigned int idx, ScriptNodePtr p); const unsigned int idx; const Glib::ustring name; diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index 4ce8c82..5bfe6bc 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -3,7 +3,16 @@ #include "safeMapFind.h" #include "appEngine.h" #include "xmlObjectLoader.h" -#include "xmlScriptParser.h" + +CommonObjects::CommonObjects() +{ +} + +CommonObjects::CommonObjects(ScriptReaderPtr s) : + script(s) +{ + s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&rowSets)); +} CommonObjects::~CommonObjects() { @@ -18,13 +27,18 @@ CommonObjects::getSource(const std::string & name) const CommonObjects::DataSources::const_iterator CommonObjects::loadDataSource(const std::string & name) const { - XmlScriptParser xml(Environment::getCurrent()->resolveScript( - Environment::getCurrent()->datasourceRoot, name), true); - - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&datasources)); - loader.collectAll(xml.get_document()->get_root_node(), false); - + ScriptReaderPtr dbs = Environment::getCurrent()->resolveScript(Environment::getCurrent()->datasourceRoot, name, true); + dbs->loader.addLoadTarget(dbs->root(), Storer::into<ElementLoader>(&datasources)); + dbs->loader.collectAll(NULL, false, dbs->root()); return safeMapFind<DataSourceNotFound>(datasources, name); } +void +CommonObjects::loadScriptComponents() const +{ + if (script) { + script->loader.collectAll(this, true, script->root()); + script.reset(); + } +} + diff --git a/project2/common/commonObjects.h b/project2/common/commonObjects.h index fe6bd5c..2e00442 100644 --- a/project2/common/commonObjects.h +++ b/project2/common/commonObjects.h @@ -13,7 +13,9 @@ class CommonObjects : public virtual IntrusivePtrBase { SimpleMessageException(DataSourceNotFound); SimpleMessageException(DataSourceNotCompatible); - virtual ~CommonObjects(); + CommonObjects(); + CommonObjects(ScriptReaderPtr script); + ~CommonObjects(); RowSetPtr getSource(const std::string &) const; template <class DataSourceType> @@ -29,9 +31,13 @@ class CommonObjects : public virtual IntrusivePtrBase { } return s; } + void loadScriptComponents() const; + protected: RowSets rowSets; mutable DataSources datasources; + mutable ScriptReaderPtr script; + private: DataSources::const_iterator loadDataSource(const std::string & name) const; }; diff --git a/project2/common/dataSource.cpp b/project2/common/dataSource.cpp index 3fedbd8..cd03300 100644 --- a/project2/common/dataSource.cpp +++ b/project2/common/dataSource.cpp @@ -1,7 +1,7 @@ #include <pch.hpp> #include "dataSource.h" -DataSource::DataSource(const xmlpp::Element * p) : +DataSource::DataSource(ScriptNodePtr p) : SourceObject(p) { } diff --git a/project2/common/dataSource.h b/project2/common/dataSource.h index d8a5a9a..1f557dd 100644 --- a/project2/common/dataSource.h +++ b/project2/common/dataSource.h @@ -10,7 +10,7 @@ typedef boost::intrusive_ptr<DataSource> DataSourcePtr; /// Base class for data sources providing transaction support class DataSource : public SourceObject { public: - DataSource(const xmlpp::Element * p); + DataSource(ScriptNodePtr p); virtual ~DataSource(); virtual void commit() { }; diff --git a/project2/common/definedColumns.cpp b/project2/common/definedColumns.cpp index 2db8f24..cc88939 100644 --- a/project2/common/definedColumns.cpp +++ b/project2/common/definedColumns.cpp @@ -1,16 +1,12 @@ #include <pch.hpp> #include "definedColumns.h" #include <boost/function.hpp> -#include <libxml++/nodes/textnode.h> -DefinedColumns::DefinedColumns(const xmlpp::Element * p, const Glib::ustring & colPath, const ColCreator & func) +DefinedColumns::DefinedColumns(ScriptNodePtr p, const Glib::ustring & colPath, const ColCreator & func) { unsigned int colNo = 0; - BOOST_FOREACH(const xmlpp::Node * node, p->find(colPath)) { - const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); - if (elem) { - columns.insert(func(colNo++, elem)); - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn(colPath)) { + columns.insert(func(colNo++, node)); } } diff --git a/project2/common/definedColumns.h b/project2/common/definedColumns.h index 2fc6bbd..89d42be 100644 --- a/project2/common/definedColumns.h +++ b/project2/common/definedColumns.h @@ -1,7 +1,6 @@ #ifndef DEFINEDCOLUMNS_H #define DEFINEDCOLUMNS_H -#include <libxml++/nodes/element.h> #include <boost/foreach.hpp> #include "variables.h" #include "rowSet.h" @@ -9,8 +8,8 @@ class DefinedColumns { public: - typedef boost::function2<Column *, unsigned int, const xmlpp::Element *> ColCreator; - DefinedColumns(const xmlpp::Element * p, const Glib::ustring & colPath, const ColCreator & func); + typedef boost::function2<Column *, unsigned int, ScriptNodePtr> ColCreator; + DefinedColumns(ScriptNodePtr p, const Glib::ustring & colPath, const ColCreator & func); Columns columns; }; diff --git a/project2/common/environment.cpp b/project2/common/environment.cpp index 18d60a0..e99be54 100644 --- a/project2/common/environment.cpp +++ b/project2/common/environment.cpp @@ -90,20 +90,21 @@ Environment::getCurrent() return currentEnv; } -boost::filesystem::path -Environment::resolveScript(const std::string & group, const std::string & name) const +ScriptReaderPtr +Environment::resolveScript(const std::string & group, const std::string & name, bool ii) const { - boost::filesystem::path script(boost::filesystem::current_path() / group); - BOOST_FOREACH(const boost::filesystem::path & e, boost::filesystem::path(name)) { - if (boost::filesystem::is_directory(script / e)) { - script /= e; - } - else { - if (boost::filesystem::is_regular_file((script / e).replace_extension(".xml"))) { - return ((script / e).replace_extension(".xml")); - } + typedef std::map<std::string, boost::shared_ptr<ScriptReaderLoader> > ReaderLoaders; + BOOST_FOREACH(const ReaderLoaders::value_type & rl, *LoaderBase::objLoaders<ScriptReaderLoader>()) { + ScriptReaderPtr rs = rl.second->resolveScript(group, name); + if (rs) { + return rs; } } - return script; + if (ii) { + throw DependencyNotFound(group, name); + } + else { + throw ScriptNotFound(group, name); + } } diff --git a/project2/common/environment.h b/project2/common/environment.h index 6185178..c2b9474 100644 --- a/project2/common/environment.h +++ b/project2/common/environment.h @@ -7,6 +7,7 @@ #include <boost/filesystem/path.hpp> #include "options.h" #include "exceptions.h" +#include "scripts.h" SimpleMessageException(NoSuchPlatform); @@ -26,7 +27,7 @@ class Environment { virtual std::string getScriptName() const = 0; virtual const Glib::ustring & platform() const = 0; - boost::filesystem::path resolveScript(const std::string & group, const std::string & name) const; + ScriptReaderPtr resolveScript(const std::string & group, const std::string & name, bool ii) const; private: Options commonOptions; diff --git a/project2/common/exceptions.cpp b/project2/common/exceptions.cpp index d347f5f..2fa5509 100644 --- a/project2/common/exceptions.cpp +++ b/project2/common/exceptions.cpp @@ -25,3 +25,26 @@ numeric_error::what() const throw() return buf; } +two_part_error::two_part_error(const std::string & w1, const std::string & w2) : + what1(w1), + what2(w2), + buf(NULL) +{ +} + +two_part_error::~two_part_error() throw() +{ + free(buf); +} + +const char * +two_part_error::what() const throw() +{ + if (!buf) { + if (asprintf(&buf, "%s, %s", what1.c_str(), what2.c_str()) < 1) { + throw std::bad_alloc(); + } + } + return buf; +} + diff --git a/project2/common/exceptions.h b/project2/common/exceptions.h index a9d4952..a45e53d 100644 --- a/project2/common/exceptions.h +++ b/project2/common/exceptions.h @@ -12,6 +12,16 @@ class numeric_error : public std::exception { int err; mutable char * buf; }; +class two_part_error : public std::exception { + public: + two_part_error(const std::string & what1, const std::string & what2); + ~two_part_error() throw(); + const char * what() const throw(); + private: + const std::string what1; + const std::string what2; + mutable char * buf; +}; #define StaticMessageException(Name, Text) \ class Name : public std::runtime_error { \ public: \ @@ -22,6 +32,11 @@ class Name : public std::runtime_error { \ public: \ Name(const std::string & what) : std::runtime_error(what) { } \ } +#define SimpleMessage2Exception(Name) \ +class Name : public two_part_error { \ + public: \ + Name(const std::string & what1, const std::string & what2) : two_part_error(what1, what2) { } \ +} #define SimpleMessageExceptionBase(Name, Base) \ class Name : public Base { \ public: \ diff --git a/project2/common/functions/dates.cpp b/project2/common/functions/dates.cpp index da169cf..8028789 100644 --- a/project2/common/functions/dates.cpp +++ b/project2/common/functions/dates.cpp @@ -11,7 +11,7 @@ class ParseError { }; /// Variable implementation to access platform configuration values class ParseDate : public VariableImplDyn { public: - ParseDate(const xmlpp::Element * e) : + ParseDate(ScriptNodePtr e) : VariableImplDyn(e), string(e, "string"), format(e, "format") @@ -41,7 +41,7 @@ DECLARE_COMPONENT_LOADER("parsedate", ParseDate, VariableLoader); class FormatDate : public VariableImplDyn { public: - FormatDate(const xmlpp::Element * e) : + FormatDate(ScriptNodePtr e) : VariableImplDyn(e), date(e, "date"), format(e, "format") @@ -64,7 +64,7 @@ DECLARE_COMPONENT_LOADER("formatdate", FormatDate, VariableLoader); class AdjustDate : public VariableImplDyn { public: - AdjustDate(const xmlpp::Element * e) : + AdjustDate(ScriptNodePtr e) : VariableImplDyn(e), date(e, "date"), offset(e, "offset") @@ -82,7 +82,7 @@ DECLARE_COMPONENT_LOADER("adjustdate", AdjustDate, VariableLoader); class CurrentDate : public VariableImplDyn { public: - CurrentDate(const xmlpp::Element * e) : + CurrentDate(ScriptNodePtr e) : VariableImplDyn(e) { } diff --git a/project2/common/functions/strings.cpp b/project2/common/functions/strings.cpp index 1272c6c..d2967d2 100644 --- a/project2/common/functions/strings.cpp +++ b/project2/common/functions/strings.cpp @@ -6,7 +6,7 @@ /// Variable implementation to access platform configuration values class Trim : public VariableImplDyn { public: - Trim(const xmlpp::Element * e) : + Trim(ScriptNodePtr e) : VariableImplDyn(e), string(e, "string") { diff --git a/project2/common/iHaveParameters.cpp b/project2/common/iHaveParameters.cpp index cded7e1..5272e5f 100644 --- a/project2/common/iHaveParameters.cpp +++ b/project2/common/iHaveParameters.cpp @@ -7,12 +7,10 @@ IHaveParameters::Stack IHaveParameters::scope; -IHaveParameters::IHaveParameters(const xmlpp::Element * p) +IHaveParameters::IHaveParameters(ScriptNodePtr p) { - BOOST_FOREACH(xmlpp::Node * node, p->find("parameters/*")) { - if (const xmlpp::Element * pelem = dynamic_cast<const xmlpp::Element *>(node)) { - parameters.insert(Parameters::value_type(pelem->get_name(), Variable(pelem, boost::optional<Glib::ustring>()))); - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("parameters")) { + parameters.insert(Parameters::value_type(node->get_name(), Variable(node))); } } diff --git a/project2/common/iHaveParameters.h b/project2/common/iHaveParameters.h index 08c8d00..2b7ed2a 100644 --- a/project2/common/iHaveParameters.h +++ b/project2/common/iHaveParameters.h @@ -1,7 +1,6 @@ #ifndef IHAVEPARAMETERS #define IHAVEPARAMETERS -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <vector> #include "variables.h" @@ -12,7 +11,7 @@ class IHaveParameters { public: typedef std::map<Glib::ustring, Variable> Parameters; - IHaveParameters(const xmlpp::Element * p); + IHaveParameters(ScriptNodePtr p); virtual ~IHaveParameters() = 0; const Parameters & allParameters() const; diff --git a/project2/common/iHaveSubTasks.cpp b/project2/common/iHaveSubTasks.cpp index 586dff8..78868aa 100644 --- a/project2/common/iHaveSubTasks.cpp +++ b/project2/common/iHaveSubTasks.cpp @@ -2,7 +2,7 @@ #include "iHaveSubTasks.h" #include <boost/foreach.hpp> -IHaveSubTasks::IHaveSubTasks(const xmlpp::Element * e) : +IHaveSubTasks::IHaveSubTasks(ScriptNodePtr e) : SourceObject(e), NoOutputExecute(e) { diff --git a/project2/common/iHaveSubTasks.h b/project2/common/iHaveSubTasks.h index c2d2022..e52a9be 100644 --- a/project2/common/iHaveSubTasks.h +++ b/project2/common/iHaveSubTasks.h @@ -8,7 +8,7 @@ class IHaveSubTasks : public NoOutputExecute { public: typedef ANONORDEREDSTORAGEOF(NoOutputExecute) Tasks; - IHaveSubTasks(const xmlpp::Element * p); + IHaveSubTasks(ScriptNodePtr p); IHaveSubTasks(const std::string & n); virtual ~IHaveSubTasks(); diff --git a/project2/common/if.cpp b/project2/common/if.cpp index a810146..0f982ec 100644 --- a/project2/common/if.cpp +++ b/project2/common/if.cpp @@ -10,12 +10,10 @@ DECLARE_LOADER("if", If); SimpleMessageException(IfModeIsNonsense); -IfSet::IfSet(const xmlpp::Element * e) : - mode(e->get_attribute_value("mode") == "or" ? Or : And) +IfSet::IfSet(ScriptNodePtr e) : + mode(e->value("mode", "and").as<Glib::ustring>() == "or" ? Or : And) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&checks)); - loader.collectAll(e, true, IgnoreUnsupported); + e->script->loader.addLoadTarget(e, Storer::into<ElementLoader>(&checks)); } template <class Range, class Pred> @@ -41,23 +39,21 @@ IfSet::passes() const throw IfModeIsNonsense(getName()); } -If::If(const xmlpp::Element * e) : +If::If(ScriptNodePtr e) : SourceObject(e), IHaveSubTasks(e), View(e), IfSet(e) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&normal)); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&subViews)); - loader.collectAll(e, true, IgnoreUnsupported); + e->script->loader.addLoadTarget(e, Storer::into<ElementLoader>(&normal)); + e->script->loader.addLoadTarget(e, Storer::into<ElementLoader>(&subViews)); } void If::execute(const MultiRowSetPresenter * presenter) const { if (passes()) { - Logger()->messagef(LOG_DEBUG, "IfSet passed, showing %zu views", subViews.size()); + Logger()->messagef(LOG_DEBUG, "IfSet passed %zu checks, showing %zu views", checks.size(), subViews.size()); BOOST_FOREACH(const SubViews::value_type & sq, subViews) { sq->execute(presenter); } diff --git a/project2/common/if.h b/project2/common/if.h index 28299ba..e27003d 100644 --- a/project2/common/if.h +++ b/project2/common/if.h @@ -7,7 +7,7 @@ class IfSet : public virtual IntrusivePtrBase { public: - IfSet(const xmlpp::Element *); + IfSet(ScriptNodePtr); bool passes() const; private: @@ -15,13 +15,14 @@ class IfSet : public virtual IntrusivePtrBase { enum Mode { And, Or }; Mode mode; typedef ANONORDEREDSTORAGEOF(ParamChecker) ParamCheckers; + protected: ParamCheckers checks; }; /// Project2 component to conditionally execute its children class If : public IHaveSubTasks, public View, public IfSet { public: - If(const xmlpp::Element *); + If(ScriptNodePtr); virtual void execute(const MultiRowSetPresenter*) const; virtual void execute() const; diff --git a/project2/common/iterate.cpp b/project2/common/iterate.cpp index ba8a4b9..9c7592e 100644 --- a/project2/common/iterate.cpp +++ b/project2/common/iterate.cpp @@ -8,14 +8,12 @@ DECLARE_LOADER("iterate", Iterate); -Iterate::Iterate(const xmlpp::Element * p) : +Iterate::Iterate(ScriptNodePtr p) : SourceObject(p), IHaveSubTasks(p), RowProcessor(p) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&normal)); - loader.collectAll(p, true, IgnoreUnsupported); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&normal)); } Iterate::~Iterate() diff --git a/project2/common/iterate.h b/project2/common/iterate.h index 50fd879..aa0b0e8 100644 --- a/project2/common/iterate.h +++ b/project2/common/iterate.h @@ -1,7 +1,6 @@ #ifndef ITERATE_H #define ITERATE_H -#include <libxml++/nodes/element.h> #include "rowProcessor.h" #include "iHaveSubTasks.h" #include "xmlStorage.h" @@ -12,7 +11,7 @@ typedef boost::intrusive_ptr<Iterate> IteratePtr; /// Project2 component to iterate over a row set, executing its children for each record class Iterate : public IHaveSubTasks, public RowProcessor { public: - Iterate(const xmlpp::Element * p); + Iterate(ScriptNodePtr p); virtual ~Iterate(); void loadComplete(const CommonObjects *); diff --git a/project2/common/library.cpp b/project2/common/library.cpp index 711e14f..0c4fa7b 100644 --- a/project2/common/library.cpp +++ b/project2/common/library.cpp @@ -2,12 +2,13 @@ #include <dlfcn.h> #include "xmlStorage.h" #include "exceptions.h" +#include "scripts.h" #include "library.h" SimpleMessageException(LoadLibraryFailed); SimpleMessageException(UnloadLibraryFailed); -Library::Library(const xmlpp::Element * p) : +Library::Library(ScriptNodePtr p) : SourceObject(p), handle(dlopen(Variable(p, "path")(), RTLD_NOW)) { diff --git a/project2/common/library.h b/project2/common/library.h index 523dcf4..892c075 100644 --- a/project2/common/library.h +++ b/project2/common/library.h @@ -5,7 +5,7 @@ class Library : public SourceObject { public: - Library(const xmlpp::Element * p); + Library(ScriptNodePtr p); ~Library(); private: diff --git a/project2/common/memoryCache.cpp b/project2/common/memoryCache.cpp index 5942cb8..ea7fb84 100644 --- a/project2/common/memoryCache.cpp +++ b/project2/common/memoryCache.cpp @@ -94,7 +94,7 @@ class MemoryCache : public Cache { boost::multi_index::tag<IndexByTime>, BOOST_MULTI_INDEX_MEMBER(CachedRowSet, const time_t, createdAt)> > > CacheStore; - MemoryCache(const xmlpp::Element * p) : + MemoryCache(ScriptNodePtr p) : Cache(p) { } diff --git a/project2/common/noOutputExecute.cpp b/project2/common/noOutputExecute.cpp index 5b1cb36..02c8f71 100644 --- a/project2/common/noOutputExecute.cpp +++ b/project2/common/noOutputExecute.cpp @@ -2,7 +2,7 @@ #include "noOutputExecute.h" #include <boost/foreach.hpp> -NoOutputExecute::NoOutputExecute(const xmlpp::Element * p) : +NoOutputExecute::NoOutputExecute(ScriptNodePtr p) : SourceObject(p) { } diff --git a/project2/common/noOutputExecute.h b/project2/common/noOutputExecute.h index 1047f38..fffea9c 100644 --- a/project2/common/noOutputExecute.h +++ b/project2/common/noOutputExecute.h @@ -10,7 +10,7 @@ typedef boost::intrusive_ptr<NoOutputExecute> NoOutputExecutePtr; /// Base class for Project2 compoments that perform actions, but product no output class NoOutputExecute : public virtual SourceObject { public: - NoOutputExecute(const xmlpp::Element * p); + NoOutputExecute(ScriptNodePtr p); NoOutputExecute(const std::string & n); virtual ~NoOutputExecute(); diff --git a/project2/common/paramChecker.cpp b/project2/common/paramChecker.cpp index ad61b3a..fe49fa3 100644 --- a/project2/common/paramChecker.cpp +++ b/project2/common/paramChecker.cpp @@ -2,11 +2,11 @@ #include "paramChecker.h" #include "xmlObjectLoader.h" -ParamChecker::ParamChecker(const xmlpp::Element * p) : +ParamChecker::ParamChecker(ScriptNodePtr p) : SourceObject(p), - message(p, "message", false, "Check failed"), - group(p, "group", false, "default"), - present(p, "present", false, "") + message(p, "message", "Check failed"), + group(p, "group", "default"), + present(p, "present", "") { } diff --git a/project2/common/paramChecker.h b/project2/common/paramChecker.h index b0940c9..db3d8de 100644 --- a/project2/common/paramChecker.h +++ b/project2/common/paramChecker.h @@ -1,14 +1,13 @@ #ifndef PARAMCHECKER_H #define PARAMCHECKER_H -#include <libxml/tree.h> #include "sourceObject.h" #include "variables.h" /// Base class for Project2 compoments that perform tests/checks class ParamChecker : public SourceObject { public: - ParamChecker(const xmlpp::Element * p); + ParamChecker(ScriptNodePtr p); virtual ~ParamChecker(); virtual bool performCheck() const = 0; diff --git a/project2/common/pch.hpp b/project2/common/pch.hpp index 536dc5a..54637e0 100644 --- a/project2/common/pch.hpp +++ b/project2/common/pch.hpp @@ -14,9 +14,6 @@ #include <glibmm/ustring.h> #include <intrusivePtrBase.h> #include <iostream> -#include <libxml++/attribute.h> -#include <libxml++/nodes/element.h> -#include <libxml++/nodes/textnode.h> #include <list> #include <map> #include <set> @@ -29,6 +26,7 @@ #include "xmlObjectLoader.h" #include "variables.h" #include "sourceObject.h" +#include "scripts.h" #endif #endif diff --git a/project2/common/presenter.h b/project2/common/presenter.h index 6a72495..c0cc700 100644 --- a/project2/common/presenter.h +++ b/project2/common/presenter.h @@ -77,14 +77,14 @@ typedef boost::intrusive_ptr<NameValuePairPresenter> NameValuePairPresenterPtr; /// Base class to implement presenter modules class PresenterLoader : public ComponentLoader { public: - virtual MultiRowSetPresenterPtr createFrom(const xmlpp::Element * e) const = 0; + virtual MultiRowSetPresenterPtr createFrom(ScriptNodePtr e) const = 0; }; /// Helper implemention for specific presenters template <class PresenterType> class PresenterLoaderImpl : public PresenterLoader { public: - virtual MultiRowSetPresenterPtr createFrom(const xmlpp::Element * e) const + virtual MultiRowSetPresenterPtr createFrom(ScriptNodePtr e) const { return new PresenterType(e); } diff --git a/project2/common/rowProcessor.cpp b/project2/common/rowProcessor.cpp index e186c43..e2ce6ba 100644 --- a/project2/common/rowProcessor.cpp +++ b/project2/common/rowProcessor.cpp @@ -5,16 +5,14 @@ #include "scopeObject.h" #include <boost/foreach.hpp> -RowProcessor::RowProcessor(const xmlpp::Element * p) : +RowProcessor::RowProcessor(ScriptNodePtr p) : IHaveParameters(p), - recordSource(p->get_attribute_value("source")), - filter(p->get_attribute_value("filter")), - CROE(Variable(p, "cacheRowsOnError", false, false)()), - IRSE(Variable(p, "ignoreRowSourceError", false, false)()) + recordSource(p->value("source").as<std::string>()), + filter(p->value("filter", "").as<Glib::ustring>()), + CROE(p->value("cacheRowsOnError", false)), + IRSE(p->value("ignoreRowSourceError", false)) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&caches)); - loader.collectAll(p, true, IgnoreUnsupported); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&caches)); } void diff --git a/project2/common/rowProcessor.h b/project2/common/rowProcessor.h index e435bf4..18beac7 100644 --- a/project2/common/rowProcessor.h +++ b/project2/common/rowProcessor.h @@ -13,7 +13,7 @@ class Presenter; /// Base class for Project2 components that work with row sets class RowProcessor : public IHaveParameters { public: - RowProcessor(const xmlpp::Element *); + RowProcessor(ScriptNodePtr); void loadComplete(const CommonObjects *); const std::string recordSource; diff --git a/project2/common/rowSet.cpp b/project2/common/rowSet.cpp index 77d2a2d..cc397d1 100644 --- a/project2/common/rowSet.cpp +++ b/project2/common/rowSet.cpp @@ -10,7 +10,7 @@ RowState::RowValuesStack RowState::stack; -RowSet::RowSet(const xmlpp::Element * p) : +RowSet::RowSet(ScriptNodePtr p) : SourceObject(p) { } diff --git a/project2/common/rowSet.h b/project2/common/rowSet.h index a181059..2845983 100644 --- a/project2/common/rowSet.h +++ b/project2/common/rowSet.h @@ -23,7 +23,7 @@ class RowSet : public SourceObject { SimpleMessageException(FieldDoesNotExist); SimpleNumericException(FieldOutOfRange); - RowSet(const xmlpp::Element *); + RowSet(ScriptNodePtr); virtual ~RowSet() = 0; virtual void execute(const Glib::ustring &, const RowProcessor *) const = 0; diff --git a/project2/common/rowView.cpp b/project2/common/rowView.cpp index 5e01061..35b410d 100644 --- a/project2/common/rowView.cpp +++ b/project2/common/rowView.cpp @@ -6,25 +6,20 @@ #include "scopeObject.h" #include <boost/foreach.hpp> #include <boost/bind.hpp> -#include <libxml++/nodes/textnode.h> DECLARE_LOADER("view", RowView); -RowView::RowView(const xmlpp::Element * p) : +RowView::RowView(ScriptNodePtr p) : SourceObject(p), View(p), RowProcessor(p), rootName(p, "rootname"), recordName(p, "recordname") { - BOOST_FOREACH(xmlpp::Node * node, p->find("columns/*")) { - if (const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node)) { - viewColumns.insert(Columns::value_type(elem->get_name(), Variable(elem, boost::optional<Glib::ustring>()))); - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) { + viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); } - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&subViews)); - loader.collectAll(p, true, IgnoreUnsupported); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&subViews)); } RowView::~RowView() diff --git a/project2/common/rowView.h b/project2/common/rowView.h index 558284c..4b90884 100644 --- a/project2/common/rowView.h +++ b/project2/common/rowView.h @@ -1,7 +1,6 @@ #ifndef ROWVIEW_H #define ROWVIEW_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include "rowProcessor.h" #include "view.h" @@ -9,7 +8,7 @@ /// Project2 component to create output based on a records in a row set class RowView : public View, public RowProcessor { public: - RowView(const xmlpp::Element *); + RowView(ScriptNodePtr); virtual ~RowView(); void loadComplete(const CommonObjects *); diff --git a/project2/common/scripts.cpp b/project2/common/scripts.cpp new file mode 100644 index 0000000..4d15cfe --- /dev/null +++ b/project2/common/scripts.cpp @@ -0,0 +1,29 @@ +#include "scripts.h" +#include "variables-modfixed.h" + +ScriptNode::ScriptNode(ScriptReaderPtr s) : + script(s) +{ +} + +VariableImpl * +ScriptNode::variable(const Glib::ustring & n, const VariableType & def) const +{ + try { + return variable(n); + } + catch (const ValueNotFound &) { + return new VariableFixed(def); + } +} + +VariableType +ScriptNode::value(const Glib::ustring & n, const VariableType & def) const +{ + try { + return value(n); + } + catch (const ValueNotFound &) { + return def; + } +} diff --git a/project2/common/scripts.h b/project2/common/scripts.h new file mode 100644 index 0000000..2db4bad --- /dev/null +++ b/project2/common/scripts.h @@ -0,0 +1,64 @@ +#ifndef SCRIPTS_H +#define SCRIPTS_H + +#include "intrusivePtrBase.h" +#include <boost/intrusive_ptr.hpp> +#include <boost/function.hpp> +#include <boost/optional.hpp> +#include "xmlObjectLoader.h" +#include "exceptions.h" +#include "variables.h" +#include <vector> + +SimpleMessageException(ValueNotFound); +SimpleMessage2Exception(ScriptNotFound); +SimpleMessage2Exception(DependencyNotFound); + +class ScriptNode; +class ScriptReader; +typedef boost::intrusive_ptr<const ScriptNode> ScriptNodePtr; +typedef boost::intrusive_ptr<ScriptReader> ScriptReaderPtr; + +class ScriptNode : public IntrusivePtrBase { + public: + ScriptNode(ScriptReaderPtr); + + typedef std::vector<ScriptNodePtr> ScriptNodes; + typedef boost::function1<void, const VariableType &> LiteralCallback; + typedef boost::function1<void, ScriptNodePtr> NodeCallback; + + virtual bool componentNamespace() const = 0; + virtual std::string get_name() const = 0; + + // Child called name + virtual ScriptNodePtr child(const Glib::ustring & name) const = 0; + // All children + virtual ScriptNodes children() const = 0; + // All children in sub + virtual ScriptNodes childrenIn(const Glib::ustring & sub) const = 0; + + virtual bool valueExists(const Glib::ustring & name) const = 0; + virtual VariableImpl * variable(const boost::optional<Glib::ustring> & defaultSource = boost::optional<Glib::ustring>()) const = 0; + virtual VariableImpl * variable(const Glib::ustring & name) const = 0; + VariableImpl * variable(const Glib::ustring & name, const VariableType & def) const; + virtual VariableType value(const Glib::ustring & name) const = 0; + VariableType value(const Glib::ustring & name, const VariableType & def) const; + virtual void composeWithCallbacks(const LiteralCallback &, const NodeCallback &) const = 0; + + const ScriptReaderPtr script; +}; + +class ScriptReader : public virtual IntrusivePtrBase { + public: + virtual ScriptNodePtr root() = 0; + LoaderBase loader; +}; + +/// Base class to implement script reader modules +class ScriptReaderLoader : public ComponentLoader { + public: + virtual ScriptReaderPtr resolveScript(const std::string & group, const std::string & name) const = 0; +}; + +#endif + diff --git a/project2/common/sessionClearTask.cpp b/project2/common/sessionClearTask.cpp index 17dcf8f..9fba697 100644 --- a/project2/common/sessionClearTask.cpp +++ b/project2/common/sessionClearTask.cpp @@ -7,10 +7,10 @@ DECLARE_LOADER("sessionclear", SessionClearTask); -SessionClearTask::SessionClearTask(const xmlpp::Element * p) : +SessionClearTask::SessionClearTask(ScriptNodePtr p) : SourceObject(p), Task(p), - key(p->get_attribute_value("key")) + key(p->value("key").as<Glib::ustring>()) { } diff --git a/project2/common/sessionClearTask.h b/project2/common/sessionClearTask.h index 5df0aa5..224c951 100644 --- a/project2/common/sessionClearTask.h +++ b/project2/common/sessionClearTask.h @@ -1,7 +1,6 @@ #ifndef SESSIONCLEARTASK_H #define SESSIONCLEARTASK_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <map> #include "sourceObject.h" @@ -13,7 +12,7 @@ class CommonObjects; /// Project2 component to remove a variable from the session class SessionClearTask : public Task { public: - SessionClearTask(const xmlpp::Element * p); + SessionClearTask(ScriptNodePtr p); virtual ~SessionClearTask(); void execute() const; diff --git a/project2/common/sessionSetTask.cpp b/project2/common/sessionSetTask.cpp index 69e05c5..8cf0788 100644 --- a/project2/common/sessionSetTask.cpp +++ b/project2/common/sessionSetTask.cpp @@ -7,10 +7,10 @@ DECLARE_LOADER("sessionset", SessionSetTask); -SessionSetTask::SessionSetTask(const xmlpp::Element * p) : +SessionSetTask::SessionSetTask(ScriptNodePtr p) : SourceObject(p), Task(p), - key(p->get_attribute_value("key")), + key(p->value("key").as<Glib::ustring>()), value(p, "value") { } diff --git a/project2/common/sessionSetTask.h b/project2/common/sessionSetTask.h index 1fddbba..c9b22e5 100644 --- a/project2/common/sessionSetTask.h +++ b/project2/common/sessionSetTask.h @@ -1,7 +1,6 @@ #ifndef SESSIONSETTASK_H #define SESSIONSETTASK_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <map> #include "sourceObject.h" @@ -14,7 +13,7 @@ class CommonObjects; /// Project2 component to add/update a variable in the session class SessionSetTask : public Task { public: - SessionSetTask(const xmlpp::Element * p); + SessionSetTask(ScriptNodePtr p); virtual ~SessionSetTask(); void execute() const; diff --git a/project2/common/singleton.cpp b/project2/common/singleton.cpp index eb78a48..91c80ff 100644 --- a/project2/common/singleton.cpp +++ b/project2/common/singleton.cpp @@ -1,5 +1,4 @@ #include <pch.hpp> -#include <libxml++/nodes/element.h> #include "view.h" #include "iHaveParameters.h" #include "presenter.h" @@ -7,18 +6,14 @@ class Singleton : public View { public: - Singleton(const xmlpp::Element * p) : + Singleton(ScriptNodePtr p) : SourceObject(p), View(p), rootName(p, "rootname") { - BOOST_FOREACH(xmlpp::Node * node, p->find("columns/*")) { - if (const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node)) { - viewColumns.insert(Columns::value_type(elem->get_name(), Variable(elem, boost::optional<Glib::ustring>()))); - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) { + viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); } - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&subViews)); - loader.collectAll(p, true, IgnoreUnsupported); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&subViews)); } void execute(const MultiRowSetPresenter * p) const { diff --git a/project2/common/sourceObject.cpp b/project2/common/sourceObject.cpp index f0423cb..ccc1034 100644 --- a/project2/common/sourceObject.cpp +++ b/project2/common/sourceObject.cpp @@ -3,8 +3,8 @@ unsigned int SourceObject::loadOrder = 1; -SourceObject::SourceObject(const xmlpp::Element * p) : - name(p ? p->get_attribute_value("name") : "anon"), +SourceObject::SourceObject(ScriptNodePtr p) : + name(p ? p->value("name", "anon").as<std::string>() : "anon"), order(loadOrder++) { } diff --git a/project2/common/sourceObject.h b/project2/common/sourceObject.h index 6a6df55..4d10dd4 100644 --- a/project2/common/sourceObject.h +++ b/project2/common/sourceObject.h @@ -1,17 +1,19 @@ #ifndef SOURCEOBJECT_H #define SOURCEOBJECT_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> +#include <string> #include "intrusivePtrBase.h" class CommonObjects; class SourceObject; +class ScriptNode; typedef boost::intrusive_ptr<SourceObject> SourceObjectPtr; +typedef boost::intrusive_ptr<const ScriptNode> ScriptNodePtr; /// Base class for all Project2 components that can be placed in a Project2 script class SourceObject : public virtual IntrusivePtrBase { public: - SourceObject(const xmlpp::Element * p); + SourceObject(ScriptNodePtr p); SourceObject(const std::string & name); virtual ~SourceObject() = 0; diff --git a/project2/common/structExceptHandling.cpp b/project2/common/structExceptHandling.cpp index 0f176c9..bfd2f2b 100644 --- a/project2/common/structExceptHandling.cpp +++ b/project2/common/structExceptHandling.cpp @@ -2,30 +2,44 @@ #include "structExceptHandling.h" #include "xmlObjectLoader.h" #include "xmlStorage.h" +#include "scripts.h" #include <boost/foreach.hpp> DECLARE_LOADER("handler", StructuredExceptionHandler); -static void -loadHelper(const char * name, const xmlpp::Element * root, ANONORDEREDSTORAGEOF(NoOutputExecute) * noes) +static +ScriptNodePtr +loadHelperSub(const char * name, bool required, ScriptNodePtr root) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(noes)); - BOOST_FOREACH(const xmlpp::Node * node, root->find(name)) { - const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); - if (elem) { - loader.collectAll(elem, true, ErrorOnUnsupported); + if (required) { + return root->child(name); + } + else { + try { + return root->child(name); } + catch (const ValueNotFound &) { + return NULL; + } + } +} +static +void +loadHelper(const char * name, bool required, ScriptNodePtr root, ANONORDEREDSTORAGEOF(NoOutputExecute) * noes) +{ + ScriptNodePtr c = loadHelperSub(name, required, root); + if (c) { + root->script->loader.addLoadTarget(c, Storer::into<ElementLoader>(noes)); } } -StructuredExceptionHandler::StructuredExceptionHandler(const xmlpp::Element * e) : +StructuredExceptionHandler::StructuredExceptionHandler(ScriptNodePtr e) : SourceObject(e), IHaveSubTasks(e) { - loadHelper("try", e, &normal); - loadHelper("catch", e, &catches); - loadHelper("finally", e, &finallies); + loadHelper("try", true, e, &normal); + loadHelper("catch", false, e, &catches); + loadHelper("finally", false, e, &finallies); } void diff --git a/project2/common/structExceptHandling.h b/project2/common/structExceptHandling.h index eabd384..067c389 100644 --- a/project2/common/structExceptHandling.h +++ b/project2/common/structExceptHandling.h @@ -5,7 +5,7 @@ class StructuredExceptionHandler : public IHaveSubTasks { public: - StructuredExceptionHandler(const xmlpp::Element *); + StructuredExceptionHandler(ScriptNodePtr); void loadComplete(const CommonObjects*); void execute() const; diff --git a/project2/common/task.cpp b/project2/common/task.cpp index 823382b..c4275f8 100644 --- a/project2/common/task.cpp +++ b/project2/common/task.cpp @@ -2,7 +2,7 @@ #include "task.h" #include <boost/foreach.hpp> -Task::Task(const xmlpp::Element * p) : +Task::Task(ScriptNodePtr p) : SourceObject(p), NoOutputExecute(p) { diff --git a/project2/common/task.h b/project2/common/task.h index 57697e2..5303f15 100644 --- a/project2/common/task.h +++ b/project2/common/task.h @@ -1,14 +1,13 @@ #ifndef TASK_H #define TASK_H -#include <libxml++/nodes/element.h> #include "sourceObject.h" #include "noOutputExecute.h" /// Base class for Project2 components that perform some specific task class Task : public NoOutputExecute { public: - Task(const xmlpp::Element * p); + Task(ScriptNodePtr p); virtual ~Task(); virtual void execute() const = 0; }; diff --git a/project2/common/taskHost.cpp b/project2/common/taskHost.cpp index 98a1fa5..9ee0304 100644 --- a/project2/common/taskHost.cpp +++ b/project2/common/taskHost.cpp @@ -3,15 +3,17 @@ #include "noOutputExecute.h" #include "dataSource.h" #include "scopeObject.h" +#include "xmlObjectLoader.h" +#include "commonObjects.h" #include <boost/foreach.hpp> -TaskHost::TaskHost(const boost::filesystem::path & file) : - XmlScriptParser(file, false), - SourceObject(get_document()->get_root_node()), - CheckHost(file), - IHaveSubTasks(get_document()->get_root_node()) +TaskHost::TaskHost(ScriptReaderPtr s) : + SourceObject(s->root()), + CommonObjects(s), + CheckHost(s), + IHaveSubTasks(s->root()) { - loader.supportedStorers.insert(Storer::into<ElementLoader>(&tasks)); + s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&tasks)); } TaskHost::~TaskHost() @@ -27,7 +29,7 @@ TaskHost::loadComplete(const CommonObjects * co) void TaskHost::execute() const { - parseDocument(); + loadScriptComponents(); ScopeObject txHandler(boost::bind(&TaskHost::commitAll, this), boost::bind(&TaskHost::rollbackAll, this)); run(tasks); } @@ -35,7 +37,7 @@ TaskHost::execute() const void TaskHost::commitAll() const { - BOOST_FOREACH(const DataSources::value_type & ds, datasources) { + BOOST_FOREACH(const CommonObjects::DataSources::value_type & ds, CommonObjects::datasources) { ds.second->commit(); } } @@ -43,7 +45,7 @@ TaskHost::commitAll() const void TaskHost::rollbackAll() const { - BOOST_FOREACH(const DataSources::value_type & ds, datasources) { + BOOST_FOREACH(const CommonObjects::DataSources::value_type & ds, CommonObjects::datasources) { ds.second->rollback(); } } diff --git a/project2/common/taskHost.h b/project2/common/taskHost.h index ca8275c..9f9a1c5 100644 --- a/project2/common/taskHost.h +++ b/project2/common/taskHost.h @@ -2,16 +2,16 @@ #define TASKHOST_H #include "xmlStorage.h" -#include "xmlScriptParser.h" #include "checkHost.h" #include "iHaveSubTasks.h" +#include "commonObjects.h" class NoOutputExecute; class DataSource; -class TaskHost : virtual public XmlScriptParser, public IHaveSubTasks, virtual public CheckHost { +class TaskHost : public IHaveSubTasks, virtual public CheckHost, virtual public CommonObjects { protected: - TaskHost(const boost::filesystem::path & file); + TaskHost(ScriptReaderPtr script); virtual ~TaskHost(); void loadComplete(const CommonObjects *); diff --git a/project2/common/transform.cpp b/project2/common/transform.cpp index d109c19..0dafcd5 100644 --- a/project2/common/transform.cpp +++ b/project2/common/transform.cpp @@ -9,7 +9,7 @@ TransformChainLink::~TransformChainLink() typedef std::map<std::string, boost::shared_ptr<TransformLoader> > TransformLoaderMap; void -TransformSource::addTarget(TransformChainLinkPtr tcl, const xmlpp::Element * e) +TransformSource::addTarget(TransformChainLinkPtr tcl, ScriptNodePtr e) { BOOST_FOREACH(const TransformLoaderMap::value_type & tl, *LoaderBase::objLoaders<TransformLoader>()) { TransformPtr t = tl.second->create(); diff --git a/project2/common/transform.h b/project2/common/transform.h index ded356b..06db2c7 100644 --- a/project2/common/transform.h +++ b/project2/common/transform.h @@ -17,7 +17,7 @@ typedef boost::intrusive_ptr<Transform> TransformPtr; class TransformSource : public TransformChainLink { public: - void addTarget(TransformChainLinkPtr, const xmlpp::Element * e = NULL); + void addTarget(TransformChainLinkPtr, ScriptNodePtr e = NULL); void doTransforms() const; private: virtual const TransformChainLink * object() const { return this; } @@ -35,7 +35,7 @@ class Transform : public virtual IntrusivePtrBase { public: virtual void transform(const TransformSource * src, TransformChainLink * dest) const = 0; virtual bool canTransform(const TransformSource * src, TransformChainLink * dest) const = 0; - virtual void configure(const xmlpp::Element *) { }; + virtual void configure(ScriptNodePtr) { }; }; class TransformLoader : public ComponentLoader { diff --git a/project2/common/validDateCheck.cpp b/project2/common/validDateCheck.cpp index 6f731bb..987fa87 100644 --- a/project2/common/validDateCheck.cpp +++ b/project2/common/validDateCheck.cpp @@ -4,14 +4,15 @@ #include "commonObjects.h" #include "paramChecker.h" #include "variables.h" +#include "scripts.h" class ValidDateCheck : public ParamChecker { public: - ValidDateCheck(const xmlpp::Element * p) : + ValidDateCheck(ScriptNodePtr p) : ParamChecker(p), applyTo(p, "apply-to"), format(p, "format"), - warnLev(p->get_attribute_value("warn") == "no" ? LOG_INFO : LOG_WARNING) + warnLev(p->value("warn", true).as<bool>() ? LOG_WARNING : LOG_INFO) { } diff --git a/project2/common/variableConvert.cpp b/project2/common/variableConvert.cpp index 7eb16cf..a7ddca4 100644 --- a/project2/common/variableConvert.cpp +++ b/project2/common/variableConvert.cpp @@ -28,7 +28,7 @@ set(const VariableType * var, const T * t) return ::set(var, t, deleter<T>); } -SimpleMessageException(InvalidConversionTo); +SimpleMessage2Exception(InvalidConversionTo); class NullVariable : std::runtime_error { public: @@ -131,7 +131,7 @@ class ConvertVisitor : public boost::static_visitor<DestType> { return boost::lexical_cast<DestType>(r); } DestType operator()(const boost::posix_time::ptime &) const { - throw InvalidConversionTo(typeid(DestType).name()); + throw InvalidConversionTo(typeid(DestType).name(), "<Date Time>"); } DestType operator()(const Null &) const { throw NullVariable(); @@ -162,7 +162,7 @@ class ConvertVisitorDateTime : public boost::static_visitor<const boost::posix_t } template <typename T> const boost::posix_time::ptime & operator()(const T &) const { - throw InvalidConversionTo("DateTime"); + throw InvalidConversionTo("DateTime", typeid(T).name()); } private: const VariableType * var; @@ -176,10 +176,10 @@ class ConvertVisitorBool : public boost::static_visitor<bool> { const char * str = s.c_str(); if (strcasecmp(str, "true") == 0 || strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0) return true; if (strcasecmp(str, "false") == 0 || strcasecmp(str, "no") == 0 || strcasecmp(str, "off") == 0) return false; - throw InvalidConversionTo("bool"); + throw InvalidConversionTo("bool", s); } bool operator()(const boost::posix_time::ptime &) const { - throw InvalidConversionTo("bool"); + throw InvalidConversionTo("bool", "<Date time>"); } bool operator()(const Null &) const { throw NullVariable(); diff --git a/project2/common/variables-modconfig.cpp b/project2/common/variables-modconfig.cpp index c44daf2..5a031be 100644 --- a/project2/common/variables-modconfig.cpp +++ b/project2/common/variables-modconfig.cpp @@ -13,9 +13,9 @@ SimpleMessageException(NoSuchConfigurationValue); /// Variable implementation to access platform configuration values class VariableConfig : public VariableImplDyn { public: - VariableConfig(const xmlpp::Element * e) : + VariableConfig(ScriptNodePtr e) : VariableImplDyn(e), - name(e->get_attribute_value("name")) + name(e->value("name").as<Glib::ustring>()) { } VariableType value() const diff --git a/project2/common/variables-modfixed.cpp b/project2/common/variables-modfixed.cpp new file mode 100644 index 0000000..45fa74e --- /dev/null +++ b/project2/common/variables-modfixed.cpp @@ -0,0 +1,13 @@ +#include "variables-modfixed.h" + +VariableFixed::VariableFixed(VariableType v) : + var(v) +{ +} + +VariableType +VariableFixed::value() const +{ + return var; +} + diff --git a/project2/common/variables-modfixed.h b/project2/common/variables-modfixed.h new file mode 100644 index 0000000..eceb548 --- /dev/null +++ b/project2/common/variables-modfixed.h @@ -0,0 +1,17 @@ +#ifndef VARIABLES_MODFIXED_H +#define VARIABLES_MODFIXED_H + +#include "variables.h" + +/// Variable implementation which has some fixed value +class VariableFixed : public VariableImpl { + public: + VariableFixed(VariableType v); + VariableType value() const; + + private: + VariableType var; +}; + +#endif + diff --git a/project2/common/variables-modliteral.cpp b/project2/common/variables-modliteral.cpp new file mode 100644 index 0000000..8c165ee --- /dev/null +++ b/project2/common/variables-modliteral.cpp @@ -0,0 +1,78 @@ +#include "variables-modliteral.h" +#include "scripts.h" +#include <stdio.h> +#include <boost/foreach.hpp> +#include <boost/bind.hpp> + +/// Variable implementation whose value is a literal value of some known type +VariableLiteral::VariableLiteral(const Glib::ustring & src, const VT_typeID format) : + val(VariableType::make(src, format)) +{ +} + +template <typename X, typename Y> +static +void +append(VariableLiteral::Vals * vals, const Y & y) +{ + vals->push_back(new X(y)); +} + +VariableLiteral::VariableLiteral(ScriptNodePtr s) { + try { + val = VariableType::make(s->value("value"), VariableType::getTypeFromName(s->value("type", ""))); + } + catch (const ValueNotFound &) { + s->composeWithCallbacks( + boost::bind(&append<TextPart, Glib::ustring>, &vals, _1), + boost::bind(&append<VarPart, ScriptNodePtr>, &vals, _1)); + } +} + +VariableType +VariableLiteral::value() const +{ + if (vals.empty()) { + return val; + } + if (vals.size() == 1) { + return *vals.front(); + } + Glib::ustring v; + BOOST_FOREACH(PartCPtr p, vals) { + p->appendTo(v); + } + return v; +} + +VariableLiteral::TextPart::TextPart(const Glib::ustring & e) : + txt(e) +{ +} +void +VariableLiteral::TextPart::appendTo(Glib::ustring & str) const +{ + str += txt; +} +VariableLiteral::TextPart::operator VariableType() const +{ + return txt; +} + +VariableLiteral::VarPart::VarPart(ScriptNodePtr e) : Variable(e) +{ +} +void +VariableLiteral::VarPart::appendTo(Glib::ustring & str) const +{ + str += (*this)().operator const Glib::ustring &(); +} +VariableLiteral::VarPart::operator VariableType() const +{ + return (*this)(); +} + +DECLARE_COMPONENT_LOADER("literal", VariableLiteral, VariableLoader); +DECLARE_CUSTOM_COMPONENT_LOADER("", VariableLiteralDef, VariableLoaderImpl<VariableLiteral>, VariableLoader); + + diff --git a/project2/common/variables-modliteral.h b/project2/common/variables-modliteral.h new file mode 100644 index 0000000..77a43cc --- /dev/null +++ b/project2/common/variables-modliteral.h @@ -0,0 +1,40 @@ +#ifndef VARIABLES_MODLITERAL_H +#define VARIABLES_MODLITERAL_H + +#include "variables.h" +#include <list> + +class VariableLiteral : public VariableImpl { + public: + VariableLiteral(const Glib::ustring & src, const VT_typeID format = DefaultType); + VariableLiteral(ScriptNodePtr); + virtual VariableType value() const; + class Part; + typedef boost::intrusive_ptr<Part> PartCPtr; + typedef std::list<PartCPtr> Vals; + + class Part : public IntrusivePtrBase { + public: + virtual void appendTo(Glib::ustring & str) const = 0; + virtual operator VariableType() const = 0; + }; + class TextPart : public Part { + public: + TextPart(const Glib::ustring & e); + void appendTo(Glib::ustring & str) const; + operator VariableType() const; + const Glib::ustring txt; + }; + class VarPart : public Part, public Variable { + public: + VarPart(ScriptNodePtr e); + void appendTo(Glib::ustring & str) const; + operator VariableType() const; + }; + private: + VariableType val; + Vals vals; +}; + +#endif + diff --git a/project2/common/variables-modlocalparam.cpp b/project2/common/variables-modlocalparam.cpp index 957f76a..f6fd31c 100644 --- a/project2/common/variables-modlocalparam.cpp +++ b/project2/common/variables-modlocalparam.cpp @@ -8,9 +8,9 @@ /// Variable implementation to access call parameters class VariableLocalParam : public VariableImplDyn { public: - VariableLocalParam(const xmlpp::Element * e) : + VariableLocalParam(ScriptNodePtr e) : VariableImplDyn(e), - name(e->get_attribute_value("name")) + name(e->value("name").as<Glib::ustring>()) { } VariableType value() const diff --git a/project2/common/variables-modlookup.cpp b/project2/common/variables-modlookup.cpp index 82c3539..c5a2a2e 100644 --- a/project2/common/variables-modlookup.cpp +++ b/project2/common/variables-modlookup.cpp @@ -30,14 +30,12 @@ class VariableLookup : public VariableImplDyn, public RowProcessor { return l; } }; - VariableLookup(const xmlpp::Element * e) : + VariableLookup(ScriptNodePtr e) : VariableImplDyn(e), RowProcessor(e), - name(e->get_attribute_value("name")) + name(e->value("name").as<Glib::ustring>()) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&rowSets)); - loader.collectAll(e, false); + e->script->loader.addLoadTarget(e, Storer::into<ElementLoader>(&rowSets)); } VariableType value() const { diff --git a/project2/common/variables-modparam.cpp b/project2/common/variables-modparam.cpp index 4908a89..f17cae5 100644 --- a/project2/common/variables-modparam.cpp +++ b/project2/common/variables-modparam.cpp @@ -7,9 +7,9 @@ /// Variable implementation to access call parameters class VariableParam : public VariableImplDyn { public: - VariableParam(const xmlpp::Element * e) : + VariableParam(ScriptNodePtr e) : VariableImplDyn(e), - name(e->get_attribute_value("name")) + name(e->value("name").as<Glib::ustring>()) { } VariableType value() const diff --git a/project2/common/variables-modsession.cpp b/project2/common/variables-modsession.cpp index 27f1db2..68d0e56 100644 --- a/project2/common/variables-modsession.cpp +++ b/project2/common/variables-modsession.cpp @@ -7,9 +7,9 @@ /// Variable implementation to access session contents class VariableSession : public VariableImplDyn { public: - VariableSession(const xmlpp::Element * e) : + VariableSession(ScriptNodePtr e) : VariableImplDyn(e), - name(e->get_attribute_value("name")) + name(e->value("name").as<Glib::ustring>()) { } VariableType value() const diff --git a/project2/common/variables-moduri.cpp b/project2/common/variables-moduri.cpp index f91423a..8096203 100644 --- a/project2/common/variables-moduri.cpp +++ b/project2/common/variables-moduri.cpp @@ -7,9 +7,9 @@ /// Variable implementation to access URI path fragments class VariableUri : public VariableImplDyn { public: - VariableUri(const xmlpp::Element * e) : + VariableUri(ScriptNodePtr e) : VariableImplDyn(e), - index(atoi(e->get_attribute_value("index").c_str())) + index(e->value("index").as<int32_t>()) { } VariableType value() const diff --git a/project2/common/variables.cpp b/project2/common/variables.cpp index a3669aa..8df00e2 100644 --- a/project2/common/variables.cpp +++ b/project2/common/variables.cpp @@ -1,12 +1,12 @@ #include <pch.hpp> #include "variables.h" +#include "variables-modfixed.h" #include "iHaveParameters.h" #include "xmlObjectLoader.h" #include "exceptions.h" #include "appEngine.h" #include "session.h" #include "rowSet.h" -#include <libxml++/nodes/textnode.h> #include <stdexcept> #include <boost/numeric/conversion/cast.hpp> #include <boost/foreach.hpp> @@ -16,8 +16,6 @@ #include <boost/date_time/posix_time/posix_time.hpp> SimpleMessageException(UnknownVariableType); -SimpleMessageException(UnknownVariableSource); -SimpleMessageException(NoVariableDefinition); bool Null::operator<(const Null &) const @@ -54,41 +52,20 @@ operator<<(std::basic_ostream<unsigned char> & os, const Boolean & b) return os; } -enum VT_typeID { - DefaultType, - String, - Int, - UInt, - LInt, - LUInt, - LLInt, - LLUInt, - Float, - Double, - DateTime, -}; - -static VT_typeID -getVariableTypeFromName(const std::string & src) +VariableType::getTypeFromName(const std::string & src) { if (src.empty()) return String; if (src == "string") return String; if (src == "int") return Int; - if (src == "uint") return UInt; - if (src == "lint") return LInt; - if (src == "luint") return LUInt; - if (src == "llint") return LLInt; - if (src == "lluint") return LLUInt; if (src == "float") return Float; - if (src == "double") return Double; if (src == "datetime") return DateTime; + if (src == "null") return Nul; throw UnknownVariableType(src); } -static VariableType -makeVariableType(const Glib::ustring & src, const VT_typeID format = DefaultType) +VariableType::make(const Glib::ustring & src, const VT_typeID format) { switch (format) { default: @@ -96,23 +73,13 @@ makeVariableType(const Glib::ustring & src, const VT_typeID format = DefaultType case String: return src; case Int: - return boost::lexical_cast<int>(src); - case UInt: - return boost::lexical_cast<unsigned int>(src); - case LInt: - return boost::lexical_cast<long int>(src); - case LUInt: - return boost::lexical_cast<long unsigned int>(src); - case LLInt: - return boost::lexical_cast<long long int>(src); - case LLUInt: - return boost::lexical_cast<long long unsigned int>(src); + return boost::lexical_cast<int64_t>(src); case Float: - return boost::lexical_cast<float>(src); - case Double: return boost::lexical_cast<double>(src); case DateTime: return boost::posix_time::time_from_string(src); + case Nul: + return Null(); } } @@ -241,88 +208,7 @@ VariableType::operator<(const VariableType & b) const return false; } -/// Variable implementation whose value is a literal value of some known type -class VariableLiteral : public VariableImpl { - public: - VariableLiteral(const Glib::ustring & src, const VT_typeID format = DefaultType) : - val(makeVariableType(src, format)) - { - } - VariableLiteral(const xmlpp::Element * c) - { - if (const xmlpp::Attribute * la = c->get_attribute("value")) { - val = makeVariableType(la->get_value(), getVariableTypeFromName(c->get_attribute_value("type"))); - } - else { - BOOST_FOREACH(const xmlpp::Node * n, c->get_children()) { - if (const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n)) { - vals.push_back(new VarPart(e)); - } - else if (const xmlpp::TextNode * t = dynamic_cast<const xmlpp::TextNode *>(n)) { - vals.push_back(new TextPart(t)); - } - } - } - } - - virtual VariableType value() const - { - if (vals.empty()) { - return val; - } - if (vals.size() == 1) { - return *vals.front(); - } - Glib::ustring v; - BOOST_FOREACH(PartCPtr p, vals) { - p->appendTo(v); - } - return v; - } - private: - VariableType val; - class Part : public IntrusivePtrBase { - public: - virtual void appendTo(Glib::ustring & str) const = 0; - virtual operator VariableType() const = 0; - }; - class TextPart : public Part { - public: - TextPart(const xmlpp::TextNode * e) : - txt(e->get_content()) - { - } - void appendTo(Glib::ustring & str) const - { - str += txt; - } - operator VariableType() const - { - return txt; - } - const Glib::ustring txt; - }; - class VarPart : public Part, public Variable { - public: - VarPart(const xmlpp::Element * e) : Variable(e, boost::optional<Glib::ustring>()) - { - } - void appendTo(Glib::ustring & str) const - { - str += (*this)().operator const Glib::ustring &(); - } - operator VariableType() const - { - return (*this)(); - } - }; - typedef boost::intrusive_ptr<Part> PartCPtr; - std::list<PartCPtr> vals; -}; -DECLARE_COMPONENT_LOADER("literal", VariableLiteral, VariableLoader); -DECLARE_CUSTOM_COMPONENT_LOADER("", VariableLiteralDef, VariableLoaderImpl<VariableLiteral>, VariableLoader); - -VariableImplDyn::VariableImplDyn(const xmlpp::Element * e) +VariableImplDyn::VariableImplDyn(ScriptNodePtr e) { if (e) { defaultValue = Variable(e, "default", false); @@ -332,11 +218,11 @@ VariableImplDyn::VariableImplDyn(const xmlpp::Element * e) /// Variable implementation to access fields in row sets class VariableParent : public VariableImplDyn { public: - VariableParent(const xmlpp::Element * e) : + VariableParent(ScriptNodePtr e) : VariableImplDyn(e), - depth(e->get_attribute("depth") ? atoi(e->get_attribute_value("depth").c_str()) : 1), - attr(e->get_attribute("attribute")), - name(attr ? e->get_attribute_value("attribute") : e->get_attribute_value("name")) + depth(e->value("depth", 1).as<int32_t>()), + attr(e->valueExists("attribute")), + name((attr ? e->value("attribute") : e->value("name")).as<Glib::ustring>()) { } VariableParent(const Glib::ustring & n, bool a, unsigned int d) : @@ -387,66 +273,23 @@ class VariableParent : public VariableImplDyn { }; DECLARE_COMPONENT_LOADER("parent", VariableParent, VariableLoader); -/// Variable implementation which has some fixed value -class VariableFixed : public VariableImpl { - public: - VariableFixed(VariableType v) : - var(v) - { - } - VariableType value() const - { - return var; - } - private: - VariableType var; -}; Variable::Variable(VariableType def) : var(new VariableFixed(def)) { } -Variable::Variable(const xmlpp::Element * e, const Glib::ustring & n, bool required, VariableType def) +Variable::Variable(ScriptNodePtr s, const boost::optional<Glib::ustring> & defaultSource) : + var(s->variable(defaultSource)) { - xmlpp::Attribute * a = e->get_attribute(n); - if (a) { - var = new VariableLiteral(a->get_value()); - return; - } - xmlpp::Element::NodeList cs = e->get_children(n); - if (cs.size() == 1) { - const xmlpp::Element * c = dynamic_cast<const xmlpp::Element *>(cs.front()); - if (c) { - xmlpp::Attribute * source = c->get_attribute("source"); - if (source) { - var = LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(source->get_value())->create(c); - } - else { - var = new VariableLiteral(c); - } - return; - } - } - if (!required) { - var = new VariableFixed(def); - return; - } - throw NoVariableDefinition(n); } - -Variable::Variable(const xmlpp::Element * c, const boost::optional<Glib::ustring> & defaultSource) +Variable::Variable(ScriptNodePtr s, const Glib::ustring & n) : + var(s->variable(n)) +{ +} +Variable::Variable(ScriptNodePtr s, const Glib::ustring & n, const VariableType & d) : + var(s->variable(n, d)) { - xmlpp::Attribute * source = c->get_attribute("source"); - if (source) { - var = LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(source->get_value())->create(c); - } - else if (defaultSource) { - var = LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(defaultSource.get())->create(c); - } - else { - var = new VariableLiteral(c); - } } Variable::Variable(VariableImpl * v) : diff --git a/project2/common/variables.h b/project2/common/variables.h index e42de0c..05b7855 100644 --- a/project2/common/variables.h +++ b/project2/common/variables.h @@ -6,13 +6,22 @@ #include <boost/date_time/posix_time/posix_time_types.hpp> #include <stdint.h> #include <glibmm/ustring.h> -#include <libxml++/nodes/element.h> -#include <libxml++/attribute.h> #include "intrusivePtrBase.h" #include "xmlObjectLoader.h" #include <boost/variant.hpp> #include <boost/shared_ptr.hpp> +SimpleMessageException(UnknownVariableSource); + +enum VT_typeID { + DefaultType, + Nul, + String, + Int, + Float, + DateTime, +}; + class Null { public: bool operator<(const Null &) const; @@ -64,6 +73,9 @@ class VariableType : public _VT { VariableType(); VariableType(const VariableType &); ~VariableType(); + static VariableType make(const Glib::ustring & src, const VT_typeID format = DefaultType); + static VT_typeID getTypeFromName(const std::string & src); + void operator=(const VariableType &); bool operator<(const VariableType &) const; @@ -98,8 +110,9 @@ class Variable { public: typedef boost::intrusive_ptr<VariableImpl> VariableImplPtr; - Variable(const xmlpp::Element *, const Glib::ustring & n, bool required = true, VariableType def = VariableType()); - Variable(const xmlpp::Element *, const boost::optional<Glib::ustring> &); + Variable(ScriptNodePtr, const boost::optional<Glib::ustring> & = boost::optional<Glib::ustring>()); + Variable(ScriptNodePtr, const Glib::ustring & n); + Variable(ScriptNodePtr, const Glib::ustring & n, const VariableType & def); Variable(VariableType def); static Variable makeParent(const Glib::ustring & name, bool attr, unsigned int depth); @@ -116,7 +129,7 @@ class Variable { /// Base class for variables whose content is dynamic class VariableImplDyn : public VariableImpl { public: - VariableImplDyn(const xmlpp::Element * e); + VariableImplDyn(ScriptNodePtr e); virtual VariableType value() const = 0; protected: @@ -126,13 +139,13 @@ class VariableImplDyn : public VariableImpl { /// Base class to create variables class VariableLoader : public ComponentLoader { public: - virtual VariableImpl * create(const xmlpp::Element *) const = 0; + virtual VariableImpl * create(ScriptNodePtr) const = 0; }; /// Helper implementation of VariableLoader for specific variable types template <class VarType> class VariableLoaderImpl : public VariableLoader { public: - virtual VariableImpl * create(const xmlpp::Element * e) const + virtual VariableImpl * create(ScriptNodePtr e) const { return new VarType(e); } diff --git a/project2/common/view.cpp b/project2/common/view.cpp index 34ff3d4..30a6491 100644 --- a/project2/common/view.cpp +++ b/project2/common/view.cpp @@ -1,7 +1,7 @@ #include <pch.hpp> #include "view.h" -View::View(const xmlpp::Element * p) : +View::View(ScriptNodePtr p) : SourceObject(p) { } diff --git a/project2/common/view.h b/project2/common/view.h index 5a4b751..23c292f 100644 --- a/project2/common/view.h +++ b/project2/common/view.h @@ -9,7 +9,7 @@ class MultiRowSetPresenter; /// Base class for Project2 components that output data class View : public virtual SourceObject { public: - View(const xmlpp::Element *); + View(ScriptNodePtr); virtual ~View(); virtual void execute(const MultiRowSetPresenter *) const = 0; diff --git a/project2/common/viewHost.cpp b/project2/common/viewHost.cpp index 9d3c14b..4c19370 100644 --- a/project2/common/viewHost.cpp +++ b/project2/common/viewHost.cpp @@ -1,17 +1,17 @@ #include <pch.hpp> #include "viewHost.h" +#include "commonObjects.h" #include "transform.h" #include <boost/foreach.hpp> #include <iostream> -#define FOREACH_PRESENTER BOOST_FOREACH (const PresenterPtr & p, presenters) - -ViewHost::ViewHost(const boost::filesystem::path & file) : - XmlScriptParser(file, false), - CheckHost(file) +ViewHost::ViewHost(ScriptReaderPtr s) : + CommonObjects(s), + CheckHost(s), + root(s->root()) { - loader.supportedStorers.insert(Storer::into<ElementLoader>(&views)); - loader.supportedStorers.insert(Storer::into<PresenterLoader>(&presenter)); + s->loader.addLoadTarget(root, Storer::into<ElementLoader>(&views)); + s->loader.addLoadTarget(root, Storer::into<PresenterLoader>(&presenter)); } ViewHost::~ViewHost() @@ -21,16 +21,17 @@ ViewHost::~ViewHost() void ViewHost::executeViews(const DefaultPresenterProvider & dpp) const { - parseDocument(); + loadScriptComponents(); if (!presenter) { - presenter = dpp(get_document()->get_root_node()); + presenter = dpp(root); + root.reset(); } BOOST_FOREACH(const Views::value_type & s, views) { s->execute(presenter.get()); } // Caches might open transactions - BOOST_FOREACH(const DataSources::value_type & ds, datasources) { + BOOST_FOREACH(const CommonObjects::DataSources::value_type & ds, CommonObjects::datasources) { ds.second->commit(); } } diff --git a/project2/common/viewHost.h b/project2/common/viewHost.h index 409f195..589e2b1 100644 --- a/project2/common/viewHost.h +++ b/project2/common/viewHost.h @@ -1,19 +1,19 @@ #ifndef VIEWHOST_H #define VIEWHOST_H -#include "xmlScriptParser.h" #include "paramChecker.h" #include "xmlStorage.h" #include "presenter.h" #include "checkHost.h" #include <set> #include <boost/filesystem/path.hpp> +#include "commonObjects.h" -class ViewHost : virtual public XmlScriptParser, virtual public CheckHost { +class ViewHost : virtual public CheckHost, virtual public CommonObjects { public: - typedef boost::function1<MultiRowSetPresenterPtr, const xmlpp::Element *> DefaultPresenterProvider; + typedef boost::function1<MultiRowSetPresenterPtr, ScriptNodePtr> DefaultPresenterProvider; - ViewHost(const boost::filesystem::path & file); + ViewHost(ScriptReaderPtr script); ~ViewHost(); void executeViews(const DefaultPresenterProvider &) const; @@ -23,6 +23,7 @@ class ViewHost : virtual public XmlScriptParser, virtual public CheckHost { private: typedef ANONORDEREDSTORAGEOF(View) Views; Views views; + mutable ScriptNodePtr root; }; typedef boost::intrusive_ptr<ViewHost> ViewHostPtr; diff --git a/project2/common/xmlObjectLoader.cpp b/project2/common/xmlObjectLoader.cpp index d430194..f25ba6b 100644 --- a/project2/common/xmlObjectLoader.cpp +++ b/project2/common/xmlObjectLoader.cpp @@ -6,7 +6,8 @@ #include "appEngine.h" #include <boost/shared_ptr.hpp> #include <boost/foreach.hpp> -#include <libxml++/nodes/textnode.h> +#include <boost/function.hpp> +#include <boost/function_equal.hpp> unsigned int LoaderBase::depth = 0; std::set<SourceObjectPtr> LoaderBase::loadedObjects; @@ -26,25 +27,21 @@ class DepthCounter { typedef std::map<std::string, boost::shared_ptr<ElementLoader> > ElementLoaderMap; typedef std::set<boost::shared_ptr<ComponentLoader> > ComponentLoaderSet; -LoaderBase::LoaderBase(bool r) : - recursive(r), - ns(Environment::getCurrent()->xmlNamespace) +LoaderBase::LoaderBase() : + recursive(true) { - supportedStorers.insert(Storer::into<ElementLoader>(&libraries)); } -LoaderBase::LoaderBase(const Glib::ustring & n, bool r) : - recursive(r), - ns(n) +LoaderBase::~LoaderBase() { - supportedStorers.insert(Storer::into<ElementLoader>(&libraries)); } -LoaderBase::~LoaderBase() -{ +void +LoaderBase::addLoadTarget(ScriptNodePtr src, boost::intrusive_ptr<Storer> target) { + targets[src].push_back(target); } -std::set<boost::shared_ptr<ComponentLoader> > * & + std::set<boost::shared_ptr<ComponentLoader> > * & LoaderBase::componentLoaders() { static std::set<boost::shared_ptr<ComponentLoader> > * _compLoaders = NULL; @@ -55,54 +52,62 @@ LoaderBase::componentLoaders() } void -LoaderBase::collectAll(const xmlpp::Element * node, bool childrenOnly, UnsupportedHandling uh) const +LoaderBase::collectAll(ScriptNodePtr node, bool childrenOnly, const StorerPtrs & sts) const { - if (!node) { - return; - } DepthCounter dc(depth); unsigned int created = 0; - if (!childrenOnly && node->get_namespace_uri() == ns) { + if (!childrenOnly && node->componentNamespace()) { Glib::ustring name = node->get_name(); unsigned int stored = 0; created += 1; - BOOST_FOREACH(std::set<boost::intrusive_ptr<Storer> >::value_type s, supportedStorers) { - boost::intrusive_ptr<IntrusivePtrBase> o = s->save(node); - if (boost::intrusive_ptr<SourceObject> t = boost::dynamic_pointer_cast<SourceObject>(o)) { - loadedObjects.insert(t); + boost::intrusive_ptr<IntrusivePtrBase> o; + BOOST_FOREACH(const StorerPtr & s, sts) { + try { + o = s->create(node); + break; } - if (o) { + catch (const NotSupported &) { + } + } + if (!o) { + throw NotSupported(name); + } + BOOST_FOREACH(const StorerPtr & s, sts) { + if (s->save(o, node)) { stored += 1; + break; } } if (stored < 1) { - if (uh == ErrorOnUnsupported) { - throw NotSupported(name); - } - else if (uh == WarnOnUnsupported) { - Logger()->messagef(LOG_WARNING, "'%s' unsupported in this location", name.c_str()); - } + throw NotSupported(name); } } if (created == 0 && (recursive || childrenOnly)) { - BOOST_FOREACH(const xmlpp::Node * child, node->get_children()) { - collectAll(dynamic_cast<const xmlpp::Element *>(child), false, uh); + BOOST_FOREACH(ScriptNodePtr child, node->children()) { + collectAll(child, false, sts); } } } void -LoaderBase::collectAll(const CommonObjects * co, const xmlpp::Element * node, bool childrenOnly, UnsupportedHandling uh) const +LoaderBase::collectAll(const CommonObjects * co, bool childrenOnly, ScriptNodePtr node) { - if (depth != 0) { + (void)co; + addLoadTarget(node, Storer::into<ElementLoader>(&libraries)); + if (depth != 0 && co) { throw std::logic_error("Cannot set CommonObjects in subloader"); } - loadedObjects.clear(); - collectAll(node, childrenOnly, uh); - BOOST_FOREACH(SourceObjectPtr o, loadedObjects) { - o->loadComplete(co); + Targets::iterator i; + while ((i = targets.begin()) != targets.end()) { + collectAll(i->first, childrenOnly, i->second); + targets.erase(i); + } + if (co) { + BOOST_FOREACH(SourceObjectPtr o, loadedObjects) { + o->loadComplete(co); + } + loadedObjects.clear(); } - loadedObjects.clear(); } void @@ -117,22 +122,6 @@ LoaderBase::onAllComponents(const boost::function1<void, ComponentLoader *> & fu } } -Glib::ustring -xmlChildText(const xmlpp::Node * p, const Glib::ustring & t) -{ - Glib::ustring rtn; - BOOST_FOREACH(const xmlpp::Node * child, p->get_children(t)) { - const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(child); - if (e) { - const xmlpp::ContentNode * cn = e->get_child_text(); - if (cn) { - rtn += cn->get_content(); - } - } - } - return rtn; -} - void ComponentLoader::onBegin() { diff --git a/project2/common/xmlObjectLoader.h b/project2/common/xmlObjectLoader.h index 3c6fa34..3dd12a4 100644 --- a/project2/common/xmlObjectLoader.h +++ b/project2/common/xmlObjectLoader.h @@ -9,84 +9,86 @@ #include "intrusivePtrBase.h" #include "sourceObject.h" #include "exceptions.h" - -namespace xmlpp { - class Element; -} -Glib::ustring xmlChildText(const xmlpp::Node * p, const Glib::ustring & n); +#include <glibmm/ustring.h> +#include <map> +#include <vector> enum UnsupportedHandling { ErrorOnUnsupported, WarnOnUnsupported, IgnoreUnsupported }; class ElementLoader; class ComponentLoader; class CommonObjects; class Storer; +class ScriptReader; class LoaderBase { public: - LoaderBase(bool recursive); - LoaderBase(const Glib::ustring & ns, bool recursive); + typedef boost::intrusive_ptr<Storer> StorerPtr; + typedef std::vector<StorerPtr> StorerPtrs; + typedef std::map<ScriptNodePtr, StorerPtrs> Targets; + + LoaderBase(); virtual ~LoaderBase(); - void collectAll(const CommonObjects * co, const xmlpp::Element * node, bool childrenOnly, - UnsupportedHandling uh = ErrorOnUnsupported) const; - void collectAll(const xmlpp::Element * node, bool childrenOnly, - UnsupportedHandling uh = ErrorOnUnsupported) const; + void collectAll(const CommonObjects * co, bool childrenOnly, ScriptNodePtr script); - std::set<boost::intrusive_ptr<Storer> > supportedStorers; + void addLoadTarget(ScriptNodePtr src, boost::intrusive_ptr<Storer> target); static void onAllComponents(const boost::function1<void, ComponentLoader *> &); static std::set<boost::shared_ptr<ComponentLoader> > * & componentLoaders(); template <class T> - static std::map<std::string, boost::shared_ptr<T> > * & objLoaders() - { - static std::map<std::string, boost::shared_ptr<T> > * _objLoaders = NULL; - if (!_objLoaders) { - _objLoaders = new std::map<std::string, boost::shared_ptr<T> >(); + static std::map<std::string, boost::shared_ptr<T> > * & objLoaders() + { + static std::map<std::string, boost::shared_ptr<T> > * _objLoaders = NULL; + if (!_objLoaders) { + _objLoaders = new std::map<std::string, boost::shared_ptr<T> >(); + } + return _objLoaders; } - return _objLoaders; - } template <class T> - static void newLoader(const std::string & n, T * l) - { - boost::shared_ptr<T> p = boost::shared_ptr<T>(l); - objLoaders<T>()->insert(std::pair<std::string, boost::shared_ptr<T> >(n, p)); - componentLoaders()->insert(boost::shared_ptr<T>(p)); - } + static void newLoader(const std::string & n, T * l) + { + boost::shared_ptr<T> p = boost::shared_ptr<T>(l); + objLoaders<T>()->insert(std::pair<std::string, boost::shared_ptr<T> >(n, p)); + componentLoaders()->insert(boost::shared_ptr<T>(p)); + } template <class T> - static void removeLoader(const std::string & n) - { - std::map<std::string, boost::shared_ptr<T> > * & o = objLoaders<T>(); - std::set<boost::shared_ptr<ComponentLoader> > * & c = componentLoaders(); - typename std::map<std::string, boost::shared_ptr<T> >::iterator i = o->find(n); - c->erase(i->second); - o->erase(i); - if (o->empty()) { - delete o; - o = NULL; - } - if (c->empty()) { - delete c; - c = NULL; + static void removeLoader(const std::string & n) + { + std::map<std::string, boost::shared_ptr<T> > * & o = objLoaders<T>(); + std::set<boost::shared_ptr<ComponentLoader> > * & c = componentLoaders(); + typename std::map<std::string, boost::shared_ptr<T> >::iterator i = o->find(n); + c->erase(i->second); + o->erase(i); + if (o->empty()) { + delete o; + o = NULL; + } + if (c->empty()) { + delete c; + c = NULL; + } } - } template <class L, class E> - static boost::shared_ptr<L> getLoader(const std::string & n) - { - typename std::map<std::string, boost::shared_ptr<L> >::const_iterator i = objLoaders<L>()->find(n); - if (i != objLoaders<L>()->end()) { - return i->second; - } - else { - throw E(n); + static boost::shared_ptr<L> getLoader(const std::string & n) + { + typename std::map<std::string, boost::shared_ptr<L> >::const_iterator i = objLoaders<L>()->find(n); + if (i != objLoaders<L>()->end()) { + return i->second; + } + else { + throw E(n); + } } - } private: + void collectAll(ScriptNodePtr script, bool childrenOnly, const StorerPtrs & sts) const; + Targets targets; static unsigned int depth; + template <class X> friend class ElementLoaderImpl; static std::set<SourceObjectPtr> loadedObjects; const bool recursive; @@ -121,16 +123,18 @@ class ComponentLoader { /// Helper for loading and maintaining Project2 script components class ElementLoader : public ComponentLoader { public: - virtual SourceObjectPtr createFrom(const xmlpp::Element * xml) const = 0; + virtual SourceObjectPtr createFrom(ScriptNodePtr) const = 0; }; /// Helper for loading and maintaining Project2 script components (typed implementation) template <class X> class ElementLoaderImpl : public ElementLoader { public: - SourceObjectPtr createFrom(const xmlpp::Element * xml) const + SourceObjectPtr createFrom(ScriptNodePtr sn) const { - return new X(xml); + SourceObjectPtr sop = new X(sn); + LoaderBase::loadedObjects.insert(sop); + return sop; } }; #endif diff --git a/project2/common/xmlScriptParser.cpp b/project2/common/xmlScriptParser.cpp deleted file mode 100644 index 1db1841..0000000 --- a/project2/common/xmlScriptParser.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include <pch.hpp> -#include "xmlScriptParser.h" -#include <libxml/xinclude.h> -#include <boost/filesystem/convenience.hpp> - -XmlScriptParser::XmlScriptParser(const boost::filesystem::path & file, bool ii) : - IsInclusion(ii), - loader(true), - documentParsed(false) -{ - loadDocument(file); -} - -void -XmlScriptParser::loadDocument(const boost::filesystem::path & file) -{ - if (!boost::filesystem::exists(file)) { - if (IsInclusion) { - throw DependencyNotFound(file.string()); - } - else { - throw NotFound(file.string()); - } - } - try { - parse_file(file.string()); - } - catch (const xmlpp::internal_error &) { - throw NotReadable(file.string()); - } - for (int x; (x = xmlXIncludeProcessFlags(get_document()->cobj(), XML_PARSE_NOXINCNODE)); ) { - if (x < 0) { - throw IncludesError(file.string()); - } - } - loader.supportedStorers.insert(Storer::into<ElementLoader>(&rowSets)); -} - -void -XmlScriptParser::parseDocument() const -{ - if (!documentParsed) { - loader.collectAll(this, get_document()->get_root_node(), true, ErrorOnUnsupported); - documentParsed = true; - } -} - diff --git a/project2/common/xmlScriptParser.h b/project2/common/xmlScriptParser.h deleted file mode 100644 index 9f1406d..0000000 --- a/project2/common/xmlScriptParser.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef XMLSCRIPTPARSER_H -#define XMLSCRIPTPARSER_H - -#include <libxml++/parsers/domparser.h> -#include <boost/function.hpp> -#include "exceptions.h" -#include "xmlObjectLoader.h" -#include <intrusivePtrBase.h> -#include "commonObjects.h" -#include <boost/filesystem/path.hpp> - -class XmlScriptParser : public xmlpp::DomParser, virtual public CommonObjects, virtual public IntrusivePtrBase { - public: - SimpleMessageException(ParseError); - SimpleMessageExceptionBase(NotFound, ParseError); - SimpleMessageExceptionBase(DependencyNotFound, ParseError); - SimpleMessageExceptionBase(NotReadable, ParseError); - SimpleMessageExceptionBase(IncludesError, ParseError); - - XmlScriptParser(const boost::filesystem::path & file, bool isInclusion); - - const bool IsInclusion; - - protected: - LoaderBase loader; - mutable bool documentParsed; - void parseDocument() const; - - private: - void loadDocument(const boost::filesystem::path & file); -}; - - -#endif - diff --git a/project2/common/xmlStorage.h b/project2/common/xmlStorage.h index ceae899..267343f 100644 --- a/project2/common/xmlStorage.h +++ b/project2/common/xmlStorage.h @@ -4,6 +4,7 @@ #include "sourceObject.h" #include "xmlObjectLoader.h" #include "exceptions.h" +#include "scripts.h" #include <set> #include <list> #include <map> @@ -33,36 +34,34 @@ class Storer : public virtual IntrusivePtrBase { template <class L, class X> static StorerPtr into(ANONORDEREDSTORAGEOF(X) * list); - virtual boost::intrusive_ptr<IntrusivePtrBase> save(const xmlpp::Element *) = 0; + virtual boost::intrusive_ptr<IntrusivePtrBase> create(ScriptNodePtr) const = 0; + virtual bool save(boost::intrusive_ptr<IntrusivePtrBase>, ScriptNodePtr) = 0; }; template <class X, class M, class L> class StorerBase : public Storer { public: typedef M * Map; - boost::intrusive_ptr<IntrusivePtrBase> save(const xmlpp::Element * p) { - try { - boost::intrusive_ptr<X> O = boost::dynamic_pointer_cast<X>( - LoaderBase::getLoader<L, NotSupported>(p->get_name())->createFrom(p)); - if (O) { - if (!insert(p, O)) { - throw StoreFailed(p->get_attribute_value("name")); - } + boost::intrusive_ptr<IntrusivePtrBase> create(ScriptNodePtr p) const { + return LoaderBase::getLoader<L, NotSupported>(p->get_name())->createFrom(p); + } + bool save(boost::intrusive_ptr<IntrusivePtrBase> o, ScriptNodePtr p) { + boost::intrusive_ptr<X> O = boost::dynamic_pointer_cast<X>(o); + if (O) { + if (!insert(p, O)) { + throw StoreFailed(p->get_name()); } - return O; - } - catch (NotSupported) { - return NULL; } + return O; } - virtual bool insert(const xmlpp::Element *, boost::intrusive_ptr<X>) = 0; + virtual bool insert(ScriptNodePtr, boost::intrusive_ptr<X>) = 0; }; template <class X, class M, class L> class StorerImpl : public StorerBase<X, M, L> { public: StorerImpl(M * m); - bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O); + bool insert(ScriptNodePtr, boost::intrusive_ptr<X> O); }; template <class X, class L> class StorerImpl<X, SINGLE(X), L> : public StorerBase<X, SINGLE(X), L> { @@ -71,7 +70,7 @@ class StorerImpl<X, SINGLE(X), L> : public StorerBase<X, SINGLE(X), L> { StorerImpl(SINGLE(X) * o) : obj(o) { } - bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O) + bool insert(ScriptNodePtr, boost::intrusive_ptr<X> O) { *obj = O; return true; @@ -85,7 +84,7 @@ class StorerImpl<X, STORAGEOF(X), L> : public StorerBase<X, STORAGEOF(X), L> { StorerImpl(STORAGEOF(X) * m) : map(m) { } - bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O) + bool insert(ScriptNodePtr, boost::intrusive_ptr<X> O) { return map->insert(typename Map::value_type(O->name, O)).second; } @@ -98,7 +97,7 @@ class StorerImpl<X, ANONSTORAGEOF(X), L> : public StorerBase<X, ANONSTORAGEOF(X) StorerImpl(ANONSTORAGEOF(X) * m) : map(m) { } - bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O) + bool insert(ScriptNodePtr, boost::intrusive_ptr<X> O) { map->insert(O); return true; @@ -112,7 +111,7 @@ class StorerImpl<X, ANONORDEREDSTORAGEOF(X), L> : public StorerBase<X, ANONORDER StorerImpl(ANONORDEREDSTORAGEOF(X) * m) : map(m) { } - bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O) + bool insert(ScriptNodePtr, boost::intrusive_ptr<X> O) { map->push_back(O); return true; diff --git a/project2/console/Jamfile.jam b/project2/console/Jamfile.jam index 3a95bd6..b3b60a1 100644 --- a/project2/console/Jamfile.jam +++ b/project2/console/Jamfile.jam @@ -1,10 +1,10 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; - +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; cpp-pch pch : pch.hpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>..//p2parts ; exe p2console : diff --git a/project2/console/claOptions.cpp b/project2/console/claOptions.cpp index 135eebc..d3f7745 100644 --- a/project2/console/claOptions.cpp +++ b/project2/console/claOptions.cpp @@ -1,8 +1,11 @@ #include <pch.hpp> #include <boost/foreach.hpp> #include "../common/optionsSource.h" +#include "../common/exceptions.h" #include "consoleEnvironment.h" +StaticMessageException(InvalidScriptName, "Script name should be group/name"); + class CommandLineArguments : public OptionsSource { public: typedef std::list<Glib::ustring> optionList; @@ -51,7 +54,16 @@ class CommandLineArguments : public OptionsSource { } BOOST_FOREACH (const optionList::value_type & i, values) { - ConsoleEnvironment::todolist.push_back(i.raw()); + Glib::ustring group, name; + Glib::ustring::size_type sl = i.find('/'); + if (sl != (Glib::ustring::size_type)-1) { + group = i.substr(0, sl); + name = i.substr(sl + 1); + } + else { + throw InvalidScriptName(); + } + ConsoleEnvironment::todolist.push_back(ConsoleEnvironment::ToDo(group, name)); } } }; diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 40d369e..7229c36 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -12,12 +12,12 @@ SimpleMessageException(UnknownPlatformAlias); -ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * env, const boost::filesystem::path & f) : - XmlScriptParser(f, false), - SourceObject(get_document()->get_root_node()), - CheckHost(f), - TaskHost(f), - ViewHost(f), +ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * env, ScriptReaderPtr script) : + SourceObject(script->root()), + CommonObjects(script), + CheckHost(script), + TaskHost(script), + ViewHost(script), _env(env), runtime(new Session(UUID::generate_random())) { diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h index f2a0519..d53574f 100644 --- a/project2/console/consoleAppEngine.h +++ b/project2/console/consoleAppEngine.h @@ -16,7 +16,7 @@ class ConsoleEnvironment; class ConsoleApplicationEngine : public ApplicationEngine, TaskHost, ViewHost { public: - ConsoleApplicationEngine(const ConsoleEnvironment *, const boost::filesystem::path &); + ConsoleApplicationEngine(const ConsoleEnvironment *, ScriptReaderPtr); virtual ~ConsoleApplicationEngine(); void process() const; diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h index 5f4545c..a5530a9 100644 --- a/project2/console/consoleEnvironment.h +++ b/project2/console/consoleEnvironment.h @@ -3,12 +3,13 @@ #include <string> #include <vector> -#include <boost/filesystem/path.hpp> +#include <boost/tuple/tuple.hpp> #include "environment.h" class ConsoleEnvironment : public Environment { public: - typedef std::vector<boost::filesystem::path> ToDoList; + typedef boost::tuple<Glib::ustring, Glib::ustring> ToDo; + typedef std::vector<ToDo> ToDoList; typedef std::vector<std::string> UriParams; typedef std::vector<std::pair<std::string, std::string> > QueryParams; diff --git a/project2/console/consolePresenter.cpp b/project2/console/consolePresenter.cpp index 47c846a..33a7af9 100644 --- a/project2/console/consolePresenter.cpp +++ b/project2/console/consolePresenter.cpp @@ -1,9 +1,10 @@ #include <pch.hpp> +#include <stdio.h> #include "consolePresenter.h" DECLARE_COMPONENT_LOADER("console", ConsolePresenter, PresenterLoader) -ConsolePresenter::ConsolePresenter(const xmlpp::Element *) : +ConsolePresenter::ConsolePresenter(ScriptNodePtr) : indent(0), out(stdout, true) { diff --git a/project2/console/consolePresenter.h b/project2/console/consolePresenter.h index a411765..6122f7f 100644 --- a/project2/console/consolePresenter.h +++ b/project2/console/consolePresenter.h @@ -6,7 +6,7 @@ class ConsolePresenter : public Presenter { public: - ConsolePresenter(const xmlpp::Element *); + ConsolePresenter(ScriptNodePtr); void pushSub(const Glib::ustring & ns, const Glib::ustring & name) const; void addAttribute(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const; void addNamedValue(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const; diff --git a/project2/console/p2consoleMain.cpp b/project2/console/p2consoleMain.cpp index c194510..c560bfd 100644 --- a/project2/console/p2consoleMain.cpp +++ b/project2/console/p2consoleMain.cpp @@ -13,10 +13,10 @@ main(int argc, char ** argv) ConsoleEnvironment env(argc, argv); LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1)); env.init(); - BOOST_FOREACH(const boost::filesystem::path & file, env.todoList()) { + BOOST_FOREACH(const ConsoleEnvironment::ToDo & todo, env.todoList()) { LoaderBase::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1)); - Logger()->messagef(LOG_DEBUG, "%s: Beginning file '%s'", __FUNCTION__, file.string().c_str()); - ConsoleApplicationEngine app(&env, file); + Logger()->messagef(LOG_DEBUG, "%s: Beginning script '%s/%s'", __FUNCTION__, todo.get<0>().c_str(), todo.get<1>().c_str()); + ConsoleApplicationEngine app(&env, env.resolveScript(todo.get<0>(), todo.get<1>(), false)); Logger()->messagef(LOG_DEBUG, "%s: Processing file", __FUNCTION__); app.process(); diff --git a/project2/files/Jamfile.jam b/project2/files/Jamfile.jam index 1b34e3c..dd818b3 100644 --- a/project2/files/Jamfile.jam +++ b/project2/files/Jamfile.jam @@ -1,6 +1,7 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib boost_system : : <name>boost_system ; lib boost_filesystem : : <name>boost_filesystem ; @@ -8,7 +9,7 @@ lib p2files : [ glob *.cpp ] : <include>../libmisc - <library>libxmlpp + <library>glibmm <library>boost_filesystem <library>boost_system <library>../common//p2common diff --git a/project2/files/fileRows.cpp b/project2/files/fileRows.cpp index 8ba5c0c..af11f55 100644 --- a/project2/files/fileRows.cpp +++ b/project2/files/fileRows.cpp @@ -7,7 +7,7 @@ DECLARE_LOADER("filerows", FileRows); -FileRows::FileRows(const xmlpp::Element * p) : +FileRows::FileRows(ScriptNodePtr p) : StreamRows(p), path(p, "path") { diff --git a/project2/files/fileRows.h b/project2/files/fileRows.h index 7d92d20..fccbd08 100644 --- a/project2/files/fileRows.h +++ b/project2/files/fileRows.h @@ -9,7 +9,7 @@ class CommonObjects; /// Project2 component to create a row set from the contents of a file on the local filesystem class FileRows : public StreamRows { public: - FileRows(const xmlpp::Element * p); + FileRows(ScriptNodePtr p); ~FileRows(); void execute(const Glib::ustring &, const RowProcessor *) const; diff --git a/project2/files/fsRows.cpp b/project2/files/fsRows.cpp index a76cc02..41ec4b6 100644 --- a/project2/files/fsRows.cpp +++ b/project2/files/fsRows.cpp @@ -127,7 +127,7 @@ class FsRowSpecMaxDepth : public FsRows::SpecBase { const unsigned int maxDepth; }; -FsRows::FsRows(const xmlpp::Element * p) : +FsRows::FsRows(ScriptNodePtr p) : RowSet(p) { } diff --git a/project2/files/fsRows.h b/project2/files/fsRows.h index 6ef6b31..a6b9c8c 100644 --- a/project2/files/fsRows.h +++ b/project2/files/fsRows.h @@ -1,7 +1,6 @@ #ifndef FSROWS_H #define FSROWS_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <boost/filesystem/path.hpp> #include <sys/stat.h> @@ -28,7 +27,7 @@ class FsRows : public RowSet { typedef std::list<Glib::ustring> SpecSpec; typedef boost::filesystem::path Path; - FsRows(const xmlpp::Element * p); + FsRows(ScriptNodePtr p); ~FsRows(); void execute(const Glib::ustring &, const RowProcessor *) const; diff --git a/project2/files/streamRows.cpp b/project2/files/streamRows.cpp index 0be76cd..fc2572d 100644 --- a/project2/files/streamRows.cpp +++ b/project2/files/streamRows.cpp @@ -1,17 +1,17 @@ #include "streamRows.h" #include "rowProcessor.h" -StreamRows::StreamRows(const xmlpp::Element * p) : - DefinedColumns(p, "columns/column", boost::bind(&Column::make, _1, _2)), +StreamRows::StreamRows(ScriptNodePtr p) : + DefinedColumns(p, "columns", boost::bind(&Column::make, _1, _2)), RowSet(p), - fieldSep(p->get_attribute_value("fieldSep")[0]), - quoteChar(p->get_attribute_value("quoteChar")[0]), - keepBlankRows(p->get_attribute_value("keepBlankRows") == "true"), - countBlankRows(p->get_attribute_value("keepBlankRows") == "count"), - newline(p->get_attribute_value("newline")), + fieldSep(p->value("fieldSep", ",").as<Glib::ustring>()[0]), + quoteChar(p->value("quoteChar", "\"").as<Glib::ustring>()[0]), + keepBlankRows(p->value("keepBlankRows", false)), + countBlankRows(p->value("countBlankRows", false)), + newline(p->value("newline", "\n").as<Glib::ustring>()), newlin(newline, 0, newline.length() - 1), - encoding(p->get_attribute_value("encoding")), - skipheader(atoi(p->get_attribute_value("skipheader").c_str())) + encoding(p->value("encoding", "utf-8").as<std::string>()), + skipheader(p->value("skipheader", 0).as<int64_t>()) { } diff --git a/project2/files/streamRows.h b/project2/files/streamRows.h index 2d10116..95d8131 100644 --- a/project2/files/streamRows.h +++ b/project2/files/streamRows.h @@ -9,7 +9,7 @@ class RowProcessor; /// Base class for Project2 components that create a row set based on the contents of a byte stream class StreamRows : public DefinedColumns, public RowSet { public: - StreamRows(const xmlpp::Element * p); + StreamRows(ScriptNodePtr p); ~StreamRows(); protected: diff --git a/project2/json/Jamfile.jam b/project2/json/Jamfile.jam index 92a6e28..323e4fe 100644 --- a/project2/json/Jamfile.jam +++ b/project2/json/Jamfile.jam @@ -1,19 +1,20 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib boost_filesystem : : <name>boost_filesystem ; lib boost_date_time : : <name>boost_date_time ; cpp-pch pch : pch.hpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>../common//p2common ; lib p2json : pch [ glob *.cpp ] : <include>../libmisc - <library>libxmlpp + <library>glibmm <library>../common//p2common <library>../uuid//p2uuid <library>../url//p2url diff --git a/project2/json/presenter.cpp b/project2/json/presenter.cpp index 4afd1a0..3b069a4 100644 --- a/project2/json/presenter.cpp +++ b/project2/json/presenter.cpp @@ -7,7 +7,7 @@ class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf<json::Object> { public: - JsonPresenter(const xmlpp::Element *) : + JsonPresenter(ScriptNodePtr) : ContentPresenter("application/json; charset=UTF-8") { curRowSet.push(&object); } diff --git a/project2/mail/Jamfile.jam b/project2/mail/Jamfile.jam index 8c8f189..91e507d 100644 --- a/project2/mail/Jamfile.jam +++ b/project2/mail/Jamfile.jam @@ -1,13 +1,14 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib esmtp : : <name>esmtp ; lib p2mail : sendmailTask.cpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>esmtp <library>../common//p2common <library>../xml//p2xml diff --git a/project2/mail/sendmailTask.cpp b/project2/mail/sendmailTask.cpp index e2ca703..e8b354f 100644 --- a/project2/mail/sendmailTask.cpp +++ b/project2/mail/sendmailTask.cpp @@ -43,13 +43,13 @@ class SendEmailFailed : public std::runtime_error { typedef boost::shared_ptr<xmlDoc> XmlDocumentPtr; -SendMailTask::SendMailTask(const xmlpp::Element * p) : +SendMailTask::SendMailTask(ScriptNodePtr p) : SourceObject(p), Task(p), to(p, "to"), subject(p, "subject"), from(p, "from"), - server(p, "server", defaultMailServer.empty(), defaultMailServer), + server(p, "server", defaultMailServer), present(p, "present") { } @@ -189,7 +189,7 @@ class TransformTextToEmail : public TransformImpl<TextDocument, SendMailTask::Pa DECLARE_TRANSFORM(TransformTextToEmail); PresenterPtr -SendMailTask::createDefaultPresenter(const xmlpp::Element * n) const +SendMailTask::createDefaultPresenter(ScriptNodePtr n) const { Logger()->message(LOG_DEBUG, "Building default email transform chain"); XmlPresenterPtr xpp = new XmlPresenter(n); @@ -215,7 +215,7 @@ SendMailTask::execute() const parts->parts.insert(new Header("Content-Transfer-Encoding", "binary")); parts->parts.insert(new BoundaryEnd()); - ViewHostPtr vsp = new ViewHost(Environment::getCurrent()->resolveScript("emails", present())); + ViewHostPtr vsp = new ViewHost(Environment::getCurrent()->resolveScript("emails", present(), false)); vsp->executeViews(boost::bind(&SendMailTask::createDefaultPresenter, this, _1)); vsp->doTransforms(); part = parts->parts.begin(); diff --git a/project2/mail/sendmailTask.h b/project2/mail/sendmailTask.h index 5b10d44..6e2a10b 100644 --- a/project2/mail/sendmailTask.h +++ b/project2/mail/sendmailTask.h @@ -31,7 +31,7 @@ class SendMailTask : public Task { PartList parts; }; - SendMailTask(const xmlpp::Element * p); + SendMailTask(ScriptNodePtr p); virtual ~SendMailTask(); virtual void execute() const; @@ -45,7 +45,7 @@ class SendMailTask : public Task { private: static const char * writeMailWrapper(void ** buf, int * len, void * arg); const char * writeMail(void ** buf, int * len) const; - PresenterPtr createDefaultPresenter(const xmlpp::Element * n) const; + PresenterPtr createDefaultPresenter(ScriptNodePtr n) const; mutable boost::intrusive_ptr<Parts> parts; mutable PartList::iterator part; diff --git a/project2/processes/Jamfile.jam b/project2/processes/Jamfile.jam index 4c0c2b4..aef9251 100644 --- a/project2/processes/Jamfile.jam +++ b/project2/processes/Jamfile.jam @@ -1,12 +1,12 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; - +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib p2processes : procRows.cpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>../common//p2common <library>../files//p2files ; diff --git a/project2/processes/procRows.cpp b/project2/processes/procRows.cpp index c868323..a8b6829 100644 --- a/project2/processes/procRows.cpp +++ b/project2/processes/procRows.cpp @@ -1,5 +1,6 @@ #include "procRows.h" #include "xmlObjectLoader.h" +#include "scripts.h" #include <exception> DECLARE_LOADER("procrows", ProcRows); @@ -7,7 +8,7 @@ DECLARE_LOADER("procrows", ProcRows); SimpleMessageException(SubProcessFailedToStart); SimpleNumericException(SubProcessFailed); -ProcRows::ProcRows(const xmlpp::Element * p) : +ProcRows::ProcRows(ScriptNodePtr p) : FileRows(p) { } diff --git a/project2/processes/procRows.h b/project2/processes/procRows.h index 09b6f04..f39749d 100644 --- a/project2/processes/procRows.h +++ b/project2/processes/procRows.h @@ -6,7 +6,7 @@ /// Project2 component to create a row set from the output of a locally executed program class ProcRows : public FileRows { public: - ProcRows(const xmlpp::Element * p); + ProcRows(ScriptNodePtr p); ~ProcRows(); virtual FileStarChannel doOpen() const; diff --git a/project2/regex/Jamfile.jam b/project2/regex/Jamfile.jam index a83697f..7bb9d16 100644 --- a/project2/regex/Jamfile.jam +++ b/project2/regex/Jamfile.jam @@ -1,12 +1,12 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; - +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib p2regex : regexCheck.cpp regexRows.cpp : <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>../common//p2common ; diff --git a/project2/regex/regexCheck.cpp b/project2/regex/regexCheck.cpp index 1a1add3..e58e8f1 100644 --- a/project2/regex/regexCheck.cpp +++ b/project2/regex/regexCheck.cpp @@ -5,7 +5,7 @@ DECLARE_LOADER("regexcheck", RegexCheck); -RegexCheck::RegexCheck(const xmlpp::Element * p) : +RegexCheck::RegexCheck(ScriptNodePtr p) : ParamChecker(p), applyTo(p, "apply-to"), regex(p, "regex") diff --git a/project2/regex/regexCheck.h b/project2/regex/regexCheck.h index c4f6e02..2ddc545 100644 --- a/project2/regex/regexCheck.h +++ b/project2/regex/regexCheck.h @@ -7,7 +7,7 @@ /// Project2 component to test the value of a variable against a regular expression class RegexCheck : public ParamChecker { public: - RegexCheck(const xmlpp::Element * p); + RegexCheck(ScriptNodePtr p); virtual ~RegexCheck(); bool performCheck() const; diff --git a/project2/regex/regexRows.cpp b/project2/regex/regexRows.cpp index a822cf1..1238eb5 100644 --- a/project2/regex/regexRows.cpp +++ b/project2/regex/regexRows.cpp @@ -6,8 +6,8 @@ DECLARE_LOADER("regexrows", RegexRows); -RegexRows::RegexRows(const xmlpp::Element * p) : - DefinedColumns(p, "columns/column", boost::bind(&Column::make, _1, _2)), +RegexRows::RegexRows(ScriptNodePtr p) : + DefinedColumns(p, "columns", boost::bind(&Column::make, _1, _2)), RowSet(p), sourceText(p, "sourceText"), regex(p, "regex") diff --git a/project2/regex/regexRows.h b/project2/regex/regexRows.h index 21d9dfa..4d94f52 100644 --- a/project2/regex/regexRows.h +++ b/project2/regex/regexRows.h @@ -7,7 +7,7 @@ /// Base class for Project2 components that create a row set based on the contents of a byte stream class RegexRows : public DefinedColumns, public RowSet { public: - RegexRows(const xmlpp::Element * p); + RegexRows(ScriptNodePtr p); ~RegexRows(); void execute(const Glib::ustring&, const RowProcessor*) const; diff --git a/project2/sql/Jamfile.jam b/project2/sql/Jamfile.jam index 779aba3..068394f 100644 --- a/project2/sql/Jamfile.jam +++ b/project2/sql/Jamfile.jam @@ -1,12 +1,12 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; - +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; explicit object sql-modODBC ; obj sql-modODBC : sql-modODBC.cpp : <library>../../libodbcpp//odbcpp - <library>libxmlpp + <library>glibmm <include>../../libmisc <include>../common : : @@ -17,7 +17,7 @@ explicit object sql-modPQ ; obj sql-modPQ : sql-modPQ.cpp : <library>../../libpqpp//pqpp - <library>libxmlpp + <library>glibmm <include>../../libmisc <include>../common : : @@ -27,7 +27,7 @@ obj sql-modPQ : cpp-pch pch : pch.hpp : <include>../../libmisc <include>../../libdbpp - <library>libxmlpp + <library>glibmm <library>../common//p2common ; lib p2sql : @@ -38,7 +38,7 @@ lib p2sql : : <odbc>yes:<library>sql-modODBC <pq>yes:<library>sql-modPQ - <library>libxmlpp + <library>glibmm <library>../common//p2common <include>../../libmisc ; diff --git a/project2/sql/pch.hpp b/project2/sql/pch.hpp index a212245..01c68d4 100644 --- a/project2/sql/pch.hpp +++ b/project2/sql/pch.hpp @@ -21,13 +21,13 @@ #include "sqlWriter.h" #include "variables.h" #include "xmlObjectLoader.h" +#include "scripts.h" #include <boost/bind.hpp> #include <boost/foreach.hpp> #include "options.h" #include <buffer.h> #include <column.h> #include <errno.h> -#include <libxml++/nodes/textnode.h> #include <stdexcept> #endif diff --git a/project2/sql/rdbmsDataSource.cpp b/project2/sql/rdbmsDataSource.cpp index 20ccaec..4c6ae17 100644 --- a/project2/sql/rdbmsDataSource.cpp +++ b/project2/sql/rdbmsDataSource.cpp @@ -1,7 +1,6 @@ #include <pch.hpp> #include "rdbmsDataSource.h" #include "connectionLoader.h" -#include <libxml++/nodes/textnode.h> #include <sys/utsname.h> #include "logger.h" #include <errno.h> @@ -40,16 +39,13 @@ RdbmsDataSource::DBHosts RdbmsDataSource::dbhosts; RdbmsDataSource::FailedHosts RdbmsDataSource::failedhosts; RdbmsDataSource::DSNSet RdbmsDataSource::changedDSNs; -RdbmsDataSource::RdbmsDataSource(const xmlpp::Element * p) : +RdbmsDataSource::RdbmsDataSource(ScriptNodePtr p) : DataSource(p), - masterDsn(dynamic_cast<const xmlpp::Element *>(p->find("masterdsn").front())), - preferLocal(p->get_attribute_value("preferlocal") != "false") + masterDsn(p->child("masterdsn")), + preferLocal(p->value("preferlocal", true)) { - BOOST_FOREACH(const xmlpp::Node * node, p->find("readonly/dsn")) { - const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); - if (elem) { - roDSNs.insert(ReadonlyDSNs::value_type(elem->get_attribute_value("host"), elem)); - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("readonly")) { + roDSNs.insert(ReadonlyDSNs::value_type(node->value("host"), node)); } } @@ -194,12 +190,10 @@ RdbmsDataSource::RdbmsConnection::isExpired() const return (time(NULL) > lastUsedTime + keepAliveTime); } -RdbmsDataSource::ConnectionInfo::ConnectionInfo(const xmlpp::Element * n) +RdbmsDataSource::ConnectionInfo::ConnectionInfo(ScriptNodePtr node) { - BOOST_FOREACH(const xmlpp::Node * node, n->get_children()) { - typeId = LoaderBase::getLoader<ConnectionLoader, UnknownConnectionProvider>(node->get_name()); - dsn = dynamic_cast<const xmlpp::Element *>(node)->get_child_text()->get_content(); - } + typeId = LoaderBase::getLoader<ConnectionLoader, UnknownConnectionProvider>(node->value("provider")); + dsn = node->value("dsn").as<std::string>(); } DB::Connection * diff --git a/project2/sql/rdbmsDataSource.h b/project2/sql/rdbmsDataSource.h index 60206ff..bc72b05 100644 --- a/project2/sql/rdbmsDataSource.h +++ b/project2/sql/rdbmsDataSource.h @@ -1,7 +1,6 @@ #ifndef RDBMSDATASOURCE_H #define RDBMSDATASOURCE_H -#include <libxml/tree.h> #include <boost/shared_ptr.hpp> #include <map> #include <set> @@ -32,7 +31,7 @@ class RdbmsDataSource : public DataSource { class ConnectionInfo { public: - ConnectionInfo(const xmlpp::Element *); + ConnectionInfo(ScriptNodePtr); DB::Connection * connect() const; @@ -48,7 +47,7 @@ class RdbmsDataSource : public DataSource { typedef std::map<ConnectionInfo, ConnectionPtr> DBHosts; // Map DSN strings to connections typedef std::map<ConnectionInfo, const DB::ConnectionError> FailedHosts; // Map DSN strings to failures - RdbmsDataSource(const xmlpp::Element * p); + RdbmsDataSource(ScriptNodePtr p); ~RdbmsDataSource(); const DB::Connection & getReadonly() const; diff --git a/project2/sql/sqlCache.cpp b/project2/sql/sqlCache.cpp index d1ae930..7ed4ae1 100644 --- a/project2/sql/sqlCache.cpp +++ b/project2/sql/sqlCache.cpp @@ -21,7 +21,7 @@ typedef boost::shared_ptr<DB::ModifyCommand> ModifyPtr; class SqlCache : public Cache { public: - SqlCache(const xmlpp::Element * p) : + SqlCache(ScriptNodePtr p) : Cache(p) { } diff --git a/project2/sql/sqlCheck.cpp b/project2/sql/sqlCheck.cpp index d6e0651..879cbca 100644 --- a/project2/sql/sqlCheck.cpp +++ b/project2/sql/sqlCheck.cpp @@ -13,13 +13,13 @@ DECLARE_LOADER("sqlcheck", SqlCheck); class CantCompareNulls : public std::exception { }; -SqlCheck::SqlCheck(const xmlpp::Element * p) : +SqlCheck::SqlCheck(ScriptNodePtr p) : ParamChecker(p), dataSource(p, "datasource"), - filter(p, "filter", false, ""), - testOp(p, "testOp", false, "=="), + filter(p, "filter", ""), + testOp(p, "testOp", "=="), testValue(p, "testValue"), - sqlCommand(dynamic_cast<xmlpp::Element *>(p->get_children("sql").front())) + sqlCommand(p->child("sql")) { } diff --git a/project2/sql/sqlCheck.h b/project2/sql/sqlCheck.h index c9933d7..86492dc 100644 --- a/project2/sql/sqlCheck.h +++ b/project2/sql/sqlCheck.h @@ -10,7 +10,7 @@ class RdbmsDataSource; /// Project2 component to check the value of a variable against an RDBMS data source class SqlCheck : public ParamChecker { public: - SqlCheck(const xmlpp::Element * p); + SqlCheck(ScriptNodePtr p); virtual ~SqlCheck(); virtual void loadComplete(const CommonObjects *); @@ -22,7 +22,7 @@ class SqlCheck : public ParamChecker { const Variable testValue; private: - const DynamicSql::SqlCommand sqlCommand; + DynamicSql::SqlCommand sqlCommand; const RdbmsDataSource * db; }; diff --git a/project2/sql/sqlMergeTask.cpp b/project2/sql/sqlMergeTask.cpp index 96a895a..972b299 100644 --- a/project2/sql/sqlMergeTask.cpp +++ b/project2/sql/sqlMergeTask.cpp @@ -12,7 +12,6 @@ #include <boost/algorithm/string/join.hpp> #include <boost/foreach.hpp> #include <boost/bind.hpp> -#include <libxml++/nodes/textnode.h> bool SqlMergeTask::defaultUseTempTable = true; static void attach(boost::intrusive_ptr<IHaveSubTasks> i, DB::ModifyCommand * insert); @@ -22,7 +21,7 @@ typedef boost::intrusive_ptr<SqlMergeInsert> SqlMergeInsertPtr; /// Project2 component insert custom constructed records during an SQL Merge task class SqlMergeInsert : IHaveParameters, public Task { public: - SqlMergeInsert(const xmlpp::Element * p) : + SqlMergeInsert(ScriptNodePtr p) : SourceObject(p), IHaveParameters(p), Task(p) { @@ -43,51 +42,51 @@ DECLARE_LOADER("sqlmerge", SqlMergeTask); DECLARE_LOADER("sqlmergeinsert", SqlMergeInsert); // Conversion logic -SqlMergeTask::SqlMergeTask(const xmlpp::Element * p) : +SqlMergeTask::SqlMergeTask(ScriptNodePtr p) : SourceObject(p), Task(p), - updateWhere(p, "updatewhere", false), - patchOrder(p, "patchorder", false), - earlyKeys(p, "earlykeys", false, false), - useView(p, "useview", false, false), + updateWhere(p, "updatewhere", Null()), + patchOrder(p, "patchorder", Null()), + earlyKeys(p, "earlykeys", false), + useView(p, "useview", false), tempTableCreated(false), + sqlCommand(NULL), insCmd(NULL), destdb(NULL), dataSource(p, "datasource"), - dtable(p->get_attribute_value("targettable")), + dtable(p->value("targettable").as<std::string>()), dtablet(stringf("tmp_%s_%d", dtable.c_str(), getpid())) { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into<ElementLoader>(&sources)); - loader.collectAll(p, true); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&sources)); if (!sources.empty() && useView()) { throw NotSupported("useview not supported with iterate fillers"); } - BOOST_FOREACH(xmlpp::Node * psi, p->find("columns/column")) { - xmlpp::Element * e = static_cast<xmlpp::Element *>(psi); - TargetColumnPtr tcp(new TargetColumn(e->get_child_text()->get_content())); - tcp->maptable = e->get_attribute_value("maptable"); + BOOST_FOREACH(ScriptNodePtr e, p->childrenIn("columns")) { + TargetColumnPtr tcp(new TargetColumn(e->get_name())); + tcp->maptable = e->value("maptable", "").as<std::string>(); if (!tcp->maptable.empty()) { if (useView()) { throw NotSupported("useview not supported with mapped columns"); } - tcp->mapcolumn = e->get_attribute_value("mapcolumn"); + tcp->mapcolumn = e->value("mapcolumn").as<std::string>(); } cols.insert(tcp); + tcp->isKey = e->value("key", false); + if (tcp->isKey) { + keys.insert(tcp->column); + } } - BOOST_FOREACH(xmlpp::Node * psi, p->find("columns/column[@key='true']")) { - keys.insert(static_cast<xmlpp::Element *>(psi)->get_child_text()->get_content()); - } - BOOST_FOREACH(xmlpp::Node * psi, p->find("sql")) { - sqls.push_back(static_cast<xmlpp::Element *>(psi)->get_child_text()->get_content()); + if (p->valueExists("sql")) { + sqlCommand = new DynamicSql::SqlCommand(p->child("sql")); } } SqlMergeTask::~SqlMergeTask() { delete insCmd; + delete sqlCommand; } void @@ -143,7 +142,7 @@ SqlMergeTask::createTempTable() const DB::ModifyCommand * cv = destdb->newModifyCommand(stringf( "CREATE VIEW %s AS %s", dtablet.c_str(), - boost::algorithm::join(sqls, " UNION ").c_str())); + sqlCommand->getSqlFor("").c_str())); cv->execute(); delete cv; } @@ -280,11 +279,13 @@ attach(boost::intrusive_ptr<IHaveSubTasks> i, DB::ModifyCommand * insert) void SqlMergeTask::copyToTempTable() const { - if (useView()) return; + if (useView()) { + return; + } BOOST_FOREACH(const Sources::value_type & i, sources) { i->execute(); } - BOOST_FOREACH(const std::string & sql, sqls) { + if (sqlCommand) { Buffer ins; ins.appendf("INSERT INTO %s(", dtablet.c_str()); foreach(Columns::const_iterator, cols, c) { @@ -300,7 +301,7 @@ SqlMergeTask::copyToTempTable() const } ins.append((*c)->column); } - ins.appendf(" FROM (%s) tmp_src", sql.c_str()); + ins.appendf(" FROM (%s) tmp_src", sqlCommand->getSqlFor("").c_str()); DB::ModifyCommand * cttt = destdb->newModifyCommand(ins); cttt->execute(); delete cttt; diff --git a/project2/sql/sqlMergeTask.h b/project2/sql/sqlMergeTask.h index 41d1269..dc23936 100644 --- a/project2/sql/sqlMergeTask.h +++ b/project2/sql/sqlMergeTask.h @@ -32,13 +32,14 @@ class SqlMergeTask : public Task { Column column; Column mapcolumn; Table maptable; + bool isKey; }; typedef std::set<TargetColumnPtr, TargetColumn::Sort> Columns; typedef std::set<Column> Keys; - SqlMergeTask(const xmlpp::Element * p); + SqlMergeTask(ScriptNodePtr p); virtual ~SqlMergeTask(); virtual void loadComplete(const CommonObjects *); @@ -60,7 +61,7 @@ class SqlMergeTask : public Task { mutable bool tempTableCreated; typedef ANONSTORAGEOF(Iterate) Sources; Sources sources; - std::list<std::string> sqls; + DynamicSql::SqlCommand * sqlCommand; protected: DB::ModifyCommand * insertCommand() const; DB::ModifyCommand * insCmd; diff --git a/project2/sql/sqlRows.cpp b/project2/sql/sqlRows.cpp index ed2d71b..dbcc7be 100644 --- a/project2/sql/sqlRows.cpp +++ b/project2/sql/sqlRows.cpp @@ -2,7 +2,6 @@ #include "sqlRows.h" #include "sqlHandleAsVariableType.h" #include "rowProcessor.h" -#include "xml.h" #include "selectcommand.h" #include "rdbmsDataSource.h" #include "column.h" @@ -14,10 +13,10 @@ DECLARE_LOADER("sqlrows", SqlRows); -SqlRows::SqlRows(const xmlpp::Element * p) : +SqlRows::SqlRows(ScriptNodePtr p) : RowSet(p), dataSource(p, "datasource"), - sqlCommand(dynamic_cast<xmlpp::Element *>(p->get_children("sql").front())), + sqlCommand(p->child("sql")), db(NULL) { } diff --git a/project2/sql/sqlRows.h b/project2/sql/sqlRows.h index 5614fa1..7ed5d3f 100644 --- a/project2/sql/sqlRows.h +++ b/project2/sql/sqlRows.h @@ -1,7 +1,6 @@ #ifndef SQLROWS_H #define SQLROWS_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <map> #include "selectcommand.h" @@ -14,7 +13,7 @@ class RdbmsDataSource; /// Project2 component to create a row set based on an SQL SELECT statement issued against an RDBMS data source class SqlRows : public RowSet { public: - SqlRows(const xmlpp::Element * p); + SqlRows(ScriptNodePtr p); ~SqlRows(); void execute(const Glib::ustring &, const RowProcessor *) const; diff --git a/project2/sql/sqlTask.cpp b/project2/sql/sqlTask.cpp index 9f881de..6ff05af 100644 --- a/project2/sql/sqlTask.cpp +++ b/project2/sql/sqlTask.cpp @@ -17,27 +17,26 @@ class SqlIfChangesStorer : public StorerBase<NoOutputExecute, ANONORDEREDSTORAGE noChanges(nc) { } - bool insert(const xmlpp::Element * p, NoOutputExecutePtr O) { - xmlpp::Attribute * runon = p->get_attribute("runon"); - if (!runon) { + bool insert(ScriptNodePtr p, NoOutputExecutePtr O) { + try { + ((p->value("runon").as<std::string>() == "changes") ? changes : noChanges)->push_back(O); + return true; + } + catch (const ValueNotFound &) { throw RunOnNotSpecified(); } - ((runon->get_value() == "changes") ? changes : noChanges)->push_back(O); - return true; } Map changes, noChanges; }; -SqlTask::SqlTask(const xmlpp::Element * p) : +SqlTask::SqlTask(ScriptNodePtr p) : SourceObject(p), Task(p), dataSource(p, "datasource"), - filter(p, "filter", false, ""), - sqlCommand(dynamic_cast<xmlpp::Element *>(p->get_children("sql").front())) + filter(p, "filter", ""), + sqlCommand(p->child("sql")) { - LoaderBase loader(true); - loader.supportedStorers.insert(new SqlIfChangesStorer(&changesNOEs, &noChangesNOEs)); - loader.collectAll(p, true, IgnoreUnsupported); + p->script->loader.addLoadTarget(p, new SqlIfChangesStorer(&changesNOEs, &noChangesNOEs)); } SqlTask::~SqlTask() diff --git a/project2/sql/sqlTask.h b/project2/sql/sqlTask.h index 384b000..b0d0d27 100644 --- a/project2/sql/sqlTask.h +++ b/project2/sql/sqlTask.h @@ -1,7 +1,6 @@ #ifndef SQLTASK_H #define SQLTASK_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <map> #include "task.h" @@ -14,7 +13,7 @@ class RdbmsDataSource; /// Project2 component to execute a modifying SQL statement against an RDBMS data source class SqlTask : public Task { public: - SqlTask(const xmlpp::Element * p); + SqlTask(ScriptNodePtr p); virtual ~SqlTask(); virtual void loadComplete(const CommonObjects *); virtual void execute() const; diff --git a/project2/sql/sqlWriter.cpp b/project2/sql/sqlWriter.cpp index 90de82f..867e1bd 100644 --- a/project2/sql/sqlWriter.cpp +++ b/project2/sql/sqlWriter.cpp @@ -11,25 +11,33 @@ DynamicSql::SqlWriter::~SqlWriter() { } -DynamicSql::SqlCommand::SqlCommand(const xmlpp::Element * N) +template <typename Type, typename Cons> +static +void +appendNew(DynamicSql::Writers * w, const Cons & cons) { - BOOST_FOREACH(xmlpp::Node * n, N->get_children()) { - const xmlpp::TextNode * t = dynamic_cast<const xmlpp::TextNode *>(n); - if (t) { - writers.push_back(new SqlText(t)); - } - const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n); - if (e) { - if (e->get_name() == "filter") { - SqlFilterPtr f = new SqlFilter(e); - writers.push_back(f); - filters.insert(Filters::value_type(f->name, f)); - } - else if (e->get_name() == "param") { - writers.push_back(new SqlParameter(e)); - } - } + w->push_back(new Type(cons)); +} + +static +void +appendNewFromNode(DynamicSql::Writers * w, DynamicSql::SqlCommand::Filters * fs, ScriptNodePtr p) +{ + if (fs && p->get_name() == "filter") { + DynamicSql::SqlFilterPtr f = new DynamicSql::SqlFilter(p); + w->push_back(f); + fs->insert(DynamicSql::SqlCommand::Filters::value_type(f->name, f)); } + else if (p->get_name() == "param") { + w->push_back(new DynamicSql::SqlParameter(p)); + } +} + +DynamicSql::SqlCommand::SqlCommand(ScriptNodePtr s) +{ + s->composeWithCallbacks( + boost::bind(&appendNew<SqlText, Glib::ustring>, &writers, _1), + boost::bind(&appendNewFromNode, &writers, &filters, _1)); } Glib::ustring @@ -59,22 +67,13 @@ DynamicSql::SqlCommand::bindParams(DB::Command * cmd, unsigned int & offset) con } } -DynamicSql::SqlFilter::SqlFilter(const xmlpp::Element * N) : - name(N->get_attribute_value("name")), +DynamicSql::SqlFilter::SqlFilter(ScriptNodePtr p) : + name(p->value("name").as<Glib::ustring>()), active(false) { - BOOST_FOREACH(xmlpp::Node * n, N->get_children()) { - const xmlpp::TextNode * t = dynamic_cast<const xmlpp::TextNode *>(n); - if (t) { - writers.push_back(new SqlText(t)); - } - const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n); - if (e) { - if (e->get_name() == "param") { - writers.push_back(new SqlParameter(e)); - } - } - } + p->composeWithCallbacks( + boost::bind(&appendNew<SqlText, Glib::ustring>, &writers, _1), + boost::bind(&appendNewFromNode, &writers, (DynamicSql::SqlCommand::Filters *)NULL, _1)); } void @@ -97,7 +96,7 @@ DynamicSql::SqlFilter::bindParams(DB::Command * cmd, unsigned int & offset) cons } } -DynamicSql::SqlParameter::SqlParameter(const xmlpp::Element * n) : +DynamicSql::SqlParameter::SqlParameter(ScriptNodePtr n) : Variable(n, boost::optional<Glib::ustring>("local")) { } @@ -114,8 +113,8 @@ DynamicSql::SqlParameter::bindParams(DB::Command * cmd, unsigned int & offset) c boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(cmd, offset++), (*this)); } -DynamicSql::SqlText::SqlText(const xmlpp::TextNode * n) : - text(n->get_content()) +DynamicSql::SqlText::SqlText(const Glib::ustring & n) : + text(n) { } diff --git a/project2/sql/sqlWriter.h b/project2/sql/sqlWriter.h index 7693e19..4b57fa9 100644 --- a/project2/sql/sqlWriter.h +++ b/project2/sql/sqlWriter.h @@ -2,7 +2,6 @@ #define SQLWRITER_H #include <intrusivePtrBase.h> -#include <libxml++/nodes/textnode.h> #include <command.h> #include <glibmm/ustring.h> #include <list> @@ -22,7 +21,7 @@ namespace DynamicSql { }; class SqlText : public SqlWriter { public: - SqlText(const xmlpp::TextNode *); + SqlText(const Glib::ustring &); virtual void writeSql(Glib::ustring & sql) const; virtual void bindParams(DB::Command *, unsigned int & offset) const; @@ -30,13 +29,13 @@ namespace DynamicSql { }; class SqlParameter : public SqlWriter, Variable { public: - SqlParameter(const xmlpp::Element *); + SqlParameter(ScriptNodePtr); virtual void writeSql(Glib::ustring & sql) const; virtual void bindParams(DB::Command *, unsigned int & offset) const; }; class SqlFilter : public SqlWriter { public: - SqlFilter(const xmlpp::Element *); + SqlFilter(ScriptNodePtr); virtual void writeSql(Glib::ustring & sql) const; virtual void bindParams(DB::Command *, unsigned int & offset) const; @@ -48,7 +47,7 @@ namespace DynamicSql { typedef boost::intrusive_ptr<SqlFilter> SqlFilterPtr; class SqlCommand : public SqlWriter { public: - SqlCommand(const xmlpp::Element *); + SqlCommand(ScriptNodePtr); virtual void writeSql(Glib::ustring & sql) const; virtual void bindParams(DB::Command *, unsigned int & offset) const; typedef std::multimap<Glib::ustring, SqlFilterPtr> Filters; diff --git a/project2/url/Jamfile.jam b/project2/url/Jamfile.jam index 6e6dc36..1710e17 100644 --- a/project2/url/Jamfile.jam +++ b/project2/url/Jamfile.jam @@ -1,6 +1,7 @@ -alias libxmlpp : : : : - <cflags>"`pkg-config --cflags libxml++-2.6`" - <linkflags>"`pkg-config --libs libxml++-2.6`" ; +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; lib curl : : <name>curl ; lib p2url : @@ -11,7 +12,7 @@ lib p2url : <library>../common//p2common <library>../files//p2files <include>../../libmisc - <library>libxmlpp + <library>glibmm <library>curl : : <include>. diff --git a/project2/url/curlHelper.cpp b/project2/url/curlHelper.cpp index 1b98d3b..7f698cb 100644 --- a/project2/url/curlHelper.cpp +++ b/project2/url/curlHelper.cpp @@ -1,15 +1,16 @@ #include "curlHelper.h" +#include "scripts.h" -VariableCurlHelper::VariableCurlHelper(const xmlpp::Element * p) : +VariableCurlHelper::VariableCurlHelper(ScriptNodePtr p) : url(p, "url"), - userAgent(p, "useragent", false, "project2/0.3"), - cookieJar(p, "cookiejar", false), - proxy(p, "proxy", false), - referer(p, "referer", false), - method(p, "method", false), - userName(p, "username", false), - password(p, "password", false), - timeout(p, "timeout", false, Variable(6000)) + userAgent(p, "useragent", "project2/0.3"), + cookieJar(p, "cookiejar", Null()), + proxy(p, "proxy", Null()), + referer(p, "referer", Null()), + method(p, "method", Null()), + userName(p, "username", Null()), + password(p, "password", Null()), + timeout(p, "timeout", 6000) { } diff --git a/project2/url/curlHelper.h b/project2/url/curlHelper.h index 28395e5..e3e4484 100644 --- a/project2/url/curlHelper.h +++ b/project2/url/curlHelper.h @@ -1,7 +1,6 @@ #ifndef CURLHELPER_H #define CURLHELPER_H -#include <libxml++/nodes/element.h> #include "variables.h" #include "../libmisc/curlsup.h" @@ -35,7 +34,7 @@ class CurlHelper { /// Project2 helper component to configure CurlHelper from variables class VariableCurlHelper : public CurlHelper { public: - VariableCurlHelper(const xmlpp::Element * p); + VariableCurlHelper(ScriptNodePtr p); ~VariableCurlHelper(); const Variable url; diff --git a/project2/url/urlRows.cpp b/project2/url/urlRows.cpp index b3abddd..a634126 100644 --- a/project2/url/urlRows.cpp +++ b/project2/url/urlRows.cpp @@ -8,7 +8,7 @@ DECLARE_LOADER("urlrows", UrlRows); -UrlRows::UrlRows(const xmlpp::Element * p) : +UrlRows::UrlRows(ScriptNodePtr p) : StreamRows(p), VariableCurlHelper(p), convertRequired(encoding != "utf-8") diff --git a/project2/url/urlRows.h b/project2/url/urlRows.h index 9bd4302..77c85ab 100644 --- a/project2/url/urlRows.h +++ b/project2/url/urlRows.h @@ -1,7 +1,6 @@ #ifndef URLROWS_H #define URLROWS_H -#include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <boost/shared_ptr.hpp> #include <map> @@ -11,7 +10,7 @@ /// Project2 component to create a row set from the contents of a file accessible via libcurl class UrlRows : public StreamRows, VariableCurlHelper { public: - UrlRows(const xmlpp::Element * p); + UrlRows(ScriptNodePtr p); ~UrlRows(); void execute(const Glib::ustring &, const RowProcessor *) const; diff --git a/project2/xml/Jamfile.jam b/project2/xml/Jamfile.jam index 6078290..1e8fcf7 100644 --- a/project2/xml/Jamfile.jam +++ b/project2/xml/Jamfile.jam @@ -14,8 +14,7 @@ cpp-pch pch : pch.hpp : ; lib p2xml : pch - rawView.cpp xmlPresenter.cpp transformXml.cpp transformHtml.cpp transformText.cpp xmlRows.cpp - xmlRawRows.cpp xpathRows.cpp xmlDocumentCache.cpp xmlDocumentPrefetch.cpp xmlCache.cpp sessionXml.cpp + [ glob *.cpp ] : <include>../libmisc <library>libxmlpp diff --git a/project2/xml/rawView.cpp b/project2/xml/rawView.cpp index 151d594..8feceb3 100644 --- a/project2/xml/rawView.cpp +++ b/project2/xml/rawView.cpp @@ -6,15 +6,16 @@ #include "xmlObjectLoader.h" #include "environment.h" #include "appEngine.h" +#include "xmlScriptParser.h" #include <boost/foreach.hpp> #include <libxml++/nodes/textnode.h> DECLARE_LOADER("rawview", RawView); -RawView::RawView(const xmlpp::Element * p) : +RawView::RawView(ScriptNodePtr p) : SourceObject(p), View(p), - copyRoot(p) + copyRoot(boost::dynamic_pointer_cast<const XmlScriptNode>(p)->xmlElement()) { } diff --git a/project2/xml/rawView.h b/project2/xml/rawView.h index 54f7b2e..67d5628 100644 --- a/project2/xml/rawView.h +++ b/project2/xml/rawView.h @@ -9,7 +9,7 @@ /// Project2 component to create output based on its own XML tree node class RawView : public View { public: - RawView(const xmlpp::Element * p); + RawView(ScriptNodePtr p); void execute(const MultiRowSetPresenter *) const; private: diff --git a/project2/xml/xmlCache.cpp b/project2/xml/xmlCache.cpp index 8c0dd00..96cf914 100644 --- a/project2/xml/xmlCache.cpp +++ b/project2/xml/xmlCache.cpp @@ -14,7 +14,7 @@ class XmlCache : public Cache { public: - XmlCache(const xmlpp::Element * p) : + XmlCache(ScriptNodePtr p) : Cache(p) { } diff --git a/project2/xml/xmlDocumentPrefetch.cpp b/project2/xml/xmlDocumentPrefetch.cpp index e5565e6..2be3eea 100644 --- a/project2/xml/xmlDocumentPrefetch.cpp +++ b/project2/xml/xmlDocumentPrefetch.cpp @@ -4,14 +4,14 @@ DECLARE_LOADER("xmldocumentprefetch", XmlDocumentPrefetch); -XmlDocumentPrefetch::XmlDocumentPrefetch(const xmlpp::Element * p) : +XmlDocumentPrefetch::XmlDocumentPrefetch(ScriptNodePtr p) : SourceObject(p), View(p), Task(p), VariableCurlHelper(p), - html(p, "html", false, false), - warnings(p, "warnings", false, true), - encoding(p, "encoding", false) + html(p, "html", false), + warnings(p, "warnings", true), + encoding(p, "encoding", Null()) { } diff --git a/project2/xml/xmlDocumentPrefetch.h b/project2/xml/xmlDocumentPrefetch.h index f75fabe..454492a 100644 --- a/project2/xml/xmlDocumentPrefetch.h +++ b/project2/xml/xmlDocumentPrefetch.h @@ -10,7 +10,7 @@ /// Project2 component to queue up CURL objects to be downloaded class XmlDocumentPrefetch : public View, public Task, XmlDocumentCache, VariableCurlHelper { public: - XmlDocumentPrefetch(const xmlpp::Element * p); + XmlDocumentPrefetch(ScriptNodePtr p); ~XmlDocumentPrefetch(); void execute(const MultiRowSetPresenter*) const; diff --git a/project2/xml/xmlPresenter.cpp b/project2/xml/xmlPresenter.cpp index 249e4f4..86ec831 100644 --- a/project2/xml/xmlPresenter.cpp +++ b/project2/xml/xmlPresenter.cpp @@ -16,11 +16,11 @@ XmlPresenter::XmlPresenter(const Glib::ustring & responseRootNodeName, const Gli createDoc(responseRootNodeName, responseStyle); } -XmlPresenter::XmlPresenter(const xmlpp::Element * e) : - ContentPresenter(e->get_attribute_value("contenttype")), +XmlPresenter::XmlPresenter(ScriptNodePtr e) : + ContentPresenter(e->value("contenttype", "")), responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0"))) { - createDoc(e->get_attribute_value("root"), e->get_attribute_value("style")); + createDoc(e->value("root", ""), e->value("style", "")); } XmlPresenter::~XmlPresenter() diff --git a/project2/xml/xmlPresenter.h b/project2/xml/xmlPresenter.h index 4f3fdbb..38244be 100644 --- a/project2/xml/xmlPresenter.h +++ b/project2/xml/xmlPresenter.h @@ -3,16 +3,18 @@ #include "presenter.h" #include "transform.h" +#include <libxml/tree.h> namespace xmlpp { class Document; + class Element; } class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<xmlpp::Document>, public SourceOf<xmlDoc>, public SourceOf<boost::shared_ptr<xmlpp::Document> > { public: typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr; XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & contentType); - XmlPresenter(const xmlpp::Element * e); + XmlPresenter(ScriptNodePtr e); ~XmlPresenter(); void declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const; diff --git a/project2/xml/xmlRawRows.cpp b/project2/xml/xmlRawRows.cpp index 73685aa..faca679 100644 --- a/project2/xml/xmlRawRows.cpp +++ b/project2/xml/xmlRawRows.cpp @@ -42,7 +42,7 @@ class XmlRowState : public RowState { }; -XmlRawRowsBase::XmlRawRowsBase(const xmlpp::Element * p) : +XmlRawRowsBase::XmlRawRowsBase(ScriptNodePtr p) : RowSet(p) { } @@ -81,7 +81,7 @@ void XmlRawRowsBase::execute(const xmlpp::Document * doc, const RowProcessor * r } } -XmlRawRows::XmlRawRows(const xmlpp::Element * p) : +XmlRawRows::XmlRawRows(ScriptNodePtr p) : XmlRawRowsBase(p), path(p, "path") { diff --git a/project2/xml/xmlRawRows.h b/project2/xml/xmlRawRows.h index 81c04a5..15dad48 100644 --- a/project2/xml/xmlRawRows.h +++ b/project2/xml/xmlRawRows.h @@ -6,7 +6,7 @@ namespace xmlpp { class XmlRawRowsBase : public RowSet { public: - XmlRawRowsBase(const xmlpp::Element * p); + XmlRawRowsBase(ScriptNodePtr p); XmlRawRowsBase(); protected: @@ -15,7 +15,7 @@ class XmlRawRowsBase : public RowSet { class XmlRawRows : public XmlRawRowsBase { public: - XmlRawRows(const xmlpp::Element * p); + XmlRawRows(ScriptNodePtr p); XmlRawRows(const Glib::ustring & p); void execute(const Glib::ustring&, const RowProcessor * rp) const; diff --git a/project2/xml/xmlRows.cpp b/project2/xml/xmlRows.cpp index d648b10..9ec7be0 100644 --- a/project2/xml/xmlRows.cpp +++ b/project2/xml/xmlRows.cpp @@ -14,7 +14,7 @@ DECLARE_LOADER("xmlrows", XmlRows); -XmlRows::XmlRows(const xmlpp::Element * p) : +XmlRows::XmlRows(ScriptNodePtr p) : RowSet(p), recordRoot(p, "recordroot"), recordTrigger(p, "recordtrigger"), @@ -29,22 +29,19 @@ XmlRows::XmlRows(const xmlpp::Element * p) : boost::split(trigger, rT, boost::is_any_of("/")); unsigned int col = 0; - BOOST_FOREACH(const xmlpp::Node * node, p->find("fields/field")) { - const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); - if (elem) { - Path p(root); - Glib::ustring path(elem->get_child_text()->get_content()); + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("fields")) { + Path p(root); + Glib::ustring path = node->value("path"); - for(ssi It = make_split_iterator(path, first_finder("/", boost::is_equal())); It!=ssi(); ++It) { - if (It->front() == '@') { - anyInterestingAttributes = true; - } - p.push_back(Glib::ustring(It->begin(), It->end())); + for(ssi It = make_split_iterator(path, first_finder("/", boost::is_equal())); It!=ssi(); ++It) { + if (It->front() == '@') { + anyInterestingAttributes = true; } - - fields[p] = col; - fieldNames.insert(new Column(col++, elem->get_attribute_value("name"))); + p.push_back(Glib::ustring(It->begin(), It->end())); } + + fields[p] = col; + fieldNames.insert(new Column(col++, node->get_name())); } } diff --git a/project2/xml/xmlRows.h b/project2/xml/xmlRows.h index d9971bc..975e290 100644 --- a/project2/xml/xmlRows.h +++ b/project2/xml/xmlRows.h @@ -12,7 +12,7 @@ class XmlRows : public RowSet { typedef std::vector<std::string> Path; typedef std::map<Path, unsigned int> Interests; - XmlRows(const xmlpp::Element * p); + XmlRows(ScriptNodePtr p); ~XmlRows(); void execute(const Glib::ustring &, const RowProcessor *) const; diff --git a/project2/xml/xmlScriptParser.cpp b/project2/xml/xmlScriptParser.cpp new file mode 100644 index 0000000..4963b8f --- /dev/null +++ b/project2/xml/xmlScriptParser.cpp @@ -0,0 +1,191 @@ +#include <pch.hpp> +#include "xmlScriptParser.h" +#include "scripts.h" +#include "commonObjects.h" +#include "variables-modliteral.h" +#include <libxml/xinclude.h> +#include <boost/filesystem/convenience.hpp> + +XmlScriptParser::XmlScriptParser(const boost::filesystem::path & file) +{ + try { + parse_file(file.string()); + } + catch (const xmlpp::internal_error &) { + throw NotReadable(file.string()); + } + for (int x; (x = xmlXIncludeProcessFlags(get_document()->cobj(), XML_PARSE_NOXINCNODE)); ) { + if (x < 0) { + throw IncludesError(file.string()); + } + } +} + +ScriptNodePtr +XmlScriptParser::root() { + if (!_root) { + _root = new XmlScriptNode(get_document()->get_root_node(), this); + } + return _root; +} + +class XmlScriptReaderLoader : public ScriptReaderLoader { + public: + ScriptReaderPtr resolveScript(const std::string & group, const std::string & name) const { + boost::filesystem::path script(boost::filesystem::current_path() / group); + BOOST_FOREACH(const boost::filesystem::path & e, boost::filesystem::path(name)) { + if (boost::filesystem::is_directory(script / e)) { + script /= e; + } + else { + boost::filesystem::path path = (script / e).string() + ".xml"; + if (boost::filesystem::is_regular_file(path)) { + return new XmlScriptParser(path); + } + } + } + return NULL; + } +}; + + +XmlScriptNode::XmlScriptNode(const xmlpp::Element * e, ScriptReaderPtr p) : + ScriptNode(p), + element(e) +{ +} + +const xmlpp::Element * +XmlScriptNode::xmlElement() const +{ + return element; +} + +bool +XmlScriptNode::componentNamespace() const +{ + return element->get_namespace_uri () == Environment::getCurrent()->xmlNamespace; +} + +std::string +XmlScriptNode::get_name() const +{ + return element->get_name(); +} + +bool +XmlScriptNode::valueExists(const Glib::ustring & n) const +{ + return (element->get_attribute(n) || !element->get_children(n).empty()); +} + +ScriptNode::ScriptNodes +XmlScriptNode::children() const +{ + ScriptNodes sns; + BOOST_FOREACH(const xmlpp::Node * n, element->get_children()) { + if (const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n)) { + sns.push_back(new XmlScriptNode(e, script)); + } + } + return sns; +} + +ScriptNodePtr +XmlScriptNode::child(const Glib::ustring & n) const +{ + const xmlpp::Element::NodeList cs = element->get_children(n); + if (cs.size() == 1) { + if (const xmlpp::Element * c = dynamic_cast<const xmlpp::Element *>(cs.front())) { + return new XmlScriptNode(c, script); + } + } + throw ValueNotFound(n); +} + +ScriptNode::ScriptNodes +XmlScriptNode::childrenIn(const Glib::ustring & c) const +{ + ScriptNodes sns; + BOOST_FOREACH(const xmlpp::Node * n, element->get_children(c)) { + if (const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n)) { + BOOST_FOREACH(const xmlpp::Node * n1, e->get_children()) { + if (const xmlpp::Element * e1 = dynamic_cast<const xmlpp::Element *>(n1)) { + sns.push_back(new XmlScriptNode(e1, script)); + } + } + } + } + return sns; +} + +VariableImpl * +XmlScriptNode::variable(const Glib::ustring & n) const +{ + if (const xmlpp::Attribute * a = element->get_attribute(n)) { + return new VariableLiteral(a->get_value()); + } + const xmlpp::Element::NodeList cs = element->get_children(n); + if (cs.size() == 1) { + if (const xmlpp::Element * c = dynamic_cast<const xmlpp::Element *>(cs.front())) { + if (const xmlpp::Attribute * source = c->get_attribute("source")) { + return LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(source->get_value())->create(new XmlScriptNode(c, script)); + } + else { + return new VariableLiteral(new XmlScriptNode(c, script)); + } + } + } + throw ValueNotFound(n); +} + +VariableImpl * +XmlScriptNode::variable(const boost::optional<Glib::ustring> & defaultSource) const +{ + if (const xmlpp::Attribute * source = element->get_attribute("source")) { + return LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(source->get_value())->create(new XmlScriptNode(element, script)); + } + else if (defaultSource) { + return LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(defaultSource.get())->create(new XmlScriptNode(element, script)); + } + else { + return new VariableLiteral(new XmlScriptNode(element, script)); + } +} + +VariableType +XmlScriptNode::value(const Glib::ustring & n) const +{ + if (const xmlpp::Attribute * a = element->get_attribute(n)) { + return a->get_value(); + } + const xmlpp::Element::NodeList cs = element->get_children(n); + if (cs.size() == 1) { + if (const xmlpp::Element * c = dynamic_cast<const xmlpp::Element *>(cs.front())) { + boost::intrusive_ptr<VariableImpl> v; + if (const xmlpp::Attribute * source = c->get_attribute("source")) { + v = LoaderBase::getLoader<VariableLoader, UnknownVariableSource>(source->get_value())->create(new XmlScriptNode(c, script)); + } + else { + v = new VariableLiteral(new XmlScriptNode(c, script)); + } + return v->value(); + } + } + throw ValueNotFound(n); +} + +void +XmlScriptNode::composeWithCallbacks(const LiteralCallback & lcb, const NodeCallback & ncb) const +{ + BOOST_FOREACH(const xmlpp::Node * n, element->get_children()) { + if (const xmlpp::TextNode * t = dynamic_cast<const xmlpp::TextNode *>(n)) { + lcb(t->get_content()); + } + else if (const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n)) { + ncb(new XmlScriptNode(e, script)); + } + } +} + +DECLARE_CUSTOM_COMPONENT_LOADER("xmlScriptReader", XmlScriptReaderLoader, XmlScriptReaderLoader, ScriptReaderLoader); diff --git a/project2/xml/xmlScriptParser.h b/project2/xml/xmlScriptParser.h new file mode 100644 index 0000000..ad0b1bf --- /dev/null +++ b/project2/xml/xmlScriptParser.h @@ -0,0 +1,48 @@ +#ifndef XMLSCRIPTPARSER_H +#define XMLSCRIPTPARSER_H + +#include <boost/function.hpp> +#include "exceptions.h" +#include "xmlObjectLoader.h" +#include "scripts.h" +#include <intrusivePtrBase.h> +#include <boost/filesystem/path.hpp> +#include <libxml++/document.h> +#include <libxml++/nodes/element.h> +#include <libxml++/parsers/domparser.h> + +class XmlScriptNode : public ScriptNode { + public: + XmlScriptNode(const xmlpp::Element * xmlElement, ScriptReaderPtr p); + + const xmlpp::Element * xmlElement() const; + bool componentNamespace() const; + std::string get_name() const; + ScriptNodePtr child(const Glib::ustring&) const; + ScriptNodes children() const; + ScriptNodes childrenIn(const Glib::ustring&) const; + bool valueExists(const Glib::ustring&) const; + VariableImpl * variable(const boost::optional<Glib::ustring> & defaultSource) const; + VariableImpl * variable(const Glib::ustring&) const; + VariableType value(const Glib::ustring&) const; + void composeWithCallbacks(const ScriptNode::LiteralCallback&, const ScriptNode::NodeCallback&) const; + + private: + const xmlpp::Element * element; +}; + +class XmlScriptParser : public xmlpp::DomParser, public ScriptReader { + public: + SimpleMessageException(ParseError); + SimpleMessageExceptionBase(NotReadable, ParseError); + SimpleMessageExceptionBase(IncludesError, ParseError); + + XmlScriptParser(const boost::filesystem::path & file); + ScriptNodePtr root(); + private: + ScriptNodePtr _root; +}; + + +#endif + diff --git a/project2/xml/xpathRows.cpp b/project2/xml/xpathRows.cpp index e65104d..bc9481a 100644 --- a/project2/xml/xpathRows.cpp +++ b/project2/xml/xpathRows.cpp @@ -17,25 +17,19 @@ DECLARE_LOADER("xpathrows", XPathRows); SimpleMessageException(XpathInitError); SimpleMessageException(XpathEvalError); -XPathRows::XPathRows(const xmlpp::Element * p) : +XPathRows::XPathRows(ScriptNodePtr p) : RowSet(p), VariableCurlHelper(p), - html(p, "html", false, false), - warnings(p, "warnings", false, true), - encoding(p, "encoding", false) + html(p, "html", false), + warnings(p, "warnings", true), + encoding(p, "encoding", Null()) { - BOOST_FOREACH(const xmlpp::Node * node, p->find("filterview")) { - const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); - if (elem) { - FilterViewPtr fv = new FilterView(elem); - fvs[fv->name] = fv; - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("filterviews")) { + FilterViewPtr fv = new FilterView(node); + fvs[fv->name] = fv; } - BOOST_FOREACH(const xmlpp::Node * node, p->find("namespace")) { - const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); - if (elem) { - namespaces[elem->get_attribute_value("prefix")] = elem->get_attribute_value("url"); - } + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("namespaces")) { + namespaces[node->value("prefix")] = node->value("url").as<Glib::ustring>(); } } @@ -122,21 +116,21 @@ XPathRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const } } -XPathRows::FilterView::FilterView(const xmlpp::Element * p) : - DefinedColumns(p, "field", boost::bind(XPathRows::FilterViewColumn::make, _1, _2)), - name(p->get_attribute_value("name")), +XPathRows::FilterView::FilterView(ScriptNodePtr p) : + DefinedColumns(p, "fields", boost::bind(XPathRows::FilterViewColumn::make, _1, _2)), + name(p->get_name()), root(p, "root") { } -XPathRows::FilterViewColumn::FilterViewColumn(unsigned int idx, const xmlpp::Element * p) : +XPathRows::FilterViewColumn::FilterViewColumn(unsigned int idx, ScriptNodePtr p) : Column(idx, p), path(p, "xpath") { } XPathRows::FilterViewColumn * -XPathRows::FilterViewColumn::make(unsigned int idx, const xmlpp::Element * p) +XPathRows::FilterViewColumn::make(unsigned int idx, ScriptNodePtr p) { return new FilterViewColumn(idx, p); } diff --git a/project2/xml/xpathRows.h b/project2/xml/xpathRows.h index e2c6327..47d34eb 100644 --- a/project2/xml/xpathRows.h +++ b/project2/xml/xpathRows.h @@ -14,7 +14,7 @@ /// Project2 component to create a row set based on the contents of an XML resource and specific XPaths with its hierarchy class XPathRows : public RowSet, XmlDocumentCache, VariableCurlHelper { public: - XPathRows(const xmlpp::Element * p); + XPathRows(ScriptNodePtr p); ~XPathRows(); void execute(const Glib::ustring &, const RowProcessor *) const; @@ -22,15 +22,15 @@ class XPathRows : public RowSet, XmlDocumentCache, VariableCurlHelper { private: class FilterViewColumn : public Column { public: - FilterViewColumn(unsigned int, const xmlpp::Element *); - static FilterViewColumn * make(unsigned int, const xmlpp::Element *); + FilterViewColumn(unsigned int, ScriptNodePtr); + static FilterViewColumn * make(unsigned int, ScriptNodePtr); const Variable path; }; class FilterView : public DefinedColumns, public virtual IntrusivePtrBase { public: typedef std::map<const Glib::ustring, Variable> XPaths; - FilterView(const xmlpp::Element * p); + FilterView(ScriptNodePtr p); const Glib::ustring name; const Variable root; |