aboutsummaryrefslogtreecommitdiff
path: root/src/support/error
diff options
context:
space:
mode:
Diffstat (limited to 'src/support/error')
-rw-r--r--src/support/error/error_capacitor.cc37
-rw-r--r--src/support/error/error_capacitor.h46
-rw-r--r--src/support/error/error_multiplexer.cc170
-rw-r--r--src/support/error/error_multiplexer.h84
4 files changed, 337 insertions, 0 deletions
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 <memory>
+
+#include "error_multiplexer.h"
+
+namespace InputXSLT {
+
+class ErrorCapacitor : public ErrorMultiplexer::Receiver {
+ public:
+ class exception;
+
+ typedef std::vector<std::string> error_cache;
+ typedef std::unique_ptr<error_cache> 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 <xercesc/sax/SAXParseException.hpp>
+
+#include <xalanc/PlatformSupport/DOMStringPrintWriter.hpp>
+
+#include <algorithm>
+
+#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<char>(exception.getMessage()))
+ + ". (Occurred in entity '"
+ + std::string(*XercesStringGuard<char>(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 <xercesc/sax/ErrorHandler.hpp>
+
+#include <xalanc/XSLT/ProblemListener.hpp>
+#include <xalanc/XalanTransformer/XalanTransformer.hpp>
+
+#include <vector>
+#include <string>
+
+#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<Receiver*> 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_