From 78bb3387b15d15d766fb5d17a99612f0480f2bee Mon Sep 17 00:00:00 2001 From: Adrian Kummerländer Date: Thu, 5 Jun 2014 20:44:26 +0200 Subject: Implemented ErrorMultiplexer as primary error handler * ErrorMultiplexer is derived from both xercesc::ErrorHandler and xalan::ProblemListener * registers itself as XalanTransformer's ErrorHandler and ProblemListener * distributes captured errors and warnings to all registered ErrorMultiplexer::Receiver instances ** ErrorCapacitor implements the ErrorMultiplexer::Receiver interface and as such registers itself in a given ErrorMultiplexer instance ** ErrorMultiplexer reduces the different xalan and xercesc internal error classifications into either warnings or errors * this was implemented to make it possible to easily differentiate between warnings and errors ** previously warnings were treated as errors ** ErrorCapacitor ignores warnings and only captures errors ** WarningCapacitor will be implemented to handle warnings during XSLT processing --- src/support/error/error_capacitor.cc | 37 +++++++ src/support/error/error_capacitor.h | 46 +++++++++ src/support/error/error_multiplexer.cc | 170 +++++++++++++++++++++++++++++++++ src/support/error/error_multiplexer.h | 84 ++++++++++++++++ 4 files changed, 337 insertions(+) create mode 100644 src/support/error/error_capacitor.cc create mode 100644 src/support/error/error_capacitor.h create mode 100644 src/support/error/error_multiplexer.cc create mode 100644 src/support/error/error_multiplexer.h (limited to 'src/support/error') diff --git a/src/support/error/error_capacitor.cc b/src/support/error/error_capacitor.cc new file mode 100644 index 0000000..58cfb81 --- /dev/null +++ b/src/support/error/error_capacitor.cc @@ -0,0 +1,37 @@ +#include "error_capacitor.h" + +namespace InputXSLT { + +ErrorCapacitor::ErrorCapacitor(ErrorMultiplexer* multiplexer): + multiplexer_(multiplexer), + error_cache_(new error_cache()) { + this->multiplexer_->connectReceiver(this); +} + +ErrorCapacitor::~ErrorCapacitor() { + this->multiplexer_->disconnectReceiver(this); +} + +void ErrorCapacitor::discharge() { + if ( !this->error_cache_->empty() ) { + throw exception(std::move(this->error_cache_)); + } +} + +void ErrorCapacitor::receive( + const ErrorMultiplexer::ErrorType type, + const std::string& message +) { + if ( type == ErrorMultiplexer::ErrorType::Error ) { + this->error_cache_->emplace_back(message); + } +} + +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(); +} + +} diff --git a/src/support/error/error_capacitor.h b/src/support/error/error_capacitor.h new file mode 100644 index 0000000..6017cb4 --- /dev/null +++ b/src/support/error/error_capacitor.h @@ -0,0 +1,46 @@ +#ifndef INPUTXSLT_SRC_SUPPORT_ERROR_ERROR_CAPACITOR_H_ +#define INPUTXSLT_SRC_SUPPORT_ERROR_ERROR_CAPACITOR_H_ + +#include + +#include "error_multiplexer.h" + +namespace InputXSLT { + +class ErrorCapacitor : public ErrorMultiplexer::Receiver { + public: + class exception; + + typedef std::vector error_cache; + typedef std::unique_ptr error_cache_ptr; + + ErrorCapacitor(ErrorMultiplexer*); + ~ErrorCapacitor(); + + void discharge(); + + virtual void receive( + const ErrorMultiplexer::ErrorType, + const std::string& + ); + + private: + ErrorMultiplexer* const multiplexer_; + error_cache_ptr error_cache_; + +}; + +class ErrorCapacitor::exception { + public: + exception(error_cache_ptr); + + const error_cache* getCachedErrors() const; + + private: + error_cache_ptr error_cache_; + +}; + +} + +#endif // INPUTXSLT_SRC_SUPPORT_ERROR_ERROR_CAPACITOR_H_ diff --git a/src/support/error/error_multiplexer.cc b/src/support/error/error_multiplexer.cc new file mode 100644 index 0000000..f5d4e0f --- /dev/null +++ b/src/support/error/error_multiplexer.cc @@ -0,0 +1,170 @@ +#include "error_multiplexer.h" + +#include + +#include + +#include + +#include "support/xalan_string.h" +#include "support/xerces_string_guard.h" + +namespace { + +using InputXSLT::XercesStringGuard; +using InputXSLT::ErrorMultiplexer; + +inline std::string getMessage(const xercesc::SAXParseException& exception) { + return ( + std::string(*XercesStringGuard(exception.getMessage())) + + ". (Occurred in entity '" + + std::string(*XercesStringGuard(exception.getSystemId())) + + "', at line " + + std::to_string(exception.getLineNumber()) + + ", column " + + std::to_string(exception.getColumnNumber()) + + ".)" + ); +} + +inline ErrorMultiplexer::ErrorType toErrorType( + const xalan::ProblemListenerBase::eClassification classification) { + switch ( classification ) { + case xalan::ProblemListenerBase::eClassification::eMessage || + xalan::ProblemListenerBase::eClassification::eWarning: { + return ErrorMultiplexer::ErrorType::Warning; + } + default: { + return ErrorMultiplexer::ErrorType::Error; + } + } +} + +} + +namespace InputXSLT { + +ErrorMultiplexer::ErrorMultiplexer(xalan::XalanTransformer* transformer): + transformer_(transformer), + receivers_() { + this->transformer_->setErrorHandler(this); + this->transformer_->setProblemListener(this); +} + +ErrorMultiplexer::~ErrorMultiplexer() { + this->transformer_->setErrorHandler(nullptr); + this->transformer_->setProblemListener(nullptr); +} + +void ErrorMultiplexer::connectReceiver(Receiver* receiver) { + this->receivers_.push_back(receiver); +} + +void ErrorMultiplexer::disconnectReceiver(Receiver* receiver) { + this->receivers_.erase( + std::remove( + this->receivers_.begin(), + this->receivers_.end(), + receiver + ) + ); +} + +void ErrorMultiplexer::warning(const xercesc::SAXParseException& exception) { + this->multiplex( + ErrorType::Warning, + "Warning: " + getMessage(exception) + ); +} + +void ErrorMultiplexer::error(const xercesc::SAXParseException& exception) { + this->multiplex( + ErrorType::Error, + "Error: " + getMessage(exception) + ); +} + +void ErrorMultiplexer::fatalError(const xercesc::SAXParseException& exception) { + this->multiplex( + ErrorType::Error, + "Fatal error: " + getMessage(exception) + ); +} + +void ErrorMultiplexer::resetErrors() { } + +void ErrorMultiplexer::problem( + xalan::ProblemListenerBase::eSource source, + xalan::ProblemListenerBase::eClassification classification, + const xalan::XalanDOMString& message, + const xalan::Locator* locator, + const xalan::XalanNode* node +) { + xalan::XalanDOMString problemSummary; + xalan::DOMStringPrintWriter writer(problemSummary); + + defaultFormat( + writer, + source, + classification, + message, + locator, + node + ); + + this->multiplex( + toErrorType(classification), + toString(problemSummary) + ); +} + +void ErrorMultiplexer::problem( + xalan::ProblemListenerBase::eSource source, + xalan::ProblemListenerBase::eClassification classification, + const xalan::XalanDOMString& message, + const xalan::XalanNode* node +) { + xalan::XalanDOMString problemSummary; + xalan::DOMStringPrintWriter writer(problemSummary); + + defaultFormat( + writer, + source, + classification, + message, + node + ); + + this->multiplex( + toErrorType(classification), + toString(problemSummary) + ); +} + +void ErrorMultiplexer::problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanNode*, + const xalan::ElemTemplateElement*, + const xalan::XalanDOMString&, + const xalan::XalanDOMChar*, + xalan::XalanFileLoc, + xalan::XalanFileLoc +) { } + +void ErrorMultiplexer::setPrintWriter(xalan::PrintWriter*) { } + +void ErrorMultiplexer::multiplex( + const ErrorType type, + const std::string& message +) { + std::for_each( + this->receivers_.begin(), + this->receivers_.end(), + [&type, &message](Receiver* const receiver) -> void { + receiver->receive(type, message); + } + ); +} + +} diff --git a/src/support/error/error_multiplexer.h b/src/support/error/error_multiplexer.h new file mode 100644 index 0000000..02cfaf8 --- /dev/null +++ b/src/support/error/error_multiplexer.h @@ -0,0 +1,84 @@ +#ifndef INPUTXSLT_SRC_SUPPORT_ERROR_ERROR_MULTIPLEXER_H_ +#define INPUTXSLT_SRC_SUPPORT_ERROR_ERROR_MULTIPLEXER_H_ + +#include + +#include +#include + +#include +#include + +#include "common.h" + +namespace InputXSLT { + +class ErrorMultiplexer : public xercesc::ErrorHandler, + public xalan::ProblemListener { + public: + enum class ErrorType; + struct Receiver; + + ErrorMultiplexer(xalan::XalanTransformer*); + ~ErrorMultiplexer(); + + void connectReceiver(Receiver*); + void disconnectReceiver(Receiver*); + + virtual void warning(const xercesc::SAXParseException&); + virtual void error(const xercesc::SAXParseException&); + virtual void fatalError(const xercesc::SAXParseException&); + virtual void resetErrors(); + + virtual void problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanDOMString&, + const xalan::Locator*, + const xalan::XalanNode* + ); + + virtual void problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanDOMString&, + const xalan::XalanNode* + ); + + virtual void problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanNode*, + const xalan::ElemTemplateElement*, + const xalan::XalanDOMString&, + const xalan::XalanDOMChar*, + xalan::XalanFileLoc, + xalan::XalanFileLoc + ); + + virtual void setPrintWriter(xalan::PrintWriter*); + + private: + xalan::XalanTransformer* const transformer_; + + std::vector receivers_; + + void multiplex(const ErrorType, const std::string&); + +}; + +enum class ErrorMultiplexer::ErrorType { + Warning, + Error +}; + +struct ErrorMultiplexer::Receiver { + virtual void receive( + const ErrorMultiplexer::ErrorType, + const std::string& + ) = 0; +}; + +} + +#endif // INPUTXSLT_SRC_SUPPORT_ERROR_ERROR_MULTIPLEXER_H_ -- cgit v1.2.3