#include "variables.h" #include "appEngine.h" #include "perRowValues.h" #include "session.h" #include #include #include #include #include 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 { cache = ApplicationEngine::getCurrent()->session()->GetValue(source.substr(1)); 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 RowUser { public: VariableParent(const Glib::ustring & src, const RowUser * d) : VariableImplDyn(Glib::ustring(std::find_if(src.begin(), src.end(), isalpha), src.end())), row(NULL), depth(src.length() - source.length()), dep(d) { } const Glib::ustring & value() const { if (!cacheValid) { if (!row) { PerRowValues::RowValuesStack::const_reverse_iterator r = PerRowValues::Stack().rbegin(); for (size_t p = depth; --p; r++) ; row = *r; row->use(this); if (dep) { row->use(dep); } } cache = row->getCurrentValue(source); cacheValid = true; } return cache; } void rowChanged() const { cacheValid = false; } protected: mutable const PerRowValues * row; const size_t depth; const RowUser * dep; }; class VariableParse : public VariableImplDyn, public RowUser { public: VariableParse(const Glib::ustring & src) : VariableImplDyn(src) { boost::char_separator sep(" "); boost::tokenizer > tokens(source.raw(), sep); BOOST_FOREACH(std::string t, tokens) { vars.push_back(Variable::create(t, this)); } } const Glib::ustring & value() const { if (!cacheValid) { size_t len = 0; BOOST_FOREACH(Variable::VariableImplPtr vip, vars) { len += vip->value().length() + 1; } cache.reserve(len); BOOST_FOREACH(Variable::VariableImplPtr v, vars) { if (cache.length()) { cache.append(" "); } cache.append(v->value()); } cacheValid = true; } return cache; } void rowChanged() const { cacheValid = false; } private: std::list vars; }; 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, RowUser * dep) { switch (s[0]) { case '$': // param return VariableImplPtr(new VariableParam(s)); case '%': // session return VariableImplPtr(new VariableSession(s)); case '^': // parent return VariableImplPtr(new VariableParent(s, dep)); 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)); } }