summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2010-07-07 19:12:01 +0000
committerrandomdan <randomdan@localhost>2010-07-07 19:12:01 +0000
commitf0fb1f9bd8c9ba6c8d58defc7972b6e6a075cf78 (patch)
tree55146ff28a345e1e3a2d82893530c2f356c0d47a
parentImplement connection caching and checking (requires ODBCv3 driver) (diff)
downloadproject2-f0fb1f9bd8c9ba6c8d58defc7972b6e6a075cf78.tar.bz2
project2-f0fb1f9bd8c9ba6c8d58defc7972b6e6a075cf78.tar.xz
project2-f0fb1f9bd8c9ba6c8d58defc7972b6e6a075cf78.zip
Implement variables (prefixed strings to find values elsewhere)
-rw-r--r--project2/appEngine.cpp8
-rw-r--r--project2/appEngine.h7
-rw-r--r--project2/cgiAppEngine.cpp11
-rw-r--r--project2/cgiAppEngine.h4
-rw-r--r--project2/iHaveParameters.cpp3
-rw-r--r--project2/iHaveParameters.h4
-rw-r--r--project2/iterate.cpp12
-rw-r--r--project2/paramChecker.cpp1
-rw-r--r--project2/paramChecker.h2
-rw-r--r--project2/perRowValues.cpp28
-rw-r--r--project2/perRowValues.h11
-rw-r--r--project2/regexCheck.cpp3
-rw-r--r--project2/regexCheck.h1
-rw-r--r--project2/sessionClearTask.cpp3
-rw-r--r--project2/sessionSetTask.cpp16
-rw-r--r--project2/sessionSetTask.h5
-rw-r--r--project2/sqlCheck.cpp7
-rw-r--r--project2/sqlIterate.cpp23
-rw-r--r--project2/sqlIterate.h2
-rw-r--r--project2/sqlTask.cpp16
-rw-r--r--project2/sqlView.cpp22
-rw-r--r--project2/sqlView.h2
-rw-r--r--project2/variables.cpp148
-rw-r--r--project2/variables.h37
-rw-r--r--project2/view.cpp12
25 files changed, 284 insertions, 104 deletions
diff --git a/project2/appEngine.cpp b/project2/appEngine.cpp
index 632bb11..be49c10 100644
--- a/project2/appEngine.cpp
+++ b/project2/appEngine.cpp
@@ -1,10 +1,18 @@
#include "appEngine.h"
+#include <stdexcept>
+
+ApplicationEngine * ApplicationEngine::currentEngine = NULL;
ApplicationEngine::ApplicationEngine(const Environment *)
{
+ if (currentEngine) {
+ throw std::runtime_error("One application at a time, please");
+ }
+ currentEngine = this;
}
ApplicationEngine::~ApplicationEngine()
{
+ currentEngine = NULL;
}
diff --git a/project2/appEngine.h b/project2/appEngine.h
index d2cff10..59e0d4d 100644
--- a/project2/appEngine.h
+++ b/project2/appEngine.h
@@ -3,6 +3,7 @@
#include "environment.h"
#include "dataSource.h"
+#include "session.h"
class ApplicationEngine {
public:
@@ -14,8 +15,7 @@ class ApplicationEngine {
virtual void process() const = 0;
virtual const Environment * env() const = 0;
- virtual void SessionSet(const Glib::ustring & name, const Glib::ustring & value) const = 0;
- virtual void SessionClear(const Glib::ustring & name) const = 0;
+ virtual SessionPtr session() const = 0;
template <class DataSourceType>
const DataSourceType * dataSource(const std::string & name) const
@@ -30,8 +30,11 @@ class ApplicationEngine {
}
return s;
}
+ static ApplicationEngine * getCurrent() { return currentEngine; }
protected:
mutable DataSources datasources;
+ private:
+ static ApplicationEngine * currentEngine;
};
#endif
diff --git a/project2/cgiAppEngine.cpp b/project2/cgiAppEngine.cpp
index 60b1ed3..a419be0 100644
--- a/project2/cgiAppEngine.cpp
+++ b/project2/cgiAppEngine.cpp
@@ -185,14 +185,9 @@ CgiApplicationEngine::RequestStage::run()
return new PresentStage(appEngine, present);
}
-void
-CgiApplicationEngine::SessionSet(const Glib::ustring & name, const Glib::ustring & value) const
-{
- sessionsContainer->GetSession(sessionID)->SetValue(name, value);
-}
-void
-CgiApplicationEngine::SessionClear(const Glib::ustring & name) const
+SessionPtr
+CgiApplicationEngine::session() const
{
- sessionsContainer->GetSession(sessionID)->ClearValue(name);
+ return sessionsContainer->GetSession(sessionID);
}
diff --git a/project2/cgiAppEngine.h b/project2/cgiAppEngine.h
index f6f37d0..0172eee 100644
--- a/project2/cgiAppEngine.h
+++ b/project2/cgiAppEngine.h
@@ -10,6 +10,7 @@
#include <libxml++/parsers/domparser.h>
class CgiEnvironment;
+class Session;
namespace cgicc {
class HTTPContentHeader;
}
@@ -26,8 +27,7 @@ class CgiApplicationEngine : public ApplicationEngine {
w(doc->cobj());
}
const Environment * env() const;
- virtual void SessionSet(const Glib::ustring & name, const Glib::ustring & value) const;
- virtual void SessionClear(const Glib::ustring & name) const;
+ SessionPtr session() const;
const CgiEnvironment * _env;
protected:
cgicc::HTTPContentHeader * header;
diff --git a/project2/iHaveParameters.cpp b/project2/iHaveParameters.cpp
index c13eddf..0f1084e 100644
--- a/project2/iHaveParameters.cpp
+++ b/project2/iHaveParameters.cpp
@@ -18,8 +18,7 @@ IHaveParameters::~IHaveParameters()
}
IHaveParameters::_Parameter::_Parameter(const xmlpp::Element * p) :
- source(p->get_attribute_value("source")),
- id(p->get_attribute_value("id")),
+ value(p->get_attribute("value")),
bind(atoi(p->get_attribute_value("bind").c_str()))
{
}
diff --git a/project2/iHaveParameters.h b/project2/iHaveParameters.h
index 31c597a..329e341 100644
--- a/project2/iHaveParameters.h
+++ b/project2/iHaveParameters.h
@@ -3,14 +3,14 @@
#include <libxml++/nodes/element.h>
#include <boost/shared_ptr.hpp>
+#include "variables.h"
class IHaveParameters {
public:
class _Parameter {
public:
_Parameter(const xmlpp::Element * p);
- const std::string source;
- const std::string id;
+ const Variable value;
const unsigned int bind;
};
IHaveParameters(const xmlpp::Element * p);
diff --git a/project2/iterate.cpp b/project2/iterate.cpp
index 02fc149..843d598 100644
--- a/project2/iterate.cpp
+++ b/project2/iterate.cpp
@@ -34,8 +34,16 @@ _Iterate::AddLoaders(Loaders & l, NoOutputExecutes & iterates)
void
_Iterate::executeChildren(const ApplicationEngine * ep, const PerRowValues * parent) const
{
- BOOST_FOREACH(NoOutputExecutes::value_type sq, subIterates) {
- sq.second->execute(ep, this);
+ try {
+ PerRowValues::beginRow(this);
+ BOOST_FOREACH(NoOutputExecutes::value_type sq, subIterates) {
+ sq.second->execute(ep, this);
+ }
+ PerRowValues::endRow(this);
+ }
+ catch (...) {
+ PerRowValues::endRow(this);
+ throw;
}
}
diff --git a/project2/paramChecker.cpp b/project2/paramChecker.cpp
index 627f1be..5455f22 100644
--- a/project2/paramChecker.cpp
+++ b/project2/paramChecker.cpp
@@ -7,7 +7,6 @@
_ParamChecker::_ParamChecker(const xmlpp::Element * p) :
_SourceObject(p),
message(xmlChildText(p, "message")),
- applyTo(p->get_attribute_value("apply-to")),
present(p->get_attribute_value("present"))
{
}
diff --git a/project2/paramChecker.h b/project2/paramChecker.h
index 1ffe89f..b22a1f9 100644
--- a/project2/paramChecker.h
+++ b/project2/paramChecker.h
@@ -6,6 +6,7 @@
#include <map>
#include "sourceObject.h"
#include "xmlObjectLoader.h"
+#include "variables.h"
class ApplicationEngine;
class _ParamChecker;
@@ -21,7 +22,6 @@ class _ParamChecker : public virtual _SourceObject {
virtual bool performCheck(const ApplicationEngine *) const = 0;
const Glib::ustring message;
- const std::string applyTo;
const std::string present;
static void AddLoaders(Loaders & l, OrderedParamCheckers & vs);
diff --git a/project2/perRowValues.cpp b/project2/perRowValues.cpp
new file mode 100644
index 0000000..30433fd
--- /dev/null
+++ b/project2/perRowValues.cpp
@@ -0,0 +1,28 @@
+#include "perRowValues.h"
+#include <cstdlib>
+
+PerRowValues::RowValuesStack PerRowValues::stack;
+
+PerRowValues::PerRowValues()
+{
+}
+
+PerRowValues::~PerRowValues()
+{
+}
+
+void
+PerRowValues::beginRow(const PerRowValues * r)
+{
+ stack.push_back(r);
+}
+
+void
+PerRowValues::endRow(const PerRowValues * r)
+{
+ if ((*stack.rbegin()) != r) {
+ std::abort();
+ }
+ stack.pop_back();
+}
+
diff --git a/project2/perRowValues.h b/project2/perRowValues.h
index 2a46763..eec8e37 100644
--- a/project2/perRowValues.h
+++ b/project2/perRowValues.h
@@ -2,10 +2,21 @@
#define PERROWVALUES_H
#include <glibmm/ustring.h>
+#include <vector>
class PerRowValues {
public:
+ typedef std::vector<const PerRowValues *> RowValuesStack;
+ PerRowValues();
+ virtual ~PerRowValues() = 0;
+
virtual Glib::ustring getCurrentValue(const Glib::ustring & id) const = 0;
+ static const RowValuesStack & Stack() { return stack; }
+ static void beginRow(const PerRowValues * r);
+ static void endRow(const PerRowValues * r);
+
+ private:
+ static RowValuesStack stack;
};
#endif
diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp
index 672194f..d6e1bb0 100644
--- a/project2/regexCheck.cpp
+++ b/project2/regexCheck.cpp
@@ -6,6 +6,7 @@
_RegexCheck::_RegexCheck(const xmlpp::Element * p) :
_SourceObject(p),
_ParamChecker(p),
+ applyTo(p->get_attribute("apply-to")),
regex(xmlChildText(p, "regex").raw())
{
}
@@ -17,7 +18,7 @@ _RegexCheck::~_RegexCheck()
bool
_RegexCheck::performCheck(const ApplicationEngine * ep) const
{
- const Glib::ustring & param = ep->env()->getParamQuery(applyTo);
+ const Glib::ustring & param(applyTo);
return boost::regex_match(param.begin(), param.end(), regex);
}
diff --git a/project2/regexCheck.h b/project2/regexCheck.h
index 5db92f5..b515d54 100644
--- a/project2/regexCheck.h
+++ b/project2/regexCheck.h
@@ -11,6 +11,7 @@ class _RegexCheck : public _ParamChecker {
bool performCheck(const ApplicationEngine *) const;
+ const Variable applyTo;
const boost::regex regex;
};
typedef boost::shared_ptr<_RegexCheck> RegexCheck;
diff --git a/project2/sessionClearTask.cpp b/project2/sessionClearTask.cpp
index 963ebeb..696f250 100644
--- a/project2/sessionClearTask.cpp
+++ b/project2/sessionClearTask.cpp
@@ -2,6 +2,7 @@
#include "xmlObjectLoader.h"
#include "sessionClearTask.h"
#include "appEngine.h"
+#include "session.h"
_SessionClearTask::_SessionClearTask(const xmlpp::Element * p) :
_SourceObject(p),
@@ -17,6 +18,6 @@ _SessionClearTask::~_SessionClearTask()
void
_SessionClearTask::execute(const ApplicationEngine * ep, const PerRowValues *) const
{
- ep->SessionClear(key);
+ ep->session()->ClearValue(key);
}
diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp
index abd02b0..8304494 100644
--- a/project2/sessionSetTask.cpp
+++ b/project2/sessionSetTask.cpp
@@ -3,12 +3,13 @@
#include "xmlObjectLoader.h"
#include "sessionSetTask.h"
#include "appEngine.h"
+#include "session.h"
_SessionSetTask::_SessionSetTask(const xmlpp::Element * p) :
_SourceObject(p),
_Task(p),
- IHaveParameters(p),
- key(p->get_attribute_value("key"))
+ key(p->get_attribute_value("key")),
+ value(p->get_attribute("value"))
{
}
@@ -19,15 +20,6 @@ _SessionSetTask::~_SessionSetTask()
void
_SessionSetTask::execute(const ApplicationEngine * ep, const PerRowValues * parent) const
{
- Parameter p = parameters.find(0)->second;
- if (p->source == "uri") {
- ep->SessionSet(key, ep->env()->getParamUri(p->id));
- }
- else if (p->source == "parent") {
- ep->SessionSet(key, parent->getCurrentValue(p->id));
- }
- else if (p->source == "query") {
- ep->SessionSet(key, ep->env()->getParamQuery(p->id));
- }
+ ep->session()->SetValue(key, value);
}
diff --git a/project2/sessionSetTask.h b/project2/sessionSetTask.h
index 32df37b..491c55d 100644
--- a/project2/sessionSetTask.h
+++ b/project2/sessionSetTask.h
@@ -7,19 +7,20 @@
#include "sourceObject.h"
#include "xmlObjectLoader.h"
#include "task.h"
-#include "iHaveParameters.h"
+#include "variables.h"
class ApplicationEngine;
class _SessionSetTask;
typedef boost::shared_ptr<_SessionSetTask> SessionSetTask;
-class _SessionSetTask : public virtual _Task, public IHaveParameters {
+class _SessionSetTask : public virtual _Task {
public:
_SessionSetTask(const xmlpp::Element * p);
virtual ~_SessionSetTask();
void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const;
const Glib::ustring key;
+ const Variable value;
};
#endif
diff --git a/project2/sqlCheck.cpp b/project2/sqlCheck.cpp
index 1dab147..65cf0e3 100644
--- a/project2/sqlCheck.cpp
+++ b/project2/sqlCheck.cpp
@@ -26,12 +26,7 @@ _SqlCheck::performCheck(const ApplicationEngine * ep) const
{
ODBC::SelectCommand * query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);
BOOST_FOREACH(Parameters::value_type p, parameters) {
- if (p.second->source == "uri") {
- query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id));
- }
- else if (p.second->source == "query") {
- query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id));
- }
+ query->bindParamS(p.second->bind, p.second->value);
}
bool retVal = false;
while (query->fetch()) {
diff --git a/project2/sqlIterate.cpp b/project2/sqlIterate.cpp
index 90a8bc1..5499940 100644
--- a/project2/sqlIterate.cpp
+++ b/project2/sqlIterate.cpp
@@ -25,32 +25,11 @@ _SqlIterate::getCurrentValue(const Glib::ustring & id) const
return (*query)[id].compose();
}
-void
-_SqlIterate::rebindCurrentValue(const Glib::ustring & id, ODBC::Command * cmd, unsigned int bind) const
-{
- (*query)[id].rebind(cmd, bind);
-}
-
void _SqlIterate::execute(const ApplicationEngine * ep, const PerRowValues * parent) const
{
- typedef std::map<std::string, xmlpp::Element *> Columns;
query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);
BOOST_FOREACH(Parameters::value_type p, parameters) {
- if (p.second->source == "uri") {
- query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id));
- }
- else if (p.second->source == "query") {
- query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id));
- }
- else if (parent && p.second->source == "parent") {
- const _SqlIterate * psqlIterate = dynamic_cast<const _SqlIterate *>(parent);
- if (psqlIterate) {
- psqlIterate->rebindCurrentValue(p.second->id, query, p.second->bind);
- }
- else {
- query->bindParamS(p.second->bind, parent->getCurrentValue(p.second->id));
- }
- }
+ query->bindParamS(p.second->bind, p.second->value());
}
while (query->fetch()) {
executeChildren(ep, this);
diff --git a/project2/sqlIterate.h b/project2/sqlIterate.h
index c9cef49..41b5648 100644
--- a/project2/sqlIterate.h
+++ b/project2/sqlIterate.h
@@ -18,7 +18,7 @@ class _SqlIterate : public IHaveParameters, public _Iterate {
Glib::ustring getCurrentValue(const Glib::ustring & id) const;
const std::string dataSource;
const Glib::ustring sql;
- void rebindCurrentValue(const Glib::ustring & id, ODBC::Command *, unsigned int) const;
+
private:
mutable ODBC::SelectCommand * query;
};
diff --git a/project2/sqlTask.cpp b/project2/sqlTask.cpp
index e6fec24..3811b43 100644
--- a/project2/sqlTask.cpp
+++ b/project2/sqlTask.cpp
@@ -24,21 +24,7 @@ _SqlTask::execute(const ApplicationEngine * ep, const PerRowValues * parent) con
{
ODBC::ModifyCommand modify(ep->dataSource<_RdbmsDataSource>(dataSource)->getWritable(), sql);
BOOST_FOREACH(Parameters::value_type p, parameters) {
- if (p.second->source == "uri") {
- modify.bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id));
- }
- else if (p.second->source == "query") {
- modify.bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id));
- }
- else if (parent && p.second->source == "parent") {
- const _SqlView * psqlview = dynamic_cast<const _SqlView *>(parent);
- if (psqlview) {
- psqlview->rebindCurrentValue(p.second->id, &modify, p.second->bind);
- }
- else {
- modify.bindParamS(p.second->bind, parent->getCurrentValue(p.second->id));
- }
- }
+ modify.bindParamS(p.second->bind, p.second->value);
}
modify.execute();
}
diff --git a/project2/sqlView.cpp b/project2/sqlView.cpp
index cab4ca5..41fa441 100644
--- a/project2/sqlView.cpp
+++ b/project2/sqlView.cpp
@@ -27,32 +27,12 @@ _SqlView::getCurrentValue(const Glib::ustring & id) const
return (*query)[id].compose();
}
-void
-_SqlView::rebindCurrentValue(const Glib::ustring & id, ODBC::Command * cmd, unsigned int bind) const
-{
- (*query)[id].rebind(cmd, bind);
-}
-
void _SqlView::execute(xmlpp::Element * par, const ApplicationEngine * ep, const _View * parent) const
{
typedef std::map<std::string, xmlpp::Element *> Columns;
query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);
BOOST_FOREACH(Parameters::value_type p, parameters) {
- if (p.second->source == "uri") {
- query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id));
- }
- else if (p.second->source == "query") {
- query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id));
- }
- else if (parent && p.second->source == "parent") {
- const _SqlView * psqlview = dynamic_cast<const _SqlView *>(parent);
- if (psqlview) {
- psqlview->rebindCurrentValue(p.second->id, query, p.second->bind);
- }
- else {
- query->bindParamS(p.second->bind, parent->getCurrentValue(p.second->id));
- }
- }
+ query->bindParamS(p.second->bind, p.second->value);
}
xmlpp::Element * set = par->add_child(name);
while (query->fetch()) {
diff --git a/project2/sqlView.h b/project2/sqlView.h
index 1a77e7d..5fd8a48 100644
--- a/project2/sqlView.h
+++ b/project2/sqlView.h
@@ -18,7 +18,7 @@ class _SqlView : public IHaveParameters, public _View {
Glib::ustring getCurrentValue(const Glib::ustring & id) const;
const std::string dataSource;
const Glib::ustring sql;
- void rebindCurrentValue(const Glib::ustring & id, ODBC::Command *, unsigned int) const;
+
private:
mutable ODBC::SelectCommand * query;
};
diff --git a/project2/variables.cpp b/project2/variables.cpp
new file mode 100644
index 0000000..f8fe4bb
--- /dev/null
+++ b/project2/variables.cpp
@@ -0,0 +1,148 @@
+#include "variables.h"
+#include "appEngine.h"
+#include "perRowValues.h"
+#include "session.h"
+#include <libxml++/nodes/textnode.h>
+#include <stdexcept>
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+
+class VariableLiteral : public VariableImpl {
+ public:
+ VariableLiteral(const Glib::ustring & src) : VariableImpl(src) { }
+
+ virtual const Glib::ustring & value() const { return source; }
+};
+
+class VariableImplDyn : public VariableImpl {
+ public:
+ VariableImplDyn(const Glib::ustring & src) : VariableImpl(src), cacheValid(false) { }
+ virtual const Glib::ustring & value() const = 0;
+
+ protected:
+ mutable Glib::ustring cache;
+ mutable bool cacheValid;
+};
+
+class VariableSession : public VariableImplDyn {
+ public:
+ VariableSession(const Glib::ustring & src) : VariableImplDyn(src) { }
+ const Glib::ustring & value() const
+ {
+ if (!cacheValid) {
+ cache = ApplicationEngine::getCurrent()->session()->GetValue(source.substr(1));
+ cacheValid = true;
+ }
+ return cache;
+ }
+};
+
+class VariableParam : public VariableImplDyn {
+ public:
+ VariableParam(const Glib::ustring & src) : VariableImplDyn(src) { }
+ const Glib::ustring & value() const
+ {
+ if (!cacheValid) {
+ cache = ApplicationEngine::getCurrent()->env()->getParamQuery(source.substr(1));
+ cacheValid = true;
+ }
+ return cache;
+ }
+};
+
+class VariableUri : public VariableImplDyn {
+ public:
+ VariableUri(const Glib::ustring & src) : VariableImplDyn(src) { }
+ const Glib::ustring & value() const
+ {
+ if (!cacheValid) {
+ cache = ApplicationEngine::getCurrent()->env()->getParamUri(source.substr(1));
+ cacheValid = true;
+ }
+ return cache;
+ }
+};
+
+class VariableParent : public VariableImplDyn {
+ public:
+ VariableParent(const Glib::ustring & src) : VariableImplDyn(src) { }
+ const Glib::ustring & value() const
+ {
+ if (!cacheValid) {
+ PerRowValues::RowValuesStack::const_iterator r = PerRowValues::Stack().end();
+ Glib::ustring::const_iterator c = source.begin();
+ while (*c == '^') {
+ r--;
+ c++;
+ }
+ cache = (*r)->getCurrentValue(Glib::ustring(c, source.end()));
+ cacheValid = true;
+ }
+ return cache;
+ }
+};
+
+class VariableParse : public VariableImplDyn {
+ public:
+ VariableParse(const Glib::ustring & src) : VariableImplDyn(src) { }
+ const Glib::ustring & value() const
+ {
+ if (!cacheValid) {
+ boost::char_separator<char> sep(" ");
+ boost::tokenizer<boost::char_separator<char> > tokens(source.raw(), sep);
+ std::list<Variable::VariableImplPtr> vars;
+ size_t len = 0;
+ BOOST_FOREACH(std::string t, tokens) {
+ Variable::VariableImplPtr vip = Variable::create(t);
+ len += vip->value().length() + 1;
+ vars.push_back(vip);
+ }
+ cache.reserve(len);
+ BOOST_FOREACH(Variable::VariableImplPtr v, vars) {
+ if (cache.length()) {
+ cache.append(" ");
+ }
+ cache.append(v->value());
+ }
+ cacheValid = true;
+ }
+ return cache;
+ }
+};
+
+Variable::Variable(const Glib::ustring & s) :
+ var(create(s))
+{
+}
+
+Variable::Variable(xmlpp::Attribute * a) :
+ var(create(a->get_value()))
+{
+}
+
+Variable::Variable(xmlpp::Element * e) :
+ var(create(e->get_child_text()->get_content()))
+{
+}
+
+Variable::VariableImplPtr
+Variable::create(const Glib::ustring & s)
+{
+ switch (s[0]) {
+ case '$': // param
+ return VariableImplPtr(new VariableParam(s));
+ case '%': // session
+ return VariableImplPtr(new VariableSession(s));
+ case '^': // parent
+ return VariableImplPtr(new VariableParent(s));
+ case '/': // uri
+ return VariableImplPtr(new VariableUri(s));
+ case '*': // parser
+ return VariableImplPtr(new VariableParse(s));
+ case '=': // literal (explicit)
+ return VariableImplPtr(new VariableParse(s.substr(1)));
+ default:
+ return VariableImplPtr(new VariableLiteral(s));
+ }
+}
+
diff --git a/project2/variables.h b/project2/variables.h
new file mode 100644
index 0000000..cba303e
--- /dev/null
+++ b/project2/variables.h
@@ -0,0 +1,37 @@
+#ifndef VARIABLES_H
+#define VARIABLES_H
+
+#include <boost/shared_ptr.hpp>
+#include <glibmm/ustring.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/attribute.h>
+
+class VariableImpl {
+ public:
+ virtual const Glib::ustring & value() const = 0;
+
+ protected:
+ VariableImpl(const Glib::ustring & src) : source(src) { }
+ const Glib::ustring source;
+};
+
+
+class Variable {
+ public:
+ typedef boost::shared_ptr<VariableImpl> VariableImplPtr;
+
+ Variable(xmlpp::Attribute *);
+ Variable(xmlpp::Element *);
+ Variable(const Glib::ustring & s);
+
+ operator const Glib::ustring & () const { return var->value(); }
+ const Glib::ustring & operator()() const { return var->value(); }
+
+ private:
+ friend class VariableParse;
+ static VariableImplPtr create(const Glib::ustring & s);
+ VariableImplPtr var;
+};
+
+#endif
+
diff --git a/project2/view.cpp b/project2/view.cpp
index c36c43d..3a99aa6 100644
--- a/project2/view.cpp
+++ b/project2/view.cpp
@@ -24,8 +24,16 @@ _View::AddLoaders(Loaders & l, Views & views)
void
_View::executeChildren(xmlpp::Element * record, const ApplicationEngine * ep, const _View * parent) const
{
- BOOST_FOREACH(Views::value_type sq, subViews) {
- sq.second->execute(record, ep, this);
+ try {
+ PerRowValues::beginRow(this);
+ BOOST_FOREACH(Views::value_type sq, subViews) {
+ sq.second->execute(record, ep, this);
+ }
+ PerRowValues::endRow(this);
+ }
+ catch (...) {
+ PerRowValues::endRow(this);
+ throw;
}
}