#ifndef JEZUK_SimpleDOM_ATTRMAP_H #define JEZUK_SimpleDOM_ATTRMAP_H #include #include #include namespace Arabica { namespace SimpleDOM { template class AttrMap : public NamedNodeMapImpl { public: typedef NamedNodeMapImpl NamedNodeMapImplT; typedef AttrImpl AttrImplT; typedef AttrNSImpl AttrNSImplT; typedef ElementImpl ElementImplT; typedef DocumentImpl DocumentImplT; typedef DocumentTypeImpl DocumentTypeImplT; typedef DOM::Node_impl DOMNode_implT; typedef DOM::Attr_impl DOMAttr_implT; typedef DOM::NamedNodeMap_impl DOMNamedNodeMap_implT; AttrMap(DocumentImplT* ownerDoc) : NamedNodeMapImplT(ownerDoc), ownerElement_(0) { } // AttrMap ~AttrMap() { } // ~AttrMap ///////////////////////////////////////////////////// virtual DOMNode_implT* setNamedItem(DOMNode_implT* newAttr) { AttrImplT* attr = dynamic_cast(newAttr); if(alreadyHere(attr)) return attr; NamedNodeMapImplT::throwIfReadOnly(); checkNotInUse(attr); attr->setOwnerElement(ownerElement_); return dynamic_cast(NamedNodeMapImplT::setNamedItem(attr)); } // setNamedItem virtual DOMNode_implT* removeNamedItem(const stringT& name) { DOMNode_implT* n = NamedNodeMapImplT::removeNamedItem(name); createDefault(name); return n; } // removeNamedItem virtual DOMNode_implT* removeNamedItemNS(const stringT& namespaceURI, const stringT& localName) { DOMNode_implT* n = NamedNodeMapImplT::removeNamedItemNS(namespaceURI, localName); createDefault(namespaceURI, localName); return n; } // removedNamedItemNS ///////////////////////////////////////////////////// const stringT& getAttribute(const stringT& name) const { DOMNode_implT* attr = NamedNodeMapImplT::getNamedItem(name); return attr ? attr->getNodeValue() : NamedNodeMapImplT::ownerDoc_->empty_string(); } // getAttribute void setAttribute(const stringT& name, const stringT& value) { AttrImplT* a = new AttrImplT(NamedNodeMapImplT::ownerDoc_, name, value); a->setOwnerElement(ownerElement_); NamedNodeMapImplT::setNamedItem(a); } // setAttribute void removeAttribute(const stringT& name) { removeNamedItem(name); } // removeAttribute DOMAttr_implT* getAttributeNode(const stringT& name) const { return dynamic_cast(NamedNodeMapImplT::getNamedItem(name)); } // getAttributeNode DOMAttr_implT* setAttributeNode(DOMAttr_implT* newAttr) { return dynamic_cast(setNamedItem(newAttr)); } // setAttributeNode DOMAttr_implT* removeAttributeNode(DOMAttr_implT* oldAttr) { if(oldAttr->getOwnerElement() != ownerElement_) throw DOM::DOMException(DOM::DOMException::NOT_FOUND_ERR); removeNamedItem(oldAttr->getNodeName()); return oldAttr; } // removeAttributeNode stringT getAttributeNS(const stringT& namespaceURI, const stringT& localName) const { DOMNode_implT* attr = NamedNodeMapImplT::getNamedItemNS(namespaceURI, localName); return attr ? attr->getNodeValue() : stringT(); } // getAttributeNS void setAttributeNS(const stringT& namespaceURI, const stringT& qualifiedName, const stringT& value) { AttrNSImplT* a = new AttrNSImplT(NamedNodeMapImplT::ownerDoc_, namespaceURI, !string_adaptorT::empty(namespaceURI), qualifiedName); a->setValue(value); a->setOwnerElement(ownerElement_); NamedNodeMapImplT::setNamedItemNS(a); } // setAttributeNS void removeAttributeNS(const stringT& namespaceURI, const stringT& localName) { removeNamedItemNS(namespaceURI, localName); } // removeAttributeNS DOMAttr_implT* getAttributeNodeNS(const stringT& namespaceURI, const stringT& localName) const { return dynamic_cast(NamedNodeMapImplT::getNamedItemNS(namespaceURI, localName)); } // getAttributeNodeNS DOMAttr_implT* setAttributeNodeNS(DOMAttr_implT* newAttr) { return dynamic_cast(setNamedItemNS(newAttr)); } // setAttributeNodeNS virtual DOMNode_implT* setNamedItemNS(DOMNode_implT* newAttr) { AttrImplT* attr = dynamic_cast(newAttr); if(alreadyHere(attr)) return attr; NamedNodeMapImplT::throwIfReadOnly(); checkNotInUse(attr); attr->setOwnerElement(ownerElement_); return dynamic_cast(NamedNodeMapImplT::setNamedItemNS(newAttr)); } // setNamedItem bool hasAttribute(const stringT& name) const { return (NamedNodeMapImplT::getNamedItem(name) != 0); } // hasAttribute bool hasAttributeNS(const stringT& namespaceURI, const stringT& localName) const { return (NamedNodeMapImplT::getNamedItemNS(namespaceURI, localName) != 0); } // hasAttributeNS void setOwnerElement(ElementImplT* element) { ownerElement_ = element; getDefaults(); } // setOwnerElement virtual void setOwnerDoc(DocumentImplT* ownerDoc) { NamedNodeMapImplT::setOwnerDoc(ownerDoc); getDefaults(); } // setOwnerDoc private: void createDefault(const stringT& name) { DOMNamedNodeMap_implT* attrs = getDefaultAttrs(); if(attrs) { DOMNode_implT* attr = attrs->getNamedItem(name); if(attr) setAttributeNode(dynamic_cast(attr->cloneNode(true))); } } // createDefault void createDefault(const stringT& namespaceURI, const stringT& localName) { DOMNamedNodeMap_implT* attrs = getDefaultAttrs(); if(attrs) { DOMNode_implT* attr = attrs->getNamedItemNS(namespaceURI, localName); if(attr) setAttributeNodeNS(dynamic_cast(attr->cloneNode(true))); } } // createDefault void getDefaults() { DOMNamedNodeMap_implT* attrs = getDefaultAttrs(); if(attrs) { for(unsigned int i = 0; i < attrs->getLength(); ++i) { DOMNode_implT* attr = attrs->item(i); if(getAttributeNodeNS(attr->getNamespaceURI(), attr->getNodeName()) == 0) setAttributeNodeNS(dynamic_cast(attr->cloneNode(true))); } } } // getDefaults DOMNamedNodeMap_implT* getDefaultAttrs() { if(!NamedNodeMapImplT::ownerDoc_) return 0; DocumentTypeImplT* docType = dynamic_cast(NamedNodeMapImplT::ownerDoc_->getDoctype()); if(docType) { DOMNode_implT* exemplar = docType->getElements()->getNamedItem(ownerElement_->getNodeName()); if(exemplar) return exemplar->getAttributes(); } return 0; } // getDefaultAttrs bool alreadyHere(AttrImplT* attr) { return ((!attr->isOrphaned()) && (attr->getOwnerElement() == ownerElement_)); } // alreadyHere void checkNotInUse(AttrImplT* attr) { if((!attr->isOrphaned()) && (attr->getOwnerElement() != ownerElement_)) throw DOM::DOMException(DOM::DOMException::INUSE_ATTRIBUTE_ERR); } // checkNotInUse ElementImplT* ownerElement_; }; // class AttrMap } // namespace SAX2DOM } // namespace Arabica #endif