#ifndef JEZUK_SimpleDOM_NAMEDNODEMAPIMPL_H #define JEZUK_SimpleDOM_NAMEDNODEMAPIMPL_H #include #include #include #include #include namespace Arabica { namespace SimpleDOM { template class nameIs { public: explicit nameIs(const stringT& name) : name_(name) { } bool operator()(const Arabica::SimpleDOM::NodeImpl* node) const { return node->getNodeName() == name_; } // operator() private: stringT name_; }; // class nameIs template class namespaceAndNameIs { public: namespaceAndNameIs(const stringT& namespaceURI, const stringT& localName) : namespaceURI_(namespaceURI), localName_(localName) { } bool operator()(const NodeImpl* node) const { if(string_adaptorT::empty(namespaceURI_)) { if((node->hasNamespaceURI() == false) && ((node->getLocalName() == localName_) || (string_adaptorT::empty(node->getLocalName()) && node->getNodeName() == localName_) ) ) return true; } // if(namespaceURI_.empty()) if((node->getNamespaceURI() == namespaceURI_) && (node->getLocalName() == localName_)) return true; return false; } // operator() private: stringT namespaceURI_; stringT localName_; }; // class namespaceAndNameIs template class NamedNodeMapImpl : public DOM::NamedNodeMap_impl { public: typedef DOM::Node_impl DOMNode_implT; typedef NodeImpl NodeImplT; typedef NamedNodeMapImpl NamedNodeMapImplT; typedef DocumentImpl DocumentImplT; NamedNodeMapImpl(DocumentImplT* ownerDoc) : DOM::NamedNodeMap_impl(), nodes_(), readOnly_(false), ownerDoc_(ownerDoc) { } // NamedNodeMapImpl virtual ~NamedNodeMapImpl() { for(typename NodeListT::iterator i = nodes_.begin(); i != nodes_.end(); ++i) delete (*i); } // ~NodeImpl /////////////////////////////////////////////////////// // Ref counting virtual void addRef() { if(ownerDoc_) ownerDoc_->addRef(); } // addRef virtual void releaseRef() { if(ownerDoc_) ownerDoc_->releaseRef(); } // releaseRef virtual void setOwnerDoc(DocumentImplT* ownerDoc) { ownerDoc_ = ownerDoc; for(typename NodeListT::iterator i = nodes_.begin(); i != nodes_.end(); ++i) (*i)->setOwnerDoc(ownerDoc); } // setOwnerDoc /////////////////////////////////////////////////// // DOM::NamedNodeMap methods virtual DOMNode_implT* getNamedItem(const stringT& name) const { return getNode(const_cast(this)->findByName(name)); } // getNamedItem virtual DOMNode_implT* setNamedItem(DOMNode_implT* arg) { throwIfReadOnly(); checkOwnerDocument(arg); return setNode(findByName(arg->getNodeName()), dynamic_cast(arg)); } // setNamedItem virtual DOMNode_implT* removeNamedItem(const stringT& name) { throwIfReadOnly(); return removeNode(findByName(name)); } // removedNamedItem virtual DOMNode_implT* item(unsigned int index) const { return do_item(index); } // item virtual unsigned int getLength() const { return static_cast(nodes_.size()); } // getLength virtual DOMNode_implT* getNamedItemNS(const stringT& namespaceURI, const stringT& localName) const { return getNode(const_cast(this)->findByNamespaceAndName(namespaceURI, localName)); } // getNamedItemNS virtual DOMNode_implT* setNamedItemNS(DOMNode_implT* arg) { throwIfReadOnly(); checkOwnerDocument(arg); return setNode(findByNamespaceAndName(arg->getNamespaceURI(), arg->getLocalName()), dynamic_cast(arg)); } // setNamedItemNS virtual DOMNode_implT* removeNamedItemNS(const stringT& namespaceURI, const stringT& localName) { throwIfReadOnly(); return removeNode(findByNamespaceAndName(namespaceURI, localName)); } // removeNamedItemNS /////////////////////////////////////////////////////// // extensions void setReadOnly(bool readOnly) { readOnly_ = readOnly; } // setReadOnly NodeImplT* do_item(unsigned int index) const { if(index >= nodes_.size()) return 0; return nodes_[index]; } // item protected: void throwIfReadOnly() const { if(readOnly_) throw DOM::DOMException(DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR); } // throwIfReadOnly void checkOwnerDocument(const DOMNode_implT* arg) { if(!ownerDoc_) return; if(arg->getOwnerDocument() != ownerDoc_) throw DOM::DOMException(DOM::DOMException::WRONG_DOCUMENT_ERR); } // checkOwnerDocument private: typedef std::deque NodeListT; NodeImplT* getNode(typename NodeListT::const_iterator n) const { if(n == nodes_.end()) return 0; return *n; } // getNode NodeImplT* setNode(typename NodeListT::iterator n, NodeImplT* arg) { if(ownerDoc_) ownerDoc_->adopted(arg); if(n == nodes_.end()) { nodes_.push_back(arg); return 0; } // if(n == nodes_.end()) NodeImplT* removedNode = *n; *n = arg; ownerDoc_->orphaned(removedNode); return removedNode; } // setNode NodeImplT* removeNode(typename NodeListT::iterator n) { if(n == nodes_.end()) throw DOM::DOMException(DOM::DOMException::NOT_FOUND_ERR); NodeImplT* removedNode = *n; nodes_.erase(n); ownerDoc_->orphaned(removedNode); return removedNode; } // removeNode typename NodeListT::iterator findByName(const stringT& name) { return std::find_if(nodes_.begin(), nodes_.end(), nameIs(name)); } // findByName typename NodeListT::iterator findByNamespaceAndName(const stringT& namespaceURI, const stringT& localName) { return std::find_if(nodes_.begin(), nodes_.end(), namespaceAndNameIs(namespaceURI, localName)); } // findByName NodeListT nodes_; bool readOnly_; protected: DocumentImplT* ownerDoc_; }; // class NamedNodeMapImpl } // namespace SAX2DOM } // namespace Arabica #endif