summaryrefslogtreecommitdiff
path: root/project2/basics
diff options
context:
space:
mode:
Diffstat (limited to 'project2/basics')
-rw-r--r--project2/basics/caches/memoryCache.cpp166
-rw-r--r--project2/basics/loggers/consoleLog.cpp29
-rw-r--r--project2/basics/loggers/syslogLog.cpp39
-rw-r--r--project2/basics/options/preload.cpp (renamed from project2/basics/preload.cpp)0
-rw-r--r--project2/basics/tasks/session/sessionClearTask.cpp26
-rw-r--r--project2/basics/tasks/session/sessionClearTask.h25
-rw-r--r--project2/basics/tasks/session/sessionSetTask.cpp27
-rw-r--r--project2/basics/tasks/session/sessionSetTask.h27
-rw-r--r--project2/basics/tasks/structExceptHandling.cpp44
-rw-r--r--project2/basics/tasks/structExceptHandling.h18
-rw-r--r--project2/basics/views/flatView.cpp58
-rw-r--r--project2/basics/views/flatView.h28
-rw-r--r--project2/basics/views/rowView.cpp102
-rw-r--r--project2/basics/views/rowView.h38
-rw-r--r--project2/basics/views/singleton.cpp45
-rw-r--r--project2/basics/views/viewGroup.cpp27
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);