aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerländer2014-06-06 22:00:39 +0200
committerAdrian Kummerländer2014-06-06 22:00:39 +0200
commit272b34c1a4639cd0f909bfb52d30339c93b0c42b (patch)
treed3bed13ddf28e86f8de319222daf535305082431
parent78bb3387b15d15d766fb5d17a99612f0480f2bee (diff)
downloadInputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.tar
InputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.tar.gz
InputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.tar.bz2
InputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.tar.lz
InputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.tar.xz
InputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.tar.zst
InputXSLT-272b34c1a4639cd0f909bfb52d30339c93b0c42b.zip
Implemented WarningCapacitor as a counterpart to ErrorCapacitor
* in difference to ErrorCapacitor this class doesn't throw an exception on "discharge" but returns the gathered warnings * adapted FunctionTransform and frontend error handling to include warnings * added static "try_create" method to TransformationFacade ** wraps construction error handling ** custom logic may be embedded using the std::function argument *** this was implemented to prevent unneccessary code duplication for handling both construction and generation errors * adapted FunctionTransform to return warning as "warning" nodes in the result tree ** added functional lambda expression factory method "handleErrors" *** returns a error handling lambda expression for a given ResultNodeFacade * implemented WarningGuard class in frontend executable ** guarantees warnings to be printed to std::cerr independent of any exceptions
-rw-r--r--CMakeLists.txt1
-rw-r--r--ixslt.cc68
-rw-r--r--src/function/transform.cc46
-rw-r--r--src/support/error/error_capacitor.cc18
-rw-r--r--src/support/error/error_capacitor.h8
-rw-r--r--src/support/error/error_multiplexer.cc29
-rw-r--r--src/support/error/error_multiplexer.h36
-rw-r--r--src/support/error/warning_capacitor.cc26
-rw-r--r--src/support/error/warning_capacitor.h31
-rw-r--r--src/transformation_facade.cc26
-rw-r--r--src/transformation_facade.h15
11 files changed, 228 insertions, 76 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ea46ab6..c0b5b97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,7 @@ set(
src/support/include_entity_resolver.cc
src/support/error/error_multiplexer.cc
src/support/error/error_capacitor.cc
+ src/support/error/warning_capacitor.cc
src/support/tuple/xobject_value.cc
src/support/dom/document_cache.cc
src/support/dom/document_cache_item.cc
diff --git a/ixslt.cc b/ixslt.cc
index d65e5aa..86b883e 100644
--- a/ixslt.cc
+++ b/ixslt.cc
@@ -7,7 +7,26 @@
#include "plattform_guard.h"
#include "transformation_facade.h"
-#include "support/error/error_capacitor.h"
+
+class WarningGuard {
+ public:
+ WarningGuard(InputXSLT::TransformationFacade* transformation):
+ transformation_(transformation) { };
+
+ ~WarningGuard() {
+ InputXSLT::WarningCapacitor::warning_cache_ptr warnings(
+ this->transformation_->getCachedWarnings()
+ );
+
+ for ( auto&& warning : *warnings ) {
+ std::cerr << warning << std::endl;
+ }
+ };
+
+ private:
+ InputXSLT::TransformationFacade* const transformation_;
+
+};
boost::optional<boost::program_options::variables_map> input(
int argc,
@@ -57,6 +76,12 @@ boost::optional<boost::program_options::variables_map> input(
return boost::make_optional(variables);
}
+void handleErrors(const InputXSLT::ErrorCapacitor::error_cache& errors) {
+ for ( auto&& error : errors ) {
+ std::cerr << error << std::endl;
+ }
+}
+
bool process(const boost::program_options::variables_map& variables) {
std::vector<std::string> includePath;
@@ -66,29 +91,32 @@ bool process(const boost::program_options::variables_map& variables) {
InputXSLT::PlattformGuard plattform(includePath);
- try {
- InputXSLT::TransformationFacade transformation(
- variables["transformation"].as<std::string>(),
- plattform.getEntityResolver()
- );
-
- if ( variables.count("target") ) {
- transformation.generate(
- variables["target"].as<std::string>()
- );
- } else {
- transformation.generate(std::cout);
+ if ( auto transformation = InputXSLT::TransformationFacade::try_create(
+ variables["transformation"].as<std::string>(),
+ plattform.getEntityResolver(),
+ handleErrors
+ ) ) {
+ WarningGuard guard(transformation.get());
+
+ try {
+ if ( variables.count("target") ) {
+ transformation->generate(
+ variables["target"].as<std::string>()
+ );
+ } else {
+ transformation->generate(std::cout);
+ }
+
+ return true;
}
+ catch (const InputXSLT::ErrorCapacitor::exception& exception) {
+ handleErrors(*exception);
- return true;
- }
- catch (const InputXSLT::ErrorCapacitor::exception& exception) {
- for ( auto&& error : *(exception.getCachedErrors()) ) {
- std::cerr << error << std::endl;
+ return false;
}
-
- return false;
}
+
+ return false;
}
int main(int argc, char** argv) {
diff --git a/src/function/transform.cc b/src/function/transform.cc
index 86bc91c..844dee9 100644
--- a/src/function/transform.cc
+++ b/src/function/transform.cc
@@ -9,6 +9,23 @@
#include "support/dom/result_node_facade.h"
#include "support/error/error_capacitor.h"
+namespace {
+
+using InputXSLT::ErrorCapacitor;
+
+inline std::function<void(const ErrorCapacitor::error_cache&)> handleErrors(
+ InputXSLT::ResultNodeFacade& result) {
+ return [&result](const ErrorCapacitor::error_cache& errors) {
+ result.setAttribute("result", "error");
+
+ for ( auto&& error : errors ) {
+ result.setValueNode("error", error);
+ }
+ };
+}
+
+}
+
namespace InputXSLT {
xercesc::DOMDocument* FunctionTransform::constructDocument(
@@ -42,21 +59,26 @@ xercesc::DOMDocument* FunctionTransform::constructDocument(
ResultNodeFacade result(domDocument, rootNode, "transformation");
result.setAttribute("target", targetPath);
- try {
- InputXSLT::TransformationFacade transformation(
- transformationPath,
- this->include_resolver_
- );
+ if ( auto transformation = TransformationFacade::try_create(
+ transformationPath,
+ this->include_resolver_,
+ handleErrors(result)
+ ) ) {
+ try {
+ transformation->generate(targetPath, parameterObject);
- transformation.generate(targetPath, parameterObject);
+ result.setAttribute("result", "success");
+ }
+ catch (const ErrorCapacitor::exception& exception) {
+ handleErrors(result)(*exception);
+ }
- result.setAttribute("result", "success");
- }
- catch (const ErrorCapacitor::exception& exception) {
- result.setAttribute("result", "error");
+ WarningCapacitor::warning_cache_ptr warnings(
+ transformation->getCachedWarnings()
+ );
- for ( auto&& error : *(exception.getCachedErrors()) ) {
- result.setValueNode("error", error);
+ for ( auto&& warning : *warnings ) {
+ result.setValueNode("warning", warning);
}
}
diff --git a/src/support/error/error_capacitor.cc b/src/support/error/error_capacitor.cc
index 58cfb81..cc7dd01 100644
--- a/src/support/error/error_capacitor.cc
+++ b/src/support/error/error_capacitor.cc
@@ -3,14 +3,8 @@
namespace InputXSLT {
ErrorCapacitor::ErrorCapacitor(ErrorMultiplexer* multiplexer):
- multiplexer_(multiplexer),
- error_cache_(new error_cache()) {
- this->multiplexer_->connectReceiver(this);
-}
-
-ErrorCapacitor::~ErrorCapacitor() {
- this->multiplexer_->disconnectReceiver(this);
-}
+ ErrorMultiplexer::receiver(multiplexer),
+ error_cache_(new error_cache()) { }
void ErrorCapacitor::discharge() {
if ( !this->error_cache_->empty() ) {
@@ -19,10 +13,10 @@ void ErrorCapacitor::discharge() {
}
void ErrorCapacitor::receive(
- const ErrorMultiplexer::ErrorType type,
+ const ErrorMultiplexer::error_type type,
const std::string& message
) {
- if ( type == ErrorMultiplexer::ErrorType::Error ) {
+ if ( type == ErrorMultiplexer::error_type::error ) {
this->error_cache_->emplace_back(message);
}
}
@@ -30,8 +24,8 @@ void ErrorCapacitor::receive(
ErrorCapacitor::exception::exception(error_cache_ptr ptr):
error_cache_(std::move(ptr)) { }
-auto ErrorCapacitor::exception::getCachedErrors() const -> const error_cache* {
- return this->error_cache_.get();
+auto ErrorCapacitor::exception::operator*() const -> const error_cache& {
+ return *(this->error_cache_.get());
}
}
diff --git a/src/support/error/error_capacitor.h b/src/support/error/error_capacitor.h
index 6017cb4..1c225e9 100644
--- a/src/support/error/error_capacitor.h
+++ b/src/support/error/error_capacitor.h
@@ -7,7 +7,7 @@
namespace InputXSLT {
-class ErrorCapacitor : public ErrorMultiplexer::Receiver {
+class ErrorCapacitor : public ErrorMultiplexer::receiver {
public:
class exception;
@@ -15,17 +15,15 @@ class ErrorCapacitor : public ErrorMultiplexer::Receiver {
typedef std::unique_ptr<error_cache> error_cache_ptr;
ErrorCapacitor(ErrorMultiplexer*);
- ~ErrorCapacitor();
void discharge();
virtual void receive(
- const ErrorMultiplexer::ErrorType,
+ const ErrorMultiplexer::error_type,
const std::string&
);
private:
- ErrorMultiplexer* const multiplexer_;
error_cache_ptr error_cache_;
};
@@ -34,7 +32,7 @@ class ErrorCapacitor::exception {
public:
exception(error_cache_ptr);
- const error_cache* getCachedErrors() const;
+ const error_cache& operator*() const;
private:
error_cache_ptr error_cache_;
diff --git a/src/support/error/error_multiplexer.cc b/src/support/error/error_multiplexer.cc
index f5d4e0f..bbf0e71 100644
--- a/src/support/error/error_multiplexer.cc
+++ b/src/support/error/error_multiplexer.cc
@@ -27,15 +27,15 @@ inline std::string getMessage(const xercesc::SAXParseException& exception) {
);
}
-inline ErrorMultiplexer::ErrorType toErrorType(
+inline ErrorMultiplexer::error_type toErrorType(
const xalan::ProblemListenerBase::eClassification classification) {
switch ( classification ) {
case xalan::ProblemListenerBase::eClassification::eMessage ||
xalan::ProblemListenerBase::eClassification::eWarning: {
- return ErrorMultiplexer::ErrorType::Warning;
+ return ErrorMultiplexer::error_type::warning;
}
default: {
- return ErrorMultiplexer::ErrorType::Error;
+ return ErrorMultiplexer::error_type::error;
}
}
}
@@ -56,11 +56,11 @@ ErrorMultiplexer::~ErrorMultiplexer() {
this->transformer_->setProblemListener(nullptr);
}
-void ErrorMultiplexer::connectReceiver(Receiver* receiver) {
+void ErrorMultiplexer::connectReceiver(receiver* receiver) {
this->receivers_.push_back(receiver);
}
-void ErrorMultiplexer::disconnectReceiver(Receiver* receiver) {
+void ErrorMultiplexer::disconnectReceiver(receiver* receiver) {
this->receivers_.erase(
std::remove(
this->receivers_.begin(),
@@ -72,21 +72,21 @@ void ErrorMultiplexer::disconnectReceiver(Receiver* receiver) {
void ErrorMultiplexer::warning(const xercesc::SAXParseException& exception) {
this->multiplex(
- ErrorType::Warning,
+ error_type::warning,
"Warning: " + getMessage(exception)
);
}
void ErrorMultiplexer::error(const xercesc::SAXParseException& exception) {
this->multiplex(
- ErrorType::Error,
+ error_type::error,
"Error: " + getMessage(exception)
);
}
void ErrorMultiplexer::fatalError(const xercesc::SAXParseException& exception) {
this->multiplex(
- ErrorType::Error,
+ error_type::error,
"Fatal error: " + getMessage(exception)
);
}
@@ -155,16 +155,25 @@ void ErrorMultiplexer::problem(
void ErrorMultiplexer::setPrintWriter(xalan::PrintWriter*) { }
void ErrorMultiplexer::multiplex(
- const ErrorType type,
+ const error_type type,
const std::string& message
) {
std::for_each(
this->receivers_.begin(),
this->receivers_.end(),
- [&type, &message](Receiver* const receiver) -> void {
+ [&type, &message](receiver* const receiver) -> void {
receiver->receive(type, message);
}
);
}
+ErrorMultiplexer::receiver::receiver(ErrorMultiplexer* multiplexer):
+ multiplexer_(multiplexer) {
+ this->multiplexer_->connectReceiver(this);
+}
+
+ErrorMultiplexer::receiver::~receiver() {
+ this->multiplexer_->disconnectReceiver(this);
+}
+
}
diff --git a/src/support/error/error_multiplexer.h b/src/support/error/error_multiplexer.h
index 02cfaf8..7d8544a 100644
--- a/src/support/error/error_multiplexer.h
+++ b/src/support/error/error_multiplexer.h
@@ -16,14 +16,14 @@ namespace InputXSLT {
class ErrorMultiplexer : public xercesc::ErrorHandler,
public xalan::ProblemListener {
public:
- enum class ErrorType;
- struct Receiver;
+ enum class error_type;
+ class receiver;
ErrorMultiplexer(xalan::XalanTransformer*);
~ErrorMultiplexer();
- void connectReceiver(Receiver*);
- void disconnectReceiver(Receiver*);
+ void connectReceiver(receiver*);
+ void disconnectReceiver(receiver*);
virtual void warning(const xercesc::SAXParseException&);
virtual void error(const xercesc::SAXParseException&);
@@ -61,22 +61,30 @@ class ErrorMultiplexer : public xercesc::ErrorHandler,
private:
xalan::XalanTransformer* const transformer_;
- std::vector<Receiver*> receivers_;
+ std::vector<receiver*> receivers_;
- void multiplex(const ErrorType, const std::string&);
+ void multiplex(const error_type, const std::string&);
};
-enum class ErrorMultiplexer::ErrorType {
- Warning,
- Error
+enum class ErrorMultiplexer::error_type {
+ warning,
+ error
};
-struct ErrorMultiplexer::Receiver {
- virtual void receive(
- const ErrorMultiplexer::ErrorType,
- const std::string&
- ) = 0;
+class ErrorMultiplexer::receiver {
+ public:
+ receiver(ErrorMultiplexer*);
+ virtual ~receiver();
+
+ virtual void receive(
+ const ErrorMultiplexer::error_type,
+ const std::string&
+ ) = 0;
+
+ private:
+ ErrorMultiplexer* const multiplexer_;
+
};
}
diff --git a/src/support/error/warning_capacitor.cc b/src/support/error/warning_capacitor.cc
new file mode 100644
index 0000000..f8d2b99
--- /dev/null
+++ b/src/support/error/warning_capacitor.cc
@@ -0,0 +1,26 @@
+#include "warning_capacitor.h"
+
+namespace InputXSLT {
+
+WarningCapacitor::WarningCapacitor(ErrorMultiplexer* multiplexer):
+ ErrorMultiplexer::receiver(multiplexer),
+ warning_cache_(new warning_cache()) { }
+
+auto WarningCapacitor::discharge() -> warning_cache_ptr {
+ warning_cache_ptr tmp(std::move(this->warning_cache_));
+
+ this->warning_cache_.reset(new warning_cache());
+
+ return std::move(tmp);
+}
+
+void WarningCapacitor::receive(
+ const ErrorMultiplexer::error_type type,
+ const std::string& message
+) {
+ if ( type == ErrorMultiplexer::error_type::warning ) {
+ this->warning_cache_->emplace_back(message);
+ }
+}
+
+}
diff --git a/src/support/error/warning_capacitor.h b/src/support/error/warning_capacitor.h
new file mode 100644
index 0000000..6b7058b
--- /dev/null
+++ b/src/support/error/warning_capacitor.h
@@ -0,0 +1,31 @@
+#ifndef INPUTXSLT_SRC_SUPPORT_ERROR_WARNING_CAPACITOR_H_
+#define INPUTXSLT_SRC_SUPPORT_ERROR_WARNING_CAPACITOR_H_
+
+#include <memory>
+
+#include "error_multiplexer.h"
+
+namespace InputXSLT {
+
+class WarningCapacitor : public ErrorMultiplexer::receiver {
+ public:
+ typedef std::vector<std::string> warning_cache;
+ typedef std::unique_ptr<warning_cache> warning_cache_ptr;
+
+ WarningCapacitor(ErrorMultiplexer*);
+
+ warning_cache_ptr discharge();
+
+ virtual void receive(
+ const ErrorMultiplexer::error_type,
+ const std::string&
+ );
+
+ private:
+ warning_cache_ptr warning_cache_;
+
+};
+
+}
+
+#endif // INPUTXSLT_SRC_SUPPORT_ERROR_WARNING_CAPACITOR_H_
diff --git a/src/transformation_facade.cc b/src/transformation_facade.cc
index 6d7b7a3..3c94bdd 100644
--- a/src/transformation_facade.cc
+++ b/src/transformation_facade.cc
@@ -7,17 +7,33 @@
#include <sstream>
-#include "support/error/error_capacitor.h"
-
namespace InputXSLT {
+auto TransformationFacade::try_create(
+ const std::string& transformation,
+ IncludeEntityResolver* resolver,
+ const std::function<void(const ErrorCapacitor::error_cache&)>& handleErrors
+) -> ptr{
+ try {
+ return ptr(
+ new InputXSLT::TransformationFacade(transformation, resolver)
+ );
+ }
+ catch (const ErrorCapacitor::exception& exception) {
+ handleErrors(*exception);
+
+ return ptr();
+ }
+}
+
TransformationFacade::TransformationFacade(
const std::string& transformation,
IncludeEntityResolver* resolver
):
transformation_{},
transformer_(),
- error_multiplexer_(&transformer_) {
+ error_multiplexer_(&transformer_),
+ warning_capacitor_(&error_multiplexer_) {
this->transformer_.setEntityResolver(resolver);
ErrorCapacitor errorCapacitor(&this->error_multiplexer_);
@@ -36,6 +52,10 @@ TransformationFacade::~TransformationFacade() {
);
}
+WarningCapacitor::warning_cache_ptr TransformationFacade::getCachedWarnings() {
+ return this->warning_capacitor_.discharge();
+}
+
void TransformationFacade::generate(
const std::string& targetPath,
StylesheetParameterGuard& parameters
diff --git a/src/transformation_facade.h b/src/transformation_facade.h
index 53f1bbd..f69786a 100644
--- a/src/transformation_facade.h
+++ b/src/transformation_facade.h
@@ -4,16 +4,28 @@
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
#include <string>
+#include <memory>
+#include <functional>
#include "common.h"
#include "support/include_entity_resolver.h"
#include "support/stylesheet_parameter_guard.h"
#include "support/error/error_multiplexer.h"
+#include "support/error/error_capacitor.h"
+#include "support/error/warning_capacitor.h"
namespace InputXSLT {
class TransformationFacade {
public:
+ typedef std::unique_ptr<TransformationFacade> ptr;
+
+ static ptr try_create(
+ const std::string&,
+ IncludeEntityResolver*,
+ const std::function<void(const ErrorCapacitor::error_cache&)>&
+ );
+
TransformationFacade(const std::string&, IncludeEntityResolver*);
~TransformationFacade();
@@ -26,11 +38,14 @@ class TransformationFacade {
template <typename Target>
void generate(Target&, const xalan::XObjectPtr&);
+ WarningCapacitor::warning_cache_ptr getCachedWarnings();
+
private:
const xalan::XalanCompiledStylesheet* transformation_;
xalan::XalanTransformer transformer_;
ErrorMultiplexer error_multiplexer_;
+ WarningCapacitor warning_capacitor_;
void generate(const std::string&, StylesheetParameterGuard&);
void generate(std::basic_ostream<char>&, StylesheetParameterGuard&);