diff options
-rw-r--r-- | project2/appEngine.cpp | 8 | ||||
-rw-r--r-- | project2/appEngine.h | 7 | ||||
-rw-r--r-- | project2/cgiAppEngine.cpp | 11 | ||||
-rw-r--r-- | project2/cgiAppEngine.h | 4 | ||||
-rw-r--r-- | project2/iHaveParameters.cpp | 3 | ||||
-rw-r--r-- | project2/iHaveParameters.h | 4 | ||||
-rw-r--r-- | project2/iterate.cpp | 12 | ||||
-rw-r--r-- | project2/paramChecker.cpp | 1 | ||||
-rw-r--r-- | project2/paramChecker.h | 2 | ||||
-rw-r--r-- | project2/perRowValues.cpp | 28 | ||||
-rw-r--r-- | project2/perRowValues.h | 11 | ||||
-rw-r--r-- | project2/regexCheck.cpp | 3 | ||||
-rw-r--r-- | project2/regexCheck.h | 1 | ||||
-rw-r--r-- | project2/sessionClearTask.cpp | 3 | ||||
-rw-r--r-- | project2/sessionSetTask.cpp | 16 | ||||
-rw-r--r-- | project2/sessionSetTask.h | 5 | ||||
-rw-r--r-- | project2/sqlCheck.cpp | 7 | ||||
-rw-r--r-- | project2/sqlIterate.cpp | 23 | ||||
-rw-r--r-- | project2/sqlIterate.h | 2 | ||||
-rw-r--r-- | project2/sqlTask.cpp | 16 | ||||
-rw-r--r-- | project2/sqlView.cpp | 22 | ||||
-rw-r--r-- | project2/sqlView.h | 2 | ||||
-rw-r--r-- | project2/variables.cpp | 148 | ||||
-rw-r--r-- | project2/variables.h | 37 | ||||
-rw-r--r-- | project2/view.cpp | 12 |
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; } } |