summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-07-25 23:50:58 +0000
committerrandomdan <randomdan@localhost>2011-07-25 23:50:58 +0000
commit4d0c9685212e57caf83a641043f6244a60cb0679 (patch)
tree4cb9b2a1d8d0dc0679eedcb3bf1d7c10579aac5b
parentRemove the pointer versions of variable type members (diff)
downloadproject2-4d0c9685212e57caf83a641043f6244a60cb0679.tar.bz2
project2-4d0c9685212e57caf83a641043f6244a60cb0679.tar.xz
project2-4d0c9685212e57caf83a641043f6244a60cb0679.zip
Plugable variable doobries
-rw-r--r--project2/Jamfile.jam5
-rw-r--r--project2/variables-modconfig.cpp26
-rw-r--r--project2/variables-modlookup.cpp110
-rw-r--r--project2/variables-modparam.cpp34
-rw-r--r--project2/variables-modsession.cpp31
-rw-r--r--project2/variables-moduri.cpp34
-rw-r--r--project2/variables.cpp279
-rw-r--r--project2/variables.h28
8 files changed, 298 insertions, 249 deletions
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 <boost/foreach.hpp>
+#include "xmlObjectLoader.h"
+#include "xmlStorage.h"
+
+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
+ throw std::logic_error("Shouldn't ever be comparing variables of different type");
+ }
+ 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;
+};
+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 <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;
}
}
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 <libxml++/nodes/element.h>
#include <libxml++/attribute.h>
#include "intrusivePtrBase.h"
+#include "xmlObjectLoader.h"
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
@@ -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<Variable> 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 VarType>
+class VariableLoaderImpl : public VariableLoader {
+ public:
+ virtual VariableImpl * create(const xmlpp::Element * e) const
+ {
+ return new VarType(e);
+ }
+};
+
#endif