From 3bc793d95293d40dbab62c593ce4ceaa86fae25b Mon Sep 17 00:00:00 2001 From: Adrian Kummerländer Date: Thu, 29 May 2014 13:26:37 +0200 Subject: Improved TransformationFacade error handling * ErrorHandler class created in 5859cb6 now caches all errors instead of pushing them to std::cerr ** cached errors are retrieved by TransformationFacade's "generate" member method * test frontend pushes all errors to std::cerr * FunctionTransform returns errors to the calling template as XML ** FunctionTransform test case demonstrates how one may test for successful transformation * "generate" member method returns std::string vector wrapped in a std::unique_ptr ** this is used as a kind of optional pointer, as the std::unique_ptr instance only wraps a vector if errors where actually generated --- src/function/transform.cc | 15 +++++--- src/support/error_handler.cc | 63 +++++++++++++++++++++------------- src/support/error_handler.h | 13 +++++-- src/support/include_entity_resolver.cc | 4 ++- src/transformation_facade.cc | 32 ++++++++++------- src/transformation_facade.h | 24 +++++++------ test.cc | 12 +++++-- test/transform/transformation.xsl | 31 +++++++++++------ 8 files changed, 126 insertions(+), 68 deletions(-) diff --git a/src/function/transform.cc b/src/function/transform.cc index fd28b34..7e8a844 100644 --- a/src/function/transform.cc +++ b/src/function/transform.cc @@ -38,17 +38,22 @@ xercesc::DOMDocument* FunctionTransform::constructDocument( domDocument->getDocumentElement() ); + ResultNodeFacade result(domDocument, rootNode, "result"); + result.setAttribute("name", targetPath); + InputXSLT::TransformationFacade transformation( transformationPath, this->include_resolver_ ); - if ( transformation.generate(targetPath, parameterObject) == 0 ) { - ResultNodeFacade result(domDocument, rootNode, "result"); + InputXSLT::TransformationFacade::return_type errors( + transformation.generate(targetPath, parameterObject) + ); - result.setAttribute("name", targetPath); - } else { - ResultNodeFacade result(domDocument, rootNode, "error"); + if ( errors ) { + for ( auto&& error : *errors ) { + result.setValueNode("error", error); + } } return domDocument; diff --git a/src/support/error_handler.cc b/src/support/error_handler.cc index 9a898a6..db54225 100644 --- a/src/support/error_handler.cc +++ b/src/support/error_handler.cc @@ -6,38 +6,55 @@ #include "support/xerces_string_guard.h" +namespace { + +inline std::string getMessage(const xercesc::SAXParseException& exception) { + return std::string( + *InputXSLT::XercesStringGuard(exception.getMessage()) + ); +} + +} + namespace InputXSLT { -ErrorHandler::ErrorHandler(const std::string& transformation): - transformation_path_(transformation) { } +ErrorHandler::ErrorHandler(): + error_cache_{} { } + +void ErrorHandler::warning(const xercesc::SAXParseException& exception) { + this->constructErrorCache(); -void ErrorHandler::warning(const xercesc::SAXParseException& e) { - std::cerr << "Warning in " - << "'" - << this->transformation_path_ - << "': " - << *XercesStringGuard(e.getMessage()) - << std::endl; + this->error_cache_->emplace_back( + "Warning: " + getMessage(exception) + ); } -void ErrorHandler::error(const xercesc::SAXParseException& e) { - std::cerr << "Error in " - << "'" - << this->transformation_path_ - << "': " - << *XercesStringGuard(e.getMessage()) - << std::endl; +void ErrorHandler::error(const xercesc::SAXParseException& exception) { + this->constructErrorCache(); + + this->error_cache_->emplace_back( + "Error: " + getMessage(exception) + ); } -void ErrorHandler::fatalError(const xercesc::SAXParseException& e) { - std::cerr << "Fatal error in " - << "'" - << this->transformation_path_ - << "': " - << *XercesStringGuard(e.getMessage()) - << std::endl; +void ErrorHandler::fatalError(const xercesc::SAXParseException& exception) { + this->constructErrorCache(); + + this->error_cache_->emplace_back( + "Fatal error: " + getMessage(exception) + ); } void ErrorHandler::resetErrors() { } +auto ErrorHandler::getCachedErrors() -> error_cache_ptr { + return error_cache_ptr(this->error_cache_.release()); +} + +void ErrorHandler::constructErrorCache() { + if ( !this->error_cache_ ) { + this->error_cache_.reset(new error_cache()); + } +} + } diff --git a/src/support/error_handler.h b/src/support/error_handler.h index 7835292..77a46d8 100644 --- a/src/support/error_handler.h +++ b/src/support/error_handler.h @@ -3,21 +3,30 @@ #include +#include +#include #include namespace InputXSLT { class ErrorHandler : public xercesc::ErrorHandler { public: - ErrorHandler(const std::string&); + typedef std::vector error_cache; + typedef std::unique_ptr error_cache_ptr; + + ErrorHandler(); virtual void warning(const xercesc::SAXParseException&); virtual void error(const xercesc::SAXParseException&); virtual void fatalError(const xercesc::SAXParseException&); virtual void resetErrors(); + error_cache_ptr getCachedErrors(); + private: - const std::string& transformation_path_; + error_cache_ptr error_cache_; + + void constructErrorCache(); }; diff --git a/src/support/include_entity_resolver.cc b/src/support/include_entity_resolver.cc index 948a61b..e63a3c4 100644 --- a/src/support/include_entity_resolver.cc +++ b/src/support/include_entity_resolver.cc @@ -48,7 +48,9 @@ xercesc::InputSource* IncludeEntityResolver::resolveEntity( *XercesStringGuard((*resolvedPath).string()) ); } else { - return nullptr; + return new xercesc::LocalFileInputSource( + *XercesStringGuard(*filePath) + ); } } else { return nullptr; diff --git a/src/transformation_facade.cc b/src/transformation_facade.cc index fc7e1de..0f174d8 100644 --- a/src/transformation_facade.cc +++ b/src/transformation_facade.cc @@ -6,7 +6,6 @@ #include "boost/filesystem.hpp" #include -#include namespace InputXSLT { @@ -16,7 +15,7 @@ TransformationFacade::TransformationFacade( ): transformation_{}, transformer_(), - error_handler_(transformation) { + error_handler_() { this->transformer_.setEntityResolver(resolver); this->transformer_.setErrorHandler(&this->error_handler_); @@ -32,10 +31,10 @@ TransformationFacade::~TransformationFacade() { ); } -int TransformationFacade::generate( +auto TransformationFacade::generate( const std::string& targetPath, StylesheetParameterGuard& parameters -) { +) -> return_type { const boost::filesystem::path targetPathHelper( boost::filesystem::absolute(targetPath) ); @@ -53,22 +52,22 @@ int TransformationFacade::generate( ); } -int TransformationFacade::generate( +auto TransformationFacade::generate( std::basic_ostream& targetStream, StylesheetParameterGuard& parameters -) { +) -> return_type { return this->generate( xalan::XSLTResultTarget(targetStream), parameters ); } -int TransformationFacade::generate( +auto TransformationFacade::generate( xalan::XSLTResultTarget&& outputTarget, StylesheetParameterGuard& -) { - std::stringstream emptyStream(""); - xalan::XSLTInputSource inputSource(emptyStream); +) -> return_type { + std::stringstream emptyStream(""); + xalan::XSLTInputSource inputSource(emptyStream); const int resultCode = this->transformer_.transform( inputSource, @@ -76,11 +75,18 @@ int TransformationFacade::generate( outputTarget ); - if ( resultCode != 0 ) { - std::cerr << this->transformer_.getLastError() << std::endl; + return_type errors(this->error_handler_.getCachedErrors()); + + if ( errors && resultCode != 0 ) { + errors->emplace_back( + "Transformation error with code " + + std::to_string(resultCode) + + ": " + + this->transformer_.getLastError() + ); } - return resultCode; + return errors; } } diff --git a/src/transformation_facade.h b/src/transformation_facade.h index ab76cac..28d1895 100644 --- a/src/transformation_facade.h +++ b/src/transformation_facade.h @@ -14,17 +14,19 @@ namespace InputXSLT { class TransformationFacade { public: + typedef ErrorHandler::error_cache_ptr return_type; + TransformationFacade(const std::string&, IncludeEntityResolver*); ~TransformationFacade(); template - int generate(Target&); + return_type generate(Target&); template - int generate(Target&, const StylesheetParameterGuard::map&); + return_type generate(Target&, const StylesheetParameterGuard::map&); template - int generate(Target&, const xalan::XObjectPtr&); + return_type generate(Target&, const xalan::XObjectPtr&); private: const xalan::XalanCompiledStylesheet* transformation_; @@ -32,34 +34,34 @@ class TransformationFacade { xalan::XalanTransformer transformer_; ErrorHandler error_handler_; - int generate(const std::string&, StylesheetParameterGuard&); - int generate(std::basic_ostream&, StylesheetParameterGuard&); - int generate(xalan::XSLTResultTarget&&, StylesheetParameterGuard&); + return_type generate(const std::string&, StylesheetParameterGuard&); + return_type generate(std::basic_ostream&, StylesheetParameterGuard&); + return_type generate(xalan::XSLTResultTarget&&, StylesheetParameterGuard&); }; template -int TransformationFacade::generate(Target& target) { +auto TransformationFacade::generate(Target& target) -> return_type { StylesheetParameterGuard guard(this->transformer_); return this->generate(target, guard); } template -int TransformationFacade::generate( +auto TransformationFacade::generate( Target& target, const StylesheetParameterGuard::map& parameters -) { +) -> return_type { StylesheetParameterGuard guard(this->transformer_, parameters); return this->generate(target, guard); } template -int TransformationFacade::generate( +auto TransformationFacade::generate( Target& target, const xalan::XObjectPtr& parameter -) { +) -> return_type { StylesheetParameterGuard guard(this->transformer_); guard.set("parameters", parameter); diff --git a/test.cc b/test.cc index 9d1dd3a..0c5e4b2 100644 --- a/test.cc +++ b/test.cc @@ -48,12 +48,20 @@ int main(int ac, char** av) { plattform.getEntityResolver() ); + InputXSLT::TransformationFacade::return_type errors{}; + if ( variables.count("target") ) { - return transformation.generate( + errors = transformation.generate( variables["target"].as() ); } else { - return transformation.generate(std::cout); + errors = transformation.generate(std::cout); + } + + if ( errors ) { + for ( auto&& error : *errors ) { + std::cerr << error << std::endl; + } } } else { std::cout << optionDescription << std::endl; diff --git a/test/transform/transformation.xsl b/test/transform/transformation.xsl index f2cc787..19c42ae 100644 --- a/test/transform/transformation.xsl +++ b/test/transform/transformation.xsl @@ -23,21 +23,30 @@ ) - + - - test.xsl - test_actual.xml - - 21 - - + + + test.xsl + test_actual.xml + + 21 + + + - + + + + + + + + -- cgit v1.2.3