diff options
Diffstat (limited to 'project2/variables.cpp')
-rw-r--r-- | project2/variables.cpp | 115 |
1 files changed, 107 insertions, 8 deletions
diff --git a/project2/variables.cpp b/project2/variables.cpp index f633ccd..969c17f 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -1,10 +1,13 @@ #include "variables.h" +#include "logger.h" +#include "iHaveParameters.h" #include "xmlObjectLoader.h" #include "exceptions.h" #include "appEngine.h" #include "session.h" #include "rowUser.h" #include "rowSet.h" +#include "rowProcessor.h" #include <libxml++/nodes/textnode.h> #include <stdexcept> #include <boost/tokenizer.hpp> @@ -20,7 +23,6 @@ SimpleMessageException(NoVariableDefinition); enum VT_typeID { DefaultType, - StringPtr, String, Int, UInt, @@ -31,7 +33,6 @@ enum VT_typeID { Float, Double, DateTime, - DateTimePtr, }; static @@ -40,7 +41,6 @@ getVariableTypeFromName(const std::string & src) { if (src.empty()) return String; if (src == "string") return String; - if (src == "stringptr") return StringPtr; if (src == "int") return Int; if (src == "uint") return UInt; if (src == "lint") return LInt; @@ -50,7 +50,6 @@ getVariableTypeFromName(const std::string & src) if (src == "float") return Float; if (src == "double") return Double; if (src == "datetime") return DateTime; - if (src == "datetimeptr") return DateTimePtr; throw UnknownVariableType(src); } static @@ -60,8 +59,6 @@ makeVariableType(const Glib::ustring & src, const VT_typeID format = DefaultType switch (format) { default: case DefaultType: - case StringPtr: - return boost::shared_ptr<Glib::ustring>(new Glib::ustring(src)); case String: return src; case Int: @@ -82,8 +79,6 @@ makeVariableType(const Glib::ustring & src, const VT_typeID format = DefaultType return boost::lexical_cast<double>(src); case DateTime: return boost::posix_time::time_from_string(src); - case DateTimePtr: - return boost::shared_ptr<boost::posix_time::ptime>(new boost::posix_time::ptime(boost::posix_time::time_from_string(src))); } } @@ -364,6 +359,108 @@ class VariableConfig : public VariableImplDyn { 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)) { @@ -391,6 +488,8 @@ Variable::Variable(const xmlpp::Element * e, const Glib::ustring & n, bool requi 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"))); |