diff options
author | Adrian Kummerländer | 2014-04-26 11:21:10 +0200 |
---|---|---|
committer | Adrian Kummerländer | 2014-04-26 11:21:10 +0200 |
commit | 0b611b7bd28851fe8096b3d2c121c68e231ada11 (patch) | |
tree | 80352794dce96cec2b86659e5a8260fb9a7686c2 | |
parent | 938ed7622656c3494ae8fdb83bc2ad4b1f31d901 (diff) | |
download | InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.gz InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.bz2 InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.lz InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.xz InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.zst InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.zip |
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
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | dummy/transform.xsl | 12 | ||||
-rw-r--r-- | src/function/read_directory.cc | 103 | ||||
-rw-r--r-- | src/function/read_directory.h | 12 | ||||
-rw-r--r-- | src/support/dom/document_cache.cc | 26 | ||||
-rw-r--r-- | src/support/dom/document_cache.h | 27 | ||||
-rw-r--r-- | src/support/dom/document_cache_item.cc | 50 | ||||
-rw-r--r-- | src/support/dom/document_cache_item.h (renamed from src/support/dom_document_guard.h) | 24 | ||||
-rw-r--r-- | src/support/dom_document_guard.cc | 45 | ||||
-rw-r--r-- | src/support/filesystem_context.cc | 14 | ||||
-rw-r--r-- | src/support/utility.h | 18 | ||||
-rw-r--r-- | src/transformation_facade.cc | 5 | ||||
-rw-r--r-- | src/transformation_facade.h | 2 |
13 files changed, 218 insertions, 123 deletions
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 @@ </xsl:for-each> </ul> <ul id="filelist"> - <xsl:for-each select="external:read-directory('.')/content/item[@type='file']"> + <xsl:for-each select="external:read-directory('.')[@type='file']"> + <li><xsl:value-of select="."/></li> + </xsl:for-each> + </ul> + <ul id="filelist2"> + <xsl:for-each select="external:read-directory('../')[@type='file']"> + <li><xsl:value-of select="."/></li> + </xsl:for-each> + </ul> + <ul id="filelist3"> + <xsl:for-each select="external:read-directory('../')[@type='directory']"> <li><xsl:value-of select="."/></li> </xsl:for-each> </ul> 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 <xercesc/dom/DOMText.hpp> #include <xercesc/util/XMLString.hpp> +#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<std::stack<DomDocumentGuard>>()) { } + 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 <xalanc/XPath/Function.hpp> #include <xalanc/XPath/XObject.hpp> -#include <memory> -#include <stack> - #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<DomDocumentGuard> - > 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<item>(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 <map> +#include <string> +#include <memory> + +namespace InputXSLT { + +class DomDocumentCache { + public: + class item; + + DomDocumentCache(); + + item* get(const std::string&); + + private: + std::map<std::string, std::unique_ptr<item>> map_; + +}; + +} + +#include "document_cache_item.h" + +#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_H_ diff --git a/src/support/dom/document_cache_item.cc b/src/support/dom/document_cache_item.cc new file mode 100644 index 0000000..8cc1c24 --- /dev/null +++ b/src/support/dom/document_cache_item.cc @@ -0,0 +1,50 @@ +#include "support/dom/document_cache_item.h" + +#include <xercesc/dom/DOMImplementation.hpp> +#include <xercesc/util/XMLString.hpp> + +#include "support/xerces_string_guard.h" + +namespace InputXSLT { + +DomDocumentCache::item::item(const std::string& rootNode): + parser_(), + dom_support_(parser_), + document_( + xercesc::DOMImplementation::getImplementation()->createDocument( + nullptr, + *XercesStringGuard(rootNode), + nullptr + ) + ), + parsed_source_() { } + +DomDocumentCache::item::~item() { + this->document_->release(); +} + +bool DomDocumentCache::item::isFinalized() const { + return static_cast<bool>(this->parsed_source_); +} + +xercesc::DOMDocument* DomDocumentCache::item::getXercesDocument() const { + return this->document_; +} + +xalan::XalanDocument* DomDocumentCache::item::getXalanDocument() { + if ( this->parsed_source_ ) { + return this->parsed_source_->getDocument(); + } else { + this->parsed_source_.reset( + new xalan::XercesDOMWrapperParsedSource( + document_, + parser_, + dom_support_ + ) + ); + + return this->parsed_source_->getDocument(); + } +} + +} diff --git a/src/support/dom_document_guard.h b/src/support/dom/document_cache_item.h index decca01..1f7152b 100644 --- a/src/support/dom_document_guard.h +++ b/src/support/dom/document_cache_item.h @@ -1,5 +1,5 @@ -#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_ -#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_ +#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_ITEM_H_ +#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_ITEM_H_ #include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp> #include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp> @@ -11,21 +11,27 @@ #include <memory> #include "common.h" +#include "document_cache.h" namespace InputXSLT { -class DomDocumentGuard { +class DomDocumentCache::item { public: - DomDocumentGuard(const std::string&); - ~DomDocumentGuard(); + ~item(); - xercesc::DOMDocument* operator->(); - xalan::XalanDocument* finalize(); + bool isFinalized() const; + + xercesc::DOMDocument* getXercesDocument() const; + xalan::XalanDocument* getXalanDocument(); + + protected: + friend DomDocumentCache; + + item(const std::string&); private: xalan::XercesParserLiaison parser_; xalan::XercesDOMSupport dom_support_; - XMLCh* root_node_name_; xercesc::DOMDocument* const document_; std::unique_ptr<xalan::XercesDOMWrapperParsedSource> parsed_source_; @@ -33,4 +39,4 @@ class DomDocumentGuard { } -#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_ +#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_ITEM_H_ diff --git a/src/support/dom_document_guard.cc b/src/support/dom_document_guard.cc deleted file mode 100644 index a83345f..0000000 --- a/src/support/dom_document_guard.cc +++ /dev/null @@ -1,45 +0,0 @@ -#include "support/dom_document_guard.h" - -#include <xercesc/dom/DOMImplementation.hpp> -#include <xercesc/util/XMLString.hpp> - -namespace InputXSLT { - -DomDocumentGuard::DomDocumentGuard(const std::string& rootNode): - parser_(), - dom_support_(parser_), - root_node_name_( - xercesc::XMLString::transcode(rootNode.data()) - ), - document_( - xercesc::DOMImplementation::getImplementation()->createDocument( - nullptr, - root_node_name_, - nullptr - ) - ), - parsed_source_() { } - -DomDocumentGuard::~DomDocumentGuard() { - xercesc::XMLString::release(&this->root_node_name_); - - this->document_->release(); -} - -xercesc::DOMDocument* DomDocumentGuard::operator->() { - return this->document_; -} - -xalan::XalanDocument* DomDocumentGuard::finalize() { - this->parsed_source_.reset( - new xalan::XercesDOMWrapperParsedSource( - document_, - parser_, - dom_support_ - ) - ); - - return this->parsed_source_->getDocument(); -} - -} diff --git a/src/support/filesystem_context.cc b/src/support/filesystem_context.cc index baeccf3..9ed9bbf 100644 --- a/src/support/filesystem_context.cc +++ b/src/support/filesystem_context.cc @@ -1,18 +1,6 @@ #include "filesystem_context.h" -namespace { - -inline std::string xalanToString(const xalan::XalanDOMString& text) { - xalan::CharVectorType castHelper; - text.transcode(castHelper); - - return std::string( - castHelper.begin(), - castHelper.end() - 1 - ); -} - -} +#include "support/utility.h" namespace InputXSLT { diff --git a/src/support/utility.h b/src/support/utility.h new file mode 100644 index 0000000..4c63c72 --- /dev/null +++ b/src/support/utility.h @@ -0,0 +1,18 @@ +#ifndef INPUTXSLT_SRC_SUPPORT_UTILITY_H_ +#define INPUTXSLT_SRC_SUPPORT_UTILITY_H_ + +namespace { + +inline std::string xalanToString(const xalan::XalanDOMString& text) { + xalan::CharVectorType castHelper; + text.transcode(castHelper); + + return std::string( + castHelper.begin(), + castHelper.end() - 1 + ); +} + +} + +#endif // INPUTXSLT_SRC_SUPPORT_UTILITY_H_ diff --git a/src/transformation_facade.cc b/src/transformation_facade.cc index 38dfe93..cb89263 100644 --- a/src/transformation_facade.cc +++ b/src/transformation_facade.cc @@ -15,7 +15,8 @@ namespace InputXSLT { TransformationFacade::TransformationFacade(const std::string& transformation): fs_context_(boost::filesystem::path(transformation).parent_path().string()), transformation_{}, - transformer_() { + transformer_(), + document_cache_() { const xalan::XalanDOMString customNamespace( "http://ExternalFunction.xalan-c++.xml.apache.org" ); @@ -35,7 +36,7 @@ TransformationFacade::TransformationFacade(const std::string& transformation): this->transformer_.installExternalFunction( customNamespace, xalan::XalanDOMString("read-directory"), - InputXSLT::FunctionReadDirectory(this->fs_context_) + InputXSLT::FunctionReadDirectory(this->fs_context_, this->document_cache_) ); this->transformer_.compileStylesheet( diff --git a/src/transformation_facade.h b/src/transformation_facade.h index 765a376..3acb364 100644 --- a/src/transformation_facade.h +++ b/src/transformation_facade.h @@ -7,6 +7,7 @@ #include "common.h" #include "support/filesystem_context.h" +#include "support/dom/document_cache.h" namespace InputXSLT { @@ -22,6 +23,7 @@ class TransformationFacade { const xalan::XalanCompiledStylesheet* transformation_; xalan::XalanTransformer transformer_; + DomDocumentCache document_cache_; }; |