summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-08-09 19:46:16 +0000
committerrandomdan <randomdan@localhost>2011-08-09 19:46:16 +0000
commit7699d617956abd15215751570e0f8e3e328eca8d (patch)
treeecddb09d16b94fcfaa14bc8f41e9db7dbfbe053d
parentRemove the long since pointless complication of RowUsers and variable value c... (diff)
downloadproject2-7699d617956abd15215751570e0f8e3e328eca8d.tar.bz2
project2-7699d617956abd15215751570e0f8e3e328eca8d.tar.xz
project2-7699d617956abd15215751570e0f8e3e328eca8d.zip
Strip out some dead wood
Fix a few small things But many fix the big idiot problem with storing state in the rowset instance
-rw-r--r--project2/Jamfile.jam2
-rw-r--r--project2/columns.cpp23
-rw-r--r--project2/columns.h33
-rw-r--r--project2/console/consoleAppEngine.h4
-rw-r--r--project2/definedColumns.cpp75
-rw-r--r--project2/definedColumns.h53
-rw-r--r--project2/fileRows.cpp8
-rw-r--r--project2/fileRows.h2
-rw-r--r--project2/fileStrmVarWriter.cpp2
-rw-r--r--project2/fsRows.cpp137
-rw-r--r--project2/fsRows.h60
-rw-r--r--project2/iterate.cpp30
-rw-r--r--project2/iterate.h2
-rw-r--r--project2/regexRows.cpp22
-rw-r--r--project2/regexRows.h5
-rw-r--r--project2/rowProcessor.h4
-rw-r--r--project2/rowSet.cpp71
-rw-r--r--project2/rowSet.h44
-rw-r--r--project2/rowView.cpp25
-rw-r--r--project2/rowView.h2
-rw-r--r--project2/safeMapFind.h27
-rw-r--r--project2/scopeObject.cpp23
-rw-r--r--project2/scopeObject.h20
-rw-r--r--project2/sqlMergeTask.cpp65
-rw-r--r--project2/sqlMergeTask.h4
-rw-r--r--project2/sqlRows.cpp78
-rw-r--r--project2/sqlRows.h18
-rw-r--r--project2/streamRows.cpp136
-rw-r--r--project2/streamRows.h33
-rw-r--r--project2/tablepatch.cpp2
-rw-r--r--project2/tablepatch.h6
-rw-r--r--project2/urlRows.cpp20
-rw-r--r--project2/urlRows.h6
-rw-r--r--project2/variables-modlookup.cpp12
-rw-r--r--project2/variables.cpp12
-rw-r--r--project2/xmlRows.cpp88
-rw-r--r--project2/xmlRows.h21
-rw-r--r--project2/xslRows.cpp81
-rw-r--r--project2/xslRows.h32
39 files changed, 586 insertions, 702 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam
index 5eb1c27..80befb9 100644
--- a/project2/Jamfile.jam
+++ b/project2/Jamfile.jam
@@ -58,7 +58,7 @@ lib p2common :
iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp logger.cpp if.cpp xmlScriptParser.cpp viewHost.cpp
sourceObject.cpp task.cpp variables.cpp variableConvert.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp
sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp taskHost.cpp checkHost.cpp
- rowView.cpp rowSet.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp
+ rowView.cpp rowSet.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp columns.cpp scopeObject.cpp
transform.cpp transformHtml.cpp transformText.cpp definedColumns.cpp structExceptHandling.cpp validDateCheck.cpp
variables-modconfig.cpp
variables-modlookup.cpp
diff --git a/project2/columns.cpp b/project2/columns.cpp
new file mode 100644
index 0000000..a2511f6
--- /dev/null
+++ b/project2/columns.cpp
@@ -0,0 +1,23 @@
+#include "columns.h"
+#include <libxml++/nodes/textnode.h>
+
+Column::Column(unsigned int i, const xmlpp::Element * p) :
+ idx(i),
+ name(p->get_attribute("name") ? p->get_attribute_value("name") : p->get_child_text()->get_content()),
+ defValue(p, "default", false)
+{
+}
+
+Column::Column(unsigned int i, const Glib::ustring & n, const Variable & v) :
+ idx(i),
+ name(n),
+ defValue(v)
+{
+}
+
+Column *
+Column::make(unsigned int idx, const xmlpp::Element * p)
+{
+ return new Column(idx, p);
+}
+
diff --git a/project2/columns.h b/project2/columns.h
new file mode 100644
index 0000000..8b9b9b3
--- /dev/null
+++ b/project2/columns.h
@@ -0,0 +1,33 @@
+#ifndef COLUMNS_H
+#define COLUMNS_H
+
+#include <libxml++/nodes/element.h>
+#include "variables.h"
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+class Column : public IntrusivePtrBase {
+ public:
+ Column(unsigned int idx, const xmlpp::Element * p);
+ Column(unsigned int i, const Glib::ustring & n, const Variable & v = Variable(Null()));
+
+ static Column * make(unsigned int idx, const xmlpp::Element * p);
+
+ const unsigned int idx;
+ const Glib::ustring name;
+ const Variable defValue;
+};
+
+struct byColIdx {};
+struct byColName {};
+typedef boost::multi_index::multi_index_container<boost::intrusive_ptr<Column>,
+ boost::multi_index::indexed_by<
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<byColName>, BOOST_MULTI_INDEX_MEMBER(Column, const Glib::ustring, name)>,
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<byColIdx>, BOOST_MULTI_INDEX_MEMBER(Column, const unsigned int, idx)>
+ > > Columns;
+
+#endif
+
diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h
index 3d54a18..5e0a403 100644
--- a/project2/console/consoleAppEngine.h
+++ b/project2/console/consoleAppEngine.h
@@ -1,5 +1,5 @@
-#ifndef CGIAPPENGINE_H
-#define CGIAPPENGINE_H
+#ifndef CONSOLEAPPENGINE_H
+#define CONSOLEAPPENGINE_H
#include "../appEngine.h"
#include "../task.h"
diff --git a/project2/definedColumns.cpp b/project2/definedColumns.cpp
index 1361453..5260e51 100644
--- a/project2/definedColumns.cpp
+++ b/project2/definedColumns.cpp
@@ -1,84 +1,31 @@
#include "definedColumns.h"
-#include <boost/foreach.hpp>
+#include <boost/function.hpp>
#include <libxml++/nodes/textnode.h>
-DefinedColumns::DefinedColumns(const xmlpp::Element * p) :
- RowSet(p)
+DefinedColumns::DefinedColumns(const xmlpp::Element * p, const Glib::ustring & colPath, const ColCreator & func)
{
unsigned int colNo = 0;
- BOOST_FOREACH(const xmlpp::Node * node, p->find("columns/column")) {
+ BOOST_FOREACH(const xmlpp::Node * node, p->find(colPath)) {
const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
if (elem) {
- columns.insert(Column(colNo++, elem));
+ columns.insert(func(colNo++, elem));
}
}
}
-DefinedColumns::Column::Column(unsigned int i, const Glib::ustring & c) :
- idx(i),
- col(c),
- defValue(VariableType())
+ColumnValues::ColumnValues(const DefinedColumns * rs) :
+ rowSet(rs)
{
+ fields.resize(rs->columns.size());
}
-DefinedColumns::Column::Column(unsigned int i, const xmlpp::Element * p) :
- idx(i),
- col(p->get_child_text()->get_content()),
- defValue(p, "default", false)
+ColumnValues::~ColumnValues()
{
}
-void
-DefinedColumns::Column::operator=(const VariableType & v) const
+const Columns &
+ColumnValues::getColumns() const
{
- value = v;
-}
-
-const Glib::ustring &
-DefinedColumns::getColumnName(unsigned int col) const
-{
- Columns::index<byColIdx>::type::iterator i = columns.get<byColIdx>().find(col);
- if (i != columns.get<byColIdx>().end()) {
- return i->col;
- }
- throw RowSet::FieldOutOfRange(col);
-}
-
-unsigned int
-DefinedColumns::columnCount() const
-{
- return columns.size();
-}
-
-VariableType
-DefinedColumns::getCurrentValue(unsigned int col) const
-{
- Columns::index<byColIdx>::type::iterator i = columns.get<byColIdx>().find(col);
- if (i != columns.get<byColIdx>().end()) {
- return i->value;
- }
- throw RowSet::FieldOutOfRange(col);
-}
-
-bool
-DefinedColumns::isNull(unsigned int col) const
-{
- return (columns.get<byColIdx>().find(col) == columns.get<byColIdx>().end());
-}
-
-bool
-DefinedColumns::isNull(const Glib::ustring & col) const
-{
- return (columns.get<byColName>().find(col) == columns.get<byColName>().end());
-}
-
-VariableType
-DefinedColumns::getCurrentValue(const Glib::ustring & col) const
-{
- Columns::const_iterator i = columns.get<byColName>().find(col);
- if (i != columns.end()) {
- return i->value;
- }
- throw RowSet::FieldDoesNotExist(col);
+ return rowSet->columns;
}
diff --git a/project2/definedColumns.h b/project2/definedColumns.h
index d6f2ba3..2fc6bbd 100644
--- a/project2/definedColumns.h
+++ b/project2/definedColumns.h
@@ -2,47 +2,26 @@
#define DEFINEDCOLUMNS_H
#include <libxml++/nodes/element.h>
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/member.hpp>
-#include <boost/multi_index/ordered_index.hpp>
+#include <boost/foreach.hpp>
#include "variables.h"
#include "rowSet.h"
+#include "columns.h"
-class DefinedColumns : public RowSet {
+class DefinedColumns {
public:
- DefinedColumns(const xmlpp::Element *);
-
- unsigned int columnCount() const;
- const Glib::ustring & getColumnName(unsigned int col) const;
- VariableType getCurrentValue(const Glib::ustring & id) const;
- VariableType getCurrentValue(unsigned int col) const;
- bool isNull(unsigned int col) const;
- bool isNull(const Glib::ustring & id) const;
-
- protected:
- class Column {
- public:
- Column(unsigned int idx, const Glib::ustring &);
- Column(unsigned int idx, const xmlpp::Element * p);
-
- void operator=(const VariableType &) const;
-
- const unsigned int idx;
- const Glib::ustring col;
- mutable VariableType value;
- const Variable defValue;
- };
- struct byColIdx {};
- struct byColName {};
- typedef boost::multi_index::multi_index_container<
- Column,
- boost::multi_index::indexed_by<
- boost::multi_index::ordered_unique<
- boost::multi_index::tag<byColName>, BOOST_MULTI_INDEX_MEMBER(Column, const Glib::ustring, col)>,
- boost::multi_index::ordered_unique<
- boost::multi_index::tag<byColIdx>, BOOST_MULTI_INDEX_MEMBER(Column, const unsigned int, idx)>
- > > Columns;
- mutable Columns columns;
+ typedef boost::function2<Column *, unsigned int, const xmlpp::Element *> ColCreator;
+ DefinedColumns(const xmlpp::Element * p, const Glib::ustring & colPath, const ColCreator & func);
+ Columns columns;
+};
+
+class ColumnValues : public RowState {
+ public:
+ ColumnValues(const DefinedColumns *);
+ virtual ~ColumnValues();
+
+ virtual const Columns & getColumns() const;
+
+ const DefinedColumns * const rowSet;
};
#endif
diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp
index 58dde13..d7c8fca 100644
--- a/project2/fileRows.cpp
+++ b/project2/fileRows.cpp
@@ -29,17 +29,15 @@ FileRows::setFilter(const Glib::ustring &)
}
void
-FileRows::execute(const RowProcessor * rp) const
+FileRows::execute(const Glib::ustring &, const RowProcessor * rp) const
{
- rowNum = 1;
FileStarChannel c(doOpen());
c.set_encoding(encoding);
gunichar ch;
- begin();
+ ParseState ps(this, rp);
while (c.read(ch) == Glib::IO_STATUS_NORMAL) {
- this->pushChar(ch, rp);
+ this->pushChar(ch, ps);
}
- end(rp);
}
FileStarChannel
diff --git a/project2/fileRows.h b/project2/fileRows.h
index a4cc863..0cf3f1d 100644
--- a/project2/fileRows.h
+++ b/project2/fileRows.h
@@ -12,7 +12,7 @@ class FileRows : public StreamRows {
FileRows(const xmlpp::Element * p);
~FileRows();
- void execute(const RowProcessor *) const;
+ void execute(const Glib::ustring &, const RowProcessor *) const;
virtual void loadComplete(const CommonObjects *);
virtual void setFilter(const Glib::ustring &);
diff --git a/project2/fileStrmVarWriter.cpp b/project2/fileStrmVarWriter.cpp
index 1af99dc..51fb487 100644
--- a/project2/fileStrmVarWriter.cpp
+++ b/project2/fileStrmVarWriter.cpp
@@ -49,9 +49,11 @@ void FileStreamVariableWriter::operator()(const double & i) const {
fprintf(out, "%g", i);
}
void FileStreamVariableWriter::operator()(const Glib::ustring & i) const {
+ fputc('\'', out);
if (fwrite(i.c_str(), i.bytes(), 1, out) < 1) {
// Care much? None of the others check.
}
+ fputc('\'', out);
}
void FileStreamVariableWriter::operator()(const boost::posix_time::ptime & i) const {
fprintf(out, "[%s]", boost::posix_time::to_iso_extended_string(i).c_str());
diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp
index 5ae8221..b308f38 100644
--- a/project2/fsRows.cpp
+++ b/project2/fsRows.cpp
@@ -28,17 +28,24 @@ const Glib::ustring field_group("owningGroup");
const Glib::ustring field_mode("mode");
const Glib::ustring field_perms("perms");
const Glib::ustring field_type("type");
+static
+Columns defCols() {
+ Columns rtn;
+ rtn.insert(new Column(0, "absPath"));
+ return rtn;
+}
+const Columns FsRows::SearchState::col(defCols());
-bool FsRows::SpecBase::recurse(const FsRows *) const { return true; }
-bool FsRows::SpecBase::matches(const FsRows *) const { return true; }
-const boost::filesystem::path & FsRows::SpecBase::curPath(const FsRows * fs) const { return fs->curPath; }
-unsigned int FsRows::SpecBase::depth(const FsRows * fs) const { return fs->depth; }
-struct stat & FsRows::SpecBase::curStat(const FsRows * fs) const { return fs->curStat; }
+bool FsRows::SpecBase::recurse(const SearchState *) const { return true; }
+bool FsRows::SpecBase::matches(const SearchState *) const { return true; }
+const boost::filesystem::path & FsRows::SpecBase::curPath(const SearchState * fs) const { return fs->curPath; }
+unsigned int FsRows::SpecBase::depth(const SearchState * fs) const { return fs->depth; }
+const struct stat & FsRows::SpecBase::curStat(const SearchState * fs) const { return fs->curStat; }
class FsRowSpecName : public FsRows::SpecBase {
public:
FsRowSpecName(const Glib::ustring & v) : pattern(v) { }
- bool matches(const FsRows * fs) const {
+ bool matches(const FsRows::SearchState * fs) const {
// Based on code written by Jack Handy - jakkhandy@hotmail.com
// from http://www.codeproject.com/KB/string/wildcmp.aspx
Glib::ustring::const_iterator wild = pattern.begin();
@@ -85,7 +92,7 @@ class FsRowSpecName : public FsRows::SpecBase {
class FsRowSpecType : public FsRows::SpecBase {
public:
FsRowSpecType(const Glib::ustring & v) : types(v) { }
- bool matches(const FsRows * fs) const {
+ bool matches(const FsRows::SearchState * fs) const {
if (S_ISREG(curStat(fs).st_mode)) {
return types.find('f') != Glib::ustring::npos;
}
@@ -114,7 +121,7 @@ class FsRowSpecType : public FsRows::SpecBase {
class FsRowSpecMaxDepth : public FsRows::SpecBase {
public:
FsRowSpecMaxDepth(const Glib::ustring & v) : maxDepth(boost::lexical_cast<unsigned int>(v)) { }
- bool recurse(const FsRows * fs) const {
+ bool recurse(const FsRows::SearchState * fs) const {
return (depth(fs) < maxDepth);
}
const unsigned int maxDepth;
@@ -134,11 +141,6 @@ FsRows::loadComplete(const CommonObjects *)
{
}
-void
-FsRows::setFilter(const Glib::ustring &)
-{
-}
-
FsRows::Path
normalisePath(const std::string & p)
{
@@ -150,12 +152,9 @@ normalisePath(const std::string & p)
}
void
-FsRows::execute(const RowProcessor * rp) const
+FsRows::execute(const Glib::ustring &, const RowProcessor * rp) const
{
- rowNum = 1;
- depth = 0;
- fsRoot = normalisePath(rp->getParameter("root"));
- specs.clear();
+ SearchState ss(normalisePath(rp->getParameter("root")));
SpecSpec s;
typedef SpecSpec & (*splitter)(SpecSpec &, const Glib::ustring &, bool (*)(gunichar), boost::algorithm::token_compress_mode_type);
splitter split = &boost::algorithm::split;
@@ -163,134 +162,108 @@ FsRows::execute(const RowProcessor * rp) const
for (SpecSpec::const_iterator sf = s.begin(); sf != s.end(); ) {
const Glib::ustring & name = (*sf++);
if (name == "-name") {
- specs.insert(new FsRowSpecName(*sf++));
+ ss.specs.insert(new FsRowSpecName(*sf++));
}
else if (name == "-type") {
- specs.insert(new FsRowSpecType(*sf++));
+ ss.specs.insert(new FsRowSpecType(*sf++));
}
else if (name == "-maxdepth") {
- specs.insert(new FsRowSpecMaxDepth(*sf++));
+ ss.specs.insert(new FsRowSpecMaxDepth(*sf++));
}
else {
throw NotSupported(name);
}
}
- execute(fsRoot, rp);
+ execute(ss, ss.fsRoot, rp);
}
void
-FsRows::execute(const Path & dir, const RowProcessor * rp) const
+FsRows::execute(SearchState & ss, const Path & dir, const RowProcessor * rp) const
{
- depth += 1;
+ ss.depth += 1;
try {
DirEnt end;
for (DirEnt itr(dir); itr != end; ++itr) {
- curPathStr = itr->path().string();
- curPath = itr->path();
- stat(curPathStr.c_str(), &curStat);
+ ss.curPathStr = itr->path().string();
+ ss.curPath = itr->path();
+ stat(ss.curPathStr.c_str(), &ss.curStat);
- if (boost::algorithm::all(specs, boost::bind(&SpecBase::matches, _1, this))) {
- rp->rowReady();
- rowNum += 1;
+ if (boost::algorithm::all(ss.specs, boost::bind(&SpecBase::matches, _1, &ss))) {
+ ss.process(rp);
}
- if (S_ISDIR(curStat.st_mode) && boost::algorithm::all(specs, boost::bind(&SpecBase::recurse, _1, this))) {
- execute(*itr, rp);
+ if (S_ISDIR(ss.curStat.st_mode) && boost::algorithm::all(ss.specs, boost::bind(&SpecBase::recurse, _1, &ss))) {
+ execute(ss, *itr, rp);
}
}
}
catch (const boost::filesystem::filesystem_error & e) {
Logger()->messagef(LOG_WARNING, "%s when processing '%s'", e.what(), dir.string().c_str());
}
- depth -= 1;
+ ss.depth -= 1;
}
-unsigned int
-FsRows::columnCount() const
-{
- return 1;
-}
-
-bool
-FsRows::isNull(unsigned int) const
-{
- return false;
-}
-
-bool
-FsRows::isNull(const Glib::ustring &) const
-{
- return false;
-}
-
-VariableType
-FsRows::getCurrentValue(const Glib::ustring &) const
-{
- return curPathStr;
-}
-
-VariableType
-FsRows::getCurrentValue(unsigned int) const
+FsRows::SearchState::SearchState(const Path & dir) :
+ fsRoot(dir)
{
- return curPathStr;
}
-const Glib::ustring &
-FsRows::getColumnName(unsigned int) const
+const Columns &
+FsRows::SearchState::getColumns() const
{
- return field_absPath;
+ return col;
}
-RowSet::RowAttribute
-FsRows::resolveAttr(const Glib::ustring & a) const
+RowState::RowAttribute
+FsRows::SearchState::resolveAttr(const Glib::ustring & a) const
{
if (a == field_relPath) {
- return boost::bind(&FsRows::fileRelPath, this);
+ return boost::bind(&FsRows::SearchState::fileRelPath, this);
}
if (a == field_size) {
- return boost::bind(&FsRows::fileSize, this);
+ return boost::bind(&FsRows::SearchState::fileSize, this);
}
if (a == field_modDate) {
- return boost::bind(&FsRows::fileModDate, this);
+ return boost::bind(&FsRows::SearchState::fileModDate, this);
}
if (a == field_user) {
- return boost::bind(&FsRows::fileUser, this);
+ return boost::bind(&FsRows::SearchState::fileUser, this);
}
if (a == field_group) {
- return boost::bind(&FsRows::fileGroup, this);
+ return boost::bind(&FsRows::SearchState::fileGroup, this);
}
if (a == field_mode) {
- return boost::bind(&FsRows::fileMode, this);
+ return boost::bind(&FsRows::SearchState::fileMode, this);
}
if (a == field_perms) {
- return boost::bind(&FsRows::filePerms, this);
+ return boost::bind(&FsRows::SearchState::filePerms, this);
}
if (a == field_type) {
- return boost::bind(&FsRows::fileType, this);
+ return boost::bind(&FsRows::SearchState::fileType, this);
}
- return RowSet::resolveAttr(a);
+ return RowState::resolveAttr(a);
}
VariableType
-FsRows::fileRelPath() const
+FsRows::SearchState::fileRelPath() const
{
return curPathStr.substr(fsRoot.string().length() - 1);
}
VariableType
-FsRows::fileSize() const
+FsRows::SearchState::fileSize() const
{
return curStat.st_size;
}
VariableType
-FsRows::fileModDate() const
+FsRows::SearchState::fileModDate() const
{
return boost::posix_time::from_time_t(curStat.st_mtime);
}
VariableType
-FsRows::fileUser() const
+FsRows::SearchState::fileUser() const
{
struct passwd * p = getpwuid(curStat.st_uid);
if (p) {
@@ -302,7 +275,7 @@ FsRows::fileUser() const
}
VariableType
-FsRows::fileGroup() const
+FsRows::SearchState::fileGroup() const
{
struct group * g = getgrgid(curStat.st_gid);
if (g) {
@@ -314,19 +287,19 @@ FsRows::fileGroup() const
}
VariableType
-FsRows::fileMode() const
+FsRows::SearchState::fileMode() const
{
throw NotSupported(__PRETTY_FUNCTION__);
}
VariableType
-FsRows::filePerms() const
+FsRows::SearchState::filePerms() const
{
throw NotSupported(__PRETTY_FUNCTION__);
}
VariableType
-FsRows::fileType() const
+FsRows::SearchState::fileType() const
{
throw NotSupported(__PRETTY_FUNCTION__);
}
diff --git a/project2/fsRows.h b/project2/fsRows.h
index 4e559cd..8cd1a9f 100644
--- a/project2/fsRows.h
+++ b/project2/fsRows.h
@@ -13,14 +13,15 @@ class CommonObjects;
/// Project2 component to create a row set based on files and directories on the local filesystem
class FsRows : public RowSet {
public:
+ class SearchState;
class SpecBase : public virtual IntrusivePtrBase {
public:
- virtual bool recurse(const FsRows * fs) const;
- virtual bool matches(const FsRows * fs) const;
+ virtual bool recurse(const SearchState * fs) const;
+ virtual bool matches(const SearchState * fs) const;
protected:
- const boost::filesystem::path & curPath(const FsRows * fs) const;
- unsigned int depth(const FsRows * fs) const;
- struct stat & curStat(const FsRows * fs) const;
+ const boost::filesystem::path & curPath(const SearchState * fs) const;
+ unsigned int depth(const SearchState * fs) const;
+ const struct stat & curStat(const SearchState * fs) const;
};
typedef boost::intrusive_ptr<SpecBase> SpecBasePtr;
typedef std::set<SpecBasePtr> SpecBases;
@@ -30,35 +31,34 @@ class FsRows : public RowSet {
FsRows(const xmlpp::Element * p);
~FsRows();
- void execute(const RowProcessor *) const;
+ void execute(const Glib::ustring &, 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;
- VariableType getCurrentValue(const Glib::ustring & id) const;
- VariableType getCurrentValue(unsigned int col) const;
- bool isNull(unsigned int col) const;
- bool isNull(const Glib::ustring & id) const;
- virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const;
+ class SearchState : public RowState {
+ public:
+ SearchState(const boost::filesystem::path & r);
- VariableType fileRelPath() const;
- VariableType fileSize() const;
- VariableType fileModDate() const;
- VariableType fileUser() const;
- VariableType fileGroup() const;
- VariableType fileMode() const;
- VariableType filePerms() const;
- VariableType fileType() const;
+ virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const;
+ virtual const Columns & getColumns() const;
- protected:
- void execute(const Path & dir, const RowProcessor *) const;
- mutable SpecBases specs;
- mutable boost::filesystem::path fsRoot;
- mutable boost::filesystem::path curPath;
- mutable Glib::ustring curPathStr;
- mutable unsigned int depth;
- mutable struct stat curStat;
+ VariableType fileRelPath() const;
+ VariableType fileSize() const;
+ VariableType fileModDate() const;
+ VariableType fileUser() const;
+ VariableType fileGroup() const;
+ VariableType fileMode() const;
+ VariableType filePerms() const;
+ VariableType fileType() const;
+ static const Columns col;
+ SpecBases specs;
+ const boost::filesystem::path fsRoot;
+ boost::filesystem::path curPath;
+ Glib::ustring curPathStr;
+ unsigned int depth;
+ struct stat curStat;
+ };
+ protected:
+ void execute(SearchState &, const Path & dir, const RowProcessor *) const;
friend class SpecBase;
};
diff --git a/project2/iterate.cpp b/project2/iterate.cpp
index 795b356..99c5004 100644
--- a/project2/iterate.cpp
+++ b/project2/iterate.cpp
@@ -26,7 +26,7 @@ Iterate::loadComplete(const CommonObjects * co)
}
void
-Iterate::rowReady() const
+Iterate::rowReady(const RowState *) const
{
executeChildren();
}
@@ -34,38 +34,14 @@ Iterate::rowReady() const
void
Iterate::execute() const
{
- if (!filter.empty()) {
- source->setFilter(filter);
- }
- RowSet::beginRow(source.get());
- try {
- source->execute(this);
- RowSet::endRow(source.get());
- }
- catch (...) {
- RowSet::endRow(source.get());
- throw;
- }
+ source->execute(filter, this);
}
void
Iterate::executeChildren() const
{
BOOST_FOREACH(const Tasks::value_type & sq, normal) {
- if (dynamic_cast<const RowProcessor *>(sq.get())) {
- sq->execute();
- }
- else {
- RowSet::beginRow(NULL);
- try {
- sq->execute();
- RowSet::endRow(NULL);
- }
- catch (...) {
- RowSet::endRow(NULL);
- throw;
- }
- }
+ sq->execute();
}
}
diff --git a/project2/iterate.h b/project2/iterate.h
index 9ea0f94..50fd879 100644
--- a/project2/iterate.h
+++ b/project2/iterate.h
@@ -16,7 +16,7 @@ class Iterate : public IHaveSubTasks, public RowProcessor {
virtual ~Iterate();
void loadComplete(const CommonObjects *);
- void rowReady() const;
+ void rowReady(const RowState *) const;
void execute() const;
protected:
diff --git a/project2/regexRows.cpp b/project2/regexRows.cpp
index 6d75d3a..1dab636 100644
--- a/project2/regexRows.cpp
+++ b/project2/regexRows.cpp
@@ -7,7 +7,8 @@
DECLARE_LOADER("regexrows", RegexRows);
RegexRows::RegexRows(const xmlpp::Element * p) :
- DefinedColumns(p),
+ DefinedColumns(p, "columns/column", boost::bind(&Column::make, _1, _2)),
+ RowSet(p),
sourceText(p, "sourceText"),
regex(p, "regex")
{
@@ -23,28 +24,19 @@ RegexRows::loadComplete(const CommonObjects*)
}
void
-RegexRows::setFilter(const Glib::ustring&)
+RegexRows::execute(const Glib::ustring&, const RowProcessor * rp) const
{
-}
-
-void
-RegexRows::execute(const RowProcessor * rp) const
-{
- rowNum = 1;
Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(regex(), Glib::REGEX_CASELESS | Glib::REGEX_DOTALL);
Glib::MatchInfo matches;
if (reg->match(sourceText(), matches)) {
+ ColumnValues cv(this);
do {
- unsigned int cols = std::min<unsigned int>(matches.get_match_count(), DefinedColumns::columnCount() + 1);
+ unsigned int cols = std::min<unsigned int>(matches.get_match_count(), cv.rowSet->columns.size() + 1);
unsigned int n;
for (n = 1; n < cols; n += 1) {
- *DefinedColumns::columns.get<byColIdx>().find(n - 1) = matches.fetch(n);
- }
- for (; n < DefinedColumns::columnCount() + 1; n += 1) {
- *DefinedColumns::columns.get<byColIdx>().find(n - 1) = Null();
+ cv.fields[n - 1] = matches.fetch(n);
}
- rp->rowReady();
- rowNum += 1;
+ cv.process(rp);
} while (matches.next());
}
}
diff --git a/project2/regexRows.h b/project2/regexRows.h
index b4b6446..cef2e71 100644
--- a/project2/regexRows.h
+++ b/project2/regexRows.h
@@ -5,13 +5,12 @@
#include "variables.h"
/// Base class for Project2 components that create a row set based on the contents of a byte stream
-class RegexRows : public DefinedColumns {
+class RegexRows : public DefinedColumns, public RowSet {
public:
RegexRows(const xmlpp::Element * p);
~RegexRows();
void loadComplete(const CommonObjects*);
- void setFilter(const Glib::ustring&);
- void execute(const RowProcessor*) const;
+ void execute(const Glib::ustring&, const RowProcessor*) const;
private:
const Variable sourceText;
diff --git a/project2/rowProcessor.h b/project2/rowProcessor.h
index 0f421f9..38142e5 100644
--- a/project2/rowProcessor.h
+++ b/project2/rowProcessor.h
@@ -10,7 +10,6 @@
class RowProcessor : public IHaveParameters {
public:
RowProcessor(const xmlpp::Element *);
- virtual void rowReady() const = 0;
void loadComplete(const CommonObjects *);
const std::string recordSource;
@@ -18,6 +17,9 @@ class RowProcessor : public IHaveParameters {
protected:
boost::intrusive_ptr<RowSet> source;
+ private:
+ friend class RowState;
+ virtual void rowReady(const RowState *) const = 0;
};
#endif
diff --git a/project2/rowSet.cpp b/project2/rowSet.cpp
index cfbb9cf..acc9246 100644
--- a/project2/rowSet.cpp
+++ b/project2/rowSet.cpp
@@ -1,15 +1,16 @@
#include "rowSet.h"
#include "commonObjects.h"
+#include "scopeObject.h"
#include "logger.h"
#include "variables.h"
+#include "rowProcessor.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
-RowSet::RowValuesStack RowSet::stack;
+RowState::RowValuesStack RowState::stack;
RowSet::RowSet(const xmlpp::Element * p) :
- SourceObject(p),
- rowNum(-1)
+ SourceObject(p)
{
}
@@ -17,34 +18,76 @@ RowSet::~RowSet()
{
}
+RowState::RowState() :
+ rowNum(0)
+{
+}
+
+RowState::~RowState()
+{
+}
+
void
-RowSet::beginRow(const RowSet * r)
+RowState::process(const RowProcessor * rp, bool r)
{
- stack.push_back(r);
+ rowNum += 1;
+ stack.push_back(this);
+ ScopeObject s(boost::bind(&RowState::RowValuesStack::pop_back, &stack));
+ rp->rowReady(this);
+ if (r) {
+ reset();
+ }
}
void
-RowSet::endRow(const RowSet * r)
+RowState::reset()
{
- if (stack.back() != r) {
- Logger()->messagef(LOG_CRIT, "%s: stack is corrupted", __PRETTY_FUNCTION__);
- std::abort();
+ BOOST_FOREACH(FieldValues::value_type & v, fields) {
+ v = Null();
}
- stack.pop_back();
+}
+
+void
+RowState::blankRow()
+{
+ rowNum += 1;
}
VariableType
-RowSet::getRowNum() const
+RowState::getRowNum() const
{
return rowNum;
}
-RowSet::RowAttribute
-RowSet::resolveAttr(const Glib::ustring & attrName) const
+RowState::RowAttribute
+RowState::resolveAttr(const Glib::ustring & attrName) const
{
if (attrName == "rownum") {
- return boost::bind(&RowSet::getRowNum, this);
+ return boost::bind(&RowState::getRowNum, this);
}
throw AttributeDoesNotExist(attrName);
}
+VariableType
+RowState::getCurrentValue(const Glib::ustring & col) const
+{
+ const Columns & columns = getColumns();
+ Columns::index<byColName>::type::iterator di = columns.get<byColName>().find(col);
+ if (di != columns.get<byColName>().end()) {
+ if (!boost::get<Null>(&fields[(*di)->idx])) {
+ return fields[(*di)->idx];
+ }
+ return (*di)->defValue;
+ }
+ throw RowSet::FieldDoesNotExist(col);
+}
+
+void
+RowState::foreachColumn(const ColumnAction & action) const
+{
+ const Columns & columns = getColumns();
+ BOOST_FOREACH(const Columns::value_type & col, columns.get<byColName>()) {
+ action(col->idx, col->name, (!boost::get<Null>(&fields[col->idx])) ? fields[col->idx] : col->defValue());
+ }
+}
+
diff --git a/project2/rowSet.h b/project2/rowSet.h
index a907cd2..a9919f9 100644
--- a/project2/rowSet.h
+++ b/project2/rowSet.h
@@ -5,6 +5,7 @@
#include <set>
#include "sourceObject.h"
#include "exceptions.h"
+#include "columns.h"
#include <boost/function.hpp>
class RowProcessor;
@@ -13,37 +14,48 @@ class VariableType;
typedef boost::intrusive_ptr<RowSet> RowSetPtr;
typedef boost::intrusive_ptr<const RowSet> ConstRowSetPtr;
+class RowState;
+
/// Base class for Project2 components that provide a row set representation of data
class RowSet : public SourceObject {
public:
- typedef boost::function0<VariableType> RowAttribute;
SimpleNumericException(ParentOutOfRange);
- SimpleMessageException(AttributeDoesNotExist);
SimpleMessageException(FieldDoesNotExist);
SimpleNumericException(FieldOutOfRange);
- typedef std::vector<const RowSet *> RowValuesStack;
+
RowSet(const xmlpp::Element *);
virtual ~RowSet() = 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 VariableType getCurrentValue(const Glib::ustring & id) const = 0;
- virtual VariableType getCurrentValue(unsigned int col) const = 0;
- virtual bool isNull(unsigned int col) const = 0;
- virtual bool isNull(const Glib::ustring & id) const = 0;
+ virtual void execute(const Glib::ustring &, const RowProcessor *) const = 0;
+};
+
+class RowState {
+ public:
+ RowState();
+ virtual ~RowState();
+
+ typedef boost::function0<VariableType> RowAttribute;
+ typedef boost::function3<void, unsigned int, const Glib::ustring &, const VariableType &> ColumnAction;
+ SimpleMessageException(AttributeDoesNotExist);
+
VariableType getRowNum() const;
- virtual void execute(const RowProcessor *) const = 0;
+ void process(const RowProcessor *, bool reset = true);
+ void blankRow();
+ void reset();
+ virtual VariableType getCurrentValue(const Glib::ustring & id) const;
virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const;
+ void foreachColumn(const ColumnAction & action) const;
+ virtual const Columns & getColumns() const = 0;
+
+ typedef std::vector<VariableType> FieldValues;
+ FieldValues fields;
- static const RowValuesStack & Stack() { return stack; }
- static void beginRow(const RowSet * r);
- static void endRow(const RowSet * r);
- protected:
- mutable unsigned long int rowNum;
+ typedef std::vector<const RowState *> RowValuesStack;
+ static const RowValuesStack & Stack() { return stack; }
private:
+ unsigned int rowNum;
static RowValuesStack stack;
};
diff --git a/project2/rowView.cpp b/project2/rowView.cpp
index 8e22c4b..2ac5081 100644
--- a/project2/rowView.cpp
+++ b/project2/rowView.cpp
@@ -1,7 +1,9 @@
#include "rowView.h"
#include "presenter.h"
+#include "scopeObject.h"
#include "xmlObjectLoader.h"
#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
#include <libxml++/nodes/textnode.h>
DECLARE_LOADER("view", RowView);
@@ -36,14 +38,11 @@ RowView::loadComplete(const CommonObjects * co)
}
void
-RowView::rowReady() const
+RowView::rowReady(const RowState * rs) const
{
presenter->pushSub(recordName);
if (viewColumns.empty()) {
- unsigned int cols = source->columnCount();
- for (unsigned int c = 0; c < cols; c += 1) {
- presenter->addField(source->getColumnName(c), source->getCurrentValue(c));
- }
+ rs->foreachColumn(boost::bind(&Presenter::addField, presenter, _2, _3));
}
else {
BOOST_FOREACH(const Columns::value_type & col, viewColumns) {
@@ -57,22 +56,10 @@ RowView::rowReady() const
void
RowView::execute(const Presenter * p) const
{
- if (!filter.empty()) {
- source->setFilter(filter);
- }
presenter = p;
presenter->pushSub(rootName);
- RowSet::beginRow(source.get());
- try {
- source->execute(this);
- RowSet::endRow(source.get());
- presenter->popSub();
- }
- catch (...) {
- presenter->popSub();
- RowSet::endRow(source.get());
- throw;
- }
+ ScopeObject pres(boost::bind(&Presenter::popSub, p));
+ source->execute(filter, this);
}
void
diff --git a/project2/rowView.h b/project2/rowView.h
index 3652e37..c065414 100644
--- a/project2/rowView.h
+++ b/project2/rowView.h
@@ -14,7 +14,7 @@ class RowView : public View, public RowProcessor {
void loadComplete(const CommonObjects *);
void execute(const Presenter *) const;
- void rowReady() const;
+ void rowReady(const RowState *) const;
const Glib::ustring rootName;
const Glib::ustring recordName;
diff --git a/project2/safeMapFind.h b/project2/safeMapFind.h
new file mode 100644
index 0000000..b27caf3
--- /dev/null
+++ b/project2/safeMapFind.h
@@ -0,0 +1,27 @@
+#ifndef SAFEMAPFIND_H
+#define SAFEMAPFIND_H
+
+template <class Ex, class Map>
+typename Map::const_iterator
+safeMapFind(const Map & map, const typename Map::key_type & key)
+{
+ typename Map::const_iterator i = map.find(key);
+ if (i == map.end()) {
+ throw Ex(key);
+ }
+ return i;
+}
+
+template <class Map>
+typename Map::mapped_type
+defaultMapFind(const Map & map, const typename Map::key_type & key, const typename Map::mapped_type & def = typename Map::mapped_type())
+{
+ typename Map::const_iterator i = map.find(key);
+ if (i == map.end()) {
+ return def;
+ }
+ return i->second;
+}
+
+#endif
+
diff --git a/project2/scopeObject.cpp b/project2/scopeObject.cpp
new file mode 100644
index 0000000..268fd2c
--- /dev/null
+++ b/project2/scopeObject.cpp
@@ -0,0 +1,23 @@
+#include "scopeObject.h"
+#include "logger.h"
+
+ScopeObject::ScopeObject(const Event & onexitpre, const Event & onsuccess, const Event & onfailure, const Event & onexitpost) :
+ onExitPre(onexitpre),
+ onSuccess(onsuccess),
+ onFailure(onfailure),
+ onExitPost(onexitpost)
+{
+}
+
+ScopeObject::~ScopeObject()
+{
+ if (onExitPre) onExitPre();
+ if (std::uncaught_exception()) {
+ if (onFailure) onFailure();
+ }
+ else {
+ if (onSuccess) onSuccess();
+ }
+ if (onExitPost) onExitPost();
+}
+
diff --git a/project2/scopeObject.h b/project2/scopeObject.h
new file mode 100644
index 0000000..d019e7d
--- /dev/null
+++ b/project2/scopeObject.h
@@ -0,0 +1,20 @@
+#ifndef SCOPE_OBJECT_H
+#define SCOPE_OBJECT_H
+
+#include <boost/function.hpp>
+
+class ScopeObject {
+ public:
+ typedef boost::function0<void> Event;
+ ScopeObject(const Event &, const Event & = Event(), const Event & = Event(), const Event & = Event());
+ ~ScopeObject();
+
+ private:
+ const Event onExitPre;
+ const Event onSuccess;
+ const Event onFailure;
+ const Event onExitPost;
+};
+
+#endif
+
diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp
index fdc6340..2c38bf1 100644
--- a/project2/sqlMergeTask.cpp
+++ b/project2/sqlMergeTask.cpp
@@ -1,4 +1,5 @@
#include "sqlMergeTask.h"
+#include "columns.h"
#include "commonObjects.h"
#include "rdbmsDataSource.h"
#include "exceptions.h"
@@ -9,10 +10,11 @@
#include <stdexcept>
#include <boost/algorithm/string/join.hpp>
#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
#include <libxml++/nodes/textnode.h>
bool SqlMergeTask::defaultUseTempTable = true;
-static void attach(boost::intrusive_ptr<IHaveSubTasks> i, ModifyCommand * insert);
+static void attach(boost::intrusive_ptr<IHaveSubTasks> i, DB::ModifyCommand * insert);
class SqlMergeInsert;
typedef boost::intrusive_ptr<SqlMergeInsert> SqlMergeInsertPtr;
@@ -34,8 +36,8 @@ class SqlMergeInsert : IHaveParameters, public Task {
insert->execute();
}
private:
- friend void attach(SqlMergeInsertPtr i, ModifyCommand * insert);
- ModifyCommand * insert;
+ friend void attach(SqlMergeInsertPtr i, DB::ModifyCommand * insert);
+ DB::ModifyCommand * insert;
};
DECLARE_LOADER("sqlmerge", SqlMergeTask);
@@ -139,7 +141,7 @@ void
SqlMergeTask::createTempTable() const
{
if (useView) {
- ModifyCommand * cv = destdb->newModifyCommand(stringf(
+ DB::ModifyCommand * cv = destdb->newModifyCommand(stringf(
"CREATE VIEW %s AS %s",
dtablet.c_str(),
boost::algorithm::join(sqls, " UNION ").c_str()));
@@ -147,7 +149,7 @@ SqlMergeTask::createTempTable() const
delete cv;
}
else {
- ModifyCommand * ctt = destdb->newModifyCommand(stringf(
+ DB::ModifyCommand * ctt = destdb->newModifyCommand(stringf(
"CREATE TEMPORARY TABLE %s AS SELECT * FROM %s WHERE 0=1",
dtablet.c_str(),
dtable.c_str()));
@@ -155,7 +157,7 @@ SqlMergeTask::createTempTable() const
delete ctt;
BOOST_FOREACH(Columns::value_type c, cols) {
if (!c->maptable.empty()) {
- ModifyCommand * at = destdb->newModifyCommand(stringf(
+ DB::ModifyCommand * at = destdb->newModifyCommand(stringf(
"ALTER TABLE %s ADD COLUMN %s VARCHAR(1000)",
dtablet.c_str(),
c->mapcolumn.c_str()));
@@ -170,7 +172,7 @@ void
SqlMergeTask::dropTempTable() const
{
if (tempTableCreated) {
- ModifyCommand * d;
+ DB::ModifyCommand * d;
if (useView) {
d = destdb->newModifyCommand("DROP VIEW " + dtablet);
}
@@ -190,13 +192,13 @@ SqlMergeTask::createTempKey() const
idx.appendf("ALTER TABLE %s ADD CONSTRAINT pk_%s PRIMARY KEY(%s)",
dtablet.c_str(), dtablet.c_str(),
boost::algorithm::join(keys, ", ").c_str());
- ModifyCommand * at = destdb->newModifyCommand(idx);
+ DB::ModifyCommand * at = destdb->newModifyCommand(idx);
at->execute();
delete at;
/* Indexes */
int n = 0;
BOOST_FOREACH(const Keys::value_type & i, indexes) {
- ModifyCommand * ci = destdb->newModifyCommand(stringf(
+ DB::ModifyCommand * ci = destdb->newModifyCommand(stringf(
"CREATE INDEX idx_%s_%d ON %s(%s)",
dtablet.c_str(), n, dtablet.c_str(), i.c_str()));
ci->execute();
@@ -204,7 +206,7 @@ SqlMergeTask::createTempKey() const
n += 1;
}
}
-ModifyCommand *
+DB::ModifyCommand *
SqlMergeTask::insertCommand() const
{
Buffer ins;
@@ -230,7 +232,7 @@ SqlMergeTask::insertCommand() const
class Populate : public NoOutputExecute {
public:
- Populate(ModifyCommand * c) :
+ Populate(DB::ModifyCommand * c) :
SourceObject(__FUNCTION__),
NoOutputExecute(__FUNCTION__),
cmd(c)
@@ -241,40 +243,21 @@ class Populate : public NoOutputExecute {
}
void execute() const
{
- const RowSet * iter = *++RowSet::Stack().rbegin();
- if (idxs.empty()) {
- idxs.resize(iter->columnCount());
- // Sure this can be improved upon... but hey.
- // Find each columns alphabetical index
- unsigned int cols = iter->columnCount();
- for (unsigned int c = 0; c < cols; c += 1) {
- idxs[c] = 0;
- for (unsigned int d = 0; d < cols; d += 1) {
- if (c != d && iter->getColumnName(d) < iter->getColumnName(c)) {
- idxs[c]++;
- }
- }
- }
- }
- unsigned int cols = iter->columnCount();
- for (unsigned int c = 0; c < cols; c += 1) {
- try {
- boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(cmd, idxs[c]), iter->getCurrentValue(c));
- }
- catch (const RowSet::FieldDoesNotExist &) {
- cmd->bindNull(idxs[c]);
- }
- }
+ unsigned int idx = 0;
+ RowState::Stack().back()->foreachColumn(boost::bind(&Populate::bind, this, boost::ref(idx), _3));
cmd->execute();
}
private:
- mutable std::vector<unsigned int> idxs;
- ModifyCommand * cmd;
+ void bind(unsigned int & idx, const VariableType & value) const
+ {
+ boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(cmd, idx++), value);
+ }
+ DB::ModifyCommand * cmd;
};
typedef boost::intrusive_ptr<Populate> PopulatePtr;
void
-attach(SqlMergeInsertPtr i, ModifyCommand * insert)
+attach(SqlMergeInsertPtr i, DB::ModifyCommand * insert)
{
if (i) {
i->insert = insert;
@@ -282,7 +265,7 @@ attach(SqlMergeInsertPtr i, ModifyCommand * insert)
}
static void
-attach(boost::intrusive_ptr<IHaveSubTasks> i, ModifyCommand * insert)
+attach(boost::intrusive_ptr<IHaveSubTasks> i, DB::ModifyCommand * insert)
{
if (!i) {
return;
@@ -322,13 +305,13 @@ SqlMergeTask::copyToTempTable() const
ins.append((*c)->column);
}
ins.appendf(" FROM (%s) tmp_src", sql.c_str());
- ModifyCommand * cttt = destdb->newModifyCommand(ins);
+ DB::ModifyCommand * cttt = destdb->newModifyCommand(ins);
cttt->execute();
delete cttt;
}
BOOST_FOREACH(Columns::value_type c, cols) {
if (!c->maptable.empty()) {
- ModifyCommand * utt = destdb->newModifyCommand(
+ DB::ModifyCommand * utt = destdb->newModifyCommand(
stringf(
"UPDATE %s d SET %s = (SELECT m.%s FROM %s m WHERE m.%s = d.%s) WHERE %s IS NULL",
dtablet.c_str(),
diff --git a/project2/sqlMergeTask.h b/project2/sqlMergeTask.h
index fc72a93..c9e206c 100644
--- a/project2/sqlMergeTask.h
+++ b/project2/sqlMergeTask.h
@@ -62,8 +62,8 @@ class SqlMergeTask : public Task {
Sources sources;
std::list<std::string> sqls;
protected:
- ModifyCommand * insertCommand() const;
- ModifyCommand * insCmd;
+ DB::ModifyCommand * insertCommand() const;
+ DB::ModifyCommand * insCmd;
public:
const DB::Connection * destdb;
diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp
index 2b8745f..fb2de33 100644
--- a/project2/sqlRows.cpp
+++ b/project2/sqlRows.cpp
@@ -33,15 +33,6 @@ SqlRows::loadComplete(const CommonObjects * co)
db = co->dataSource<RdbmsDataSource>(dataSource());
}
-void
-SqlRows::setFilter(const Glib::ustring & name)
-{
- SqlCommand::FiltersRangeType r = sqlCommand.filters.equal_range(name);
- for (SqlCommand::Filters::const_iterator i = r.first; i != r.second; i++) {
- i->second->active = true;
- }
-}
-
class HandleAsVariableType : public DB::HandleField {
public:
void null() {
@@ -62,58 +53,45 @@ class HandleAsVariableType : public DB::HandleField {
VariableType variable;
};
-VariableType
-SqlRows::getCurrentValue(const Glib::ustring & id) const
-{
- HandleAsVariableType h;
- (*query)[id].apply(h);
- return h.variable;
-}
-
-VariableType
-SqlRows::getCurrentValue(unsigned int col) const
-{
- HandleAsVariableType h;
- (*query)[col].apply(h);
- return h.variable;
-}
-
-bool
-SqlRows::isNull(unsigned int col) const
+SqlRows::SqlState::SqlState(SelectPtr s) :
+ query(s)
{
- return (*query)[col].isNull();
}
-bool
-SqlRows::isNull(const Glib::ustring & col) const
+const Columns &
+SqlRows::SqlState::getColumns() const
{
- return (*query)[col].isNull();
-}
-
-unsigned int
-SqlRows::columnCount() const
-{
- return query->columnCount();
-}
-
-const Glib::ustring &
-SqlRows::getColumnName(unsigned int col) const
-{
- return (*query)[col].name;
+ if (columns.empty()) {
+ for (unsigned int c = 0; c < query->columnCount(); c++) {
+ columns.insert(new Column(c, (*query)[c].name));
+ }
+ }
+ return columns;
}
void
-SqlRows::execute(const RowProcessor * rp) const
+SqlRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const
{
- rowNum = 1;
+ SqlCommand::FiltersRangeType r = sqlCommand.filters.equal_range(filter);
+ for (SqlCommand::Filters::const_iterator i = r.first; i != r.second; i++) {
+ i->second->active = true;
+ }
unsigned int offset = 0;
Glib::ustring sql;
sqlCommand.writeSql(sql);
- query = SelectPtr(db->getReadonly().newSelectCommand(sql));
- sqlCommand.bindParams(rp, query.get(), offset);
- while (query->fetch()) {
- rp->rowReady();
- rowNum += 1;
+ SqlState ss(SelectPtr(db->getReadonly().newSelectCommand(sql)));
+ sqlCommand.bindParams(rp, ss.query.get(), offset);
+ while (ss.query->fetch()) {
+ HandleAsVariableType h;
+ if (ss.fields.empty()) {
+ ss.fields.resize(ss.query->columnCount());
+ }
+ for (unsigned int c = 0; c < ss.query->columnCount(); c++) {
+ const DB::Column & col = (*ss.query)[c];
+ col.apply(h);
+ ss.fields[c] = h.variable;
+ }
+ ss.process(rp);
}
}
diff --git a/project2/sqlRows.h b/project2/sqlRows.h
index 901023b..10f57f1 100644
--- a/project2/sqlRows.h
+++ b/project2/sqlRows.h
@@ -16,15 +16,8 @@ class SqlRows : public RowSet {
SqlRows(const xmlpp::Element * p);
~SqlRows();
- void execute(const RowProcessor *) const;
+ void execute(const Glib::ustring &, 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;
- VariableType getCurrentValue(const Glib::ustring & id) const;
- VariableType getCurrentValue(unsigned int col) const;
- bool isNull(unsigned int col) const;
- bool isNull(const Glib::ustring & id) const;
const Variable dataSource;
@@ -80,7 +73,14 @@ class SqlRows : public RowSet {
};
SqlCommand sqlCommand;
typedef boost::shared_ptr<DB::SelectCommand> SelectPtr;
- mutable SelectPtr query;
+ class SqlState : public RowState {
+ public:
+ SqlState(SelectPtr query);
+ const Columns & getColumns() const;
+ SelectPtr query;
+ mutable Columns columns;
+ friend class SqlRows;
+ };
const RdbmsDataSource * db;
};
diff --git a/project2/streamRows.cpp b/project2/streamRows.cpp
index 825dc60..98d7f03 100644
--- a/project2/streamRows.cpp
+++ b/project2/streamRows.cpp
@@ -2,7 +2,8 @@
#include "rowProcessor.h"
StreamRows::StreamRows(const xmlpp::Element * p) :
- DefinedColumns(p),
+ DefinedColumns(p, "columns/column", boost::bind(&Column::make, _1, _2)),
+ RowSet(p),
fieldSep(p->get_attribute_value("fieldSep")[0]),
quoteChar(p->get_attribute_value("quoteChar")[0]),
keepBlankRows(p->get_attribute_value("keepBlankRows") == "true"),
@@ -10,11 +11,8 @@ StreamRows::StreamRows(const xmlpp::Element * p) :
newline(p->get_attribute_value("newline")),
newlin(newline, 0, newline.length() - 1),
encoding(p->get_attribute_value("encoding")),
- skipheader(atoi(p->get_attribute_value("skipheader").c_str())),
- inQuotes(false),
- prevWasQuote(false)
+ skipheader(atoi(p->get_attribute_value("skipheader").c_str()))
{
- mkCols = columns.empty();
}
StreamRows::~StreamRows()
@@ -22,113 +20,85 @@ StreamRows::~StreamRows()
}
void
-StreamRows::addColumn(Glib::ustring & tok) const
-{
- for (Glib::ustring::iterator i = tok.begin(); i != tok.end(); ) {
- if (!isalnum(*i)) {
- tok.erase(i);
- }
- else {
- i++;
- }
- }
- columns.insert(Column(columns.size(), tok));
-}
-
-void
-StreamRows::begin() const
-{
- curCol = columns.get<byColIdx>().begin();
- tok.clear();
-}
-
-void
-StreamRows::pushChar(gunichar c, const RowProcessor * rp) const
+StreamRows::pushChar(gunichar c, ParseState & ps) const
{
- if ((!inQuotes) && (c == *newline.rbegin()) && (tok.compare(tok.length() - newlin.length(), newlin.length(), newlin) == 0)) {
+ if ((!ps.inQuotes) && (c == *newline.rbegin()) && (ps.tok.compare(ps.tok.length() - newlin.length(), newlin.length(), newlin) == 0)) {
if (skipheader) {
- skipheader -= 1;
+ ps.skipheader -= 1;
}
else {
- tok.erase(tok.length() - newlin.length());
- if (!mkCols) {
- if (!tok.empty()) {
- *curCol++ = VariableType(tok);
- }
- if (keepBlankRows || curCol != columns.get<byColIdx>().begin()) {
- while (curCol != columns.get<byColIdx>().end()) {
- *curCol++ = curCol->defValue;
- }
- rp->rowReady();
- rowNum += 1;
- }
- else if (countBlankRows) {
- rowNum += 1;
- }
+ ps.tok.erase(ps.tok.length() - newlin.length());
+ if (!ps.tok.empty()) {
+ *ps.curCol++ = VariableType(ps.tok);
}
- else {
- if (!tok.empty()) {
- addColumn(tok);
+ if (keepBlankRows || ps.curCol != ps.fields.begin()) {
+ while (ps.curCol != ps.fields.end()) {
+ *ps.curCol++ = Null();
}
- mkCols = false;
+ ps.process(ps.rp);
}
- curCol = columns.get<byColIdx>().begin();
+ else if (countBlankRows) {
+ ps.blankRow();
+ }
+ ps.curCol = ps.fields.begin();
}
- tok.clear();
+ ps.tok.clear();
}
else if (c == quoteChar) {
- if (prevWasQuote) {
- tok += c;
- prevWasQuote = false;
- inQuotes = !inQuotes;
+ if (ps.prevWasQuote) {
+ ps.tok += c;
+ ps.prevWasQuote = false;
+ ps.inQuotes = !ps.inQuotes;
}
else {
- prevWasQuote = inQuotes;
- inQuotes = !inQuotes;
+ ps.prevWasQuote = ps.inQuotes;
+ ps.inQuotes = !ps.inQuotes;
}
}
- else if ((!inQuotes) && (c == fieldSep)) {
- prevWasQuote = false;
+ else if ((!ps.inQuotes) && (c == fieldSep)) {
+ ps.prevWasQuote = false;
if (skipheader == 0) {
- if (mkCols) {
- addColumn(tok);
- }
- else {
- *curCol++ = VariableType(tok);
- }
+ *ps.curCol++ = VariableType(ps.tok);
}
- tok.clear();
+ ps.tok.clear();
}
else {
- prevWasQuote = false;
- tok += c;
+ ps.prevWasQuote = false;
+ ps.tok += c;
}
}
+StreamRows::ParseState::ParseState(const StreamRows * rows, const RowProcessor * proc) :
+ ColumnValues(rows),
+ sr(rows),
+ rp(proc),
+ inQuotes(false),
+ prevWasQuote(false),
+ curCol(fields.begin())
+{
+}
+
+StreamRows::ParseState::~ParseState()
+{
+ sr->end(*this);
+}
+
void
-StreamRows::end(const RowProcessor * rp) const
+StreamRows::end(ParseState & ps) const
{
- if (!tok.empty()) {
+ if (!ps.tok.empty()) {
if (skipheader == 0) {
- if (mkCols) {
- addColumn(tok);
- }
- else {
- *curCol++ = VariableType(tok);
- }
+ *ps.curCol++ = VariableType(ps.tok);
}
}
- if (keepBlankRows || curCol != columns.get<byColIdx>().begin()) {
- while (curCol != columns.get<byColIdx>().end()) {
- *curCol++ = curCol->defValue;
+ if (keepBlankRows || ps.curCol != ps.fields.begin()) {
+ while (ps.curCol != ps.fields.end()) {
+ *ps.curCol++ = Null();
}
- rp->rowReady();
- rowNum += 1;
+ ps.process(ps.rp);
}
else if (countBlankRows) {
- rowNum += 1;
+ ps.blankRow();
}
- curCol = columns.get<byColIdx>().begin();
- tok.clear();
}
diff --git a/project2/streamRows.h b/project2/streamRows.h
index 4dd9064..2d10116 100644
--- a/project2/streamRows.h
+++ b/project2/streamRows.h
@@ -7,18 +7,29 @@
class RowProcessor;
/// Base class for Project2 components that create a row set based on the contents of a byte stream
-class StreamRows : public DefinedColumns {
+class StreamRows : public DefinedColumns, public RowSet {
public:
StreamRows(const xmlpp::Element * p);
~StreamRows();
protected:
- void begin() const;
- void pushChar(gunichar ch, const RowProcessor *) const;
- void end(const RowProcessor *) const;
-
- private:
- void addColumn(Glib::ustring & rawtok) const;
+ class ParseState : public ColumnValues {
+ public:
+ ParseState(const StreamRows *, const RowProcessor *);
+ ~ParseState();
+
+ const StreamRows * sr;
+ const RowProcessor * rp;
+ size_t skipheader;
+ bool inQuotes;
+ bool prevWasQuote;
+ Glib::ustring tok;
+ FieldValues::iterator curCol;
+
+ friend class StreamRows;
+ };
+ void pushChar(gunichar ch, ParseState &) const;
+ void end(ParseState &) const;
public:
const gunichar fieldSep;
@@ -28,13 +39,7 @@ class StreamRows : public DefinedColumns {
const Glib::ustring newline;
const Glib::ustring newlin;
const std::string encoding;
- // Used in callback
- mutable size_t skipheader;
- mutable bool mkCols;
- mutable bool inQuotes;
- mutable bool prevWasQuote;
- mutable Glib::ustring tok;
- mutable Columns::index<byColIdx>::type::iterator curCol;
+ const size_t skipheader;
};
#endif
diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp
index aacedbb..f87f60e 100644
--- a/project2/tablepatch.cpp
+++ b/project2/tablepatch.cpp
@@ -6,6 +6,8 @@
#include <buffer.h>
#include <boost/algorithm/string/join.hpp>
+using namespace DB;
+
TablePatch::TablePatch(const Connection & wdb, const TablePatch::Table & s, const TablePatch::Table & d,
const TablePatch::Columns & c) :
src(s),
diff --git a/project2/tablepatch.h b/project2/tablepatch.h
index 7352635..0174294 100644
--- a/project2/tablepatch.h
+++ b/project2/tablepatch.h
@@ -8,8 +8,6 @@
#include <modifycommand.h>
#include <selectcommand.h>
-using namespace DB;
-
class TablePatch {
public:
typedef std::string Table;
@@ -23,7 +21,7 @@ class TablePatch {
const char * what() const throw();
};
- TablePatch(const Connection & db, const Table & src, const Table & dest, const Columns & cols);
+ TablePatch(const DB::Connection & db, const Table & src, const Table & dest, const Columns & cols);
void addKey(const Column & col);
void patch(const char * where, const char * order);
@@ -37,7 +35,7 @@ class TablePatch {
Table dest;
PrimaryKey pk;
Columns cols;
- const Connection &db;
+ const DB::Connection &db;
};
#endif
diff --git a/project2/urlRows.cpp b/project2/urlRows.cpp
index 5669925..f8f7eed 100644
--- a/project2/urlRows.cpp
+++ b/project2/urlRows.cpp
@@ -24,27 +24,21 @@ UrlRows::loadComplete(const CommonObjects *)
{
}
-void
-UrlRows::setFilter(const Glib::ustring &)
-{
- throw NotSupported(__PRETTY_FUNCTION__);
-}
-
size_t
UrlRows::handleDataHelper(const char * ptr, size_t size, size_t nmemb, void *stream)
{
const callback * cb = static_cast<const callback *>(stream);
- size_t used = cb->urlRows->handleData(cb->rp, ptr, size * nmemb);
+ size_t used = cb->urlRows->handleData(cb->ps, ptr, size * nmemb);
return used;
}
size_t
-UrlRows::handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen) const
+UrlRows::handleData(ParseState & ps, const char * bytes, size_t bytesLen) const
{
size_t used = 0, len = 0;
const gchar * utf8 = convertRequired ? g_convert(bytes, bytesLen, "utf-8", encoding.c_str(), &used, &len, NULL) : bytes;
for (const gchar * iter = utf8; *iter; iter = g_utf8_next_char(iter)) {
- this->pushChar(*iter, rp);
+ this->pushChar(*iter, ps);
}
if (convertRequired) {
// We allocated it.. sooo....
@@ -57,21 +51,19 @@ UrlRows::handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen
}
void
-UrlRows::execute(const RowProcessor * rp) const
+UrlRows::execute(const Glib::ustring &, const RowProcessor * rp) const
{
- rowNum = 1;
- begin();
CurlHandle::Ptr c = newCurl();
callback cb(this, rp);
c->setopt(CURLOPT_WRITEDATA, &cb);
c->setopt(CURLOPT_WRITEFUNCTION, &handleDataHelper);
c->perform();
- end(rp);
}
UrlRows::callback::callback(const UrlRows * u, const RowProcessor * r) :
urlRows(u),
- rp(r)
+ rp(r),
+ ps(u, r)
{
}
diff --git a/project2/urlRows.h b/project2/urlRows.h
index ca1894d..98273bd 100644
--- a/project2/urlRows.h
+++ b/project2/urlRows.h
@@ -15,17 +15,17 @@ class UrlRows : public StreamRows, CurlHelper {
~UrlRows();
virtual void loadComplete(const CommonObjects *);
- void execute(const RowProcessor *) const;
- virtual void setFilter(const Glib::ustring &);
+ void execute(const Glib::ustring &, const RowProcessor *) const;
private:
struct callback {
callback(const UrlRows * urlRows, const RowProcessor * rp);
const UrlRows * urlRows;
const RowProcessor * rp;
+ mutable ParseState ps;
};
static size_t handleDataHelper(const char * ptr, size_t size, size_t nmemb, void * stream);
- size_t handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen) const;
+ size_t handleData(ParseState &, const char * bytes, size_t bytesLen) const;
bool convertRequired;
};
diff --git a/project2/variables-modlookup.cpp b/project2/variables-modlookup.cpp
index 24c4167..6ba489a 100644
--- a/project2/variables-modlookup.cpp
+++ b/project2/variables-modlookup.cpp
@@ -84,24 +84,20 @@ class VariableLookup : public VariableImplDyn, public RowProcessor {
void fillCache() const
{
BOOST_FOREACH(const RowSets::value_type & rs, rowSets) {
- cs = rs;
- rs->execute(this);
+ rs->execute(filter, this);
}
- cs.reset();
Logger()->messagef(LOG_DEBUG, "%s: %s has filled cached with %zu items",
__PRETTY_FUNCTION__, name.c_str(), map.size());
}
- void rowReady() const
+ void rowReady(const RowState * rs) const
{
Key k;
- k.reserve(cs->columnCount() - 1);
BOOST_FOREACH(const Parameters::value_type & p, parameters) {
- k.push_back(cs->getCurrentValue(p.first));
+ k.push_back(rs->getCurrentValue(p.first));
}
- map[k] = cs->getCurrentValue(name);
+ map[k] = rs->getCurrentValue(name);
}
mutable Map map;
- mutable RowSetPtr cs;
typedef ANONSTORAGEOF(RowSet) RowSets;
RowSets rowSets;
const Glib::ustring name;
diff --git a/project2/variables.cpp b/project2/variables.cpp
index 516e187..70f51b8 100644
--- a/project2/variables.cpp
+++ b/project2/variables.cpp
@@ -166,13 +166,10 @@ class VariableParent : public VariableImplDyn {
{
try {
if (!getValue) {
- RowSet::RowValuesStack::const_reverse_iterator r = RowSet::Stack().rbegin();
- for (size_t p = depth; p--; r++) ;
- if (r == RowSet::Stack().rend()) {
+ if (depth > RowState::Stack().size()) {
throw RowSet::ParentOutOfRange(depth);
}
- ;
- bind(*r);
+ bind(RowState::Stack()[RowState::Stack().size() - depth]);
}
return getValue();
}
@@ -190,14 +187,13 @@ class VariableParent : public VariableImplDyn {
}
}
protected:
- void bind(ConstRowSetPtr row) const
+ void bind(const RowState * row) const
{
if (attr) {
getValue = boost::bind(row->resolveAttr(name));
}
else {
- typedef VariableType (RowSet::*gCV)(const Glib::ustring &) const;
- getValue = boost::bind((gCV)&RowSet::getCurrentValue, row, name);
+ getValue = boost::bind(&RowState::getCurrentValue, row, name);
}
}
const size_t depth;
diff --git a/project2/xmlRows.cpp b/project2/xmlRows.cpp
index bd958a5..8982945 100644
--- a/project2/xmlRows.cpp
+++ b/project2/xmlRows.cpp
@@ -25,6 +25,7 @@ XmlRows::XmlRows(const xmlpp::Element * p) :
boost::split(root, recordRoot, boost::is_any_of("/"));
boost::split(trigger, recordTrigger, boost::is_any_of("/"));
+ unsigned int col = 0;
BOOST_FOREACH(const xmlpp::Node * node, p->find("fields/field")) {
const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
if (elem) {
@@ -38,12 +39,10 @@ XmlRows::XmlRows(const xmlpp::Element * p) :
p.push_back(Glib::ustring(It->begin(), It->end()));
}
- fields[p] = elem->get_attribute_value("name");
+ fields[p] = col;
+ fieldNames.insert(new Column(col++, elem->get_attribute_value("name")));
}
}
- BOOST_FOREACH(const Interests::value_type & v, fields) {
- fieldNames.push_back(v.second);
- }
}
XmlRows::~XmlRows()
@@ -55,58 +54,9 @@ XmlRows::loadComplete(const CommonObjects *)
{
}
+static
void
-XmlRows::setFilter(const Glib::ustring &)
-{
- throw NotSupported(__PRETTY_FUNCTION__);
-}
-
-VariableType
-XmlRows::getCurrentValue(const Glib::ustring & id) const
-{
- Values::const_iterator i = values.find(id);
- if (i == values.end()) {
- throw FieldDoesNotExist(id);
- }
- return i->second;
-}
-
-VariableType
-XmlRows::getCurrentValue(unsigned int col) const
-{
- Values::const_iterator i = values.find(fieldNames[col]);
- if (i == values.end()) {
- throw FieldDoesNotExist("");
- }
- return i->second;
-}
-
-bool
-XmlRows::isNull(unsigned int col) const
-{
- return (values.find(fieldNames[col]) == values.end());
-}
-
-bool
-XmlRows::isNull(const Glib::ustring & col) const
-{
- return (values.find(col) == values.end());
-}
-
-unsigned int
-XmlRows::columnCount() const
-{
- return fields.size();
-}
-
-const Glib::ustring &
-XmlRows::getColumnName(unsigned int col) const
-{
- return fieldNames[col];
-}
-
-void
-store(const XmlRows::Path & position, XmlRows::Values & values, const XmlRows::Interests & fields, const xmlChar * val)
+store(const XmlRows::Path & position, RowState::FieldValues & values, const XmlRows::Interests & fields, const xmlChar * val)
{
XmlRows::Interests::const_iterator i = fields.find(position);
if (i != fields.end()) {
@@ -115,14 +65,14 @@ store(const XmlRows::Path & position, XmlRows::Values & values, const XmlRows::I
}
void
-XmlRows::execute(const RowProcessor * rp) const
+XmlRows::execute(const Glib::ustring &, const RowProcessor * rp) const
{
- rowNum = 1;
xmlTextReaderPtr reader = xmlReaderForFile(filename.c_str(), NULL, 0);
if (reader == NULL) {
throw std::runtime_error("Failed to open file");
}
+ XmlState xs(this);
Path position;
bool enableCapture = false;
while (xmlTextReaderRead(reader) == 1) {
@@ -138,16 +88,15 @@ XmlRows::execute(const RowProcessor * rp) const
std::string attr("@");
attr += (const char *)xmlTextReaderConstName(reader);
p.push_back(attr);
- store(p, values, fields, xmlTextReaderConstValue(reader));
+ store(p, xs.fields, fields, xmlTextReaderConstValue(reader));
}
}
if (empty) {
if (position == trigger) {
- rp->rowReady();
- rowNum += 1;
+ xs.process(rp, false);
}
if (position == root) {
- values.clear();
+ xs.reset();
}
position.pop_back();
}
@@ -155,17 +104,16 @@ XmlRows::execute(const RowProcessor * rp) const
break;
case XML_READER_TYPE_TEXT:
if (enableCapture) {
- store(position, values, fields, xmlTextReaderConstValue(reader));
+ store(position, xs.fields, fields, xmlTextReaderConstValue(reader));
}
break;
case XML_READER_TYPE_END_ELEMENT:
if (enableCapture) {
if (position == trigger) {
- rp->rowReady();
- rowNum += 1;
+ xs.process(rp, false);
}
if (position == root) {
- values.clear();
+ xs.reset();
}
}
position.pop_back();
@@ -176,3 +124,13 @@ XmlRows::execute(const RowProcessor * rp) const
xmlCleanupParser();
}
+XmlRows::XmlState::XmlState(const XmlRows * rows) :
+ rs(rows)
+{
+}
+const Columns &
+XmlRows::XmlState::getColumns() const
+{
+ return rs->fieldNames;
+}
+
diff --git a/project2/xmlRows.h b/project2/xmlRows.h
index efbaf5e..3ab889e 100644
--- a/project2/xmlRows.h
+++ b/project2/xmlRows.h
@@ -9,35 +9,32 @@
/// Project2 component to create a row set based on the contents of an XML file
class XmlRows : public RowSet {
public:
- typedef std::map<Glib::ustring, Glib::ustring> Values;
typedef std::vector<std::string> Path;
- typedef std::map<Path, Glib::ustring> Interests;
+ typedef std::map<Path, unsigned int> Interests;
XmlRows(const xmlpp::Element * p);
~XmlRows();
- void execute(const RowProcessor *) const;
+ void execute(const Glib::ustring &, 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;
- VariableType getCurrentValue(const Glib::ustring & id) const;
- VariableType getCurrentValue(unsigned int col) const;
- bool isNull(unsigned int col) const;
- bool isNull(const Glib::ustring & id) const;
const Glib::ustring recordRoot;
const Glib::ustring recordTrigger;
const std::string filename;
private:
- mutable Values values;
+ class XmlState : public RowState {
+ public:
+ XmlState(const XmlRows *);
+ const Columns & getColumns() const;
+ const XmlRows * rs;
+ };
Path root;
Path trigger;
Interests fields;
bool anyInterestingAttributes;
- std::vector<Glib::ustring> fieldNames;
+ Columns fieldNames;
};
#endif
diff --git a/project2/xslRows.cpp b/project2/xslRows.cpp
index 999f196..07d57b6 100644
--- a/project2/xslRows.cpp
+++ b/project2/xslRows.cpp
@@ -1,4 +1,5 @@
#include "xslRows.h"
+#include "safeMapFind.h"
#include "rowProcessor.h"
#include "logger.h"
#include "xml.h"
@@ -46,16 +47,6 @@ XslRows::loadComplete(const CommonObjects *)
{
}
-void
-XslRows::setFilter(const Glib::ustring & f)
-{
- FilterViews::const_iterator i = fvs.find(f);
- if (i == fvs.end()) {
- throw FilterNotFound(f);
- }
- fv = i->second;
-}
-
bool
XslRows::asHtml() const
{
@@ -75,8 +66,10 @@ XslRows::newCurl() const
}
void
-XslRows::execute(const RowProcessor * rp) const
+XslRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const
{
+ FilterViewPtr fv = safeMapFind<FilterNotFound>(fvs, filter)->second;
+
typedef boost::shared_ptr<xmlXPathObject> xmlXPathObjectSPtr;
typedef boost::shared_ptr<xmlXPathContext> xmlXPathContextSPtr;
xmlDocPtr doc = getDocument(url(), encoding());
@@ -91,16 +84,15 @@ XslRows::execute(const RowProcessor * rp) const
if (!xpathObj || !xpathObj->nodesetval) {
throw XpathEvalError(xmlGetLastError()->message);
}
- rowNum = 1;
Logger()->messagef(LOG_INFO, "%d nodes matched %s", xpathObj->nodesetval->nodeNr, (const char *)(fv->root()));
+ XslState xs(fv);
for (int row = 0; row < xpathObj->nodesetval->nodeNr; row += 1) {
xmlNodePtr rowRoot = xpathObj->nodesetval->nodeTab[row];
xpathCtx->node = rowRoot;
- values.clear();
- BOOST_FOREACH(const FilterView::XPaths::value_type & xp, fv->xpaths) {
- VariableType path(xp.second());
+ BOOST_FOREACH(const Columns::value_type & _xp, fv->columns.get<byColIdx>()) {
+ const FilterViewColumn * xp = static_cast<const FilterViewColumn *>(_xp.get());
+ const VariableType & path(xp->path);
if (boost::get<Null>(&path)) {
- values[xp.first] = Null();
continue;
}
xmlXPathObjectSPtr xpathObjI = xmlXPathObjectSPtr(xmlXPathEvalExpression(path, xpathCtx.get()), xmlXPathFreeObject);
@@ -108,10 +100,10 @@ XslRows::execute(const RowProcessor * rp) const
throw XpathEvalError(xmlGetLastError()->message);
}
if (xpathObjI->floatval) {
- values[xp.first] = xpathObjI->floatval;
+ xs.fields[xp->idx] = xpathObjI->floatval;
}
else if (xpathObjI->stringval) {
- values[xp.first] = Glib::ustring((const char *)xpathObjI->stringval);
+ xs.fields[xp->idx] = Glib::ustring((const char *)xpathObjI->stringval);
}
else if (xpathObjI->nodesetval) {
Glib::ustring str;
@@ -127,64 +119,41 @@ XslRows::execute(const RowProcessor * rp) const
}
}
}
- values[xp.first] = str;
- }
- else {
- values[xp.first] = Null();
+ xs.fields[xp->idx] = str;
}
}
- rp->rowReady();
- rowNum += 1;
+ xs.process(rp);
}
}
XslRows::FilterView::FilterView(const xmlpp::Element * p) :
+ DefinedColumns(p, "field", boost::bind(XslRows::FilterViewColumn::make, _1, _2)),
name(p->get_attribute_value("name")),
root(p, "root")
{
- BOOST_FOREACH(const xmlpp::Node * node, p->find("field")) {
- const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
- if (elem) {
- xpaths.insert(XPaths::value_type(elem->get_attribute_value("name"), Variable(elem, "xpath")));
- }
- }
}
-VariableType
-XslRows::getCurrentValue(const Glib::ustring & id) const
+XslRows::FilterViewColumn::FilterViewColumn(unsigned int idx, const xmlpp::Element * p) :
+ Column(idx, p),
+ path(p, "xpath")
{
- return values.find(id)->second;
}
-VariableType
-XslRows::getCurrentValue(unsigned int col) const
-{
- return getCurrentValue(getColumnName(col));
-}
-
-bool
-XslRows::isNull(unsigned int col) const
-{
- return isNull(getColumnName(col));
-}
-
-bool
-XslRows::isNull(const Glib::ustring & col) const
+XslRows::FilterViewColumn *
+XslRows::FilterViewColumn::make(unsigned int idx, const xmlpp::Element * p)
{
- return (values.find(col) == values.end());
+ return new FilterViewColumn(idx, p);
}
-unsigned int
-XslRows::columnCount() const
+XslRows::XslState::XslState(FilterViewCPtr f) :
+ fv(f)
{
- return fv->xpaths.size();
+ fields.resize(f->columns.size());
}
-const Glib::ustring &
-XslRows::getColumnName(unsigned int col) const
+const Columns &
+XslRows::XslState::getColumns() const
{
- FilterView::XPaths::const_iterator i = fv->xpaths.begin();
- while (col--) i++;
- return i->first;
+ return fv->columns;
}
diff --git a/project2/xslRows.h b/project2/xslRows.h
index a30ca02..e33932f 100644
--- a/project2/xslRows.h
+++ b/project2/xslRows.h
@@ -9,6 +9,7 @@
#include "variables.h"
#include "xslRowsCache.h"
#include "curlHelper.h"
+#include "definedColumns.h"
/// Project2 component to create a row set based on the contents of an XML resource and specific XPaths with its hierarchy
class XslRows : public RowSet, XslRowsCache, CurlHelper {
@@ -16,21 +17,20 @@ class XslRows : public RowSet, XslRowsCache, CurlHelper {
XslRows(const xmlpp::Element * p);
~XslRows();
- void execute(const RowProcessor *) const;
+ void execute(const Glib::ustring &, 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;
- VariableType getCurrentValue(const Glib::ustring & id) const;
- VariableType getCurrentValue(unsigned int col) const;
- bool isNull(unsigned int col) const;
- bool isNull(const Glib::ustring & id) const;
const bool html;
const bool warnings;
private:
- class FilterView : public virtual IntrusivePtrBase {
+ class FilterViewColumn : public Column {
+ public:
+ FilterViewColumn(unsigned int, const xmlpp::Element *);
+ static FilterViewColumn * make(unsigned int, const xmlpp::Element *);
+ const Variable path;
+ };
+ class FilterView : public DefinedColumns, public virtual IntrusivePtrBase {
public:
typedef std::map<const Glib::ustring, Variable> XPaths;
@@ -38,21 +38,25 @@ class XslRows : public RowSet, XslRowsCache, CurlHelper {
const Glib::ustring name;
const Variable root;
- XPaths xpaths;
};
typedef boost::intrusive_ptr<FilterView> FilterViewPtr;
+ typedef boost::intrusive_ptr<const FilterView> FilterViewCPtr;
typedef std::map<const Glib::ustring, FilterViewPtr> FilterViews;
FilterViews fvs;
- FilterViewPtr fv;
virtual CurlHandle::Ptr newCurl() const;
virtual bool asHtml() const;
virtual bool withWarnings() const;
typedef std::map<const Glib::ustring, Glib::ustring> Namespaces;
- mutable Namespaces namespaces;
- typedef std::map<const Glib::ustring, VariableType> Values;
- mutable Values values;
+ Namespaces namespaces;
+ class XslState : public RowState {
+ public:
+ XslState(FilterViewCPtr);
+ const Columns & getColumns() const;
+ private:
+ const FilterViewCPtr fv;
+ };
const Variable encoding;
};