summaryrefslogtreecommitdiff
path: root/project2/variables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'project2/variables.cpp')
-rw-r--r--project2/variables.cpp115
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")));