summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/Jamfile.jam2
-rw-r--r--project2/dataSource.cpp13
-rw-r--r--project2/dataSource.h19
-rw-r--r--project2/envproc.cpp27
-rw-r--r--project2/envproc.h24
-rw-r--r--project2/p2webMain.cpp10
-rw-r--r--project2/rdbmsDataSource.cpp8
-rw-r--r--project2/rdbmsDataSource.h10
-rw-r--r--project2/sqlView.cpp54
-rw-r--r--project2/sqlView.h25
-rw-r--r--project2/view.cpp19
-rw-r--r--project2/view.h40
12 files changed, 188 insertions, 63 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam
index c662255..fe900cd 100644
--- a/project2/Jamfile.jam
+++ b/project2/Jamfile.jam
@@ -8,7 +8,9 @@ lib odbc : : <name>odbc ;
exe p2web :
p2webMain.cpp
sourceObject.cpp
+ dataSource.cpp
rdbmsDataSource.cpp
+ view.cpp
sqlView.cpp
envproc.cpp
libxmlpp
diff --git a/project2/dataSource.cpp b/project2/dataSource.cpp
new file mode 100644
index 0000000..f4b72cf
--- /dev/null
+++ b/project2/dataSource.cpp
@@ -0,0 +1,13 @@
+#include "dataSource.h"
+#include "xmlObjectLoader.h"
+#include <libxml++/nodes/textnode.h>
+
+_DataSource::_DataSource(const xmlpp::Element * p) :
+ _Project2SourceObject(p)
+{
+}
+
+_DataSource::~_DataSource()
+{
+}
+
diff --git a/project2/dataSource.h b/project2/dataSource.h
new file mode 100644
index 0000000..85bc395
--- /dev/null
+++ b/project2/dataSource.h
@@ -0,0 +1,19 @@
+#ifndef DATASOURCE_H
+#define DATASOURCE_H
+
+#include <libxml/tree.h>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include "sourceObject.h"
+
+class _DataSource : public _Project2SourceObject {
+ public:
+ _DataSource(const xmlpp::Element * p);
+ virtual ~_DataSource();
+};
+typedef boost::shared_ptr<_DataSource> DataSource;
+typedef std::map<std::string, DataSource> DataSources;
+
+#endif
+
+
diff --git a/project2/envproc.cpp b/project2/envproc.cpp
index be864a5..feb5ad1 100644
--- a/project2/envproc.cpp
+++ b/project2/envproc.cpp
@@ -17,25 +17,28 @@ EnvironmentProcessor::init()
page = elems.size() > 0 ? elems[0] : "index";
}
-
-boost::shared_ptr<xmlpp::Document>
-EnvironmentProcessor::process() const
+void
+EnvironmentProcessor::Initialise()
{
xmlpp::DomParser present("present/" + page + ".xml");
while (xmlXIncludeProcessFlags(present.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0);
xmlpp::Element * presentRoot = present.get_document()->get_root_node();
+ responseRootNodeName = presentRoot->get_attribute_value("root");
+ responseStyle = presentRoot->get_attribute_value("style");
// Collect datasources
- RdbmsDataSources rdbmsDataSources;
- collectAll<_RdbmsDataSource>(rdbmsDataSources, presentRoot, "rdbmsdatasource", &_Project2SourceObject::name, true, true);
+ collectAll<_RdbmsDataSource>(datasources, presentRoot, "rdbmsdatasource", &_Project2SourceObject::name, true, true);
// Collect views
- SqlViews sqlViews;
- collectAll<_SqlView>(sqlViews, presentRoot, "sqlview", &_SqlView::name, true, true);
- //
+ collectAll<_SqlView>(views, presentRoot, "sqlview", &_SqlView::name, true, true);
+}
+
+boost::shared_ptr<xmlpp::Document>
+EnvironmentProcessor::process() const
+{
boost::shared_ptr<xmlpp::Document> responseDoc = boost::shared_ptr<xmlpp::Document>(new xmlpp::Document("1.0"));
- xmlpp::Element * responseRoot = responseDoc->create_root_node(presentRoot->get_attribute_value("root"));
+ xmlpp::Element * responseRoot = responseDoc->create_root_node(responseRootNodeName);
try {
- BOOST_FOREACH(SqlViews::value_type s, sqlViews) {
- s.second->execute(rdbmsDataSources, responseRoot, this);
+ BOOST_FOREACH(Views::value_type s, views) {
+ s.second->execute(responseRoot, this);
}
}
catch (...) {
@@ -59,7 +62,7 @@ EnvironmentProcessor::process() const
// XSLT Style
char * buf;
if (asprintf(&buf, "type=\"text/xsl\" href=\"%s\"",
- presentRoot->get_attribute_value("style").c_str()) > 0) {
+ responseStyle.c_str()) > 0) {
xmlAddPrevSibling(responseRoot->cobj(),
xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf));
}
diff --git a/project2/envproc.h b/project2/envproc.h
index 998899a..44556b7 100644
--- a/project2/envproc.h
+++ b/project2/envproc.h
@@ -5,9 +5,13 @@
#include <libxml++/document.h>
#include <boost/shared_ptr.hpp>
#include "regexex.h"
+#include "dataSource.h"
+#include "view.h"
class EnvironmentProcessor {
public:
+ class DataSourceNotFound : std::exception { };
+ class DataSourceNotCompatible : std::exception { };
template <class getenvFunc>
EnvironmentProcessor(const getenvFunc & getenv) :
request_uri(getenv("REQUEST_URI")),
@@ -17,7 +21,22 @@ class EnvironmentProcessor {
{
init();
}
+ 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;
+ }
+ void Initialise();
virtual boost::shared_ptr<xmlpp::Document> process() const;
+
Glib::ustring getParamUri(const std::string & idx) const;
Glib::ustring getParamQuery(const std::string & idx) const;
private:
@@ -31,6 +50,11 @@ class EnvironmentProcessor {
StringSet elems;
RegMultiMatch params;
std::string page;
+ Glib::ustring responseRootNodeName;
+ Glib::ustring responseStyle;
+
+ DataSources datasources;
+ Views views;
};
#endif
diff --git a/project2/p2webMain.cpp b/project2/p2webMain.cpp
index 698cd18..b5d4c59 100644
--- a/project2/p2webMain.cpp
+++ b/project2/p2webMain.cpp
@@ -26,7 +26,7 @@ int main(void)
{
try {
EnvironmentProcessor ep(boost::bind(FCGX_GetParam, _1, envp));
-
+ ep.Initialise();
boost::shared_ptr<xmlpp::Document> doc = ep.process();
FCGX_FPrintF(_out, "Content-type: text/xml-xslt\r\n\r\n");
@@ -46,10 +46,10 @@ int main(void)
}
}
#else
- EnvironmentProcessor ep(getenv);
-
- boost::shared_ptr<xmlpp::Document> doc = ep.process();
- xmlDocDump(stdout, doc->cobj());
+ EnvironmentProcessor ep(getenv);
+ ep.Initialise();
+ boost::shared_ptr<xmlpp::Document> doc = ep.process();
+ xmlDocDump(stdout, doc->cobj());
#endif
return 0;
}
diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp
index d77d016..5e6ad16 100644
--- a/project2/rdbmsDataSource.cpp
+++ b/project2/rdbmsDataSource.cpp
@@ -3,22 +3,22 @@
#include <libxml++/nodes/textnode.h>
_RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) :
- _Project2SourceObject(p),
+ _DataSource(p),
masterDsn(xmlChildText(p, "masterdsn"))
{
}
ODBC::Connection &
-_RdbmsDataSource::getWritable()
+_RdbmsDataSource::getWritable() const
{
if (!database) {
- database = boost::shared_ptr<ODBC::Connection>(new ODBC::Connection(masterDsn.c_str()));
+ database = boost::shared_ptr<ODBC::Connection>(new ODBC::Connection(masterDsn));
}
return *database;
}
ODBC::Connection &
-_RdbmsDataSource::getReadonly()
+_RdbmsDataSource::getReadonly() const
{
// For now :)
return getWritable();
diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h
index 1fd9fac..622754e 100644
--- a/project2/rdbmsDataSource.h
+++ b/project2/rdbmsDataSource.h
@@ -4,17 +4,17 @@
#include <libxml/tree.h>
#include <boost/shared_ptr.hpp>
#include <map>
-#include "sourceObject.h"
+#include "dataSource.h"
#include "connection.h"
-class _RdbmsDataSource : public _Project2SourceObject {
+class _RdbmsDataSource : public _DataSource {
public:
_RdbmsDataSource(const xmlpp::Element * p);
- ODBC::Connection & getReadonly();
- ODBC::Connection & getWritable();
+ ODBC::Connection & getReadonly() const;
+ ODBC::Connection & getWritable() const;
const std::string masterDsn;
private:
- boost::shared_ptr<ODBC::Connection> database;
+ mutable boost::shared_ptr<ODBC::Connection> database;
};
typedef boost::shared_ptr<_RdbmsDataSource> RdbmsDataSource;
typedef std::map<std::string, RdbmsDataSource> RdbmsDataSources;
diff --git a/project2/sqlView.cpp b/project2/sqlView.cpp
index 71c4f71..928482f 100644
--- a/project2/sqlView.cpp
+++ b/project2/sqlView.cpp
@@ -6,18 +6,14 @@
#include <libxml++/nodes/textnode.h>
#include "xmlObjectLoader.h"
#include "envproc.h"
+#include <boost/bind.hpp>
_SqlView::_SqlView(const xmlpp::Element * p) :
- _Project2SourceObject(p),
+ _View(p),
sql(xmlChildText(p, "sql")),
- dataSource(p->get_attribute_value("datasource")),
- recordName(p->get_attribute_value("recordname"))
+ query(NULL)
{
- xmlpp::NodeSet ps = p->find("parameters");
- BOOST_FOREACH(xmlpp::Node * psi, ps) {
- collectAll<_Parameter>(parameters, dynamic_cast<xmlpp::Element *>(psi), "param", &_Parameter::bind, true, true);
- }
- collectAll<_SqlView>(subQueries, p, "sqlview", &_Project2SourceObject::name, true, true);
+ collectAll<_SqlView>(subViews, p, "sqlview", &_Project2SourceObject::name, true, true);
}
_SqlView::_Parameter::_Parameter(const xmlpp::Element * p) :
@@ -27,28 +23,46 @@ _SqlView::_Parameter::_Parameter(const xmlpp::Element * p) :
{
}
-void _SqlView::execute(RdbmsDataSources s, xmlpp::Element * par, const EnvironmentProcessor * ep, const ODBC::SelectCommand * parent) const
+Glib::ustring
+_SqlView::getCurrentValue(const Glib::ustring & id) const
+{
+ return (*query)[id].compose();
+}
+
+void
+_SqlView::rebindCurrentValue(const Glib::ustring & id, ODBC::Command * cmd, unsigned int bind) const
+{
+ (*query)[id].rebind(cmd, bind);
+}
+
+void _SqlView::execute(xmlpp::Element * par, const EnvironmentProcessor * ep, const _View * parent) const
{
typedef std::map<std::string, xmlpp::Element *> Columns;
- ODBC::SelectCommand query(s[dataSource]->getReadonly(), sql);
+ query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);
BOOST_FOREACH(Parameters::value_type p, parameters) {
if (p.second->source == "uri") {
- query.bindParamS(p.second->bind, ep->getParamUri(p.second->id));
+ query->bindParamS(p.second->bind, ep->getParamUri(p.second->id));
}
else if (p.second->source == "query") {
- query.bindParamS(p.second->bind, ep->getParamQuery(p.second->id));
+ query->bindParamS(p.second->bind, ep->getParamQuery(p.second->id));
}
else if (parent && p.second->source == "parent") {
- (*parent)[p.second->id].rebind(&query, p.second->bind);
+ const _SqlView * psqlview = dynamic_cast<const _SqlView *>(parent);
+ if (psqlview) {
+ psqlview->rebindCurrentValue(p.second->id, query, p.second->bind);
+ }
+ else {
+ query->bindParamS(p.second->bind, parent->getCurrentValue(p.second->id));
+ }
}
}
xmlpp::Element * set = par->add_child(name);
- while (query.fetch()) {
+ while (query->fetch()) {
Columns columns;
- unsigned int cols = query.columnCount();
+ unsigned int cols = query->columnCount();
xmlpp::Element * record = set->add_child(recordName);
for (unsigned int col = 0; col < cols; col += 1) {
- const Glib::ustring & nameattr = query[col].name;
+ const Glib::ustring & nameattr = (*query)[col].name;
char * name, * attr = NULL;
switch (sscanf(nameattr.c_str(), "%a[^_]_%as", &name, &attr))
{
@@ -61,7 +75,7 @@ void _SqlView::execute(RdbmsDataSources s, xmlpp::Element * par, const Environme
break;
}
char * buf = NULL;
- query[col].writeToBuf(&buf);
+ (*query)[col].writeToBuf(&buf);
if (buf) {
if (attr) {
if (strcmp(attr, ".") == 0) {
@@ -87,9 +101,11 @@ void _SqlView::execute(RdbmsDataSources s, xmlpp::Element * par, const Environme
free(name);
free(attr);
}
- BOOST_FOREACH(SqlViews::value_type sq, subQueries) {
- sq.second->execute(s, record, ep, &query);
+ BOOST_FOREACH(Views::value_type sq, subViews) {
+ sq.second->execute(record, ep, this);
}
}
+ delete query;
+ query = NULL;
}
diff --git a/project2/sqlView.h b/project2/sqlView.h
index 9f132bc..d8efa0f 100644
--- a/project2/sqlView.h
+++ b/project2/sqlView.h
@@ -4,35 +4,24 @@
#include <libxml++/nodes/element.h>
#include <boost/shared_ptr.hpp>
#include <map>
-#include "sourceObject.h"
+#include "selectcommand.h"
+#include "view.h"
#include "rdbmsDataSource.h"
class EnvironmentProcessor;
-namespace ODBC { class SelectCommand; }
class _SqlView;
typedef boost::shared_ptr<_SqlView> SqlView;
typedef std::map<std::string, SqlView> SqlViews;
-class _SqlView : public _Project2SourceObject {
+class _SqlView : public _View {
public:
- class _Parameter {
- public:
- _Parameter(const xmlpp::Element * p);
- const std::string source;
- const std::string id;
- const unsigned int bind;
- };
- typedef boost::shared_ptr<_Parameter> Parameter;
- typedef std::map<unsigned int, Parameter> Parameters;
-
_SqlView(const xmlpp::Element * p);
- void execute(RdbmsDataSources s, xmlpp::Element *, const EnvironmentProcessor *, const ODBC::SelectCommand * parent = NULL) const;
+ void execute(xmlpp::Element *, const EnvironmentProcessor *, const _View * parent = NULL) const;
+ Glib::ustring getCurrentValue(const Glib::ustring & id) const;
const Glib::ustring sql;
- const Glib::ustring dataSource;
- const Glib::ustring recordName;
private:
- Parameters parameters;
- SqlViews subQueries;
+ mutable ODBC::SelectCommand * query;
+ void rebindCurrentValue(const Glib::ustring & id, ODBC::Command *, unsigned int) const;
};
#endif
diff --git a/project2/view.cpp b/project2/view.cpp
new file mode 100644
index 0000000..e674af8
--- /dev/null
+++ b/project2/view.cpp
@@ -0,0 +1,19 @@
+#include "view.h"
+#include <boost/foreach.hpp>
+#include "xmlObjectLoader.h"
+
+_View::_View(const xmlpp::Element * p) :
+ _Project2SourceObject(p),
+ dataSource(p->get_attribute_value("datasource")),
+ recordName(p->get_attribute_value("recordname"))
+{
+ xmlpp::NodeSet ps = p->find("parameters");
+ BOOST_FOREACH(xmlpp::Node * psi, ps) {
+ collectAll<_Parameter>(parameters, dynamic_cast<xmlpp::Element *>(psi), "param", &_Parameter::bind, true, true);
+ }
+}
+
+_View::~_View()
+{
+}
+
diff --git a/project2/view.h b/project2/view.h
new file mode 100644
index 0000000..281f9d2
--- /dev/null
+++ b/project2/view.h
@@ -0,0 +1,40 @@
+#ifndef VIEW_H
+#define VIEW_H
+
+#include <libxml++/nodes/element.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/any.hpp>
+#include <map>
+#include "sourceObject.h"
+
+class EnvironmentProcessor;
+class _View;
+typedef boost::shared_ptr<_View> View;
+typedef std::map<std::string, View> Views;
+
+class _View : public _Project2SourceObject {
+ public:
+ class _Parameter {
+ public:
+ _Parameter(const xmlpp::Element * p);
+ const std::string source;
+ const std::string id;
+ const unsigned int bind;
+ };
+ typedef boost::shared_ptr<_Parameter> Parameter;
+ typedef std::map<unsigned int, Parameter> Parameters;
+
+ _View(const xmlpp::Element * p);
+ virtual ~_View();
+ virtual void execute(xmlpp::Element *, const EnvironmentProcessor *, const _View * parent = NULL) const = 0;
+ virtual Glib::ustring getCurrentValue(const Glib::ustring & id) const = 0;
+ const Glib::ustring dataSource;
+ const Glib::ustring recordName;
+ protected:
+ Parameters parameters;
+ Views subViews;
+};
+
+#endif
+
+