From 272b34c1a4639cd0f909bfb52d30339c93b0c42b Mon Sep 17 00:00:00 2001 From: Adrian Kummerländer Date: Fri, 6 Jun 2014 22:00:39 +0200 Subject: 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 --- CMakeLists.txt | 1 + ixslt.cc | 68 ++++++++++++++++++++++++---------- src/function/transform.cc | 46 +++++++++++++++++------ src/support/error/error_capacitor.cc | 18 +++------ src/support/error/error_capacitor.h | 8 ++-- src/support/error/error_multiplexer.cc | 29 ++++++++++----- src/support/error/error_multiplexer.h | 36 +++++++++++------- src/support/error/warning_capacitor.cc | 26 +++++++++++++ src/support/error/warning_capacitor.h | 31 ++++++++++++++++ src/transformation_facade.cc | 26 +++++++++++-- src/transformation_facade.h | 15 ++++++++ 11 files changed, 228 insertions(+), 76 deletions(-) create mode 100644 src/support/error/warning_capacitor.cc create mode 100644 src/support/error/warning_capacitor.h 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 input( int argc, @@ -57,6 +76,12 @@ boost::optional 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 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(), - plattform.getEntityResolver() - ); - - if ( variables.count("target") ) { - transformation.generate( - variables["target"].as() - ); - } else { - transformation.generate(std::cout); + if ( auto transformation = InputXSLT::TransformationFacade::try_create( + variables["transformation"].as(), + plattform.getEntityResolver(), + handleErrors + ) ) { + WarningGuard guard(transformation.get()); + + try { + if ( variables.count("target") ) { + transformation->generate( + variables["target"].as() + ); + } 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 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_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 receivers_; + std::vector 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 + +#include "error_multiplexer.h" + +namespace InputXSLT { + +class WarningCapacitor : public ErrorMultiplexer::receiver { + public: + typedef std::vector warning_cache; + typedef std::unique_ptr 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 -#include "support/error/error_capacitor.h" - namespace InputXSLT { +auto TransformationFacade::try_create( + const std::string& transformation, + IncludeEntityResolver* resolver, + const std::function& 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 #include +#include +#include #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 ptr; + + static ptr try_create( + const std::string&, + IncludeEntityResolver*, + const std::function& + ); + TransformationFacade(const std::string&, IncludeEntityResolver*); ~TransformationFacade(); @@ -26,11 +38,14 @@ class TransformationFacade { template 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&, StylesheetParameterGuard&); -- cgit v1.2.3