From d3c6af11a145cee0fb28fa40c749c315e8f8c072 Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 27 Dec 2011 14:52:27 +0000 Subject: Add type safety to XML documents Includes minor fixes around date serialisation and parsing --- project2/cgi/cgiAppEngine.cpp | 4 +++- project2/common/cache.cpp | 9 +++++++- project2/common/functions/dates.cpp | 7 +++--- project2/common/variables.cpp | 18 ++++++++++++++- project2/common/variables.h | 1 + project2/xml/xmlCache.cpp | 2 +- project2/xml/xmlPresenter.cpp | 45 ++++++++++++++++++++++++++++++++----- project2/xml/xmlRawRows.cpp | 3 ++- 8 files changed, 74 insertions(+), 15 deletions(-) diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index f94597c..8d079f9 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -95,7 +95,9 @@ CgiApplicationEngine::process() const std::fstream * ddd = NULL; if (!_env->dumpdatadoc.empty()) { ddd = new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out); - ts->addTarget(new ostreamWrapper(*ddd)); + if (ddd->good()) { + ts->addTarget(new ostreamWrapper(*ddd)); + } } ts->addTarget(new ostreamWrapper(IO)); ts->doTransforms(); diff --git a/project2/common/cache.cpp b/project2/common/cache.cpp index f5edc43..ff9f41f 100644 --- a/project2/common/cache.cpp +++ b/project2/common/cache.cpp @@ -4,6 +4,7 @@ #include "rowProcessor.h" #include "logger.h" #include +#include Cache::Cache(ScriptNodePtr p) : IHaveParameters(p), @@ -21,8 +22,14 @@ bool Cache::checkAndExecute(const Glib::ustring & n, const Glib::ustring & f, co cached->execute(f, rp); return true; } + catch (const Glib::Exception & e) { + Logger()->messagef(LOG_WARNING, "Cache failed (%s)", e.what().c_str()); + } + catch (const std::exception & e) { + Logger()->messagef(LOG_WARNING, "Cache failed (%s)", e.what()); + } catch (...) { - Logger()->messagef(LOG_WARNING, "Cache failed"); + Logger()->message(LOG_WARNING, "Cache failed"); } } return false; diff --git a/project2/common/functions/dates.cpp b/project2/common/functions/dates.cpp index c1992f7..7ace436 100644 --- a/project2/common/functions/dates.cpp +++ b/project2/common/functions/dates.cpp @@ -7,7 +7,7 @@ #include #include -class ParseError { }; +SimpleMessage2Exception(DateParseError); /// Variable implementation to access platform configuration values class ParseDate : public VariableImplDyn { public: @@ -21,15 +21,14 @@ class ParseDate : public VariableImplDyn { { const char * s = string(); const char * f = format(); - boost::posix_time::ptime t; struct tm tm; memset(&tm, 0, sizeof(struct tm)); mktime(&tm); const char * e = strptime(s, f, &tm); - if (!e) { + if (!e || *e) { Logger()->messagef(LOG_ERR, "%s: check failed (parse) for '%s' against '%s' (remaining chars='%s')", __PRETTY_FUNCTION__, s, f, e); - throw ParseError(); + throw DateParseError(string(), format()); } return boost::posix_time::ptime(boost::posix_time::ptime_from_tm(tm)); } diff --git a/project2/common/variables.cpp b/project2/common/variables.cpp index 4dc4538..6b2d7c9 100644 --- a/project2/common/variables.cpp +++ b/project2/common/variables.cpp @@ -1,4 +1,5 @@ #include +#include "logger.h" #include "variables.h" #include "variables-modfixed.h" #include "iHaveParameters.h" @@ -57,6 +58,7 @@ VariableType::getTypeFromName(const std::string & src) { if (src.empty()) return String; if (src == "string") return String; + if (src == "bool") return Bool; if (src == "int") return Int; if (src == "float") return Float; if (src == "datetime") return DateTime; @@ -64,6 +66,7 @@ VariableType::getTypeFromName(const std::string & src) throw UnknownVariableType(src); } +SimpleMessageException(DateParseError); VariableType VariableType::make(const Glib::ustring & src, const VT_typeID format) { @@ -72,12 +75,25 @@ VariableType::make(const Glib::ustring & src, const VT_typeID format) case DefaultType: case String: return src; + case Bool: + return boost::lexical_cast(src); case Int: return boost::lexical_cast(src); case Float: return boost::lexical_cast(src); case DateTime: - return boost::posix_time::time_from_string(src); + { + struct tm tm; + memset(&tm, 0, sizeof(struct tm)); + mktime(&tm); + const char * e = strptime(src.c_str(), "%FT%T", &tm); + if (!e || *e) { + Logger()->messagef(LOG_ERR, "%s: check failed (parse) for '%s' against '%s' (remaining chars='%s')", + __PRETTY_FUNCTION__, src.c_str(), "%FT%T", e); + throw DateParseError(src); + } + return boost::posix_time::ptime_from_tm(tm); + } case Nul: return Null(); } diff --git a/project2/common/variables.h b/project2/common/variables.h index a52e2b1..2c1f15d 100644 --- a/project2/common/variables.h +++ b/project2/common/variables.h @@ -17,6 +17,7 @@ enum VT_typeID { DefaultType, Nul, String, + Bool, Int, Float, DateTime, diff --git a/project2/xml/xmlCache.cpp b/project2/xml/xmlCache.cpp index 5233928..0ec745b 100644 --- a/project2/xml/xmlCache.cpp +++ b/project2/xml/xmlCache.cpp @@ -35,7 +35,7 @@ class XmlCache : public Cache { RowSetPresenterPtr openFor(const Glib::ustring & n, const Glib::ustring &, const IHaveParameters *) { - writeTo = new XmlPresenter(n, Glib::ustring(), Glib::ustring()); + writeTo = new XmlPresenter(n, Environment::getCurrent()->scriptNamespace, Environment::getCurrent()->scriptNamespacePrefix); return writeTo; } diff --git a/project2/xml/xmlPresenter.cpp b/project2/xml/xmlPresenter.cpp index 9d9f0fd..70cb743 100644 --- a/project2/xml/xmlPresenter.cpp +++ b/project2/xml/xmlPresenter.cpp @@ -84,16 +84,49 @@ XmlPresenter::addAttribute(const Glib::ustring & name, const Glib::ustring & ns, } } +class XmlNodeWriter : public boost::static_visitor { + public: + XmlNodeWriter(xmlpp::Element * n) : node(n) { } + bool operator()(const Null &) const { + addType("null"); + return false; + } + bool operator()(const Boolean &) const { + addType("bool"); + return true; + } + bool operator()(const Glib::ustring &) const { + addType("string"); + return true; + } + bool operator()(const int64_t &) const { + addType("int"); + return true; + } + bool operator()(const double &) const { + addType("float"); + return true; + } + bool operator()(const boost::posix_time::ptime & i) const { + addType("datetime"); + node->set_attribute("time", boost::posix_time::to_simple_string(i.time_of_day())); + node->set_attribute("date", boost::gregorian::to_iso_extended_string(i.date())); + return true; + } + + protected: + void addType(const char * type) const { + node->set_attribute("type", type, Environment::getCurrent()->scriptNamespacePrefix); + } + private: + xmlpp::Element * node; +}; + void XmlPresenter::addText(const VariableType & value) const { - if (!value.get()) { + if (boost::apply_visitor(XmlNodeWriter(nodeStack.back()), value)) { nodeStack.back()->add_child_text(value); - // Special cases - if (const boost::posix_time::ptime * dt = value.get()) { - nodeStack.back()->set_attribute("time", boost::posix_time::to_simple_string(dt->time_of_day())); - nodeStack.back()->set_attribute("date", boost::gregorian::to_iso_extended_string(dt->date())); - } } } diff --git a/project2/xml/xmlRawRows.cpp b/project2/xml/xmlRawRows.cpp index faca679..af550bb 100644 --- a/project2/xml/xmlRawRows.cpp +++ b/project2/xml/xmlRawRows.cpp @@ -71,7 +71,8 @@ void XmlRawRowsBase::execute(const xmlpp::Document * doc, const RowProcessor * r if (const xmlpp::Element * ie = dynamic_cast(in)) { const xmlpp::TextNode * t = ie->get_child_text(); if (t) { - rs.fields[col] = t->get_content(); + rs.fields[col] = VariableType::make(t->get_content(), + VariableType::getTypeFromName(ie->get_attribute_value("type", Environment::getCurrent()->scriptNamespacePrefix))); } col++; } -- cgit v1.2.3