diff options
Diffstat (limited to 'project2/basics')
-rw-r--r-- | project2/basics/caches/memoryCache.cpp | 166 | ||||
-rw-r--r-- | project2/basics/loggers/consoleLog.cpp | 29 | ||||
-rw-r--r-- | project2/basics/loggers/syslogLog.cpp | 39 | ||||
-rw-r--r-- | project2/basics/options/preload.cpp (renamed from project2/basics/preload.cpp) | 0 | ||||
-rw-r--r-- | project2/basics/tasks/session/sessionClearTask.cpp | 26 | ||||
-rw-r--r-- | project2/basics/tasks/session/sessionClearTask.h | 25 | ||||
-rw-r--r-- | project2/basics/tasks/session/sessionSetTask.cpp | 27 | ||||
-rw-r--r-- | project2/basics/tasks/session/sessionSetTask.h | 27 | ||||
-rw-r--r-- | project2/basics/tasks/structExceptHandling.cpp | 44 | ||||
-rw-r--r-- | project2/basics/tasks/structExceptHandling.h | 18 | ||||
-rw-r--r-- | project2/basics/views/flatView.cpp | 58 | ||||
-rw-r--r-- | project2/basics/views/flatView.h | 28 | ||||
-rw-r--r-- | project2/basics/views/rowView.cpp | 102 | ||||
-rw-r--r-- | project2/basics/views/rowView.h | 38 | ||||
-rw-r--r-- | project2/basics/views/singleton.cpp | 45 | ||||
-rw-r--r-- | project2/basics/views/viewGroup.cpp | 27 |
16 files changed, 699 insertions, 0 deletions
diff --git a/project2/basics/caches/memoryCache.cpp b/project2/basics/caches/memoryCache.cpp new file mode 100644 index 0000000..7ab271e --- /dev/null +++ b/project2/basics/caches/memoryCache.cpp @@ -0,0 +1,166 @@ +#include <pch.hpp> +#include "logger.h" +#include "cache.h" +#include <boost/foreach.hpp> +#include "options.h" +#include "rowSet.h" +#include "presenter.h" +#include "safeMapFind.h" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> + +class MemoryCache : public Cache { + public: + typedef std::vector<VariableType> Key; + class CachedRowSet : public RowSet, public RowSetPresenter { + public: + class MemoryCacheRow : public RowState { + public: + typedef std::map<Glib::ustring, const VariableType> AttrMap; + MemoryCacheRow(const Columns * c) : + columns(c) { + } + const Columns & getColumns() const { + return *columns; + } + RowAttribute resolveAttr(const Glib::ustring & attrName) const { + return boost::bind(&safeMapLookup<AttributeDoesNotExist, AttrMap>, attrs, attrName); + } + private: + friend class CachedRowSet; + const Columns * columns; + AttrMap attrs; + }; + typedef boost::shared_ptr<MemoryCacheRow> MemoryCacheRowPtr; + typedef std::list<MemoryCacheRowPtr> DataCache; + + CachedRowSet(const std::vector<VariableType> & k) : + RowSet(NULL), + key(k), + createdAt(time(NULL)), + col(0) + { + } + + void execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext *) const { + BOOST_FOREACH(const DataCache::value_type & mcr, dataCache) { + mcr->process(rp, false); + } + } + + void addAttribute(const Glib::ustring & name, const VariableType & value) const { + cur->attrs.insert(MemoryCacheRow::AttrMap::value_type(name, value)); + } + + void addNamedValue(const Glib::ustring & name, const VariableType & value) const { + if (cur->fields.size() <= col) { + cur->fields.resize(col + 1); + columns.insert(new Column(col, name)); + } + cur->fields[col++] = value; + } + + void addNewRow(const Glib::ustring&) const { + col = 0; + cur = MemoryCacheRowPtr(new MemoryCacheRow(&columns)); + } + + void finishRow() const { + dataCache.push_back(cur); + cur.reset(); + } + + const Key key; + const time_t createdAt; + + private: + mutable unsigned int col; + mutable Columns columns; + mutable DataCache dataCache; + mutable MemoryCacheRowPtr cur; + + }; + typedef boost::intrusive_ptr<CachedRowSet> CachedRowSetPtr; + typedef boost::intrusive_ptr<const CachedRowSet> CachedRowSetCPtr; + + struct IndexByKey { }; + struct IndexByTime { }; + typedef boost::multi_index::multi_index_container< + CachedRowSetCPtr, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + boost::multi_index::tag<IndexByKey>, BOOST_MULTI_INDEX_MEMBER(CachedRowSet, const Key, key)>, + boost::multi_index::ordered_non_unique< + boost::multi_index::tag<IndexByTime>, BOOST_MULTI_INDEX_MEMBER(CachedRowSet, const time_t, createdAt)> + > > CacheStore; + + MemoryCache(ScriptNodePtr p) : + Cache(p) + { + } + + RowSetCPtr getCachedRowSet(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { + Key key(makeKey(ec, n, f, ps)); + CacheStore::index<IndexByKey>::type::const_iterator i = Store.get<IndexByKey>().find(key); + if (i == Store.get<IndexByKey>().end()) { + return NULL; + } + if ((*i)->createdAt < (time(NULL) - CacheLife)) { + Store.erase(i); + return NULL; + } + return *i; + } + + RowSetPresenterPtr openFor(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) { + return (cur = new CachedRowSet(makeKey(ec, n, f, ps))); + } + + void save(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { + if (cur) { + Store.insert(cur); + cur.reset(); + } + } + + void discard(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { + cur.reset(); + } + + private: + Key makeKey(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { + Key key; + key.push_back(n); + key.push_back(f); + applyKeys(ec, [&key](const std::string &, const VariableType & v) { key.push_back(v); }, ps); + return key; + } + + CachedRowSetPtr cur; + + friend class CustomMemoryCacheLoader; + static time_t CacheLife; + static CacheStore Store; +}; +time_t MemoryCache::CacheLife; +MemoryCache::CacheStore MemoryCache::Store; + +class CustomMemoryCacheLoader : public ElementLoader::For<MemoryCache> { + public: + void onPeriodic() { + typedef MemoryCache::CacheStore::index<MemoryCache::IndexByTime>::type::iterator iter; + iter x = MemoryCache::Store.get<MemoryCache::IndexByTime>().begin(); + iter y = MemoryCache::Store.get<MemoryCache::IndexByTime>().upper_bound(time(NULL) - MemoryCache::CacheLife); + MemoryCache::Store.get<MemoryCache::IndexByTime>().erase(x, y); + } + + INITOPTIONS; +}; +DECLARE_CUSTOM_LOADER("memorycache", CustomMemoryCacheLoader); + +DECLARE_OPTIONS(CustomMemoryCacheLoader, "Memory Cache options") +("cache.memory.life", Options::value(&MemoryCache::CacheLife, 3600), + "The age of cache entries after which they are removed (seconds)") +END_OPTIONS(CustomMemoryCacheLoader); + diff --git a/project2/basics/loggers/consoleLog.cpp b/project2/basics/loggers/consoleLog.cpp new file mode 100644 index 0000000..de45245 --- /dev/null +++ b/project2/basics/loggers/consoleLog.cpp @@ -0,0 +1,29 @@ +#include "logger.h" +#include "options.h" + +/// Logger that writes to the console +class ConsoleLogDriver : public LogDriverBase { + public: + ConsoleLogDriver() + { + } + void message(int priority, const char * msg) const + { + if (priority <= level) { + fprintf(stderr, "%s\n", msg); + fflush(stderr); + } + } + INITOPTIONS; + static int level; +}; + +DECLARE_OPTIONS(ConsoleLogDriver, "Console log options") +("common.consolelogLevel", Options::value(&level, LOG_WARNING), + "Log to console with level <arg> (default WARNING)")("c") +END_OPTIONS(ConsoleLogDriver); + +int ConsoleLogDriver::level; + +DECLARE_LOGGER_LOADER("console", ConsoleLogDriver); + diff --git a/project2/basics/loggers/syslogLog.cpp b/project2/basics/loggers/syslogLog.cpp new file mode 100644 index 0000000..8e58326 --- /dev/null +++ b/project2/basics/loggers/syslogLog.cpp @@ -0,0 +1,39 @@ +#include "logger.h" +#include "options.h" + +/// Logger that writes to syslog +class SyslogLogDriver : public LogDriverBase { + public: + SyslogLogDriver() + { + openlog(ident.c_str(), 0, LOG_USER); + } + ~SyslogLogDriver() + { + closelog(); + } + void message(int priority, const char * msg) const + { + if (priority <= level) { + syslog(priority, "%s", msg); + } + } + + INITOPTIONS; + static int level; + private: + static std::string ident; +}; + +DECLARE_OPTIONS(SyslogLogDriver, "Syslog options") +("common.syslog.level", Options::value(&level, -1), + "Log to syslog with level <arg> (default OFF)")("s") +("common.syslog.ident", Options::value(&ident, "project2"), + "Log to syslog with ident <arg> (default 'project2')") +END_OPTIONS(SyslogLogDriver); + +int SyslogLogDriver::level; +std::string SyslogLogDriver::ident; + +DECLARE_LOGGER_LOADER("syslog", SyslogLogDriver); + diff --git a/project2/basics/preload.cpp b/project2/basics/options/preload.cpp index 03f275b..03f275b 100644 --- a/project2/basics/preload.cpp +++ b/project2/basics/options/preload.cpp diff --git a/project2/basics/tasks/session/sessionClearTask.cpp b/project2/basics/tasks/session/sessionClearTask.cpp new file mode 100644 index 0000000..265bb1c --- /dev/null +++ b/project2/basics/tasks/session/sessionClearTask.cpp @@ -0,0 +1,26 @@ +#include <pch.hpp> +#include <boost/foreach.hpp> +#include "scriptLoader.h" +#include "sessionClearTask.h" +#include "session.h" +#include "execContext.h" + +DECLARE_LOADER("sessionclear", SessionClearTask); + +SessionClearTask::SessionClearTask(ScriptNodePtr p) : + SourceObject(p), + Task(p), + key(p->value("key", NULL).as<Glib::ustring>()) +{ +} + +SessionClearTask::~SessionClearTask() +{ +} + +void +SessionClearTask::execute(ExecContext * ec) const +{ + ec->getSession()->ClearValue(key); +} + diff --git a/project2/basics/tasks/session/sessionClearTask.h b/project2/basics/tasks/session/sessionClearTask.h new file mode 100644 index 0000000..ead88bf --- /dev/null +++ b/project2/basics/tasks/session/sessionClearTask.h @@ -0,0 +1,25 @@ +#ifndef SESSIONCLEARTASK_H +#define SESSIONCLEARTASK_H + +#include <boost/intrusive_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "scriptLoader.h" +#include "task.h" + +class CommonObjects; + +/// Project2 component to remove a variable from the session +class SessionClearTask : public Task { + public: + SessionClearTask(ScriptNodePtr p); + virtual ~SessionClearTask(); + + void execute(ExecContext *) const; + + const Glib::ustring key; +}; + +#endif + + diff --git a/project2/basics/tasks/session/sessionSetTask.cpp b/project2/basics/tasks/session/sessionSetTask.cpp new file mode 100644 index 0000000..f46571b --- /dev/null +++ b/project2/basics/tasks/session/sessionSetTask.cpp @@ -0,0 +1,27 @@ +#include <pch.hpp> +#include <boost/foreach.hpp> +#include "scriptLoader.h" +#include "sessionSetTask.h" +#include "session.h" +#include "execContext.h" + +DECLARE_LOADER("sessionset", SessionSetTask); + +SessionSetTask::SessionSetTask(ScriptNodePtr p) : + SourceObject(p), + Task(p), + key(p->value("key", NULL).as<Glib::ustring>()), + value(p, "value") +{ +} + +SessionSetTask::~SessionSetTask() +{ +} + +void +SessionSetTask::execute(ExecContext * ec) const +{ + ec->getSession()->SetValue(key, value(ec)); +} + diff --git a/project2/basics/tasks/session/sessionSetTask.h b/project2/basics/tasks/session/sessionSetTask.h new file mode 100644 index 0000000..d38c216 --- /dev/null +++ b/project2/basics/tasks/session/sessionSetTask.h @@ -0,0 +1,27 @@ +#ifndef SESSIONSETTASK_H +#define SESSIONSETTASK_H + +#include <boost/intrusive_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "scriptLoader.h" +#include "task.h" +#include "variables.h" + +class CommonObjects; + +/// Project2 component to add/update a variable in the session +class SessionSetTask : public Task { + public: + SessionSetTask(ScriptNodePtr p); + virtual ~SessionSetTask(); + + void execute(ExecContext *) const; + + const Glib::ustring key; + const Variable value; +}; + +#endif + + diff --git a/project2/basics/tasks/structExceptHandling.cpp b/project2/basics/tasks/structExceptHandling.cpp new file mode 100644 index 0000000..917f030 --- /dev/null +++ b/project2/basics/tasks/structExceptHandling.cpp @@ -0,0 +1,44 @@ +#include <pch.hpp> +#include "structExceptHandling.h" +#include "scriptLoader.h" +#include "scriptStorage.h" +#include "scripts.h" +#include <boost/foreach.hpp> + +DECLARE_LOADER("handler", StructuredExceptionHandler); + +StructuredExceptionHandler::StructuredExceptionHandler(ScriptNodePtr e) : + SourceObject(e), + IHaveSubTasks(e) +{ + e->script->loader.addLoadTargetSub(e, "try", true, Storer::into<ElementLoader>(&normal)); + e->script->loader.addLoadTargetSub(e, "catch", false, Storer::into<ElementLoader>(&catches)); + e->script->loader.addLoadTargetSub(e, "finally", false, Storer::into<ElementLoader>(&finallies)); +} + +void +StructuredExceptionHandler::loadComplete(const CommonObjects * co) +{ + IHaveSubTasks::loadComplete(co); +} + +void +StructuredExceptionHandler::execute(ExecContext * ec) const +{ + try { + run(normal, ec); + } + catch (...) { + try { + run(catches, ec); + run(finallies, ec); + return; + } + catch (...) { + } + run(finallies, ec); + throw; + } + run(finallies, ec); +} + diff --git a/project2/basics/tasks/structExceptHandling.h b/project2/basics/tasks/structExceptHandling.h new file mode 100644 index 0000000..b6702f1 --- /dev/null +++ b/project2/basics/tasks/structExceptHandling.h @@ -0,0 +1,18 @@ +#ifndef STRUCTUREDEXCEPTIONHANDLER_H +#define STRUCTUREDEXCEPTIONHANDLER_H + +#include "iHaveSubTasks.h" + +class StructuredExceptionHandler : public IHaveSubTasks { + public: + StructuredExceptionHandler(ScriptNodePtr); + + void loadComplete(const CommonObjects*); + void execute(ExecContext * ec) const; + + private: + Tasks catches, finallies; +}; + +#endif + diff --git a/project2/basics/views/flatView.cpp b/project2/basics/views/flatView.cpp new file mode 100644 index 0000000..05e8b09 --- /dev/null +++ b/project2/basics/views/flatView.cpp @@ -0,0 +1,58 @@ +#include "pch.hpp" +#include "flatView.h" +#include "presenter.h" +#include "scopeObject.h" +#include "scriptLoader.h" +#include "scopeObject.h" +#include <boost/foreach.hpp> +#include <boost/bind.hpp> + +DECLARE_LOADER("flatview", FlatView); + +FlatView::FlatView(ScriptNodePtr p) : + SourceObject(p), + RowProcessor(p), + recordName(p, "recordname"), + required(p, "required", false) +{ + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) { + viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); + } +} + +FlatView::~FlatView() +{ +} + +void +FlatView::loadComplete(const CommonObjects * co) +{ + RowProcessor::loadComplete(co); +} + +void +FlatView::rowReady(const RowState * rs, const RowSetPresenter * presenter, ExecContext * ec, bool & rowsFound) const +{ + rowsFound = true; + presenter->addNewRow(recordName(ec)); + if (viewColumns.empty()) { + rs->foreachColumn(ec, boost::bind(&RowSetPresenter::addNamedValue, presenter, _2, _3)); + } + else { + BOOST_FOREACH(const Columns::value_type & col, viewColumns) { + presenter->addNamedValue(col.first, col.second(ec)); + } + } + presenter->finishRow(); +} + +void +FlatView::execute(const RowSetPresenter * p, ExecContext * ec) const +{ + bool rowsFound = false; + RowProcessor::execute(ec, boost::bind(&FlatView::rowReady, this, _1, p, ec, boost::ref(rowsFound))); + if (required(ec) && !rowsFound) { + throw EmptyRequiredRows(name); + } +} + diff --git a/project2/basics/views/flatView.h b/project2/basics/views/flatView.h new file mode 100644 index 0000000..5dc24dc --- /dev/null +++ b/project2/basics/views/flatView.h @@ -0,0 +1,28 @@ +#ifndef FLATVIEW_H +#define FLATVIEW_H + +#include <boost/intrusive_ptr.hpp> +#include "rowProcessor.h" +#include "view.h" +#include "aggregate.h" + +/// Project2 component to create output based on a records in a flat row set +class FlatView : public SourceObject, public RowProcessor { + public: + FlatView(ScriptNodePtr); + virtual ~FlatView(); + + void loadComplete(const CommonObjects *); + void execute(const RowSetPresenter *, ExecContext *) const; + void rowReady(const RowState *, const RowSetPresenter *, ExecContext *, bool & found) const; + + const Variable recordName; + const Variable required; + + protected: + typedef std::map<Glib::ustring, Variable> Columns; + Columns viewColumns; +}; + +#endif + diff --git a/project2/basics/views/rowView.cpp b/project2/basics/views/rowView.cpp new file mode 100644 index 0000000..b9508bd --- /dev/null +++ b/project2/basics/views/rowView.cpp @@ -0,0 +1,102 @@ +#include <pch.hpp> +#include "rowView.h" +#include "presenter.h" +#include "scopeObject.h" +#include "scriptLoader.h" +#include "scopeObject.h" +#include <boost/foreach.hpp> +#include <boost/bind.hpp> + +DECLARE_LOADER("view", RowView); + +RowView::RowView(ScriptNodePtr p) : + SourceObject(p), + View(p), + RowProcessor(p), + rootName(p, "rootname", Null()), + recordName(p, "recordname"), + required(p, "required", false), + isObject(p, "isobject", true) +{ + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) { + viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); + } + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&subViews)); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&valueAggregates)); + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&setAggregates)); +} + +RowView::~RowView() +{ +} + +void +RowView::loadComplete(const CommonObjects * co) +{ + RowProcessor::loadComplete(co); +} + +void +RowView::rowReady(const RowState * rs, const MultiRowSetPresenter * presenter, ExecContext * ec, bool & rowsFound) const +{ + rowsFound = true; + if (isObject(ec)) { + presenter->addNewRow(recordName(ec)); + } + if (viewColumns.empty()) { + rs->foreachColumn(ec, boost::bind(&RowSetPresenter::addNamedValue, presenter, _2, _3)); + } + else { + BOOST_FOREACH(const Columns::value_type & col, viewColumns) { + presenter->addNamedValue(col.first, col.second(ec)); + } + } + if (isObject(ec)) { + executeChildren(presenter, ec); + presenter->finishRow(); + } + BOOST_FOREACH(SetAggregateCPtr s, setAggregates) { + s->pushValue(ec); + } + BOOST_FOREACH(ValueAggregateCPtr a, valueAggregates) { + a->pushValue(ec); + } +} + +void +RowView::execute(const MultiRowSetPresenter * p, ExecContext * ec) const +{ + if (!rootName(ec).isNull()) { + p->addNewRowSet(rootName(ec)); + } + bool rowsFound = false; + ScopeObject pres(rootName(ec).isNull() ? ScopeObject::Event() : boost::bind(&MultiRowSetPresenter::finishRowSet, p)); + { + p->addNewArray(recordName(ec), true); + ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishArray, p, true)); + RowProcessor::execute(ec, boost::bind(&RowView::rowReady, this, _1, p, ec, boost::ref(rowsFound))); + } + if (required(ec) && !rowsFound) { + throw EmptyRequiredRows(name); + } + + BOOST_FOREACH(SetAggregateCPtr s, setAggregates) { + p->addNewArray(s->name, false); + ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishArray, p, false)); + s->onResultValues(boost::bind(&MultiRowSetPresenter::addNamedValue, p, "value", _1)); + s->reset(); + } + BOOST_FOREACH(ValueAggregateCPtr a, valueAggregates) { + p->addNamedValue(a->name, a->resultValue()); + a->reset(); + } +} + +void +RowView::executeChildren(const MultiRowSetPresenter * presenter, ExecContext * ec) const +{ + BOOST_FOREACH(const SubViews::value_type & sq, subViews) { + sq->execute(presenter, ec); + } +} + diff --git a/project2/basics/views/rowView.h b/project2/basics/views/rowView.h new file mode 100644 index 0000000..d2745db --- /dev/null +++ b/project2/basics/views/rowView.h @@ -0,0 +1,38 @@ +#ifndef ROWVIEW_H +#define ROWVIEW_H + +#include <boost/intrusive_ptr.hpp> +#include "rowProcessor.h" +#include "view.h" +#include "aggregate.h" + +/// Project2 component to create output based on a records in a row set +class RowView : public View, public RowProcessor { + public: + RowView(ScriptNodePtr); + virtual ~RowView(); + + void loadComplete(const CommonObjects *); + void execute(const MultiRowSetPresenter *, ExecContext *) const; + void rowReady(const RowState *, const MultiRowSetPresenter *, ExecContext *, bool & found) const; + + const Variable rootName; + const Variable recordName; + const Variable required; + const Variable isObject; + + protected: + typedef std::map<Glib::ustring, Variable> Columns; + Columns viewColumns; + + void executeChildren(const MultiRowSetPresenter * presenter, ExecContext *) const; + typedef ANONORDEREDSTORAGEOF(View) SubViews; + SubViews subViews; + typedef ANONSTORAGEOF(ValueAggregate) ValueAggregates; + ValueAggregates valueAggregates; + typedef ANONSTORAGEOF(SetAggregate) SetAggregates; + SetAggregates setAggregates; +}; + +#endif + diff --git a/project2/basics/views/singleton.cpp b/project2/basics/views/singleton.cpp new file mode 100644 index 0000000..eff3f94 --- /dev/null +++ b/project2/basics/views/singleton.cpp @@ -0,0 +1,45 @@ +#include <pch.hpp> +#include "view.h" +#include "iHaveParameters.h" +#include "presenter.h" +#include "scopeObject.h" +#include <boost/foreach.hpp> + +class Singleton : public View { + public: + Singleton(ScriptNodePtr p) : + SourceObject(p), + View(p), + rootName(p, "rootname") + { + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) { + viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); + } + p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&subViews)); + } + void execute(const MultiRowSetPresenter * p, ExecContext * ec) const + { + p->addNewRowSet(rootName(ec)); + ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishRowSet, p)); + BOOST_FOREACH(const Columns::value_type & col, viewColumns) { + p->addNamedValue(col.first, col.second(ec)); + } + } + + const Variable rootName; + private: + void executeChildren(const MultiRowSetPresenter * p, ExecContext * ec) const + { + BOOST_FOREACH(const SubViews::value_type & sq, subViews) { + sq->execute(p, ec); + } + } + + typedef std::map<Glib::ustring, Variable> Columns; + Columns viewColumns; + + typedef ANONSTORAGEOF(View) SubViews; + SubViews subViews; +}; +DECLARE_LOADER("singleton", Singleton); + diff --git a/project2/basics/views/viewGroup.cpp b/project2/basics/views/viewGroup.cpp new file mode 100644 index 0000000..e6e84d0 --- /dev/null +++ b/project2/basics/views/viewGroup.cpp @@ -0,0 +1,27 @@ +#include "view.h" +#include <boost/foreach.hpp> +#include "presenter.h" + +class ViewGroup : public View { + public: + ViewGroup(ScriptNodePtr s) : + SourceObject(s), + View(s) + { + s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&subViews)); + } + + void execute(const MultiRowSetPresenter * presenter, ExecContext * ec) const + { + presenter->addNewRowSet(name); + BOOST_FOREACH(const SubViews::value_type & sq, subViews) { + sq->execute(presenter, ec); + } + presenter->finishRowSet(); + } + + typedef ANONORDEREDSTORAGEOF(View) SubViews; + SubViews subViews; +}; + +DECLARE_LOADER("viewgroup", ViewGroup); |