diff options
Diffstat (limited to 'project2/variables.cpp')
-rw-r--r-- | project2/variables.cpp | 279 |
1 files changed, 30 insertions, 249 deletions
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 <libxml++/nodes/textnode.h> #include <stdexcept> #include <boost/tokenizer.hpp> @@ -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<Variable> 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<VariableLiteral>, 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<void, VariableType &, ConstRowSetPtr> 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 S> -class compi : public boost::static_visitor<bool> { - public: - compi(const S & s) : _s(s) { } - bool operator()(const S & t) const - { - return _s < t; - } - template <class T> - bool operator()(const T &) const - { - // should never be called - return false; - } - private: - const S & _s; -}; - -class comp : public boost::static_visitor<bool> { - public: - comp(const VariableType & a) : _a(a) { } - template <class T> - bool operator()(const T & t) const - { - return boost::apply_visitor(compi<T>(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<VariableType> Key; - typedef std::map<Key, VariableType> 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<const xmlpp::Element *>(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<VariableLoader, UnknownVariableSource>(source->get_value())->create(c); + } + else { + var = new VariableLiteral(c); } - else - throw UnknownVariableSource(source); return; } } |