#ifndef JEZUK_DOM_NODE_H #define JEZUK_DOM_NODE_H //////////////////////////// // C++ DOM definition //////////////////////////// #include #include #include #include #include namespace Arabica { namespace DOM { namespace Events { template class EventTarget; } // namespace Events template class Document; template class NodeList; template class NamedNodeMap; template class Node_impl; class Node_base { public: typedef int Type; static const int ELEMENT_NODE = 1; static const int ATTRIBUTE_NODE = 2; static const int TEXT_NODE = 3; static const int CDATA_SECTION_NODE = 4; static const int ENTITY_REFERENCE_NODE = 5; static const int ENTITY_NODE = 6; static const int PROCESSING_INSTRUCTION_NODE = 7; static const int COMMENT_NODE = 8; static const int DOCUMENT_NODE = 9; static const int DOCUMENT_TYPE_NODE = 10; static const int DOCUMENT_FRAGMENT_NODE = 11; static const int NOTATION_NODE = 12; static const int MAX_TYPE = 13; }; // class Node_base ///////////////////////////////////////////////// template > class Node : public Node_base { public: Node() : impl_() { } Node(Node_impl* const impl) : impl_(impl) { } Node(const Node& rhs) : impl_(rhs.impl_) { } virtual ~Node() { } operator bool() const { return impl_; } bool operator< (const Node& rhs) const { return impl_ < rhs.impl_; } bool operator==(const Node& rhs) const { return impl_ == rhs.impl_; } bool operator!=(const Node& rhs) const { return impl_ != rhs.impl_; } bool operator==(int dummy) const { return impl_ == dummy; } bool operator!=(int dummy) const { return impl_ != dummy; } Node& operator=(const Node& rhs) { impl_ = rhs.impl_; return *this; } // operator= const stringT& getNodeName() const { return impl_->getNodeName(); } const stringT& getNodeValue() const { return impl_->getNodeValue(); } void setNodeValue(const stringT& nodeValue) { impl_->setNodeValue(nodeValue); } Type getNodeType() const { return impl_->getNodeType(); } Node getParentNode() const { return impl_->getParentNode(); } const NodeList getChildNodes() const { return NodeList(impl_->getChildNodes()); } Node getFirstChild() const { return impl_->getFirstChild(); } Node getLastChild() const { return impl_->getLastChild(); } Node getPreviousSibling() const { return impl_->getPreviousSibling(); } Node getNextSibling() const { return impl_->getNextSibling(); } const NamedNodeMap getAttributes() const { return NamedNodeMap(impl_->getAttributes()); } Document getOwnerDocument() const { return impl_->getOwnerDocument(); } Node insertBefore(const Node& newChild, const Node& refChild) { return impl_->insertBefore(*newChild.impl_, *refChild.impl_); } Node replaceChild(const Node& newChild, const Node& oldChild) { return impl_->replaceChild(*newChild.impl_, *oldChild.impl_); } Node removeChild(const Node& oldChild) { return impl_->removeChild(*oldChild.impl_); } Node appendChild(const Node& newChild) { return impl_->appendChild(*newChild.impl_); } void purgeChild(Node& oldChild) { Node_impl* child = *oldChild.impl_; oldChild = 0; try { impl_->purgeChild(child); } catch(DOMException&) { oldChild = child; throw; } // catch } // purge bool hasChildNodes() const { return impl_->hasChildNodes(); } Node cloneNode(bool deep) const { return impl_->cloneNode(deep); } void normalize() { impl_->normalize(); } bool isSupported(const stringT& feature, const stringT& version) const { return impl_->isSupported(feature, version); } const stringT& getNamespaceURI() const { return impl_->getNamespaceURI(); } const stringT& getPrefix() const { return impl_->getPrefix(); } void setPrefix(const stringT& prefix) const { impl_->setPrefix(prefix); } const stringT& getLocalName() const { return impl_->getLocalName(); } // additional three methods - since C++ std::string (and by implication // stringT) don't differenciate between a null string and an empty string, // but the DOM recommendation does, I have to introduce these three methods // to disambiguate. If they return false, the corresponding attribute should be // considered null. If they return true, the attribute has been set EVEN IF // it has been set to the empty string bool hasNamespaceURI() const { return impl_->hasNamespaceURI(); } bool hasPrefix() const { return impl_->hasPrefix(); } bool hasAttributes() const { return impl_->hasAttributes(); } // you almost certainly don't need to use this function Node_impl* underlying_impl() const { return *impl_; } void set_underlying_impl(Node_impl* new_impl) { impl_ = new_impl; } protected: Proxy > impl_; typedef class Document DocumentT; friend class Document; friend class NamedNodeMap; typedef class Events::EventTarget EventTargetT; friend class Events::EventTarget; }; // class Node //////////////////////////////////////////////////////////////////// // derive from this class to implement your own // DOM provider template class Document_impl; template class NodeList_impl; template class NamedNodeMap_impl; template class Node_impl { public: virtual ~Node_impl() { } /////////////////////////////////////////////////////// // Ref counting virtual void addRef() = 0; virtual void releaseRef() = 0; /////////////////////////////////////////////////////// // Node methods virtual const stringT& getNodeName() const = 0; virtual const stringT& getNodeValue() const = 0; virtual void setNodeValue(const stringT& nodeValue) = 0; virtual Node_base::Type getNodeType() const = 0; virtual Node_impl* getParentNode() const = 0; virtual NodeList_impl* getChildNodes() const = 0; virtual Node_impl* getFirstChild() const = 0; virtual Node_impl* getLastChild() const = 0; virtual Node_impl* getPreviousSibling() const = 0; virtual Node_impl* getNextSibling() const = 0; virtual NamedNodeMap_impl* getAttributes() const = 0; virtual Document_impl* getOwnerDocument() const = 0; virtual Node_impl* insertBefore(Node_impl* newChild, Node_impl* refChild) = 0; virtual Node_impl* replaceChild(Node_impl* newChild, Node_impl* oldChild) = 0; virtual Node_impl* removeChild(Node_impl* oldChild) = 0; virtual Node_impl* appendChild(Node_impl* newChild) = 0; virtual void purgeChild(Node_impl* oldChild) = 0; virtual bool hasChildNodes() const = 0; virtual Node_impl* cloneNode(bool deep) const = 0; virtual void normalize() = 0; virtual bool isSupported(const stringT& feature, const stringT& version) const = 0; virtual const stringT& getNamespaceURI() const = 0; virtual const stringT& getPrefix() const = 0; virtual void setPrefix(const stringT& prefix) = 0; virtual const stringT& getLocalName() const = 0; // additional methods - since C++ std::string (and by implication // stringT) don't differenciate between a null string and an empty string, // but the DOM recommendation does, I have to introduce these three methods // to disambiguate. If they return false, the corresponding attribute should be // considered null. If they return true, the attribute has been set EVEN IF // it has been set to the empty string virtual bool hasNamespaceURI() const = 0; virtual bool hasPrefix() const = 0; virtual bool hasAttributes() const = 0; }; // class Node_impl } // namespace DOM } // namespace Arabica #endif // JEZUK_DOM_NODE_H // end of file