diff options
author | randomdan <randomdan@localhost> | 2010-12-14 00:20:38 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2010-12-14 00:20:38 +0000 |
commit | 3f452dd8b71e546d91377153e24e6ed530307e90 (patch) | |
tree | a4ecc86baff05083ee7149a06c735c28eb79c8b5 | |
parent | Support binding null to an SQL command parameter (diff) | |
download | project2-3f452dd8b71e546d91377153e24e6ed530307e90.tar.bz2 project2-3f452dd8b71e546d91377153e24e6ed530307e90.tar.xz project2-3f452dd8b71e546d91377153e24e6ed530307e90.zip |
All new fangled iterators, views, row engines, exceptions, the list goes on
Includes site and console updates to match
61 files changed, 892 insertions, 577 deletions
diff --git a/project2/Doxyfile b/project2/Doxyfile index e5f9500..2142e66 100644 --- a/project2/Doxyfile +++ b/project2/Doxyfile @@ -47,7 +47,7 @@ OUTPUT_DIRECTORY = docs # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. -CREATE_SUBDIRS = NO +CREATE_SUBDIRS = YES # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this @@ -313,12 +313,12 @@ EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index 4a2e6d1..7040562 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -19,8 +19,8 @@ lib curl : : <name>curl ; lib p2common : appEngine.cpp dataSource.cpp environment.cpp fileStarGlibIoChannel.cpp iHaveParameters.cpp iterate.cpp paramChecker.cpp perRowValues.cpp presenter.cpp rawView.cpp dumpTask.cpp - sourceObject.cpp task.cpp variables.cpp view.cpp xmlObjectLoader.cpp - sessionClearTask.cpp session.cpp sessionSetTask.cpp + sourceObject.cpp task.cpp variables.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp + sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp : <library>../libmisc//misc <library>libxmlpp diff --git a/project2/appEngine.h b/project2/appEngine.h index 223a928..04fe486 100644 --- a/project2/appEngine.h +++ b/project2/appEngine.h @@ -2,41 +2,20 @@ #define APPENGINE_H #include "environment.h" -#include "dataSource.h" #include "session.h" #include "presenter.h" class ApplicationEngine { public: - class UriElementOutOfRange : public std::exception { }; - class ParamNotFound : public std::exception { }; - class DataSourceNotFound : public std::exception { }; - class DataSourceNotCompatible : public std::exception { }; - ApplicationEngine(); virtual ~ApplicationEngine() = 0; virtual void process() const = 0; virtual const Environment * env() const = 0; virtual SessionPtr session() const = 0; - virtual PresenterPtr getPresenter(const std::string & group, const std::string & id) const = 0; + virtual void addAppData(const Presenter * p) const = 0; - template <class DataSourceType> - const DataSourceType * dataSource(const std::string & name) const - { - DataSources::const_iterator i = datasources.find(name); - if (i == datasources.end()) { - throw DataSourceNotFound(); - } - const DataSourceType * s = dynamic_cast<const DataSourceType *>(i->second.get()); - if (!s) { - throw DataSourceNotCompatible(); - } - return s; - } static ApplicationEngine * getCurrent() { return currentEngine; } - // protected: - mutable DataSources datasources; private: static ApplicationEngine * currentEngine; }; diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 94de818..f4a4fb0 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -72,17 +72,20 @@ CgiApplicationEngine::Stage::~Stage() CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & id) : CgiApplicationEngine::Stage(e), - Presenter("present", id) + XmlPresenter("present", id) { } + CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & group, const std::string & id) : CgiApplicationEngine::Stage(e), - Presenter(group, id) + XmlPresenter(group, id) { } + CgiApplicationEngine::PresentStage::~PresentStage() { } + CgiApplicationEngine::Stage * CgiApplicationEngine::PresentStage::run() { @@ -91,52 +94,46 @@ CgiApplicationEngine::PresentStage::run() return new PresentStage(appEngine, pc.second->present); } } + execute(); appEngine->doc = getDataDocument(); + appEngine->header = new cgicc::HTTPContentHeader(contentType); sessionsContainer->CleanUp(); return NULL; } -Presenter::XmlDocumentPtr -CgiApplicationEngine::PresentStage::getDataDocument() const +void +CgiApplicationEngine::addAppData(const Presenter * p) const { - XmlDocumentPtr responseDoc = Presenter::getDataDocument(); - xmlpp::Element * responseRoot = responseDoc->get_root_node(); // URL elements - xmlpp::Element * uriElems = responseRoot->add_child("uriElems", "project2"); - BOOST_FOREACH(std::string s, appEngine->_env->elems) { - uriElems->add_child("uriElem", "project2")->set_child_text(s); + p->pushSub("uriElems", "project2"); + BOOST_FOREACH(std::string s, _env->elems) { + p->addField("uriElem", "project2", s); } + p->popSub(); + // Parameters - xmlpp::Element * paramsXml = responseRoot->add_child("params", "project2"); - BOOST_FOREACH(cgicc::FormEntry fe, appEngine->_env->cgi->getElements()) { - xmlpp::Element * param = paramsXml->add_child("param", "project2"); - param->add_child_text(fe.getValue()); - param->set_attribute("name", fe.getName()); + p->pushSub("params", "project2"); + BOOST_FOREACH(cgicc::FormEntry fe, _env->cgi->getElements()) { + p->pushSub("param", "project2"); + p->addAttr("name", fe.getName()); + p->addAttr("value", fe.getValue()); + p->popSub(); } + p->popSub(); + // Sessions variables - if (!appEngine->sessionID.is_nil()) { - xmlpp::Element * sessionXml = responseRoot->add_child("session", "project2"); - sessionXml->set_attribute("id", boost::lexical_cast<Glib::ustring>(appEngine->sessionID)); - Session::Values session(sessionsContainer->GetSession(appEngine->sessionID)->GetValuesCopy()); + if (!sessionID.is_nil()) { + p->pushSub("session", "project2"); + p->addField("id", boost::lexical_cast<Glib::ustring>(sessionID)); + Session::Values session(sessionsContainer->GetSession(sessionID)->GetValuesCopy()); BOOST_FOREACH(Session::Values::value_type sv, session) { - xmlpp::Element * param = sessionXml->add_child("var", "project2"); - param->add_child_text(sv.second); - param->set_attribute("name", sv.first); + p->pushSub("var", "project2"); + p->addAttr("value", sv.second); + p->addAttr("name", sv.first); + p->popSub(); } + p->popSub(); } - // XSLT Style - char * buf; - if (responseStyle.length() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", - responseStyle.c_str()) > 0) { - xmlAddPrevSibling(responseRoot->cobj(), - xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf)); - free(buf); - appEngine->header = new cgicc::HTTPContentHeader("text/xml-xslt"); - } - else { - appEngine->header = new cgicc::HTTPContentHeader("text/xml"); - } - return responseDoc; } CgiApplicationEngine::RequestStage::RequestStage(const CgiApplicationEngine * e, const std::string & id) : @@ -148,10 +145,11 @@ CgiApplicationEngine::RequestStage::RequestStage(const CgiApplicationEngine * e, present = requestRoot->get_attribute_value("present"); LoaderBase loader("http://project2.randomdan.homeip.net", true); - loader.supportedStorers.insert(Storer::into(&appEngine->datasources)); + loader.supportedStorers.insert(Storer::into(&datasources)); loader.supportedStorers.insert(Storer::into(¶meterChecks)); + loader.supportedStorers.insert(Storer::into(&rowSets)); loader.supportedStorers.insert(Storer::into(&tasks)); - loader.collectAll(requestRoot, true); + loader.collectAll(this, requestRoot, true); } CgiApplicationEngine::RequestStage::~RequestStage() { @@ -169,18 +167,18 @@ CgiApplicationEngine::RequestStage::run() t.second->execute(); } // Commit data source transactions (without invoking a connection) - BOOST_FOREACH(DataSources::value_type ds, appEngine->datasources) { + BOOST_FOREACH(DataSources::value_type ds, datasources) { ds.second->commit(); } + return new PresentStage(appEngine, present); } catch (...) { // Do something about the error - BOOST_FOREACH(DataSources::value_type ds, appEngine->datasources) { + BOOST_FOREACH(DataSources::value_type ds, datasources) { ds.second->rollback(); } throw; } - return new PresentStage(appEngine, present); } SessionPtr @@ -189,9 +187,3 @@ CgiApplicationEngine::session() const return sessionsContainer->GetSession(sessionID); } -PresenterPtr -CgiApplicationEngine::getPresenter(const std::string & group, const std::string & id) const -{ - return PresenterPtr(new PresentStage(this, group, id)); -} - diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index cebb294..db4d696 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -5,6 +5,7 @@ #include "../task.h" #include "../paramChecker.h" #include "../presenter.h" +#include "../commonObjects.h" #include <boost/intrusive_ptr.hpp> #include <boost/uuid/uuid.hpp> #include <libxml++/document.h> @@ -30,13 +31,13 @@ class CgiApplicationEngine : public ApplicationEngine { } const Environment * env() const; SessionPtr session() const; - PresenterPtr getPresenter(const std::string & group, const std::string & id) const; + void addAppData(const Presenter * p) const; const CgiEnvironment * _env; protected: mutable cgicc::HTTPContentHeader * header; private: mutable boost::shared_ptr<xmlpp::Document> doc; - class Stage { + class Stage : public CommonObjects { public: Stage(const CgiApplicationEngine *); virtual ~Stage() = 0; @@ -54,14 +55,12 @@ class CgiApplicationEngine : public ApplicationEngine { OrderedParamCheckers parameterChecks; NoOutputExecutes tasks; }; - class PresentStage : public Stage, public Presenter { + class PresentStage : public Stage, public XmlPresenter { public: PresentStage(const CgiApplicationEngine *, const std::string & id); PresentStage(const CgiApplicationEngine *, const std::string & group, const std::string & id); virtual ~PresentStage(); virtual Stage * run(); - protected: - XmlDocumentPtr getDataDocument() const; }; mutable Stage * currentStage; mutable boost::uuids::uuid sessionID; diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index 630629a..3461973 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -1,5 +1,6 @@ #include "cgiEnvironment.h" #include "../appEngine.h" +#include "../exceptions.h" #include <map> #include <cgicc/Cgicc.h> #include <boost/tokenizer.hpp> @@ -25,7 +26,7 @@ Glib::ustring CgiEnvironment::getParamUri(unsigned int p) const { if (p >= elems.size()) { - throw ApplicationEngine::UriElementOutOfRange(); + throw UriElementOutOfRange(); } return elems[p]; } @@ -35,7 +36,7 @@ CgiEnvironment::getParamQuery(const std::string & p) const { cgicc::const_form_iterator i = cgi->getElement(p); if (i == cgi->getElements().end()) { - throw ApplicationEngine::ParamNotFound(); + throw ParamNotFound(); } return (*cgi)(p); } diff --git a/project2/cgi/p2webMain.cpp b/project2/cgi/p2webMain.cpp index c36335a..59e8d7b 100644 --- a/project2/cgi/p2webMain.cpp +++ b/project2/cgi/p2webMain.cpp @@ -40,6 +40,7 @@ p2webGoingIdle(int) int main(void) { if (!FCGX_IsCGI()) { + syslog(LOG_NOTICE, "FCGID Startup ($Id$)"); FCGX_Request request; FCGX_Init(); @@ -69,12 +70,17 @@ int main(void) catch (const std::exception & e) { cgicc::HTTPContentHeader header("text/plain"); header.render(IO); - IO << "Kaboom!" << std::endl << std::endl << e.what(); + IO << "Kaboom!" << std::endl + << std::endl + << typeid(e).name() << std::endl + << e.what() << std::endl; } catch (...) { cgicc::HTTPContentHeader header("text/plain"); header.render(IO); - IO << "Kaboom!" << std::endl << std::endl << "Unknown exception."; + IO << "Kaboom!" << std::endl + << std::endl + << "Unknown exception." << std::endl; } alarm(60); LoaderBase::onIteration(); diff --git a/project2/commonObjects.cpp b/project2/commonObjects.cpp new file mode 100644 index 0000000..f39eb60 --- /dev/null +++ b/project2/commonObjects.cpp @@ -0,0 +1,13 @@ +#include "commonObjects.h" + +PerRowValuesPtr +CommonObjects::getSource(const std::string & name) const +{ + RowSets::const_iterator i = rowSets.find(name); + if (i != rowSets.end()) { + return i->second; + } + throw CommonObjects::DataSourceNotFound(); +} + + diff --git a/project2/commonObjects.h b/project2/commonObjects.h new file mode 100644 index 0000000..32e201c --- /dev/null +++ b/project2/commonObjects.h @@ -0,0 +1,32 @@ +#ifndef COMMONOBJECTS_H +#define COMMONOBJECTS_H + +#include "dataSource.h" +#include "perRowValues.h" + +class CommonObjects : public virtual IntrusivePtrBase { + public: + class DataSourceNotFound : public std::exception { }; + class DataSourceNotCompatible : public std::exception { }; + + PerRowValuesPtr getSource(const std::string &) const; + template <class DataSourceType> + const DataSourceType * dataSource(const std::string & name) const + { + DataSources::const_iterator i = datasources.find(name); + if (i == datasources.end()) { + throw DataSourceNotFound(); + } + const DataSourceType * s = dynamic_cast<const DataSourceType *>(i->second.get()); + if (!s) { + throw DataSourceNotCompatible(); + } + return s; + } + protected: + RowSets rowSets; + DataSources datasources; +}; + +#endif + diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 98d280d..908c1a1 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -57,10 +57,11 @@ ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * en while (xmlXIncludeProcessFlags(request.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); LoaderBase loader("http://project2.randomdan.homeip.net", true); - loader.supportedStorers.insert(Storer::into(&this->datasources)); + loader.supportedStorers.insert(Storer::into(&datasources)); loader.supportedStorers.insert(Storer::into(¶meterChecks)); loader.supportedStorers.insert(Storer::into(&tasks)); - loader.collectAll(request.get_document()->get_root_node(), true); + loader.supportedStorers.insert(Storer::into(&rowSets)); + loader.collectAll(this, request.get_document()->get_root_node(), true); } ConsoleApplicationEngine::~ConsoleApplicationEngine() @@ -105,10 +106,9 @@ ConsoleApplicationEngine::session() const return runtime; } -PresenterPtr -ConsoleApplicationEngine::getPresenter(const std::string & group, const std::string & id) const +void +ConsoleApplicationEngine::addAppData(const Presenter * p) const { - return PresenterPtr(new ConsolePresenter(this, group, id)); } ConsoleApplicationEngine::ConsolePresenter::ConsolePresenter(const ConsoleApplicationEngine *, @@ -121,9 +121,20 @@ ConsoleApplicationEngine::ConsolePresenter::~ConsolePresenter() { } -Presenter::XmlDocumentPtr -ConsoleApplicationEngine::ConsolePresenter::getDataDocument() const +void +ConsoleApplicationEngine::ConsolePresenter::pushSub(const Glib::ustring & name, const Glib::ustring & ns) const +{ + indent += 2; +} + +void +ConsoleApplicationEngine::ConsolePresenter::addField(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +{ +} + +void +ConsoleApplicationEngine::ConsolePresenter::popSub() const { - return Presenter::getDataDocument(); + indent -= 2; } diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h index b40ef8a..9d4ee96 100644 --- a/project2/console/consoleAppEngine.h +++ b/project2/console/consoleAppEngine.h @@ -5,6 +5,7 @@ #include "../task.h" #include "../paramChecker.h" #include "../presenter.h" +#include "../commonObjects.h" #include <boost/intrusive_ptr.hpp> #include <boost/filesystem/path.hpp> #include <libxml++/document.h> @@ -12,7 +13,7 @@ class ConsoleEnvironment; -class ConsoleApplicationEngine : public ApplicationEngine { +class ConsoleApplicationEngine : public ApplicationEngine, public CommonObjects { public: ConsoleApplicationEngine(const ConsoleEnvironment *, const boost::filesystem::path &); virtual ~ConsoleApplicationEngine(); @@ -20,7 +21,7 @@ class ConsoleApplicationEngine : public ApplicationEngine { void process() const; const Environment * env() const; SessionPtr session() const; - PresenterPtr getPresenter(const std::string & group, const std::string & id) const; + virtual void addAppData(const Presenter * p) const; protected: const ConsoleEnvironment * _env; private: @@ -29,8 +30,12 @@ class ConsoleApplicationEngine : public ApplicationEngine { ConsolePresenter(const ConsoleApplicationEngine *, const std::string & id); ConsolePresenter(const ConsoleApplicationEngine *, const std::string & group, const std::string & id); virtual ~ConsolePresenter(); - protected: - XmlDocumentPtr getDataDocument() const; + + void pushSub(const Glib::ustring & ns, const Glib::ustring & name) const; + void addField(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; + void popSub() const; + private: + mutable unsigned int indent; }; OrderedParamCheckers parameterChecks; NoOutputExecutes tasks; diff --git a/project2/dumpTask.cpp b/project2/dumpTask.cpp index 1e94e65..3db29f6 100644 --- a/project2/dumpTask.cpp +++ b/project2/dumpTask.cpp @@ -16,7 +16,7 @@ _DumpTask::~_DumpTask() } void -_DumpTask::loadComplete() +_DumpTask::loadComplete(const CommonObjects *) { } diff --git a/project2/dumpTask.h b/project2/dumpTask.h index ec004c4..bc6f69c 100644 --- a/project2/dumpTask.h +++ b/project2/dumpTask.h @@ -7,7 +7,7 @@ class _DumpTask : public _Task { public: _DumpTask(const xmlpp::Element * p); virtual ~_DumpTask(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); virtual void execute() const; }; diff --git a/project2/exceptions.cpp b/project2/exceptions.cpp new file mode 100644 index 0000000..9aaeb07 --- /dev/null +++ b/project2/exceptions.cpp @@ -0,0 +1,7 @@ +#include "exceptions.h" + +NotSupported::NotSupported(const std::string & what) : + std::runtime_error(what) +{ +} + diff --git a/project2/exceptions.h b/project2/exceptions.h new file mode 100644 index 0000000..84c8c19 --- /dev/null +++ b/project2/exceptions.h @@ -0,0 +1,16 @@ +#ifndef EXCEPTION_H +#define EXCEPTION_H + +#include <stdexcept> + +class UriElementOutOfRange : public std::exception { }; +class ParamNotFound : public std::exception { }; +class NotSupported : public std::runtime_error { + public: + NotSupported(const std::string & what); +}; +class FileNotReadable : public std::exception { }; +class FileNotWritable : public std::exception { }; + +#endif + diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp index f28c96d..2f4d6cf 100644 --- a/project2/fileRows.cpp +++ b/project2/fileRows.cpp @@ -1,10 +1,12 @@ #include "fileRows.h" -#include <stdexcept> +#include "xmlObjectLoader.h" +#include "exceptions.h" -ElementLoaderImpl<_FileIterate> fileiterateLoader("fileiterate"); -ElementLoaderImpl<_FileView> fileviewLoader("fileview"); +ElementLoaderImpl<_FileRows> filerowsLoader("filerows"); _FileRows::_FileRows(const xmlpp::Element * p) : + _SourceObject(p), + PerRowValues(p), path(p->get_attribute_value("path")), fieldSep(p->get_attribute_value("fieldSep")[0]), quoteChar(p->get_attribute_value("quoteChar")[0]), @@ -24,10 +26,16 @@ _FileRows::~_FileRows() } void -_FileRows::loadComplete() +_FileRows::loadComplete(const CommonObjects *) { } +void +_FileRows::setFilter(const Glib::ustring &) +{ + throw NotSupported(__PRETTY_FUNCTION__); +} + unsigned int _FileRows::columnCount() const { @@ -41,7 +49,7 @@ _FileRows::getColumnName(unsigned int col) const } void -_FileRows::execute() const +_FileRows::execute(const RowProcessor * rp) const { FileStarChannel c(doOpen()); c.set_encoding(encoding); @@ -96,7 +104,7 @@ _FileRows::execute() const values.push_back(ValPtr(new Glib::ustring())); curCol++; } - rowReady(); + rp->rowReady(); } values.clear(); } @@ -146,13 +154,8 @@ _FileRows::doOpen() const { FILE * f = fopen(path->c_str(), "r"); if (!f) { - throw std::runtime_error("Could not open file"); + throw FileNotReadable(); } return FileStarChannel(f, true, fclose); } -#include "view.hpp" -template class _GenericView<_FileRows>; -#include "iterate.hpp" -template class _GenericIterate<_FileRows>; - diff --git a/project2/fileRows.h b/project2/fileRows.h index 7c99c55..60916ac 100644 --- a/project2/fileRows.h +++ b/project2/fileRows.h @@ -5,24 +5,25 @@ #include <boost/intrusive_ptr.hpp> #include <boost/shared_ptr.hpp> #include <map> -#include "view.h" #include "variables.h" -#include "iterate.h" +#include "perRowValues.h" #include "fileStarGlibIoChannel.h" +class CommonObjects; + class _FileRows : public PerRowValues { public: _FileRows(const xmlpp::Element * p); ~_FileRows(); - void execute() const; - virtual void loadComplete(); + void execute(const RowProcessor *) const; + virtual void loadComplete(const CommonObjects *); + virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; const Glib::ustring & getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; - virtual void rowReady() const = 0; typedef std::set<gunichar> CharSet; const Variable path; @@ -44,14 +45,6 @@ class _FileRows : public PerRowValues { }; typedef boost::intrusive_ptr<_FileRows> FileRows; -typedef _GenericView<_FileRows> _FileView; -typedef boost::intrusive_ptr<_FileView> FileView; -typedef std::map<std::string, FileView> FileViews; - -typedef _GenericIterate<_FileRows> _FileIterate; -typedef boost::intrusive_ptr<_FileIterate> FileIterate; -typedef std::map<std::string, FileIterate> FileIterates; - #endif diff --git a/project2/iHaveParameters.cpp b/project2/iHaveParameters.cpp index 9ba917d..abab80c 100644 --- a/project2/iHaveParameters.cpp +++ b/project2/iHaveParameters.cpp @@ -1,4 +1,6 @@ #include "iHaveParameters.h" +#include "exceptions.h" +#include "appEngine.h" #include "xmlObjectLoader.h" #include <boost/foreach.hpp> @@ -8,27 +10,28 @@ IHaveParameters::IHaveParameters(const xmlpp::Element * p) const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); if (elem) { Parameter p = new _Parameter(elem); - parameters[p->bind] = p; + parameters[p->name] = p; } } } -ElementLoaderImpl<IHaveParameters::_Parameter> paramLoader("param"); - IHaveParameters::~IHaveParameters() { } IHaveParameters::_Parameter::_Parameter(const xmlpp::Element * p) : - _SourceObject(p), - value(p->get_attribute("value")), - bind(atoi(p->get_attribute_value("bind").c_str())) + name(p->get_attribute_value("name")), + value(p->get_attribute("value")) { } -void -IHaveParameters::_Parameter::loadComplete() +const Glib::ustring & +IHaveParameters::getParameter(const Glib::ustring & name) const { + Parameters::const_iterator i = parameters.find(name); + if (i != parameters.end()) { + return i->second->value; + } + throw ParamNotFound(); } - diff --git a/project2/iHaveParameters.h b/project2/iHaveParameters.h index 14c1639..83a77b4 100644 --- a/project2/iHaveParameters.h +++ b/project2/iHaveParameters.h @@ -9,18 +9,19 @@ class IHaveParameters : public virtual IntrusivePtrBase { public: - class _Parameter : public _SourceObject { + class _Parameter : public virtual IntrusivePtrBase { public: _Parameter(const xmlpp::Element * p); - void loadComplete(); + const Glib::ustring name; const Variable value; - const unsigned int bind; }; IHaveParameters(const xmlpp::Element * p); virtual ~IHaveParameters() = 0; + const Glib::ustring & getParameter(const Glib::ustring &) const; + typedef boost::intrusive_ptr<_Parameter> Parameter; - typedef std::map<unsigned int, Parameter> Parameters; + typedef std::map<Glib::ustring, Parameter> Parameters; protected: Parameters parameters; }; diff --git a/project2/iterate.cpp b/project2/iterate.cpp index d114acb..7e86c4b 100644 --- a/project2/iterate.cpp +++ b/project2/iterate.cpp @@ -3,9 +3,12 @@ #include <syslog.h> #include "xmlObjectLoader.h" +ElementLoaderImpl<_Iterate> iterateLoader("iterate"); + _Iterate::_Iterate(const xmlpp::Element * p) : _SourceObject(p), - _NoOutputExecute(p) + _NoOutputExecute(p), + RowProcessor(p) { LoaderBase loader("http://project2.randomdan.homeip.net", true); loader.supportedStorers.insert(Storer::into(&subNOEs)); @@ -17,18 +20,50 @@ _Iterate::~_Iterate() } void -_Iterate::executeChildren() const +_Iterate::loadComplete(const CommonObjects * co) +{ + RowProcessor::loadComplete(co); +} + +void +_Iterate::rowReady() const { + executeChildren(); + source->rowChanged(); +} + +void +_Iterate::execute() const +{ + PerRowValues::beginRow(source.get()); try { - PerRowValues::beginRow(this); - BOOST_FOREACH(NoOutputExecutes::value_type sq, subNOEs) { - sq.second->execute(); - } - PerRowValues::endRow(this); + source->execute(this); + PerRowValues::endRow(source.get()); } catch (...) { - PerRowValues::endRow(this); + PerRowValues::endRow(source.get()); throw; } } +void +_Iterate::executeChildren() const +{ + BOOST_FOREACH(NoOutputExecutes::value_type sq, subNOEs) { + if (dynamic_cast<const RowProcessor *>(sq.second.get())) { + sq.second->execute(); + } + else { + PerRowValues::beginRow(NULL); + try { + sq.second->execute(); + PerRowValues::endRow(NULL); + } + catch (...) { + PerRowValues::endRow(NULL); + throw; + } + } + } +} + diff --git a/project2/iterate.h b/project2/iterate.h index 9dc9019..852310b 100644 --- a/project2/iterate.h +++ b/project2/iterate.h @@ -9,39 +9,25 @@ #include "perRowValues.h" #include "noOutputExecute.h" -class ApplicationEngine; class _Iterate; typedef boost::intrusive_ptr<_Iterate> Iterate; typedef std::map<std::string, Iterate> Iterates; -class _Iterate : public virtual _SourceObject, public PerRowValues, public _NoOutputExecute { +class _Iterate : public _NoOutputExecute, public RowProcessor { public: _Iterate(const xmlpp::Element * p); virtual ~_Iterate(); + void loadComplete(const CommonObjects *); + void rowReady() const; + void execute() const; + NoOutputExecutes subNOEs; protected: void executeChildren() const; }; -template <class Driver> -class _GenericIterate : public _Iterate, public Driver { - public: - _GenericIterate(const xmlpp::Element * p); - - virtual void loadComplete(); - virtual unsigned int columnCount() const; - virtual const Glib::ustring & getCurrentValue(const unsigned int id) const; - virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - virtual const Glib::ustring & getColumnName(const unsigned int id) const; - virtual bool isNull(unsigned int col) const; - virtual void executeChildren() const; - virtual void execute() const; - virtual void rowReady() const; - private: -}; - #endif diff --git a/project2/iterate.hpp b/project2/iterate.hpp deleted file mode 100644 index f71ca9e..0000000 --- a/project2/iterate.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "iterate.h" - -template <class Driver> -_GenericIterate<Driver>::_GenericIterate(const xmlpp::Element * p) : - _SourceObject(p), - _Iterate(p), - Driver(p) -{ -} - -template <class Driver> -void -_GenericIterate<Driver>::loadComplete() -{ - Driver::loadComplete(); -} - -template <class Driver> -void -_GenericIterate<Driver>::execute() const -{ - Driver::execute(); -} - -template <class Driver> -void -_GenericIterate<Driver>::rowReady() const -{ - executeChildren(); -} - -template <class Driver> -void -_GenericIterate<Driver>::executeChildren() const -{ - _Iterate::executeChildren(); -} - -template <class Driver> -unsigned int -_GenericIterate<Driver>::columnCount() const -{ - return Driver::columnCount(); -} - -template <class Driver> -const Glib::ustring & -_GenericIterate<Driver>::getCurrentValue(const unsigned int id) const -{ - return Driver::getCurrentValue(id); -} - -template <class Driver> -const Glib::ustring & -_GenericIterate<Driver>::getCurrentValue(const Glib::ustring & id) const -{ - return Driver::getCurrentValue(id); -} - -template <class Driver> -bool -_GenericIterate<Driver>::isNull(const unsigned int id) const -{ - return Driver::isNull(id); -} - -template <class Driver> -const Glib::ustring & -_GenericIterate<Driver>::getColumnName(const unsigned int id) const -{ - return Driver::getColumnName(id); -} - diff --git a/project2/noOutputExecute.h b/project2/noOutputExecute.h index 55fdf7a..3e92aba 100644 --- a/project2/noOutputExecute.h +++ b/project2/noOutputExecute.h @@ -17,5 +17,6 @@ class _NoOutputExecute : public virtual _SourceObject { virtual ~_NoOutputExecute() { } virtual void execute() const = 0; }; + #endif diff --git a/project2/perRowValues.cpp b/project2/perRowValues.cpp index 9f80924..82b46bc 100644 --- a/project2/perRowValues.cpp +++ b/project2/perRowValues.cpp @@ -1,11 +1,13 @@ #include "perRowValues.h" +#include "commonObjects.h" #include <cstdlib> #include <boost/foreach.hpp> #include <syslog.h> PerRowValues::RowValuesStack PerRowValues::stack; -PerRowValues::PerRowValues() +PerRowValues::PerRowValues(const xmlpp::Element * p) : + _SourceObject(p) { } @@ -34,12 +36,17 @@ PerRowValues::beginRow(const PerRowValues * r) void PerRowValues::endRow(const PerRowValues * r) { - if ((*stack.rbegin()) != r) { + if (stack.back() != r) { syslog(LOG_ERR, "PerRowValues::endRow: stack is corrupted"); std::abort(); } stack.pop_back(); - BOOST_FOREACH(const RowUser * ru, r->rowUsers) { +} + +void +PerRowValues::rowChanged() const +{ + BOOST_FOREACH(const RowUser * ru, rowUsers) { ru->rowChanged(); } } @@ -52,3 +59,20 @@ RowUser::~RowUser() { } +RowProcessor::RowProcessor(const xmlpp::Element * p) : + _SourceObject(p), + IHaveParameters(p), + recordSource(p->get_attribute_value("source")), + filter(p->get_attribute_value("filter")) +{ +} + +void +RowProcessor::loadComplete(const CommonObjects * co) +{ + source = co->getSource(recordSource); + if (!filter.empty()) { + source->setFilter(filter); + } +} + diff --git a/project2/perRowValues.h b/project2/perRowValues.h index 09c77f5..abd1507 100644 --- a/project2/perRowValues.h +++ b/project2/perRowValues.h @@ -4,6 +4,10 @@ #include <glibmm/ustring.h> #include <vector> #include <set> +#include <map> +#include <boost/intrusive_ptr.hpp> +#include "sourceObject.h" +#include "iHaveParameters.h" class RowUser { public: @@ -13,25 +17,45 @@ class RowUser { virtual void rowChanged() const = 0; }; -class PerRowValues { +class PerRowValues; +typedef boost::intrusive_ptr<PerRowValues> PerRowValuesPtr; +typedef std::map<std::string, PerRowValuesPtr> RowSets; + +class RowProcessor : public IHaveParameters, public virtual _SourceObject { + public: + RowProcessor(const xmlpp::Element *); + virtual void rowReady() const = 0; + void loadComplete(const CommonObjects *); + + const std::string recordSource; + const Glib::ustring filter; + + protected: + PerRowValuesPtr source; +}; + +class PerRowValues : public virtual _SourceObject { public: class ParentOutOfRange : public std::exception { }; class FieldDoesNotExist : public std::exception { }; typedef std::vector<const PerRowValues *> RowValuesStack; - PerRowValues(); + PerRowValues(const xmlpp::Element *); virtual ~PerRowValues() = 0; + virtual void setFilter(const Glib::ustring &) = 0; virtual unsigned int columnCount() const = 0; virtual const Glib::ustring & getColumnName(unsigned int col) const = 0; virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const = 0; virtual const Glib::ustring & getCurrentValue(unsigned int col) const = 0; virtual bool isNull(unsigned int col) const = 0; + virtual void execute(const RowProcessor *) const = 0; void use(const RowUser * r) const; void finish(const RowUser * r) const; static const RowValuesStack & Stack() { return stack; } static void beginRow(const PerRowValues * r); static void endRow(const PerRowValues * r); + void rowChanged() const; private: static RowValuesStack stack; diff --git a/project2/presenter.cpp b/project2/presenter.cpp index 71ed45b..d7ddf5a 100644 --- a/project2/presenter.cpp +++ b/project2/presenter.cpp @@ -4,36 +4,117 @@ #include "appEngine.h" Presenter::Presenter(const std::string & group, const std::string & file) : - present(group + "/" + file + ".xml"), - responseRootNodeName(present.get_document()->get_root_node()->get_attribute_value("root")), - responseStyle(present.get_document()->get_root_node()->get_attribute_value("style")) + present(group + "/" + file + ".xml") { while (xmlXIncludeProcessFlags(present.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); LoaderBase loader("http://project2.randomdan.homeip.net", true); - loader.supportedStorers.insert(Storer::into(&ApplicationEngine::getCurrent()->datasources)); + loader.supportedStorers.insert(Storer::into(&datasources)); + loader.supportedStorers.insert(Storer::into(&rowSets)); loader.supportedStorers.insert(Storer::into(&views)); loader.supportedStorers.insert(Storer::into(¶meterChecks)); - loader.collectAll(present.get_document()->get_root_node(), true); + loader.collectAll(this, present.get_document()->get_root_node(), true); } Presenter::~Presenter() { } -Presenter::XmlDocumentPtr -Presenter::getDataDocument() const +void +Presenter::execute() const { - ApplicationEngine * appEngine = ApplicationEngine::getCurrent(); - XmlDocumentPtr responseDoc = boost::shared_ptr<xmlpp::Document>(new xmlpp::Document("1.0")); - xmlpp::Element * responseRoot = responseDoc->create_root_node(responseRootNodeName); BOOST_FOREACH(Views::value_type s, views) { - s.second->execute(responseRoot); + s.second->execute(this); } // These were for debug... but why not pass them on? - xmlNewNs(responseRoot->cobj(), BAD_CAST "http://project2.randomdan.homeip.net", BAD_CAST "project2"); - responseRoot->add_child("servername", "project2")->set_child_text(appEngine->env()->getServerName()); - responseRoot->add_child("scriptname", "project2")->set_child_text(appEngine->env()->getScriptName()); + ApplicationEngine * appEngine = ApplicationEngine::getCurrent(); + addField("servername", "project2", appEngine->env()->getServerName()); + addField("scriptname", "project2", appEngine->env()->getScriptName()); + appEngine->addAppData(this); +} + +void +Presenter::pushSub(const Glib::ustring & name) const +{ + pushSub(name, Glib::ustring()); +} + +void +Presenter::addAttr(const Glib::ustring & name, const Glib::ustring & value) const +{ + addAttr(name, Glib::ustring(), value); +} + +void +Presenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +{ + addField(name, ns, value); +} + +void +Presenter::addField(const Glib::ustring & name, const Glib::ustring & value) const +{ + addField(name, Glib::ustring(), value); +} + +void +Presenter::addField(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +{ + pushSub(name, ns); + setText(value); + popSub(); +} + +XmlPresenter::~XmlPresenter() +{ +} + +XmlPresenter::XmlPresenter(const std::string & group, const std::string & file) : + Presenter(group, file), + responseRootNodeName(present.get_document()->get_root_node()->get_attribute_value("root")), + responseStyle(present.get_document()->get_root_node()->get_attribute_value("style")), + contentType(present.get_document()->get_root_node()->get_attribute_value("contenttype")), + responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0"))) +{ + nodeStack.push_back(responseDoc->create_root_node(responseRootNodeName)); + xmlNewNs(nodeStack.back()->cobj(), BAD_CAST "http://project2.randomdan.homeip.net", BAD_CAST "project2"); + // XSLT Style + char * buf; + if (responseStyle.length() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", + responseStyle.c_str()) > 0) { + xmlAddPrevSibling(nodeStack.back()->cobj(), + xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf)); + free(buf); + } +} + +XmlPresenter::XmlDocumentPtr +XmlPresenter::getDataDocument() const +{ return responseDoc; } +void +XmlPresenter::pushSub(const Glib::ustring & name, const Glib::ustring & ns) const +{ + nodeStack.push_back(nodeStack.back()->add_child(name, ns)); +} + +void +XmlPresenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +{ + nodeStack.back()->set_attribute(name, value, ns); +} + +void +XmlPresenter::setText(const Glib::ustring & value) const +{ + nodeStack.back()->set_child_text(value); +} + +void +XmlPresenter::popSub() const +{ + nodeStack.pop_back(); +} + diff --git a/project2/presenter.h b/project2/presenter.h index 977aa4d..7968b88 100644 --- a/project2/presenter.h +++ b/project2/presenter.h @@ -7,24 +7,55 @@ #include <libxml++/parsers/domparser.h> #include "view.h" #include "paramChecker.h" +#include "commonObjects.h" -class Presenter : public virtual IntrusivePtrBase { +class Presenter : public CommonObjects, public virtual IntrusivePtrBase { public: - typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr; Presenter(const std::string & group, const std::string & file); - ~Presenter(); + virtual ~Presenter() = 0; - virtual XmlDocumentPtr getDataDocument() const; + virtual void pushSub(const Glib::ustring & name) const; + virtual void pushSub(const Glib::ustring & name, const Glib::ustring & ns) const = 0; + virtual void addAttr(const Glib::ustring & name, const Glib::ustring & value) const; + virtual void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; + virtual void addField(const Glib::ustring & name, const Glib::ustring & value) const; + virtual void addField(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; + virtual void setText(const Glib::ustring & value) const = 0; + virtual void popSub() const = 0; + void execute() const; protected: Views views; OrderedParamCheckers parameterChecks; xmlpp::DomParser present; +}; + +typedef boost::intrusive_ptr<const Presenter> PresenterCPtr; +typedef boost::intrusive_ptr<Presenter> PresenterPtr; + +class XmlPresenter : public Presenter { public: + typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr; + XmlPresenter(const std::string & group, const std::string & file); + ~XmlPresenter(); + + void pushSub(const Glib::ustring & name, const Glib::ustring & ns) const; + void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; + void setText(const Glib::ustring & value) const; + void popSub() const; + + virtual XmlDocumentPtr getDataDocument() const; + const Glib::ustring responseRootNodeName; const Glib::ustring responseStyle; + const Glib::ustring contentType; + + private: + XmlDocumentPtr responseDoc; + mutable std::vector<xmlpp::Element *> nodeStack; }; -typedef boost::intrusive_ptr<Presenter> PresenterPtr; + +typedef boost::intrusive_ptr<XmlPresenter> XmlPresenterPtr; #endif diff --git a/project2/procRows.cpp b/project2/procRows.cpp index e5ed86a..f4a34a1 100644 --- a/project2/procRows.cpp +++ b/project2/procRows.cpp @@ -1,10 +1,14 @@ #include "procRows.h" +#include "xmlObjectLoader.h" #include <stdexcept> -ElementLoaderImpl<_ProcIterate> prociterateLoader("prociterate"); -ElementLoaderImpl<_ProcView> procviewLoader("procview"); +ElementLoaderImpl<_ProcRows> procrowsLoader("procrows"); + +class SubProcessFailedToStart : public std::exception { }; +class SubProcessFailed : public std::exception { }; _ProcRows::_ProcRows(const xmlpp::Element * p) : + _SourceObject(p), _FileRows(p) { } @@ -14,7 +18,7 @@ _ProcRows::~_ProcRows() } void -_ProcRows::loadComplete() +_ProcRows::loadComplete(const CommonObjects *) { } @@ -23,7 +27,7 @@ _ProcRows::doOpen() const { FILE * f = popen(path->c_str(), "re"); if (!f) { - throw std::runtime_error("Could not open file"); + throw SubProcessFailedToStart(); } return FileStarChannel(f, false, doClose); } @@ -33,13 +37,8 @@ _ProcRows::doClose(FILE * f) { int pclo = pclose(f); if (pclo != 0) { - throw std::runtime_error("Subprocess returned an error"); + throw SubProcessFailed(); } return 0; } -#include "view.hpp" -template class _GenericView<_ProcRows>; -#include "iterate.hpp" -template class _GenericIterate<_ProcRows>; - diff --git a/project2/procRows.h b/project2/procRows.h index e28a5f5..bada523 100644 --- a/project2/procRows.h +++ b/project2/procRows.h @@ -8,12 +8,10 @@ class _ProcRows : public _FileRows { _ProcRows(const xmlpp::Element * p); ~_ProcRows(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); virtual FileStarChannel doOpen() const; static int doClose(FILE*); }; -typedef _GenericView<_ProcRows> _ProcView; -typedef _GenericIterate<_ProcRows> _ProcIterate; #endif diff --git a/project2/rawView.cpp b/project2/rawView.cpp index 1378f17..3a97cd3 100644 --- a/project2/rawView.cpp +++ b/project2/rawView.cpp @@ -1,4 +1,4 @@ -#include <stdexcept> +#include "exceptions.h" #include "rawView.h" #include "xml.h" #include "xmlObjectLoader.h" @@ -14,46 +14,41 @@ _RawView::_RawView(const xmlpp::Element * p) : { } -void -_RawView::loadComplete() -{ -} - -unsigned int -_RawView::columnCount() const + void +_RawView::loadComplete(const CommonObjects *) { - throw std::runtime_error("_RawView::columnCount not implemented"); } -const Glib::ustring & -_RawView::getCurrentValue(unsigned int id) const -{ - throw std::runtime_error("_RawView::getCurrentValue not implemented"); -} - -const Glib::ustring & -_RawView::getCurrentValue(const Glib::ustring & id) const -{ - throw std::runtime_error("_RawView::getCurrentValue not implemented"); -} - -bool -_RawView::isNull(unsigned int id) const -{ - throw std::runtime_error("_RawView::isNull not implemented"); -} - -const Glib::ustring & -_RawView::getColumnName(unsigned int id) const +void +_RawView::execute(const Presenter * p) const { - throw std::runtime_error("_RawView::getColumnName not implemented"); + BOOST_FOREACH(xmlpp::Node * node, copyRoot->get_children()) { + const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(node); + if (e) { + copyNode(p, e); + } + } } -void _RawView::execute(xmlpp::Element * par) const +void +_RawView::copyNode(const Presenter * p, const xmlpp::Element * n) const { - BOOST_FOREACH(xmlpp::Node * node, copyRoot->get_children()) { - par->import_node(node); + p->pushSub(n->get_name()); + xmlpp::Element::AttributeList al = n->get_attributes(); + BOOST_FOREACH(const xmlpp::Attribute * a, al) { + p->addAttr(a->get_name(), a->get_value()); + } + const xmlpp::TextNode * t = n->get_child_text(); + if (t) { + p->setText(t->get_content()); } + xmlpp::Node::NodeList ch = n->get_children(); + BOOST_FOREACH(const xmlpp::Node * c, ch) { + const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(c); + if (e) { + copyNode(p, e); + } + } + p->popSub(); } - diff --git a/project2/rawView.h b/project2/rawView.h index a6d85de..3f0de83 100644 --- a/project2/rawView.h +++ b/project2/rawView.h @@ -6,19 +6,13 @@ #include <map> #include "view.h" -class ApplicationEngine; - class _RawView : public _View { public: _RawView(const xmlpp::Element * p); - void execute(xmlpp::Element *) const; - virtual void loadComplete(); - virtual unsigned int columnCount() const; - virtual const Glib::ustring & getColumnName(unsigned int col) const; - virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - virtual const Glib::ustring & getCurrentValue(unsigned int col) const; - virtual bool isNull(unsigned int col) const; + void execute(const Presenter *) const; + virtual void loadComplete(const CommonObjects *); private: + void copyNode(const Presenter *, const xmlpp::Element *) const; const xmlpp::Element * copyRoot; }; typedef boost::intrusive_ptr<_RawView> RawView; diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp index 4f9c7d7..4dccc08 100644 --- a/project2/rdbmsDataSource.cpp +++ b/project2/rdbmsDataSource.cpp @@ -28,17 +28,21 @@ class RdbmsDataSourceLoader : public ElementLoaderImpl<_RdbmsDataSource> { _RdbmsDataSource::dbhosts.erase(i); } } + void onIteration() + { + _RdbmsDataSource::changedDSNs.clear(); + } } rdbmsLoader; _RdbmsDataSource::DBHosts _RdbmsDataSource::dbhosts; _RdbmsDataSource::FailedHosts _RdbmsDataSource::failedhosts; +_RdbmsDataSource::DSNSet _RdbmsDataSource::changedDSNs; _RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) : _SourceObject(p), _DataSource(p), masterDsn(xmlChildText(p, "masterdsn")), - preferLocal(p->get_attribute_value("preferlocal") != "false"), - changesMade(false) + preferLocal(p->get_attribute_value("preferlocal") != "false") { BOOST_FOREACH(const xmlpp::Node * node, p->find("readonly/dsn")) { const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); @@ -48,8 +52,12 @@ _RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) : } } +_RdbmsDataSource::~_RdbmsDataSource() +{ +} + void -_RdbmsDataSource::loadComplete() +_RdbmsDataSource::loadComplete(const CommonObjects *) { } @@ -60,14 +68,14 @@ _RdbmsDataSource::getWritable() const if (!master->inTx()) { master->beginTx(); } - changesMade = true; + changedDSNs.insert(name); return *master; } ODBC::Connection & _RdbmsDataSource::getReadonly() const { - if (changesMade) { + if (changedDSNs.find(name) != changedDSNs.end()) { return *connectTo(masterDsn); } if (localhost.length() == 0 && preferLocal) { @@ -121,7 +129,7 @@ _RdbmsDataSource::rollback() if (m != dbhosts.end() && m->second->inTx()) { m->second->rollbackTx(); } - changesMade = false; + changedDSNs.erase(name); } _RdbmsDataSource::ConnectionPtr diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h index 77fbe3a..5421b3f 100644 --- a/project2/rdbmsDataSource.h +++ b/project2/rdbmsDataSource.h @@ -23,9 +23,10 @@ class _RdbmsDataSource : public _DataSource { typedef std::map<std::string, ConnectionPtr> DBHosts; // Map DSN strings to connections typedef std::map<std::string, const ODBC::ConnectionError> FailedHosts; // Map DSN strings to failures _RdbmsDataSource(const xmlpp::Element * p); + ~_RdbmsDataSource(); ODBC::Connection & getReadonly() const; ODBC::Connection & getWritable() const; - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); virtual void commit(); virtual void rollback(); const std::string masterDsn; @@ -34,12 +35,13 @@ class _RdbmsDataSource : public _DataSource { protected: static ConnectionPtr connectTo(const std::string & dsn); ReadonlyDSNs roDSNs; - mutable bool changesMade; private: mutable std::string localhost; static DBHosts dbhosts; static FailedHosts failedhosts; + typedef std::set<std::string> DSNSet; + static DSNSet changedDSNs; friend class RdbmsDataSourceLoader; }; diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp index 62be6b1..92b7563 100644 --- a/project2/regexCheck.cpp +++ b/project2/regexCheck.cpp @@ -1,6 +1,6 @@ #include "regexCheck.h" #include "xmlObjectLoader.h" -#include "appEngine.h" +#include "commonObjects.h" #include <boost/regex.hpp> ElementLoaderImpl<_RegexCheck> regexCheckLoader("regexcheck"); @@ -18,7 +18,7 @@ _RegexCheck::~_RegexCheck() } void -_RegexCheck::loadComplete() +_RegexCheck::loadComplete(const CommonObjects *) { } diff --git a/project2/regexCheck.h b/project2/regexCheck.h index e848ef0..868f97e 100644 --- a/project2/regexCheck.h +++ b/project2/regexCheck.h @@ -9,7 +9,7 @@ class _RegexCheck : public _ParamChecker { _RegexCheck(const xmlpp::Element * p); virtual ~_RegexCheck(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); bool performCheck() const; const Variable applyTo; diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp index 65d55d8..97c7b4f 100644 --- a/project2/sendmailTask.cpp +++ b/project2/sendmailTask.cpp @@ -13,6 +13,11 @@ ElementLoaderImpl<_SendMailTask> sendmailLoader("sendmail"); +class SendEmailFailed : public std::runtime_error { + public: + SendEmailFailed(const std::string & what) : std::runtime_error(what) { } +}; + typedef boost::shared_ptr<xmlDoc> XmlDocumentPtr; _SendMailTask::_SendMailTask(const xmlpp::Element * p) : @@ -31,7 +36,7 @@ _SendMailTask::~_SendMailTask() } void -_SendMailTask::loadComplete() +_SendMailTask::loadComplete(const CommonObjects *) { } @@ -125,18 +130,22 @@ class TextContent : public _SendMailTask::MailPart { void _SendMailTask::execute() const { - PresenterPtr p = ApplicationEngine::getCurrent()->getPresenter("emails", present); - Presenter::XmlDocumentPtr data = p->getDataDocument(); + XmlPresenterPtr p = new XmlPresenter("emails", present); + p->execute(); + XmlPresenter::XmlDocumentPtr data = p->getDataDocument(); +#if DEBUG + data->write_to_file("/tmp/email.xml"); +#endif typedef boost::shared_ptr<xsltStylesheet> XsltStyleSheetPtr; // Do transform XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST p->responseStyle.c_str()), xsltFreeStylesheet); if (!cur) { - throw std::runtime_error("Failed to load stylesheet"); + throw xmlpp::exception("Failed to load stylesheet"); } XmlDocumentPtr result = XmlDocumentPtr(xsltApplyStylesheet(cur.get(), data->cobj(), NULL), xmlFreeDoc); if (!result) { - throw std::runtime_error("Failed to perform transformation"); + throw xmlpp::exception("Failed to perform transformation"); } parts.clear(); @@ -163,7 +172,7 @@ _SendMailTask::execute() const if (!smtp_start_session(session)) { char buf[BUFSIZ]; smtp_strerror(smtp_errno(), buf, sizeof buf); - throw std::runtime_error(buf); + throw SendEmailFailed(buf); } } diff --git a/project2/sendmailTask.h b/project2/sendmailTask.h index 2193974..f9ab6bd 100644 --- a/project2/sendmailTask.h +++ b/project2/sendmailTask.h @@ -20,7 +20,7 @@ class _SendMailTask : public _Task { _SendMailTask(const xmlpp::Element * p); virtual ~_SendMailTask(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); virtual void execute() const; protected: diff --git a/project2/sessionClearTask.cpp b/project2/sessionClearTask.cpp index 95b1145..8af2b4a 100644 --- a/project2/sessionClearTask.cpp +++ b/project2/sessionClearTask.cpp @@ -18,7 +18,7 @@ _SessionClearTask::~_SessionClearTask() } void -_SessionClearTask::loadComplete() +_SessionClearTask::loadComplete(const CommonObjects *) { } diff --git a/project2/sessionClearTask.h b/project2/sessionClearTask.h index ab602b1..94bca1d 100644 --- a/project2/sessionClearTask.h +++ b/project2/sessionClearTask.h @@ -8,7 +8,7 @@ #include "xmlObjectLoader.h" #include "task.h" -class ApplicationEngine; +class CommonObjects; class _SessionClearTask; typedef boost::intrusive_ptr<_SessionClearTask> SessionClearTask; @@ -16,7 +16,7 @@ class _SessionClearTask : public virtual _Task { public: _SessionClearTask(const xmlpp::Element * p); virtual ~_SessionClearTask(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); void execute() const; const Glib::ustring key; diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp index 2340468..a8ac749 100644 --- a/project2/sessionSetTask.cpp +++ b/project2/sessionSetTask.cpp @@ -20,7 +20,7 @@ _SessionSetTask::~_SessionSetTask() } void -_SessionSetTask::loadComplete() +_SessionSetTask::loadComplete(const CommonObjects *) { } diff --git a/project2/sessionSetTask.h b/project2/sessionSetTask.h index 164b562..f85e8f1 100644 --- a/project2/sessionSetTask.h +++ b/project2/sessionSetTask.h @@ -9,7 +9,7 @@ #include "task.h" #include "variables.h" -class ApplicationEngine; +class CommonObjects; class _SessionSetTask; typedef boost::intrusive_ptr<_SessionSetTask> SessionSetTask; @@ -17,7 +17,7 @@ class _SessionSetTask : public virtual _Task { public: _SessionSetTask(const xmlpp::Element * p); virtual ~_SessionSetTask(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); void execute() const; const Glib::ustring key; diff --git a/project2/sourceObject.h b/project2/sourceObject.h index b37aad1..1ccc4af 100644 --- a/project2/sourceObject.h +++ b/project2/sourceObject.h @@ -5,6 +5,7 @@ #include <boost/intrusive_ptr.hpp> #include "intrusivePtrBase.h" +class CommonObjects; class _SourceObject; typedef boost::intrusive_ptr<_SourceObject> Project2SourceObject; class _SourceObject : public virtual IntrusivePtrBase { @@ -12,7 +13,8 @@ class _SourceObject : public virtual IntrusivePtrBase { _SourceObject(const xmlpp::Element * p); _SourceObject(const std::string & name); virtual ~_SourceObject() = 0; - virtual void loadComplete() = 0; + + virtual void loadComplete(const CommonObjects *) = 0; const std::string name; const unsigned int order; diff --git a/project2/sqlCheck.cpp b/project2/sqlCheck.cpp index 8d48d24..f348689 100644 --- a/project2/sqlCheck.cpp +++ b/project2/sqlCheck.cpp @@ -1,10 +1,10 @@ #include "sqlCheck.h" #include "xmlObjectLoader.h" -#include "appEngine.h" #include "selectcommand.h" #include "column.h" #include "rdbmsDataSource.h" #include <boost/regex.hpp> +#include "commonObjects.h" ElementLoaderImpl<_SqlCheck> sqlCheckLoader("sqlcheck"); @@ -26,17 +26,16 @@ _SqlCheck::~_SqlCheck() } void -_SqlCheck::loadComplete() +_SqlCheck::loadComplete(const CommonObjects * co) { - query = new ODBC::SelectCommand(ApplicationEngine::getCurrent()->dataSource<_RdbmsDataSource>( - dataSource)->getReadonly(), sql); + query = new ODBC::SelectCommand(co->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql); } bool _SqlCheck::performCheck() const { BOOST_FOREACH(Parameters::value_type p, parameters) { - query->bindParamS(p.second->bind, p.second->value); + query->bindParamS(atoi(p.second->name.c_str()), p.second->value); } bool retVal = false; while (query->fetch()) { diff --git a/project2/sqlCheck.h b/project2/sqlCheck.h index 0c5efcc..40c6e9a 100644 --- a/project2/sqlCheck.h +++ b/project2/sqlCheck.h @@ -11,7 +11,7 @@ class _SqlCheck : public IHaveParameters, public _ParamChecker { _SqlCheck(const xmlpp::Element * p); virtual ~_SqlCheck(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); bool performCheck() const; const std::string dataSource; diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp index 3abf4ee..279fa05 100644 --- a/project2/sqlMergeTask.cpp +++ b/project2/sqlMergeTask.cpp @@ -1,6 +1,7 @@ #include "sqlMergeTask.h" #include "appEngine.h" #include "rdbmsDataSource.h" +#include "exceptions.h" #include <misc.h> #include <stdio.h> #include <stdexcept> @@ -31,7 +32,7 @@ _SqlMergeTask::_SqlMergeTask(const xmlpp::Element * p) : loader.collectAll(p, true); if (!sources.empty() && useView) { - throw std::runtime_error("useview not supported with iterate fillers"); + throw NotSupported("useview not supported with iterate fillers"); } BOOST_FOREACH(xmlpp::Node * psi, p->find("columns/column")) { @@ -40,7 +41,7 @@ _SqlMergeTask::_SqlMergeTask(const xmlpp::Element * p) : tcp->maptable = e->get_attribute_value("maptable"); if (!tcp->maptable.empty()) { if (useView) { - throw std::runtime_error("useview not supported with mapped columns"); + throw NotSupported("useview not supported with mapped columns"); } tcp->mapcolumn = e->get_attribute_value("mapcolumn"); } @@ -60,9 +61,9 @@ _SqlMergeTask::~_SqlMergeTask() } void -_SqlMergeTask::loadComplete() +_SqlMergeTask::loadComplete(const CommonObjects * co) { - destdb = &ApplicationEngine::getCurrent()->dataSource<_RdbmsDataSource>(dataSource)->getWritable(); + destdb = &co->dataSource<_RdbmsDataSource>(dataSource)->getWritable(); insCmd = insertCommand(); BOOST_FOREACH(const Iterates::value_type & i, sources) { attach(i.second, insCmd); @@ -188,18 +189,18 @@ _SqlMergeTask::insertCommand() const class _Populate : public _NoOutputExecute { public: - _Populate(Iterate i, ModifyCommand * c) : + _Populate(ModifyCommand * c) : _SourceObject(__FUNCTION__), _NoOutputExecute(__FUNCTION__), - iter(i), cmd(c) { } - virtual void loadComplete() + virtual void loadComplete(const CommonObjects *) { } void execute() const { + const PerRowValues * iter = *++PerRowValues::Stack().rbegin(); if (idxs.empty()) { idxs.resize(iter->columnCount()); // Sure this can be improved upon... but hey. @@ -227,19 +228,18 @@ class _Populate : public _NoOutputExecute { } private: mutable std::vector<unsigned int> idxs; - Iterate iter; ModifyCommand * cmd; }; typedef boost::intrusive_ptr<_Populate> Populate; -static void attach(Iterate i, ModifyCommand * insert) +static void +attach(Iterate i, ModifyCommand * insert) { if (!i) { return; } if (i->subNOEs.empty()) { - Populate p(new _Populate(i, insert)); - i->subNOEs.insert(NoOutputExecutes::value_type(0, p)); + i->subNOEs.insert(NoOutputExecutes::value_type(0, new _Populate(insert))); } else { BOOST_FOREACH(const NoOutputExecutes::value_type & n, i->subNOEs) { diff --git a/project2/sqlMergeTask.h b/project2/sqlMergeTask.h index 633dc2a..532367e 100644 --- a/project2/sqlMergeTask.h +++ b/project2/sqlMergeTask.h @@ -40,7 +40,7 @@ class _SqlMergeTask : public _Task { _SqlMergeTask(const xmlpp::Element * p); virtual ~_SqlMergeTask(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); void execute() const; Columns cols; Keys keys; diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp index 751a459..9244a9c 100644 --- a/project2/sqlRows.cpp +++ b/project2/sqlRows.cpp @@ -6,29 +6,37 @@ #include <string.h> #include <libxml++/nodes/textnode.h> #include "xmlObjectLoader.h" -#include "appEngine.h" +#include "commonObjects.h" -ElementLoaderImpl<_SqlIterate> sqliterateLoader("sqliterate"); -ElementLoaderImpl<_SqlView> sqlviewLoader("sqlview"); +ElementLoaderImpl<_SqlRows> sqlviewLoader("sqlrows"); _SqlRows::_SqlRows(const xmlpp::Element * p) : - IHaveParameters(p), + _SourceObject(p), + PerRowValues(p), dataSource(p->get_attribute_value("datasource")), - sql(xmlChildText(p, "sql")), - query(NULL) + sqlCommand(dynamic_cast<xmlpp::Element *>(p->get_children("sql").front())), + query(NULL), + db(NULL) { } _SqlRows::~_SqlRows() { - delete query; } void -_SqlRows::loadComplete() +_SqlRows::loadComplete(const CommonObjects * co) +{ + db = co->dataSource<_RdbmsDataSource>(dataSource); +} + +void +_SqlRows::setFilter(const Glib::ustring & name) { - query = new ODBC::SelectCommand(ApplicationEngine::getCurrent()->dataSource<_RdbmsDataSource>( - dataSource)->getReadonly(), sql); + SqlCommand::FiltersRangeType r = sqlCommand.filters.equal_range(name); + for (SqlCommand::Filters::const_iterator i = r.first; i != r.second; i++) { + i->second->active = true; + } } const Glib::ustring & @@ -62,18 +70,132 @@ _SqlRows::getColumnName(unsigned int col) const } void -_SqlRows::execute() const +_SqlRows::execute(const RowProcessor * rp) const { - BOOST_FOREACH(Parameters::value_type p, parameters) { - query->bindParamS(p.second->bind, p.second->value); - } + unsigned int offset = 0; + Glib::ustring sql; + sqlCommand.writeSql(sql); + query = new ODBC::SelectCommand(db->getReadonly(), sql); + sqlCommand.bindParams(rp, query, offset); while (query->fetch()) { - rowReady(); + rp->rowReady(); + } + delete query; +} + +_SqlRows::SqlWriter::SqlWriter() +{ +} + +_SqlRows::SqlWriter::~SqlWriter() +{ +} + +_SqlRows::SqlCommand::SqlCommand(const xmlpp::Element * N) +{ + BOOST_FOREACH(xmlpp::Node * n, N->get_children()) { + const xmlpp::TextNode * t = dynamic_cast<const xmlpp::TextNode *>(n); + if (t) { + writers.push_back(new SqlText(t)); + } + const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n); + if (e) { + if (e->get_name() == "filter") { + SqlFilterPtr f = new SqlFilter(e); + writers.push_back(f); + filters.insert(Filters::value_type(f->name, f)); + } + else if (e->get_name() == "param") { + writers.push_back(new SqlParameter(e)); + } + } + } +} + +void +_SqlRows::SqlCommand::writeSql(Glib::ustring & sql) const +{ + BOOST_FOREACH(const SqlWriterPtr & w, writers) { + w->writeSql(sql); + } +} + +void +_SqlRows::SqlCommand::bindParams(const RowProcessor * rp, ODBC::SelectCommand * cmd, unsigned int & offset) const +{ + BOOST_FOREACH(const SqlWriterPtr & w, writers) { + w->bindParams(rp, cmd, offset); + } +} + +_SqlRows::SqlFilter::SqlFilter(const xmlpp::Element * N) : + name(N->get_attribute_value("name")), + active(false) +{ + BOOST_FOREACH(xmlpp::Node * n, N->get_children()) { + const xmlpp::TextNode * t = dynamic_cast<const xmlpp::TextNode *>(n); + if (t) { + writers.push_back(new SqlText(t)); + } + const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n); + if (e) { + if (e->get_name() == "param") { + writers.push_back(new SqlParameter(e)); + } + } } } -#include "view.hpp" -template class _GenericView<_SqlRows>; -#include "iterate.hpp" -template class _GenericIterate<_SqlRows>; +void +_SqlRows::SqlFilter::writeSql(Glib::ustring & sql) const +{ + if (active) { + BOOST_FOREACH(const SqlWriterPtr & w, writers) { + w->writeSql(sql); + } + } +} + +void +_SqlRows::SqlFilter::bindParams(const RowProcessor * rp, ODBC::SelectCommand * cmd, unsigned int & offset) const +{ + if (active) { + BOOST_FOREACH(const SqlWriterPtr & w, writers) { + w->bindParams(rp, cmd, offset); + } + } +} + +_SqlRows::SqlParameter::SqlParameter(const xmlpp::Element * n) : + name(n->get_attribute_value("name")) +{ +} + +void +_SqlRows::SqlParameter::writeSql(Glib::ustring & sql) const +{ + sql.append("?"); +} + +void +_SqlRows::SqlParameter::bindParams(const RowProcessor * rp, ODBC::SelectCommand * cmd, unsigned int & offset) const +{ + cmd->bindParamS(offset++, rp->getParameter(name)); +} + +_SqlRows::SqlText::SqlText(const xmlpp::TextNode * n) : + text(n->get_content()) +{ +} + +void +_SqlRows::SqlText::writeSql(Glib::ustring & sql) const +{ + sql.append(text); +} + +void +_SqlRows::SqlText::bindParams(const RowProcessor * rp, ODBC::SelectCommand * cmd, unsigned int & offset) const +{ +} diff --git a/project2/sqlRows.h b/project2/sqlRows.h index 37ca72e..b983743 100644 --- a/project2/sqlRows.h +++ b/project2/sqlRows.h @@ -1,45 +1,86 @@ -#ifndef SQLITERATE_H -#define SQLITERATE_H +#ifndef SQLROWS_H +#define SQLROWS_H #include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <map> #include "selectcommand.h" -#include "iterate.h" -#include "view.h" #include "iHaveParameters.h" +#include "perRowValues.h" -class ApplicationEngine; +class _RdbmsDataSource; -class _SqlRows : public IHaveParameters, public PerRowValues { +class _SqlRows : public PerRowValues { public: _SqlRows(const xmlpp::Element * p); ~_SqlRows(); - void execute() const; - virtual void loadComplete(); + void execute(const RowProcessor *) const; + virtual void loadComplete(const CommonObjects *); + virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; const Glib::ustring & getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; - virtual void rowReady() const = 0; const std::string dataSource; - const Glib::ustring sql; private: + class SqlWriter; + typedef boost::intrusive_ptr<SqlWriter> SqlWriterPtr; + typedef std::list<SqlWriterPtr> Writers; + class SqlWriter : public IntrusivePtrBase { + public: + SqlWriter(); + virtual ~SqlWriter(); + virtual void writeSql(Glib::ustring & sql) const = 0; + virtual void bindParams(const RowProcessor *, ODBC::SelectCommand *, unsigned int & offset) const = 0; + }; + class SqlText : public SqlWriter { + public: + SqlText(const xmlpp::TextNode *); + virtual void writeSql(Glib::ustring & sql) const; + virtual void bindParams(const RowProcessor *, ODBC::SelectCommand *, unsigned int & offset) const; + + const Glib::ustring text; + }; + class SqlParameter : public SqlWriter { + public: + SqlParameter(const xmlpp::Element *); + virtual void writeSql(Glib::ustring & sql) const; + virtual void bindParams(const RowProcessor *, ODBC::SelectCommand *, unsigned int & offset) const; + + const Glib::ustring name; + }; + class SqlFilter : public SqlWriter { + public: + SqlFilter(const xmlpp::Element *); + virtual void writeSql(Glib::ustring & sql) const; + virtual void bindParams(const RowProcessor *, ODBC::SelectCommand *, unsigned int & offset) const; + + const Glib::ustring name; + bool active; + private: + Writers writers; + }; + typedef boost::intrusive_ptr<SqlFilter> SqlFilterPtr; + class SqlCommand : public SqlWriter { + public: + SqlCommand(const xmlpp::Element *); + virtual void writeSql(Glib::ustring & sql) const; + virtual void bindParams(const RowProcessor *, ODBC::SelectCommand *, unsigned int & offset) const; + typedef std::multimap<Glib::ustring, SqlFilterPtr> Filters; + typedef std::pair<Filters::const_iterator, Filters::const_iterator> FiltersRangeType; + Filters filters; + private: + Writers writers; + }; + SqlCommand sqlCommand; mutable ODBC::SelectCommand * query; + const _RdbmsDataSource * db; }; typedef boost::intrusive_ptr<_SqlRows> SqlRows; -typedef _GenericView<_SqlRows> _SqlView; -typedef boost::intrusive_ptr<_SqlView> SqlView; -typedef std::map<std::string, SqlView> SqlViews; - -typedef _GenericIterate<_SqlRows> _SqlIterate; -typedef boost::intrusive_ptr<_SqlIterate> SqlIterate; -typedef std::map<std::string, SqlIterate> SqlIterates; - #endif diff --git a/project2/sqlTask.cpp b/project2/sqlTask.cpp index 7ff5f40..2775a74 100644 --- a/project2/sqlTask.cpp +++ b/project2/sqlTask.cpp @@ -2,8 +2,8 @@ #include <boost/foreach.hpp> #include "xmlObjectLoader.h" #include "modifycommand.h" -#include "appEngine.h" #include "rdbmsDataSource.h" +#include "commonObjects.h" ElementLoaderImpl<_SqlTask> sqltaskLoader("sqltask"); @@ -23,16 +23,16 @@ _SqlTask::~_SqlTask() } void -_SqlTask::loadComplete() +_SqlTask::loadComplete(const CommonObjects * co) { - modify = new ODBC::ModifyCommand(ApplicationEngine::getCurrent()->dataSource<_RdbmsDataSource>(dataSource)->getWritable(), sql); + modify = new ODBC::ModifyCommand(co->dataSource<_RdbmsDataSource>(dataSource)->getWritable(), sql); } void _SqlTask::execute() const { BOOST_FOREACH(Parameters::value_type p, parameters) { - modify->bindParamS(p.second->bind, p.second->value); + modify->bindParamS(atoi(p.second->name.c_str()), p.second->value); } modify->execute(); } diff --git a/project2/sqlTask.h b/project2/sqlTask.h index e24fe24..5984c6f 100644 --- a/project2/sqlTask.h +++ b/project2/sqlTask.h @@ -16,7 +16,7 @@ class _SqlTask : public _Task, public IHaveParameters { public: _SqlTask(const xmlpp::Element * p); virtual ~_SqlTask(); - virtual void loadComplete(); + virtual void loadComplete(const CommonObjects *); virtual void execute() const; const std::string dataSource; diff --git a/project2/task.h b/project2/task.h index d100042..563a623 100644 --- a/project2/task.h +++ b/project2/task.h @@ -6,10 +6,8 @@ #include <map> #include "sourceObject.h" #include "xmlObjectLoader.h" -#include "view.h" #include "noOutputExecute.h" -class ApplicationEngine; class _Task; typedef boost::intrusive_ptr<_Task> Task; typedef std::map<std::string, Task> Tasks; diff --git a/project2/urlRows.cpp b/project2/urlRows.cpp index 6354aa7..8381d68 100644 --- a/project2/urlRows.cpp +++ b/project2/urlRows.cpp @@ -1,12 +1,15 @@ #include "urlRows.h" +#include "xmlObjectLoader.h" +#include "exceptions.h" #include "../libmisc/curlsup.h" #include <stdexcept> #include <queue> -ElementLoaderImpl<_UrlIterate> urliterateLoader("urliterate"); -ElementLoaderImpl<_UrlView> urlviewLoader("urlview"); +ElementLoaderImpl<_UrlRows> urlrowsLoader("urlrows"); _UrlRows::_UrlRows(const xmlpp::Element * p) : + _SourceObject(p), + PerRowValues(p), url(p->get_attribute_value("url")), fieldSep(p->get_attribute_value("fieldSep")[0]), quoteChar(p->get_attribute_value("quoteChar")[0]), @@ -30,10 +33,16 @@ _UrlRows::~_UrlRows() } void -_UrlRows::loadComplete() +_UrlRows::loadComplete(const CommonObjects *) { } +void +_UrlRows::setFilter(const Glib::ustring &) +{ + throw NotSupported(__PRETTY_FUNCTION__); +} + unsigned int _UrlRows::columnCount() const { @@ -73,12 +82,13 @@ _UrlRows::getCurrentValue(const Glib::ustring & id) const size_t _UrlRows::_handleData(const char * ptr, size_t size, size_t nmemb, void *stream) { - size_t used = static_cast<const _UrlRows *>(stream)->handleData(ptr, size * nmemb); + const callback * cb = static_cast<const callback *>(stream); + size_t used = cb->urlRows->handleData(cb->rp, ptr, size * nmemb); return used; } size_t -_UrlRows::handleData(const char * bytes, size_t bytesLen) const +_UrlRows::handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen) const { size_t used = 0, len = 0; char * utf8 = g_convert(bytes, bytesLen, "utf-8", encoding.c_str(), &used, &len, NULL); @@ -98,7 +108,7 @@ _UrlRows::handleData(const char * bytes, size_t bytesLen) const while (values.size() < columns.size()) { values.push_back(ValPtr(new Glib::ustring())); } - rowReady(); + rp->rowReady(); } else { mkCols = false; @@ -155,7 +165,7 @@ _UrlRows::addColumn(const Glib::ustring & rawtok) const } void -_UrlRows::execute() const +_UrlRows::execute(const RowProcessor * rp) const { CurlHandle::Ptr c = new CurlHandle(); c->setopt(CURLOPT_URL, url.c_str()); @@ -165,7 +175,8 @@ _UrlRows::execute() const //c->setopt(CURLOPT_COOKIEJAR, (std::string(cacheRoot) + "/ytfs.cookies").c_str()); c->setopt(CURLOPT_ENCODING, "deflate, gzip"); c->setopt(CURLOPT_USERAGENT, "project2/0.3"); - c->setopt(CURLOPT_WRITEDATA, this); + callback cb(this, rp); + c->setopt(CURLOPT_WRITEDATA, &cb); c->setopt(CURLOPT_WRITEFUNCTION, &_handleData); c->perform(); if (!tok.empty()) { @@ -182,14 +193,15 @@ _UrlRows::execute() const while (values.size() < columns.size()) { values.push_back(ValPtr(new Glib::ustring())); } - rowReady(); + rp->rowReady(); values.clear(); } values.clear(); } -#include "view.hpp" -template class _GenericView<_UrlRows>; -#include "iterate.hpp" -template class _GenericIterate<_UrlRows>; +_UrlRows::callback::callback(const _UrlRows * u, const RowProcessor * r) : + urlRows(u), + rp(r) +{ +} diff --git a/project2/urlRows.h b/project2/urlRows.h index 5ee7597..08acffc 100644 --- a/project2/urlRows.h +++ b/project2/urlRows.h @@ -5,22 +5,21 @@ #include <boost/intrusive_ptr.hpp> #include <boost/shared_ptr.hpp> #include <map> -#include "view.h" -#include "iterate.h" +#include "perRowValues.h" class _UrlRows : public PerRowValues { public: _UrlRows(const xmlpp::Element * p); ~_UrlRows(); - virtual void loadComplete(); - void execute() const; + virtual void loadComplete(const CommonObjects *); + void execute(const RowProcessor *) const; + virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; const Glib::ustring & getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; - virtual void rowReady() const = 0; typedef std::set<gunichar> CharSet; const Glib::ustring url; @@ -32,8 +31,13 @@ class _UrlRows : public PerRowValues { mutable Values values; private: + struct callback { + callback(const _UrlRows * urlRows, const RowProcessor * rp); + const _UrlRows * urlRows; + const RowProcessor * rp; + }; static size_t _handleData(const char * ptr, size_t size, size_t nmemb, void * stream); - size_t handleData(const char * bytes, size_t bytesLen) const; + size_t handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen) const; gunichar fieldSep; gunichar quoteChar; gunichar newline; @@ -50,15 +54,5 @@ class _UrlRows : public PerRowValues { }; typedef boost::intrusive_ptr<_UrlRows> UrlRows; -typedef _GenericView<_UrlRows> _UrlView; -typedef boost::intrusive_ptr<_UrlView> UrlView; -typedef std::map<std::string, UrlView> UrlViews; - -typedef _GenericIterate<_UrlRows> _UrlIterate; -typedef boost::intrusive_ptr<_UrlIterate> UrlIterate; -typedef std::map<std::string, UrlIterate> UrlIterates; - #endif - - diff --git a/project2/variables.cpp b/project2/variables.cpp index 3c27d44..09ea36e 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -1,4 +1,5 @@ #include "variables.h" +#include "exceptions.h" #include "appEngine.h" #include "perRowValues.h" #include "session.h" @@ -52,7 +53,7 @@ class VariableParam : public VariableImplDyn { try { cache = ApplicationEngine::getCurrent()->env()->getParamQuery(name); } - catch (ApplicationEngine::ParamNotFound) { + catch (ParamNotFound) { if (!defaultValue) { throw; } @@ -73,7 +74,7 @@ class VariableUri : public VariableImplDyn { try { cache = ApplicationEngine::getCurrent()->env()->getParamUri(atoi(name.c_str())); } - catch (ApplicationEngine::UriElementOutOfRange) { + catch (UriElementOutOfRange) { if (!defaultValue) { throw; } @@ -109,7 +110,7 @@ class VariableParent : public VariableImplDyn, public RowUser { try { if (!row) { PerRowValues::RowValuesStack::const_reverse_iterator r = PerRowValues::Stack().rbegin(); - for (size_t p = depth; --p; r++) ; + for (size_t p = depth; p--; r++) ; if (r == PerRowValues::Stack().rend()) { throw PerRowValues::ParentOutOfRange(); } diff --git a/project2/view.cpp b/project2/view.cpp index 44a162a..06eb6cc 100644 --- a/project2/view.cpp +++ b/project2/view.cpp @@ -1,8 +1,24 @@ #include "view.h" +#include "presenter.h" #include <boost/foreach.hpp> +#include <stdexcept> + +ElementLoaderImpl<_RowView> viewLoader("view"); _View::_View(const xmlpp::Element * p) : + _SourceObject(p) +{ +} + +_View::~_View() +{ +} + +_RowView::_RowView(const xmlpp::Element * p) : _SourceObject(p), + _View(p), + RowProcessor(p), + rootName(p->get_attribute_value("rootname")), recordName(p->get_attribute_value("recordname")) { LoaderBase loader("http://project2.randomdan.homeip.net", true); @@ -10,23 +26,54 @@ _View::_View(const xmlpp::Element * p) : loader.collectAll(p, true); } -_View::~_View() +_RowView::~_RowView() { } void -_View::executeChildren(xmlpp::Element * record) const +_RowView::loadComplete(const CommonObjects * co) { - try { - PerRowValues::beginRow(this); - BOOST_FOREACH(Views::value_type sq, subViews) { - sq.second->execute(record); + RowProcessor::loadComplete(co); +} + +void +_RowView::rowReady() const +{ + presenter->pushSub(recordName); + unsigned int cols = source->columnCount(); + for (unsigned int c = 0; c < cols; c += 1) { + if (!source->isNull(c)) { + presenter->addField(source->getColumnName(c), source->getCurrentValue(c)); } - PerRowValues::endRow(this); + } + executeChildren(); + source->rowChanged(); + presenter->popSub(); +} + +void +_RowView::execute(const Presenter * p) const +{ + presenter = p; + presenter->pushSub(rootName); + PerRowValues::beginRow(source.get()); + try { + source->execute(this); + PerRowValues::endRow(source.get()); + presenter->popSub(); } catch (...) { - PerRowValues::endRow(this); + presenter->popSub(); + PerRowValues::endRow(source.get()); throw; } } +void +_RowView::executeChildren() const +{ + BOOST_FOREACH(Views::value_type sq, subViews) { + sq.second->execute(presenter); + } +} + diff --git a/project2/view.h b/project2/view.h index cadb4c9..332e13f 100644 --- a/project2/view.h +++ b/project2/view.h @@ -7,43 +7,37 @@ #include "sourceObject.h" #include "xmlObjectLoader.h" #include "perRowValues.h" -#include "noOutputExecute.h" -class ApplicationEngine; +class Presenter; class _View; typedef boost::intrusive_ptr<_View> View; typedef std::map<std::string, View> Views; -class _View : public virtual _SourceObject, public PerRowValues { +class _View : public virtual _SourceObject { public: - _View(const xmlpp::Element * p); + _View(const xmlpp::Element *); virtual ~_View(); - virtual void execute(xmlpp::Element *) const = 0; - virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const = 0; - const Glib::ustring recordName; - protected: - void executeChildren(xmlpp::Element *) const; - Views subViews; + virtual void execute(const Presenter *) const = 0; }; -template <class Driver> -class _GenericView : public _View, public Driver { +class _RowView : public _View, public RowProcessor { public: - _GenericView(const xmlpp::Element * p); - - virtual unsigned int columnCount() const; - virtual void loadComplete(); - virtual const Glib::ustring & getCurrentValue(const unsigned int id) const; - virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - virtual const Glib::ustring & getColumnName(const unsigned int id) const; - virtual bool isNull(unsigned int col) const; - virtual void execute(xmlpp::Element * e) const; - virtual void rowReady() const; - private: - mutable xmlpp::Element * node; + _RowView(const xmlpp::Element *); + virtual ~_RowView(); + + void loadComplete(const CommonObjects *); + void execute(const Presenter *) const; + void rowReady() const; + + const Glib::ustring rootName; + const Glib::ustring recordName; + + protected: + void executeChildren() const; + Views subViews; + mutable const Presenter * presenter; }; #endif - diff --git a/project2/view.hpp b/project2/view.hpp deleted file mode 100644 index a065097..0000000 --- a/project2/view.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "view.h" - -template <class Driver> -_GenericView<Driver>::_GenericView(const xmlpp::Element * p) : - _SourceObject(p), - _View(p), - Driver(p), - node(NULL) -{ -} - -template <class Driver> -void -_GenericView<Driver>::execute(xmlpp::Element * e) const -{ - node = e->add_child(name); - Driver::execute(); -} - -template <class Driver> -void -_GenericView<Driver>::rowReady() const -{ - xmlpp::Element * record = node->add_child(recordName); - unsigned int cols = Driver::columnCount(); - for (unsigned int col = 0; col < cols; col += 1) { - if (!Driver::isNull(col)) { - xmlpp::Element * ch = record->add_child(Driver::getColumnName(col)); - ch->set_child_text(Driver::getCurrentValue(col)); - } - } - executeChildren(record); -} - -template <class Driver> -unsigned int -_GenericView<Driver>:: columnCount() const -{ - return Driver::columnCount(); -} - -template <class Driver> -void -_GenericView<Driver>:: loadComplete() -{ - Driver::loadComplete(); -} - -template <class Driver> -bool -_GenericView<Driver>:: isNull(const unsigned int id) const -{ - return Driver::isNull(id); -} - -template <class Driver> -const Glib::ustring & -_GenericView<Driver>:: getCurrentValue(const unsigned int id) const -{ - return Driver::getCurrentValue(id); -} - -template <class Driver> -const Glib::ustring & -_GenericView<Driver>:: getCurrentValue(const Glib::ustring & id) const -{ - return Driver::getCurrentValue(id); -} - -template <class Driver> -const Glib::ustring & -_GenericView<Driver>:: getColumnName(const unsigned int id) const -{ - return Driver::getColumnName(id); -} - diff --git a/project2/xmlObjectLoader.cpp b/project2/xmlObjectLoader.cpp index e789275..cfbf1a4 100644 --- a/project2/xmlObjectLoader.cpp +++ b/project2/xmlObjectLoader.cpp @@ -1,5 +1,5 @@ #include "xmlObjectLoader.h" -#include <stdexcept> +#include "exceptions.h" #include <stdio.h> unsigned int LoaderBase::depth = 0; @@ -43,8 +43,11 @@ LoaderBase::collectAll(const xmlpp::Element * node, bool childrenOnly) const } } } + if (created < 1) { + throw NotSupported(name); + } if (stored < created) { - throw std::runtime_error("Unexpected object"); + throw NotSupported(name); } } if (created == 0 && (recursive || childrenOnly)) { @@ -53,12 +56,19 @@ LoaderBase::collectAll(const xmlpp::Element * node, bool childrenOnly) const } } depth -= 1; - if (depth == 0) { - BOOST_FOREACH(Project2SourceObject o, loadedObjects) { - o->loadComplete(); - } - loadedObjects.clear(); +} + +void +LoaderBase::collectAll(const CommonObjects * co, const xmlpp::Element * node, bool childrenOnly) const +{ + if (depth != 0) { + throw std::logic_error("Cannot set CommonObjects in subloader"); } + collectAll(node, childrenOnly); + BOOST_FOREACH(Project2SourceObject o, loadedObjects) { + o->loadComplete(co); + } + loadedObjects.clear(); } void @@ -72,6 +82,10 @@ LoaderBase::onIdle() void LoaderBase::onIteration() { + // This is a fail safe in the event that something goes pearshape + depth = 0; + loadedObjects.clear(); + BOOST_FOREACH(ElementLoaderMap::value_type l, getMap()) { l.second->onIteration(); } diff --git a/project2/xmlObjectLoader.h b/project2/xmlObjectLoader.h index 8b71561..5f79122 100644 --- a/project2/xmlObjectLoader.h +++ b/project2/xmlObjectLoader.h @@ -15,6 +15,7 @@ Glib::ustring xmlChildText(const xmlpp::Node * p, const Glib::ustring & n); class ElementLoader; +class CommonObjects; class Storer : public virtual IntrusivePtrBase { public: @@ -87,6 +88,7 @@ class LoaderBase { LoaderBase(const Glib::ustring & ns, bool recursive); virtual ~LoaderBase(); + void collectAll(const CommonObjects * co, const xmlpp::Element * node, bool childrenOnly) const; void collectAll(const xmlpp::Element * node, bool childrenOnly) const; static ElementLoaderMap & getMap(); diff --git a/project2/xmlRows.cpp b/project2/xmlRows.cpp index 8ed912e..63a14cc 100644 --- a/project2/xmlRows.cpp +++ b/project2/xmlRows.cpp @@ -1,19 +1,19 @@ #include "xmlRows.h" #include "xml.h" +#include "exceptions.h" #include <libxml++/nodes/textnode.h> #include <libxml/xmlreader.h> -#include <stdexcept> #include "xmlObjectLoader.h" -#include "appEngine.h" #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/join.hpp> #include <boost/algorithm/string/predicate.hpp> -ElementLoaderImpl<_XmlIterate> xmliterateLoader("xmliterate"); -ElementLoaderImpl<_XmlView> xmlviewLoader("xmlview"); +ElementLoaderImpl<_XmlRows> xmlrowLoader("xmlrows"); _XmlRows::_XmlRows(const xmlpp::Element * p) : + _SourceObject(p), + PerRowValues(p), recordRoot(p->get_attribute_value("recordroot")), recordTrigger(p->get_attribute_value("recordtrigger")), filename(p->get_attribute_value("filename")), @@ -49,9 +49,15 @@ _XmlRows::~_XmlRows() { } - void -_XmlRows::loadComplete() +void +_XmlRows::loadComplete(const CommonObjects *) +{ +} + +void +_XmlRows::setFilter(const Glib::ustring &) { + throw NotSupported(__PRETTY_FUNCTION__); } const Glib::ustring & @@ -102,7 +108,7 @@ store(const _XmlRows::Path & position, _XmlRows::Values & values, const _XmlRows } void -_XmlRows::execute() const +_XmlRows::execute(const RowProcessor * rp) const { xmlTextReaderPtr reader = xmlReaderForFile(filename.c_str(), NULL, 0); if (reader == NULL) { @@ -129,7 +135,7 @@ _XmlRows::execute() const } if (empty) { if (position == trigger) { - rowReady(); + rp->rowReady(); } if (position == root) { values.clear(); @@ -146,7 +152,7 @@ _XmlRows::execute() const case XML_READER_TYPE_END_ELEMENT: if (enableCapture) { if (position == trigger) { - rowReady(); + rp->rowReady(); } if (position == root) { values.clear(); @@ -160,8 +166,3 @@ _XmlRows::execute() const xmlCleanupParser(); } -#include "view.hpp" -template class _GenericView<_XmlRows>; -#include "iterate.hpp" -template class _GenericIterate<_XmlRows>; - diff --git a/project2/xmlRows.h b/project2/xmlRows.h index 8b19e9a..05c127d 100644 --- a/project2/xmlRows.h +++ b/project2/xmlRows.h @@ -4,10 +4,7 @@ #include <libxml++/nodes/element.h> #include <boost/intrusive_ptr.hpp> #include <map> -#include "iterate.h" -#include "view.h" - -class ApplicationEngine; +#include "perRowValues.h" class _XmlRows : public PerRowValues { public: @@ -18,14 +15,14 @@ class _XmlRows : public PerRowValues { _XmlRows(const xmlpp::Element * p); ~_XmlRows(); - void execute() const; - virtual void loadComplete(); + void execute(const RowProcessor *) const; + virtual void loadComplete(const CommonObjects *); + virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; const Glib::ustring & getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; - virtual void rowReady() const = 0; const Glib::ustring recordRoot; const Glib::ustring recordTrigger; @@ -42,13 +39,5 @@ class _XmlRows : public PerRowValues { }; typedef boost::intrusive_ptr<_XmlRows> XmlRows; -typedef _GenericView<_XmlRows> _XmlView; -typedef boost::intrusive_ptr<_XmlView> XmlView; -typedef std::map<std::string, XmlView> XmlViews; - -typedef _GenericIterate<_XmlRows> _XmlIterate; -typedef boost::intrusive_ptr<_XmlIterate> XmlIterate; -typedef std::map<std::string, XmlIterate> XmlIterates; - #endif |