diff options
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; |