From 0b611b7bd28851fe8096b3d2c121c68e231ada11 Mon Sep 17 00:00:00 2001
From: Adrian Kummerländer
Date: Sat, 26 Apr 2014 11:21:10 +0200
Subject: Implemented global DOM document cache * the plan to return XML-nodes
from each external function requires a better way to manage the lifetime of
many xerces DOM document instances and their support class instances ** this
is why DomDocumentCache and DomDocumentCache::item were implemented ** based
on std::map so we can easily access the result of old function calls *
changed external read-directory function to return the children of the
document node instead of the document node itself ** removes unnecessary
cruft in function calls ** will make returning status codes alongside the
function result more pleasing to the eye * updated test transformation to
reflect new features
---
CMakeLists.txt | 3 +-
dummy/transform.xsl | 12 +++-
src/function/read_directory.cc | 103 +++++++++++++++++++--------------
src/function/read_directory.h | 12 +---
src/support/dom/document_cache.cc | 26 +++++++++
src/support/dom/document_cache.h | 27 +++++++++
src/support/dom/document_cache_item.cc | 50 ++++++++++++++++
src/support/dom/document_cache_item.h | 42 ++++++++++++++
src/support/dom_document_guard.cc | 45 --------------
src/support/dom_document_guard.h | 36 ------------
src/support/filesystem_context.cc | 14 +----
src/support/utility.h | 18 ++++++
src/transformation_facade.cc | 5 +-
src/transformation_facade.h | 2 +
14 files changed, 245 insertions(+), 150 deletions(-)
create mode 100644 src/support/dom/document_cache.cc
create mode 100644 src/support/dom/document_cache.h
create mode 100644 src/support/dom/document_cache_item.cc
create mode 100644 src/support/dom/document_cache_item.h
delete mode 100644 src/support/dom_document_guard.cc
delete mode 100644 src/support/dom_document_guard.h
create mode 100644 src/support/utility.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d50af0..02a9b79 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,8 @@ add_executable(
src/function/read_xml_file.cc
src/function/read_directory.cc
src/support/filesystem_context.cc
- src/support/dom_document_guard.cc
+ src/support/dom/document_cache.cc
+ src/support/dom/document_cache_item.cc
src/support/xerces_string_guard.cc
)
diff --git a/dummy/transform.xsl b/dummy/transform.xsl
index 95467ca..62d28c2 100644
--- a/dummy/transform.xsl
+++ b/dummy/transform.xsl
@@ -24,7 +24,17 @@
+
+
diff --git a/src/function/read_directory.cc b/src/function/read_directory.cc
index 9711239..677aa1d 100644
--- a/src/function/read_directory.cc
+++ b/src/function/read_directory.cc
@@ -6,13 +6,15 @@
#include
#include
+#include "support/utility.h"
#include "support/xerces_string_guard.h"
namespace InputXSLT {
-FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context):
+FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context,
+ DomDocumentCache& cache):
fs_context_(context),
- documents_(std::make_shared>()) { }
+ document_cache_(cache) { }
xalan::XObjectPtr FunctionReadDirectory::execute(
xalan::XPathExecutionContext& executionContext,
@@ -20,53 +22,68 @@ xalan::XObjectPtr FunctionReadDirectory::execute(
const xalan::XObjectPtr argument,
const xalan::Locator*
) const {
- this->documents_->emplace("content");
- DomDocumentGuard& domDocument = this->documents_->top();
-
- xercesc::DOMNode* const rootNode = domDocument->getDocumentElement();
+ DomDocumentCache::item* const cachedDocument(
+ this->document_cache_.get(xalanToString(argument->str()))
+ );
- this->fs_context_.iterate(
- argument->str(),
- [&domDocument, &rootNode](const boost::filesystem::path& p) {
- xercesc::DOMElement* const itemNode(
- domDocument->createElement(*XercesStringGuard("item"))
+ if ( !cachedDocument->isFinalized() ) {
+ xercesc::DOMDocument* const domDocument(
+ cachedDocument->getXercesDocument()
);
- switch ( boost::filesystem::status(p).type() ) {
- case boost::filesystem::regular_file: {
- itemNode->setAttribute(
- *XercesStringGuard("type"),
- *XercesStringGuard("file")
- );
-
- break;
- };
- case boost::filesystem::directory_file: {
- itemNode->setAttribute(
- *XercesStringGuard("type"),
- *XercesStringGuard("directory")
- );
-
- break;
- };
- default: {
- break;
- };
- }
-
- xercesc::DOMText* const textNode(
- domDocument->createTextNode(
- *XercesStringGuard(p.filename().string())
- )
+ xercesc::DOMNode* const rootNode(
+ domDocument->getDocumentElement()
);
- itemNode->appendChild(textNode);
- rootNode->appendChild(itemNode);
- });
+ this->fs_context_.iterate(
+ argument->str(),
+ [&domDocument, &rootNode](const boost::filesystem::path& p) {
+ xercesc::DOMElement* const itemNode(
+ domDocument->createElement(*XercesStringGuard("item"))
+ );
+
+ switch ( boost::filesystem::status(p).type() ) {
+ case boost::filesystem::regular_file: {
+ itemNode->setAttribute(
+ *XercesStringGuard("type"),
+ *XercesStringGuard("file")
+ );
+
+ break;
+ };
+ case boost::filesystem::directory_file: {
+ itemNode->setAttribute(
+ *XercesStringGuard("type"),
+ *XercesStringGuard("directory")
+ );
+
+ break;
+ };
+ default: {
+ break;
+ };
+ }
+
+ xercesc::DOMText* const textNode(
+ domDocument->createTextNode(
+ *XercesStringGuard(p.filename().string())
+ )
+ );
+
+ itemNode->appendChild(textNode);
+ rootNode->appendChild(itemNode);
+ });
+ }
+
+ xalan::XPathExecutionContext::BorrowReturnMutableNodeRefList nodeList(
+ executionContext
+ );
- return executionContext.getXObjectFactory().createNodeSet(
- domDocument.finalize()
+ nodeList->addNodes(
+ *cachedDocument->getXalanDocument()->getDocumentElement()->getChildNodes()
);
+
+ return executionContext.getXObjectFactory().createNodeSet(nodeList);
}
FunctionReadDirectory* FunctionReadDirectory::clone(
@@ -76,7 +93,7 @@ FunctionReadDirectory* FunctionReadDirectory::clone(
const xalan::XalanDOMString& FunctionReadDirectory::getError(
xalan::XalanDOMString& result) const {
- result.assign("The read-directory() function expects one argument.");
+ result.assign("The read-directory() function expects one argument of type string.");
return result;
}
diff --git a/src/function/read_directory.h b/src/function/read_directory.h
index 782ebed..3fcf389 100644
--- a/src/function/read_directory.h
+++ b/src/function/read_directory.h
@@ -6,18 +6,15 @@
#include
#include
-#include
-#include
-
#include "common.h"
#include "support/filesystem_context.h"
-#include "support/dom_document_guard.h"
+#include "support/dom/document_cache.h"
namespace InputXSLT {
class FunctionReadDirectory : public xalan::Function {
public:
- FunctionReadDirectory(const FilesystemContext&);
+ FunctionReadDirectory(const FilesystemContext&, DomDocumentCache&);
virtual xalan::XObjectPtr execute(
xalan::XPathExecutionContext&,
@@ -33,10 +30,7 @@ class FunctionReadDirectory : public xalan::Function {
private:
const FilesystemContext& fs_context_;
-
- std::shared_ptr<
- std::stack
- > documents_;
+ DomDocumentCache& document_cache_;
const xalan::XalanDOMString& getError(xalan::XalanDOMString&) const;
diff --git a/src/support/dom/document_cache.cc b/src/support/dom/document_cache.cc
new file mode 100644
index 0000000..f814559
--- /dev/null
+++ b/src/support/dom/document_cache.cc
@@ -0,0 +1,26 @@
+#include "document_cache.h"
+
+namespace InputXSLT {
+
+DomDocumentCache::DomDocumentCache():
+ map_() { }
+
+DomDocumentCache::item* DomDocumentCache::get(const std::string& key) {
+ auto itemIter = this->map_.find(key);
+
+ if ( itemIter == this->map_.end() ) {
+ auto result = this->map_.emplace(
+ std::make_pair(key, std::unique_ptr- (new item("content")))
+ );
+
+ if ( result.second ) {
+ return (*(result.first)).second.get();
+ } else {
+ return nullptr;
+ }
+ } else {
+ return (*itemIter).second.get();
+ }
+}
+
+}
diff --git a/src/support/dom/document_cache.h b/src/support/dom/document_cache.h
new file mode 100644
index 0000000..4447a18
--- /dev/null
+++ b/src/support/dom/document_cache.h
@@ -0,0 +1,27 @@
+#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_H_
+#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_H_
+
+#include