From 1a5151e58ce5d3100f005c9c2f536f6df79b3393 Mon Sep 17 00:00:00 2001 From: randomdan Date: Mon, 25 Jul 2011 23:50:58 +0000 Subject: Plugable variable doobries --- project2/Jamfile.jam | 5 + project2/variables-modconfig.cpp | 26 ++++ project2/variables-modlookup.cpp | 110 +++++++++++++++ project2/variables-modparam.cpp | 34 +++++ project2/variables-modsession.cpp | 31 +++++ project2/variables-moduri.cpp | 34 +++++ project2/variables.cpp | 279 ++++---------------------------------- project2/variables.h | 28 ++++ 8 files changed, 298 insertions(+), 249 deletions(-) create mode 100644 project2/variables-modconfig.cpp create mode 100644 project2/variables-modlookup.cpp create mode 100644 project2/variables-modparam.cpp create mode 100644 project2/variables-modsession.cpp create mode 100644 project2/variables-moduri.cpp diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index 5d7186d..5fc26f2 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -60,6 +60,11 @@ lib p2common : sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp taskHost.cpp checkHost.cpp rowView.cpp rowSet.cpp rowUser.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp transform.cpp transformHtml.cpp transformText.cpp definedColumns.cpp + variables-modconfig.cpp + variables-modlookup.cpp + variables-modparam.cpp + variables-modsession.cpp + variables-moduri.cpp ../libmisc/buffer.cpp ../libmisc/misc.cpp : diff --git a/project2/variables-modconfig.cpp b/project2/variables-modconfig.cpp new file mode 100644 index 0000000..935e2d6 --- /dev/null +++ b/project2/variables-modconfig.cpp @@ -0,0 +1,26 @@ +#include "variables.h" +#include "xmlObjectLoader.h" +#include "xmlStorage.h" +#include "appEngine.h" + +/// Variable implementation to access platform configuration values +class VariableConfig : public VariableImplDyn { + public: + VariableConfig(const xmlpp::Element * e) : + VariableImplDyn(e), + name(e->get_attribute_value("name")) + { + } + const VariableType & value() const + { + if (!cacheValid) { + cache = ApplicationEngine::getCurrent()->getCurrentConfig()->getValue(name); + cacheValid = true; + } + return cache; + } + private: + const Glib::ustring name; +}; +DECLARE_COMPONENT_LOADER("config", VariableConfig, VariableLoader); + diff --git a/project2/variables-modlookup.cpp b/project2/variables-modlookup.cpp new file mode 100644 index 0000000..e020d9a --- /dev/null +++ b/project2/variables-modlookup.cpp @@ -0,0 +1,110 @@ +#include "variables.h" +#include "logger.h" +#include "rowProcessor.h" +#include "rowSet.h" +#include +#include "xmlObjectLoader.h" +#include "xmlStorage.h" + +template +class compi : public boost::static_visitor { + public: + compi(const S & s) : _s(s) { } + bool operator()(const S & t) const + { + return _s < t; + } + template + bool operator()(const T &) const + { + // should never be called + throw std::logic_error("Shouldn't ever be comparing variables of different type"); + } + private: + const S & _s; +}; + +class comp : public boost::static_visitor { + public: + comp(const VariableType & a) : _a(a) { } + template + bool operator()(const T & t) const + { + return boost::apply_visitor(compi(t), _a); + } + private: + const VariableType & _a; +}; + +bool +operator<(const VariableType & a, const VariableType & b) +{ + if (a.which() < b.which()) { + return true; + } + if (a.which() == b.which()) { + return boost::apply_visitor(comp(a), b); + } + return false; +} + +/// Variable implementation that looks up it's value in a map of key(s)/value pairs +class VariableLookup : public VariableImplDyn, public RowProcessor { + private: + typedef std::vector Key; + typedef std::map Map; + public: + class NotFound { }; + VariableLookup(const xmlpp::Element * e) : + VariableImplDyn(e), + RowProcessor(e), + name(e->get_attribute_value("name")) + { + LoaderBase loader(true); + loader.supportedStorers.insert(Storer::into(&rowSets)); + loader.collectAll(e, false); + } + const VariableType & value() const + { + if (map.empty()) { + fillCache(); + } + Key k; + k.reserve(parameters.size()); + BOOST_FOREACH(const Parameters::value_type & p, parameters) { + k.push_back(p.second->value()); + } + Map::const_iterator i = map.find(k); + if (i != map.end()) { + cache = i->second; + return cache; + } + throw NotFound(); + } + private: + void fillCache() const + { + BOOST_FOREACH(const RowSets::value_type & rs, rowSets) { + cs = rs; + rs->execute(this); + } + cs.reset(); + Logger()->messagef(LOG_DEBUG, "%s: %s has filled cached with %zu items", + __PRETTY_FUNCTION__, name.c_str(), map.size()); + } + void rowReady() const + { + Key k; + k.reserve(cs->columnCount() - 1); + BOOST_FOREACH(const Parameters::value_type & p, parameters) { + k.push_back(cs->getCurrentValue(p.first)); + } + map[k] = cs->getCurrentValue(name); + } + mutable Map map; + mutable RowSetPtr cs; + typedef ANONSTORAGEOF(RowSet) RowSets; + RowSets rowSets; + const Glib::ustring name; +}; +DECLARE_COMPONENT_LOADER("lookup", VariableLookup, VariableLoader); diff --git a/project2/variables-modparam.cpp b/project2/variables-modparam.cpp new file mode 100644 index 0000000..a932412 --- /dev/null +++ b/project2/variables-modparam.cpp @@ -0,0 +1,34 @@ +#include "variables.h" +#include "xmlObjectLoader.h" +#include "xmlStorage.h" +#include "appEngine.h" + +/// Variable implementation to access call parameters +class VariableParam : public VariableImplDyn { + public: + VariableParam(const xmlpp::Element * e) : + VariableImplDyn(e), + name(e->get_attribute_value("name")) + { + } + const VariableType & value() const + { + if (!cacheValid) { + try { + cache = ApplicationEngine::getCurrent()->env()->getParamQuery(name); + } + catch (ParamNotFound) { + if (!defaultValue) { + throw; + } + cache = (*defaultValue)(); + } + cacheValid = true; + } + return cache; + } + private: + const Glib::ustring name; +}; +DECLARE_COMPONENT_LOADER("param", VariableParam, VariableLoader); + diff --git a/project2/variables-modsession.cpp b/project2/variables-modsession.cpp new file mode 100644 index 0000000..0d39695 --- /dev/null +++ b/project2/variables-modsession.cpp @@ -0,0 +1,31 @@ +#include "variables.h" +#include "xmlObjectLoader.h" +#include "xmlStorage.h" +#include "appEngine.h" + +/// Variable implementation to access session contents +class VariableSession : public VariableImplDyn { + public: + VariableSession(const xmlpp::Element * e) : + VariableImplDyn(e), + name(e->get_attribute_value("name")) + { + } + const VariableType & value() const + { + try { + cache = ApplicationEngine::getCurrent()->session()->GetValue(name); + } + catch (Session::VariableNotFound) { + if (!defaultValue) { + throw; + } + cache = (*defaultValue)(); + } + return cache; + } + private: + const Glib::ustring name; +}; +DECLARE_COMPONENT_LOADER("session", VariableSession, VariableLoader); + diff --git a/project2/variables-moduri.cpp b/project2/variables-moduri.cpp new file mode 100644 index 0000000..f6793e1 --- /dev/null +++ b/project2/variables-moduri.cpp @@ -0,0 +1,34 @@ +#include "variables.h" +#include "xmlObjectLoader.h" +#include "xmlStorage.h" +#include "appEngine.h" + +/// Variable implementation to access URI path fragments +class VariableUri : public VariableImplDyn { + public: + VariableUri(const xmlpp::Element * e) : + VariableImplDyn(e), + index(atoi(e->get_attribute_value("index").c_str())) + { + } + const VariableType & value() const + { + if (!cacheValid) { + try { + cache = ApplicationEngine::getCurrent()->env()->getParamUri(index); + } + catch (UriElementOutOfRange) { + if (!defaultValue) { + throw; + } + cache = (*defaultValue)(); + } + cacheValid = true; + } + return cache; + } + private: + unsigned int index; +}; +DECLARE_COMPONENT_LOADER("uri", VariableUri, VariableLoader); + diff --git a/project2/variables.cpp b/project2/variables.cpp index 969c17f..4e18fc0 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -1,5 +1,4 @@ #include "variables.h" -#include "logger.h" #include "iHaveParameters.h" #include "xmlObjectLoader.h" #include "exceptions.h" @@ -7,7 +6,6 @@ #include "session.h" #include "rowUser.h" #include "rowSet.h" -#include "rowProcessor.h" #include #include #include @@ -121,115 +119,38 @@ class VariableLiteral : public VariableImpl { val(makeVariableType(src, format)) { } - - virtual const VariableType & value() const { return val; } - private: - VariableType val; -}; - -/// Base class for variables whose content is dynamic -class VariableImplDyn : public VariableImpl { - public: - VariableImplDyn(const xmlpp::Element * e) : - cacheValid(false) + VariableLiteral(const xmlpp::Element * c) { - try { - if (e) { - defaultValue = Variable(e, "default"); - } + if (const xmlpp::Attribute * la = c->get_attribute("value")) { + val = makeVariableType(la->get_value(), getVariableTypeFromName(c->get_attribute_value("type"))); } - catch (NoVariableDefinition) { - // That's cool... no default + else if (const xmlpp::TextNode * t = c->get_child_text()) { + val = makeVariableType(t->get_content(), getVariableTypeFromName(c->get_attribute_value("type"))); } - } - virtual const VariableType & value() const = 0; - - protected: - mutable VariableType cache; - mutable bool cacheValid; - boost::optional defaultValue; -}; - -/// Variable implementation to access session contents -class VariableSession : public VariableImplDyn { - public: - VariableSession(const xmlpp::Element * e) : - VariableImplDyn(e), - name(e->get_attribute_value("name")) - { - } - const VariableType & value() const - { - try { - cache = ApplicationEngine::getCurrent()->session()->GetValue(name); - } - catch (Session::VariableNotFound) { - if (!defaultValue) { - throw; - } - cache = (*defaultValue)(); + else { + val = VariableType(); } - return cache; } - private: - const Glib::ustring name; -}; -/// Variable implementation to access call parameters -class VariableParam : public VariableImplDyn { - public: - VariableParam(const xmlpp::Element * e) : - VariableImplDyn(e), - name(e->get_attribute_value("name")) - { - } - const VariableType & value() const - { - if (!cacheValid) { - try { - cache = ApplicationEngine::getCurrent()->env()->getParamQuery(name); - } - catch (ParamNotFound) { - if (!defaultValue) { - throw; - } - cache = (*defaultValue)(); - } - cacheValid = true; - } - return cache; - } + virtual const VariableType & value() const { return val; } private: - const Glib::ustring name; + VariableType val; }; +DECLARE_COMPONENT_LOADER("literal", VariableLiteral, VariableLoader); +DECLARE_CUSTOM_COMPONENT_LOADER("", VariableLiteralDef, VariableLoaderImpl, VariableLoader); -/// Variable implementation to access URI path fragments -class VariableUri : public VariableImplDyn { - public: - VariableUri(const xmlpp::Element * e) : - VariableImplDyn(e), - index(atoi(e->get_attribute_value("index").c_str())) - { - } - const VariableType & value() const - { - if (!cacheValid) { - try { - cache = ApplicationEngine::getCurrent()->env()->getParamUri(index); - } - catch (UriElementOutOfRange) { - if (!defaultValue) { - throw; - } - cache = (*defaultValue)(); - } - cacheValid = true; - } - return cache; +VariableImplDyn::VariableImplDyn(const xmlpp::Element * e) : + cacheValid(false) +{ + try { + if (e) { + defaultValue = Variable(e, "default"); } - private: - unsigned int index; -}; + } + catch (NoVariableDefinition) { + // That's cool... no default + } +} static void assignHelper(VariableType & dest, const VariableType & src) { dest = src; @@ -238,7 +159,7 @@ static void assignHelper(VariableType & dest, const VariableType & src) { /// Variable implementation to access fields in row sets class VariableParent : public VariableImplDyn, public RowUser { public: - VariableParent(const xmlpp::Element * e, const RowUser * d) : + VariableParent(const xmlpp::Element * e, const RowUser * d = NULL) : VariableImplDyn(e), row(NULL), depth(atoi(e->get_attribute_value("depth").c_str())), @@ -323,6 +244,7 @@ class VariableParent : public VariableImplDyn, public RowUser { const RowUser * dep; mutable boost::function2 getValue; }; +DECLARE_COMPONENT_LOADER("parent", VariableParent, VariableLoader); /// Variable implementation which has some fixed value class VariableFixed : public VariableImpl { @@ -339,128 +261,6 @@ class VariableFixed : public VariableImpl { VariableType var; }; -/// Variable implementation to access platform configuration values -class VariableConfig : public VariableImplDyn { - public: - VariableConfig(const xmlpp::Element * e) : - VariableImplDyn(e), - name(e->get_attribute_value("name")) - { - } - const VariableType & value() const - { - if (!cacheValid) { - cache = ApplicationEngine::getCurrent()->getCurrentConfig()->getValue(name); - cacheValid = true; - } - return cache; - } - private: - const Glib::ustring name; -}; - -template -class compi : public boost::static_visitor { - public: - compi(const S & s) : _s(s) { } - bool operator()(const S & t) const - { - return _s < t; - } - template - bool operator()(const T &) const - { - // should never be called - return false; - } - private: - const S & _s; -}; - -class comp : public boost::static_visitor { - public: - comp(const VariableType & a) : _a(a) { } - template - bool operator()(const T & t) const - { - return boost::apply_visitor(compi(t), _a); - } - private: - const VariableType & _a; -}; - -bool -operator<(const VariableType & a, const VariableType & b) -{ - if (a.which() < b.which()) { - return true; - } - if (a.which() == b.which()) { - return boost::apply_visitor(comp(a), b); - } - return false; -} - -/// Variable implementation that looks up it's value in a map of key(s)/value pairs -class VariableLookup : public VariableImplDyn, public RowProcessor { - private: - typedef std::vector Key; - typedef std::map Map; - public: - class NotFound { }; - VariableLookup(const xmlpp::Element * e) : - VariableImplDyn(e), - RowProcessor(e), - name(e->get_attribute_value("name")) - { - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into(&rowSets)); - loader.collectAll(e, false); - } - const VariableType & value() const - { - if (map.empty()) { - fillCache(); - } - Key k; - k.reserve(parameters.size()); - BOOST_FOREACH(const Parameters::value_type & p, parameters) { - k.push_back(p.second->value()); - } - Map::const_iterator i = map.find(k); - if (i != map.end()) { - cache = i->second; - return cache; - } - throw NotFound(); - } - private: - void fillCache() const - { - BOOST_FOREACH(const RowSets::value_type & rs, rowSets) { - cs = rs; - rs->execute(this); - } - cs.reset(); - Logger()->messagef(LOG_DEBUG, "%s: %s has filled cached with %zu items", - __PRETTY_FUNCTION__, name.c_str(), map.size()); - } - void rowReady() const - { - Key k; - k.reserve(cs->columnCount() - 1); - BOOST_FOREACH(const Parameters::value_type & p, parameters) { - k.push_back(cs->getCurrentValue(p.first)); - } - map[k] = cs->getCurrentValue(name); - } - mutable Map map; - mutable RowSetPtr cs; - typedef ANONSTORAGEOF(RowSet) RowSets; - RowSets rowSets; - const Glib::ustring name; -}; - Variable::Variable(VariableType def) : var(new VariableFixed(def)) { @@ -477,32 +277,13 @@ Variable::Variable(const xmlpp::Element * e, const Glib::ustring & n, bool requi if (cs.size() == 1) { const xmlpp::Element * c = dynamic_cast(cs.front()); if (c) { - Glib::ustring source = c->get_attribute_value("source"); - if (source == "session") - var = new VariableSession(c); - else if (source == "parent") - var = new VariableParent(c, NULL); - else if (source == "uri") - var = new VariableUri(c); - else if (source == "param") - var = new VariableParam(c); - else if (source == "config") - var = new VariableConfig(c); - else if (source == "lookup") - var = new VariableLookup(c); - else if (source == "literal" || source.empty()) { - if (const xmlpp::Attribute * la = c->get_attribute("value")) { - var = new VariableLiteral(la->get_value(), getVariableTypeFromName(c->get_attribute_value("type"))); - } - else if (const xmlpp::TextNode * t = c->get_child_text()) { - var = new VariableLiteral(t->get_content(), getVariableTypeFromName(c->get_attribute_value("type"))); - } - else { - var = new VariableLiteral(VariableType()); - } + xmlpp::Attribute * source = c->get_attribute("source"); + if (source) { + var = LoaderBase::getLoader(source->get_value())->create(c); + } + else { + var = new VariableLiteral(c); } - else - throw UnknownVariableSource(source); return; } } diff --git a/project2/variables.h b/project2/variables.h index a6dfb05..92aac4b 100644 --- a/project2/variables.h +++ b/project2/variables.h @@ -9,6 +9,7 @@ #include #include #include "intrusivePtrBase.h" +#include "xmlObjectLoader.h" #include #include @@ -88,5 +89,32 @@ class Variable { VariableImplPtr var; }; +/// Base class for variables whose content is dynamic +class VariableImplDyn : public VariableImpl { + public: + VariableImplDyn(const xmlpp::Element * e); + virtual const VariableType & value() const = 0; + + protected: + mutable VariableType cache; + mutable bool cacheValid; + boost::optional defaultValue; +}; + +/// Base class to create variables +class VariableLoader : public ComponentLoader { + public: + virtual VariableImpl * create(const xmlpp::Element *) const = 0; +}; +/// Helper implementation of VariableLoader for specific variable types +template +class VariableLoaderImpl : public VariableLoader { + public: + virtual VariableImpl * create(const xmlpp::Element * e) const + { + return new VarType(e); + } +}; + #endif -- cgit v1.2.3