summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/fileRows.cpp22
-rw-r--r--project2/fileRows.h1
-rw-r--r--project2/fsRows.cpp12
-rw-r--r--project2/genericVisitor.h8
-rw-r--r--project2/iHaveParameters.cpp2
-rw-r--r--project2/regexCheck.cpp2
-rw-r--r--project2/rowView.cpp3
-rw-r--r--project2/sendmailTask.cpp8
-rw-r--r--project2/sessionSetTask.cpp2
-rw-r--r--project2/sqlMergeTask.cpp2
-rw-r--r--project2/sqlRows.cpp4
-rw-r--r--project2/tablepatch.cpp186
-rw-r--r--project2/variables.cpp209
-rw-r--r--project2/variables.h12
-rw-r--r--project2/xslRows.cpp24
15 files changed, 265 insertions, 232 deletions
diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp
index 28de335..036cf4c 100644
--- a/project2/fileRows.cpp
+++ b/project2/fileRows.cpp
@@ -10,10 +10,11 @@ ElementLoaderImpl<FileRows> filerowsLoader("filerows");
FileRows::FileRows(const xmlpp::Element * p) :
SourceObject(p),
RowSet(p),
- path(p->get_attribute_value("path")),
+ path(p, "path"),
fieldSep(p->get_attribute_value("fieldSep")[0]),
quoteChar(p->get_attribute_value("quoteChar")[0]),
keepBlankRows(p->get_attribute_value("keepBlankRows") == "true"),
+ countBlankRows(p->get_attribute_value("keepBlankRows") == "count"),
newline(p->get_attribute_value("newline")),
encoding(p->get_attribute_value("encoding"))
{
@@ -106,13 +107,18 @@ FileRows::execute(const RowProcessor * rp) const
curCol++;
}
}
- if (!mkCols && (keepBlankRows || !values.empty())) {
- while (values.size() < columns.size()) {
- values.push_back(ValPtr(new Glib::ustring()));
- curCol++;
+ if (!mkCols) {
+ if (keepBlankRows || !values.empty()) {
+ while (values.size() < columns.size()) {
+ values.push_back(ValPtr(new Glib::ustring()));
+ curCol++;
+ }
+ rp->rowReady();
+ rowNum += 1;
+ }
+ else if (countBlankRows) {
+ rowNum +=1;
}
- rp->rowReady();
- rowNum += 1;
}
values.clear();
}
@@ -166,7 +172,7 @@ FileRows::addColumn(const Glib::ustring & rawtok) const
FileStarChannel
FileRows::doOpen() const
{
- FILE * f = LexicalCall<const char *, FILE *>(boost::bind(&popen, _1, "r"), path());
+ FILE * f = LexicalCall<const char *, FILE *>(boost::bind(&fopen, _1, "r"), path());
if (!f) {
throw FileNotReadable();
}
diff --git a/project2/fileRows.h b/project2/fileRows.h
index 0c5e3ce..1edff0b 100644
--- a/project2/fileRows.h
+++ b/project2/fileRows.h
@@ -40,6 +40,7 @@ class FileRows : public RowSet {
gunichar fieldSep;
gunichar quoteChar;
bool keepBlankRows;
+ bool countBlankRows;
std::string newline;
std::string encoding;
typedef std::vector<Glib::ustring> Columns;
diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp
index 49bb57c..486dc90 100644
--- a/project2/fsRows.cpp
+++ b/project2/fsRows.cpp
@@ -135,14 +135,19 @@ FsRows::setFilter(const Glib::ustring &)
{
}
+FsRows::Path
+normalisePath(FsRows::Path & p)
+{
+ return (p / ".").remove_filename();
+}
+
void
FsRows::execute(const RowProcessor * rp) const
{
rowNum = 1;
depth = 0;
- fsRoot = boost::lexical_cast<boost::filesystem::path>(rp->getParameter("root"));
+ fsRoot = LexicalCall<Path, Path>(boost::bind(&normalisePath, _1), rp->getParameter("root"));
// Ensure there is a trailing /
- fsRoot = (fsRoot / ".").remove_filename();
specs.clear();
SpecSpec s;
typedef SpecSpec & (*splitter)(SpecSpec &, const Glib::ustring &, bool (*)(gunichar), boost::algorithm::token_compress_mode_type);
@@ -187,7 +192,8 @@ FsRows::execute(const Path & dir, const RowProcessor * rp) const
}
}
}
- catch (const boost::filesystem::basic_filesystem_error<Path> &) {
+ catch (const boost::filesystem::basic_filesystem_error<Path> & e) {
+ fprintf(stderr, "err %s\n", e.what());
}
depth -= 1;
}
diff --git a/project2/genericVisitor.h b/project2/genericVisitor.h
index 2e66e19..ce45f3f 100644
--- a/project2/genericVisitor.h
+++ b/project2/genericVisitor.h
@@ -71,6 +71,14 @@ namespace LexicalVisitorHelper {
return func(boost::posix_time::to_iso_extended_string(i));
}
};
+ template <typename T, typename S, typename R>
+ class lexical_run<T, boost::shared_ptr<const S>, R> {
+ public:
+ R operator()(const boost::function1<R, T> & func, const boost::shared_ptr<const S> & i) const
+ {
+ return func(boost::lexical_cast<T>(*i));
+ }
+ };
template <typename S, typename R>
class lexical_run<const char *, boost::shared_ptr<const S>, R> {
public:
diff --git a/project2/iHaveParameters.cpp b/project2/iHaveParameters.cpp
index 68d657a..84adee5 100644
--- a/project2/iHaveParameters.cpp
+++ b/project2/iHaveParameters.cpp
@@ -21,7 +21,7 @@ IHaveParameters::~IHaveParameters()
IHaveParameters::Parameter::Parameter(const xmlpp::Element * p) :
name(p->get_attribute_value("name")),
- value(p->get_attribute("value"))
+ value(p, "value")
{
}
diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp
index edd2c38..5921a06 100644
--- a/project2/regexCheck.cpp
+++ b/project2/regexCheck.cpp
@@ -9,7 +9,7 @@ ElementLoaderImpl<RegexCheck> regexCheckLoader("regexcheck");
RegexCheck::RegexCheck(const xmlpp::Element * p) :
SourceObject(p),
ParamChecker(p),
- applyTo(p->get_attribute("apply-to")),
+ applyTo(p, "apply-to"),
regex(xmlChildText(p, "regex").raw())
{
}
diff --git a/project2/rowView.cpp b/project2/rowView.cpp
index 10fece5..2306474 100644
--- a/project2/rowView.cpp
+++ b/project2/rowView.cpp
@@ -14,7 +14,8 @@ RowView::RowView(const xmlpp::Element * p) :
BOOST_FOREACH(xmlpp::Node * node, p->find("columns/column")) {
const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
if (elem) {
- viewColumns.insert(Columns::value_type(elem->get_attribute_value("name"), Variable::makeParent(elem->get_child_text()->get_content(), 0)));
+ viewColumns.insert(Columns::value_type(elem->get_attribute_value("name"),
+ Variable::makeParent(elem->get_child_text()->get_content(), elem->get_attribute_value("source") == "attribute", 0)));
}
}
LoaderBase loader("http://project2.randomdan.homeip.net", true);
diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp
index 60de51c..7987d72 100644
--- a/project2/sendmailTask.cpp
+++ b/project2/sendmailTask.cpp
@@ -23,10 +23,10 @@ typedef boost::shared_ptr<xmlDoc> XmlDocumentPtr;
SendMailTask::SendMailTask(const xmlpp::Element * p) :
SourceObject(p),
Task(p),
- to(p->get_attribute("to")),
- subject(p->get_attribute("subject")),
- from(p->get_attribute("from")),
- server(p->get_attribute("server")),
+ to(p, "to"),
+ subject(p, "subject"),
+ from(p, "from"),
+ server(p, "server"),
present(p->get_attribute_value("present").raw())
{
}
diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp
index df96c66..a4b0e44 100644
--- a/project2/sessionSetTask.cpp
+++ b/project2/sessionSetTask.cpp
@@ -11,7 +11,7 @@ SessionSetTask::SessionSetTask(const xmlpp::Element * p) :
SourceObject(p),
Task(p),
key(p->get_attribute_value("key")),
- value(p->get_attribute("value"))
+ value(p, "value")
{
}
diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp
index b982473..2436f1f 100644
--- a/project2/sqlMergeTask.cpp
+++ b/project2/sqlMergeTask.cpp
@@ -42,7 +42,7 @@ ElementLoaderImpl<SqlMergeInsert> sqlmergeinsertLoader("sqlmergeinsert");
SqlMergeTask::SqlMergeTask(const xmlpp::Element * p) :
SourceObject(p),
Task(p),
- updateWhere(p->get_attribute_value("updatewhere")),
+ updateWhere(p, "updatewhere", false),
patchOrder(p->get_attribute_value("patchorder")),
earlyKeys(p->get_attribute_value("earlykeys") == "yes"),
useView(p->get_attribute_value("useview") == "yes"),
diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp
index d4c6cd8..31948df 100644
--- a/project2/sqlRows.cpp
+++ b/project2/sqlRows.cpp
@@ -45,8 +45,8 @@ SqlRows::setFilter(const Glib::ustring & name)
class HandleAsVariableType : public ODBC::HandleField {
public:
void null() { }
- void string(const std::vector<char> & c) {
- variable = boost::shared_ptr<Glib::ustring>(new Glib::ustring(&c[0], &c[c.size()]));
+ void string(const std::vector<char> & c, size_t l) {
+ variable = boost::shared_ptr<Glib::ustring>(new Glib::ustring(&c[0], &c[l]));
}
void integer(SQLINTEGER i) {
variable = i;
diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp
index 6f9c62f..ddf7e03 100644
--- a/project2/tablepatch.cpp
+++ b/project2/tablepatch.cpp
@@ -37,8 +37,8 @@ TablePatch::patch(const char * where, const char * order)
if (pk.size() == 0) {
throw PatchCheckFailure();
}
- doDeletes((where && *where) ? where : NULL, order);
- doUpdates((where && *where) ? where : NULL, order);
+ doDeletes(where, order);
+ doUpdates(where, order);
doInserts(order);
}
@@ -91,7 +91,7 @@ TablePatch::doDeletes(const char * where, const char * order)
if (where && *where) {
toDelSql.appendf(" AND %s", where);
}
- if (order) {
+ if (order && *order) {
toDelSql.appendf(" ORDER BY %s", order);
}
toDelSql.append(")");
@@ -102,100 +102,100 @@ TablePatch::doDeletes(const char * where, const char * order)
void
TablePatch::doUpdates(const char * where, const char * order)
{
- if (cols.size() == pk.size()) {
- // Can't "change" anything... it's all part of the key
- return;
- }
- // -----------------------------------------------------------------
- // Build SQL for list of updates to perform ------------------------
- // -----------------------------------------------------------------
- Buffer toUpdSel;
- toUpdSel.append("SELECT ");
- foreach (Columns::const_iterator, cols, col) {
- if (pk.find(*col) == pk.end()) {
- toUpdSel.appendf("b.%s, ",
- col->c_str());
- }
+ if (cols.size() == pk.size()) {
+ // Can't "change" anything... it's all part of the key
+ return;
}
- foreach (Columns::const_iterator, cols, col) {
- if (pk.find(*col) != pk.end()) {
- toUpdSel.appendf("b.%s, ",
- col->c_str());
- }
- }
- toUpdSel.appendf("0 FROM %s a, %s b",
- dest.c_str(), src.c_str());
- foreach (PKI, pk, pki) {
- if (pki == pk.begin()) {
- toUpdSel.append(" WHERE ");
- }
- else {
- toUpdSel.append(" AND ");
- }
- toUpdSel.appendf(" a.%s = b.%s",
- pki->c_str(), pki->c_str());
- }
- if (where && *where) {
- toUpdSel.appendf(" AND %s", where);
- }
- toUpdSel.append(" AND (");
- bool first = true;
- foreach (Columns::const_iterator, cols, col) {
- if (pk.find(*col) == pk.end()) {
- if (!first) {
- toUpdSel.append(" OR ");
- }
- first = false;
- toUpdSel.appendf(
- " (((CASE WHEN (a.%s IS NULL AND b.%s IS NULL) THEN 1 ELSE 0 END) \
- + (CASE WHEN(a.%s = b.%s) THEN 1 ELSE 0 END)) = 0)",
- col->c_str(), col->c_str(), col->c_str(), col->c_str());
- }
- }
- toUpdSel.append(")");
- if (order) {
- toUpdSel.appendf(" ORDER BY %s", order);
- }
- // -----------------------------------------------------------------
- // Build SQL to perform updates ------------------------------------
- // -----------------------------------------------------------------
- Buffer updSql;
- updSql.appendf("UPDATE %s SET ",
- dest.c_str());
- first = true;
- foreach (Columns::const_iterator, cols, col) {
- if (pk.find(*col) == pk.end()) {
- if (!first) {
- updSql.append(", ");
- }
- first = false;
- updSql.appendf(" %s = ?",
- col->c_str());
- }
- }
- foreach (PKI, pk, pki) {
- if (pki == pk.begin()) {
- updSql.append(" WHERE ");
- }
- else {
- updSql.append(" AND ");
- }
- updSql.appendf(" %s = ?",
- pki->c_str());
- }
- // -----------------------------------------------------------------
- // Iterator over update list make changes --------------------------
- // -----------------------------------------------------------------
- SelectCommand toUpd(db, toUpdSel);
- ModifyCommand upd(db, updSql);
- int cs = cols.size();
+ // -----------------------------------------------------------------
+ // Build SQL for list of updates to perform ------------------------
+ // -----------------------------------------------------------------
+ Buffer toUpdSel;
+ toUpdSel.append("SELECT ");
+ foreach (Columns::const_iterator, cols, col) {
+ if (pk.find(*col) == pk.end()) {
+ toUpdSel.appendf("b.%s, ",
+ col->c_str());
+ }
+ }
+ foreach (Columns::const_iterator, cols, col) {
+ if (pk.find(*col) != pk.end()) {
+ toUpdSel.appendf("b.%s, ",
+ col->c_str());
+ }
+ }
+ toUpdSel.appendf("0 FROM %s a, %s b",
+ dest.c_str(), src.c_str());
+ foreach (PKI, pk, pki) {
+ if (pki == pk.begin()) {
+ toUpdSel.append(" WHERE ");
+ }
+ else {
+ toUpdSel.append(" AND ");
+ }
+ toUpdSel.appendf(" a.%s = b.%s",
+ pki->c_str(), pki->c_str());
+ }
+ if (where && *where) {
+ toUpdSel.appendf(" AND %s", where);
+ }
+ toUpdSel.append(" AND (");
+ bool first = true;
+ foreach (Columns::const_iterator, cols, col) {
+ if (pk.find(*col) == pk.end()) {
+ if (!first) {
+ toUpdSel.append(" OR ");
+ }
+ first = false;
+ toUpdSel.appendf(
+ " (((CASE WHEN (a.%s IS NULL AND b.%s IS NULL) THEN 1 ELSE 0 END) \
+ + (CASE WHEN(a.%s = b.%s) THEN 1 ELSE 0 END)) = 0)",
+ col->c_str(), col->c_str(), col->c_str(), col->c_str());
+ }
+ }
+ toUpdSel.append(")");
+ if (order && *order) {
+ toUpdSel.appendf(" ORDER BY %s", order);
+ }
+ // -----------------------------------------------------------------
+ // Build SQL to perform updates ------------------------------------
+ // -----------------------------------------------------------------
+ Buffer updSql;
+ updSql.appendf("UPDATE %s SET ",
+ dest.c_str());
+ first = true;
+ foreach (Columns::const_iterator, cols, col) {
+ if (pk.find(*col) == pk.end()) {
+ if (!first) {
+ updSql.append(", ");
+ }
+ first = false;
+ updSql.appendf(" %s = ?",
+ col->c_str());
+ }
+ }
+ foreach (PKI, pk, pki) {
+ if (pki == pk.begin()) {
+ updSql.append(" WHERE ");
+ }
+ else {
+ updSql.append(" AND ");
+ }
+ updSql.appendf(" %s = ?",
+ pki->c_str());
+ }
+ // -----------------------------------------------------------------
+ // Iterator over update list make changes --------------------------
+ // -----------------------------------------------------------------
+ SelectCommand toUpd(db, toUpdSel);
+ ModifyCommand upd(db, updSql);
+ int cs = cols.size();
toUpd.execute();
for (int c = 0; c < cs; c += 1) {
toUpd[c].rebind(&upd, c);
}
- while (toUpd.fetch()) {
- upd.execute(false);
- }
+ while (toUpd.fetch()) {
+ upd.execute(false);
+ }
}
void
@@ -247,7 +247,7 @@ TablePatch::doInserts(const char * order)
toInsSql.appendf(" a.%s IS NULL",
pki->c_str());
}
- if (order) {
+ if (order && *order) {
toInsSql.appendf(" ORDER BY %s", order);
}
ModifyCommand(db, toInsSql).execute();
diff --git a/project2/variables.cpp b/project2/variables.cpp
index c8b2571..130d210 100644
--- a/project2/variables.cpp
+++ b/project2/variables.cpp
@@ -13,9 +13,35 @@
#include <boost/function.hpp>
#include <boost/bind.hpp>
+class UnknownVariableType : public std::exception { };
+class UnknownVariableSource : public std::exception { };
+class NoVariableDefinition : public std::exception { };
+
+static
+VariableType
+makeVariableType(const Glib::ustring & src, const std::string & type, const std::string & format = std::string())
+{
+ if (type == "stringptr" || type.empty()) return boost::shared_ptr<Glib::ustring>(new Glib::ustring(src));
+ if (type == "string") return src;
+ if (type == "int") return boost::lexical_cast<int>(src);
+ if (type == "uint") return boost::lexical_cast<unsigned int>(src);
+ if (type == "lint") return boost::lexical_cast<long int>(src);
+ if (type == "luint") return boost::lexical_cast<long unsigned int>(src);
+ if (type == "llint") return boost::lexical_cast<long long int>(src);
+ if (type == "lluint") return boost::lexical_cast<long long unsigned int>(src);
+ if (type == "float") return boost::lexical_cast<float>(src);
+ if (type == "double") return boost::lexical_cast<double>(src);
+ if (type == "datetime") return boost::posix_time::time_from_string(src);
+ if (type == "datetimeptr") return boost::shared_ptr<boost::posix_time::ptime>(new boost::posix_time::ptime(boost::posix_time::time_from_string(src)));
+ throw UnknownVariableType();
+}
+
class VariableLiteral : public VariableImpl {
public:
- VariableLiteral(const Glib::ustring & src) : VariableImpl(src), val(src) { }
+ VariableLiteral(const Glib::ustring & src, const std::string & type = std::string()) :
+ val(makeVariableType(src, type))
+ {
+ }
virtual const VariableType & value() const { return val; }
private:
@@ -24,17 +50,31 @@ class VariableLiteral : public VariableImpl {
class VariableImplDyn : public VariableImpl {
public:
- VariableImplDyn(const Glib::ustring & src) : VariableImpl(src), cacheValid(false) { }
+ VariableImplDyn(const xmlpp::Element * e) :
+ cacheValid(false)
+ {
+ try {
+ defaultValue = Variable(e, "default");
+ }
+ catch (NoVariableDefinition) {
+ // That's cool... no default
+ }
+ }
virtual const VariableType & value() const = 0;
protected:
mutable VariableType cache;
mutable bool cacheValid;
+ boost::optional<Variable> defaultValue;
};
class VariableSession : public VariableImplDyn {
public:
- VariableSession(const Glib::ustring & src) : VariableImplDyn(src) { }
+ VariableSession(const xmlpp::Element * e) :
+ VariableImplDyn(e),
+ name(e->get_attribute_value("name"))
+ {
+ }
const VariableType & value() const
{
try {
@@ -44,15 +84,21 @@ class VariableSession : public VariableImplDyn {
if (!defaultValue) {
throw;
}
- cache = *defaultValue;
+ cache = (*defaultValue)();
}
return cache;
}
+ private:
+ const Glib::ustring name;
};
class VariableParam : public VariableImplDyn {
public:
- VariableParam(const Glib::ustring & src) : VariableImplDyn(src) { }
+ VariableParam(const xmlpp::Element * e) :
+ VariableImplDyn(e),
+ name(e->get_attribute_value("name"))
+ {
+ }
const VariableType & value() const
{
if (!cacheValid) {
@@ -63,33 +109,41 @@ class VariableParam : public VariableImplDyn {
if (!defaultValue) {
throw;
}
- cache = *defaultValue;
+ cache = (*defaultValue)();
}
cacheValid = true;
}
return cache;
}
+ private:
+ const Glib::ustring name;
};
class VariableUri : public VariableImplDyn {
public:
- VariableUri(const Glib::ustring & src) : VariableImplDyn(src) { }
+ VariableUri(const xmlpp::Element * e) :
+ VariableImplDyn(e),
+ index(atoi(e->get_attribute_value("index").c_str()))
+ {
+ }
const VariableType & value() const
{
if (!cacheValid) {
try {
- cache = ApplicationEngine::getCurrent()->env()->getParamUri(atoi(name.c_str()));
+ cache = ApplicationEngine::getCurrent()->env()->getParamUri(index);
}
catch (UriElementOutOfRange) {
if (!defaultValue) {
throw;
}
- cache = *defaultValue;
+ cache = (*defaultValue)();
}
cacheValid = true;
}
return cache;
}
+ private:
+ unsigned int index;
};
static void assignHelper(VariableType & dest, const VariableType & src) {
@@ -98,19 +152,21 @@ static void assignHelper(VariableType & dest, const VariableType & src) {
class VariableParent : public VariableImplDyn, public RowUser {
public:
- VariableParent(const Glib::ustring & src, const RowUser * d) :
- VariableImplDyn(src),
+ VariableParent(const xmlpp::Element * e, const RowUser * d) :
+ VariableImplDyn(e),
row(NULL),
- depth(src.find_first_not_of('^')),
- attr(src[depth] == '!'),
+ depth(atoi(e->get_attribute_value("depth").c_str())),
+ attr(e->get_attribute("attribute")),
+ name(attr ? e->get_attribute_value("attribute") : e->get_attribute_value("name")),
dep(d)
{
}
- VariableParent(const Glib::ustring & name, unsigned int d) :
- VariableImplDyn(name),
+ VariableParent(const Glib::ustring & n, bool a, unsigned int d) :
+ VariableImplDyn(NULL),
row(NULL),
depth(d),
- attr(name[0] == '!'),
+ attr(a),
+ name(n),
dep(NULL)
{
}
@@ -146,13 +202,13 @@ class VariableParent : public VariableImplDyn, public RowUser {
if (!defaultValue) {
throw;
}
- cache = *defaultValue;
+ cache = (*defaultValue)();
}
catch (RowSet::FieldDoesNotExist) {
if (!defaultValue) {
throw;
}
- cache = *defaultValue;
+ cache = (*defaultValue)();
}
cacheValid = true;
}
@@ -177,57 +233,57 @@ class VariableParent : public VariableImplDyn, public RowUser {
mutable ConstRowSetPtr row;
const size_t depth;
const bool attr;
+ const Glib::ustring name;
const RowUser * dep;
mutable boost::function2<void, VariableType &, ConstRowSetPtr> getValue;
};
-class VariableParse : public VariableImplDyn, public RowUser {
+class VariableFixed : public VariableImpl {
public:
- VariableParse(const Glib::ustring & src) :
- VariableImplDyn(src)
+ VariableFixed(VariableType v) :
+ var(v)
{
- boost::tokenizer<boost::char_separator<char> > tokens(source.raw(), boost::char_separator<char>(" "));
- BOOST_FOREACH(std::string t, tokens) {
- vars.push_back(Variable::create(t, this));
- }
}
const VariableType & value() const
{
- if (!cacheValid) {
- Glib::ustring newCache;
- BOOST_FOREACH(Variable::VariableImplPtr v, vars) {
- if (newCache.length()) {
- newCache.append(" ");
- }
- typedef Glib::ustring & (Glib::ustring::*appender)(const Glib::ustring &);
- LexicalCall<Glib::ustring, Glib::ustring &>(boost::bind((appender)&Glib::ustring::append, newCache, _1), v->value());
- }
- cache = newCache;
- cacheValid = true;
- }
- return cache;
- }
- void rowChanged() const
- {
- cacheValid = false;
+ return var;
}
private:
- std::list<Variable::VariableImplPtr> vars;
+ VariableType var;
};
-Variable::Variable(const Glib::ustring & s) :
- var(create(s))
-{
-}
-
-Variable::Variable(const xmlpp::Attribute * a) :
- var(create(a->get_value()))
-{
-}
-
-Variable::Variable(const xmlpp::Element * e) :
- var(create(e->get_child_text()->get_content()))
+Variable::Variable(const xmlpp::Element * e, const Glib::ustring & n, bool required, VariableType def)
{
+ xmlpp::Attribute * a = e->get_attribute(n);
+ if (a) {
+ var = new VariableLiteral(a->get_value());
+ return;
+ }
+ xmlpp::Element::NodeList cs = e->get_children(n);
+ if (cs.size() == 1) {
+ const xmlpp::Element * c = dynamic_cast<const xmlpp::Element *>(cs.front());
+ if (c) {
+ Glib::ustring source = c->get_attribute_value("source");
+ if (source == "session")
+ var = new VariableSession(c);
+ else if (source == "parent")
+ var = new VariableParent(c, NULL);
+ else if (source == "uri")
+ var = new VariableUri(c);
+ else if (source == "param")
+ var = new VariableParam(c);
+ else if (source == "literal" || source.empty())
+ var = new VariableLiteral(c->get_attribute_value("value"), c->get_attribute_value("type"));
+ else
+ throw UnknownVariableSource();
+ return;
+ }
+ }
+ if (!required) {
+ var = new VariableFixed(def);
+ return;
+ }
+ throw NoVariableDefinition();
}
Variable::Variable(VariableImpl * v) :
@@ -235,50 +291,13 @@ Variable::Variable(VariableImpl * v) :
{
}
-Variable::VariableImplPtr
-Variable::create(const Glib::ustring & s, RowUser * dep)
+VariableImpl::~VariableImpl()
{
- if (s.empty()) {
- return VariableImplPtr(new VariableLiteral(s));
- }
- switch (s[0]) {
- case '$': // param
- return VariableImplPtr(new VariableParam(s));
- case '%': // session
- return VariableImplPtr(new VariableSession(s));
- case '^': // parent
- return VariableImplPtr(new VariableParent(s, dep));
- case '/': // uri
- return VariableImplPtr(new VariableUri(s));
- case '*': // parser
- return VariableImplPtr(new VariableParse(s.substr(1)));
- case '=': // literal (explicit)
- return VariableImplPtr(new VariableLiteral(s.substr(1)));
- default:
- return VariableImplPtr(new VariableLiteral(s));
- }
}
Variable
-Variable::makeParent(const Glib::ustring & n, unsigned int d)
-{
- return Variable(new VariableParent(n, d));
-}
-
-VariableImpl::VariableImpl(const Glib::ustring & src) :
- source(src)
-{
- Glib::ustring::const_iterator nameStart = std::find_if(source.begin(), source.end(), Glib::Unicode::isalnum);
- Glib::ustring::const_iterator nameEnd = std::find(nameStart, source.end(), '|');
- name = Glib::ustring(nameStart, nameEnd);
- Glib::ustring::const_iterator defaultStart = nameEnd;
- if (defaultStart != source.end()) {
- defaultStart++;
- defaultValue = Glib::ustring(defaultStart, source.end());
- }
-}
-
-VariableImpl::~VariableImpl()
+Variable::makeParent(const Glib::ustring & name, bool attr, unsigned int dep)
{
+ return Variable(new VariableParent(name, attr, dep));
}
diff --git a/project2/variables.h b/project2/variables.h
index 0b27419..2cccd5e 100644
--- a/project2/variables.h
+++ b/project2/variables.h
@@ -38,23 +38,17 @@ class VariableImpl : public virtual IntrusivePtrBase {
virtual const VariableType & value() const = 0;
protected:
- VariableImpl(const Glib::ustring & src);
virtual ~VariableImpl() = 0;
-
- const Glib::ustring source;
- Glib::ustring name;
- boost::optional<VariableType> defaultValue;
};
class Variable {
public:
typedef boost::intrusive_ptr<VariableImpl> VariableImplPtr;
- Variable(const xmlpp::Attribute *);
- Variable(const xmlpp::Element *);
- Variable(const Glib::ustring & s);
+ Variable(const xmlpp::Element *, const Glib::ustring & n, bool required = true, VariableType def = VariableType());
- static Variable makeParent(const Glib::ustring & name, unsigned int depth);
+ static Variable makeFromCode(const Glib::ustring & s);
+ static Variable makeParent(const Glib::ustring & name, bool attr, unsigned int depth);
operator const VariableType & () const { return var->value(); }
const VariableType & operator()() const { return var->value(); }
diff --git a/project2/xslRows.cpp b/project2/xslRows.cpp
index aa53540..0b981aa 100644
--- a/project2/xslRows.cpp
+++ b/project2/xslRows.cpp
@@ -20,7 +20,7 @@ class ResourceDownloadError : public std::exception { };
XslRows::XslRows(const xmlpp::Element * p) :
SourceObject(p),
RowSet(p),
- url(p->get_attribute_value("url")),
+ url(p, "url"),
html(p->get_attribute_value("html") == "true"),
warnings(p->get_attribute_value("warnings") != "false")
{
@@ -102,17 +102,19 @@ XslRows::getDocument(const Glib::ustring & url) const
void
XslRows::execute(const RowProcessor * rp) const
{
+ typedef boost::shared_ptr<xmlXPathObject> xmlXPathObjectSPtr;
+ typedef boost::shared_ptr<xmlXPathContext> xmlXPathContextSPtr;
xmlDocPtr doc = LexicalCall<Glib::ustring, xmlDocPtr>(boost::bind(&XslRows::getDocument, this, _1), url());
- xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
+ xmlXPathContextSPtr xpathCtx = xmlXPathContextSPtr(xmlXPathNewContext(doc), xmlXPathFreeContext);
if (!xpathCtx) {
throw XpathInitError();
}
BOOST_FOREACH(const Namespaces::value_type & ns, namespaces) {
- xmlXPathRegisterNs(xpathCtx, BAD_CAST ns.first.c_str(), BAD_CAST ns.second.c_str());
+ xmlXPathRegisterNs(xpathCtx.get(), BAD_CAST ns.first.c_str(), BAD_CAST ns.second.c_str());
}
- xmlXPathObjectPtr xpathObj = LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), fv->root());
+ xmlXPathObjectSPtr xpathObj = xmlXPathObjectSPtr(
+ LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx.get()), fv->root()), xmlXPathFreeObject);
if (!xpathObj || !xpathObj->nodesetval) {
- xmlXPathFreeContext(xpathCtx);
throw XpathEvalError();
}
rowNum = 1;
@@ -121,10 +123,9 @@ XslRows::execute(const RowProcessor * rp) const
xpathCtx->node = rowRoot;
values.clear();
BOOST_FOREACH(const FilterView::XPaths::value_type & xp, fv->xpaths) {
- xmlXPathObjectPtr xpathObjI = LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), xp.second());
+ xmlXPathObjectSPtr xpathObjI = xmlXPathObjectSPtr(LexicalCall<const xmlChar *, xmlXPathObjectPtr>(
+ boost::bind(&xmlXPathEvalExpression, _1, xpathCtx.get()), xp.second()), xmlXPathFreeObject);
if (!xpathObjI) {
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
throw XpathEvalError();
}
if (xpathObjI->floatval) {
@@ -139,23 +140,20 @@ XslRows::execute(const RowProcessor * rp) const
values[xp.first] = boost::shared_ptr<const Glib::ustring>(new Glib::ustring((const char *)val));
}
}
- xmlXPathFreeObject(xpathObjI);
}
rp->rowReady();
rowNum += 1;
}
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
}
XslRows::FilterView::FilterView(const xmlpp::Element * p) :
name(p->get_attribute_value("name")),
- root(p->get_attribute_value("root"))
+ 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"), elem->get_attribute_value("xpath")));
+ xpaths.insert(XPaths::value_type(elem->get_attribute_value("name"), Variable(elem, "xpath")));
}
}
}