arabica/include/DOM/Simple/AttrMap.hpp

237 lines
7.7 KiB
C++

#ifndef JEZUK_SimpleDOM_ATTRMAP_H
#define JEZUK_SimpleDOM_ATTRMAP_H
#include <DOM/Simple/NamedNodeMapImpl.hpp>
#include <DOM/Simple/AttrImpl.hpp>
#include <DOM/Simple/AttrNSImpl.hpp>
namespace Arabica
{
namespace SimpleDOM
{
template<class stringT, class string_adaptorT>
class AttrMap : public NamedNodeMapImpl<stringT, string_adaptorT>
{
public:
typedef NamedNodeMapImpl<stringT, string_adaptorT> NamedNodeMapImplT;
typedef AttrImpl<stringT, string_adaptorT> AttrImplT;
typedef AttrNSImpl<stringT, string_adaptorT> AttrNSImplT;
typedef ElementImpl<stringT, string_adaptorT> ElementImplT;
typedef DocumentImpl<stringT, string_adaptorT> DocumentImplT;
typedef DocumentTypeImpl<stringT, string_adaptorT> DocumentTypeImplT;
typedef DOM::Node_impl<stringT, string_adaptorT> DOMNode_implT;
typedef DOM::Attr_impl<stringT, string_adaptorT> DOMAttr_implT;
typedef DOM::NamedNodeMap_impl<stringT, string_adaptorT> DOMNamedNodeMap_implT;
AttrMap(DocumentImplT* ownerDoc) :
NamedNodeMapImplT(ownerDoc),
ownerElement_(0)
{
} // AttrMap
~AttrMap()
{
} // ~AttrMap
/////////////////////////////////////////////////////
virtual DOMNode_implT* setNamedItem(DOMNode_implT* newAttr)
{
AttrImplT* attr = dynamic_cast<AttrImplT*>(newAttr);
if(alreadyHere(attr))
return attr;
NamedNodeMapImplT::throwIfReadOnly();
checkNotInUse(attr);
attr->setOwnerElement(ownerElement_);
return dynamic_cast<DOMAttr_implT*>(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<DOMAttr_implT*>(NamedNodeMapImplT::getNamedItem(name));
} // getAttributeNode
DOMAttr_implT* setAttributeNode(DOMAttr_implT* newAttr)
{
return dynamic_cast<DOMAttr_implT*>(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<DOMAttr_implT*>(NamedNodeMapImplT::getNamedItemNS(namespaceURI, localName));
} // getAttributeNodeNS
DOMAttr_implT* setAttributeNodeNS(DOMAttr_implT* newAttr)
{
return dynamic_cast<DOMAttr_implT*>(setNamedItemNS(newAttr));
} // setAttributeNodeNS
virtual DOMNode_implT* setNamedItemNS(DOMNode_implT* newAttr)
{
AttrImplT* attr = dynamic_cast<AttrImplT*>(newAttr);
if(alreadyHere(attr))
return attr;
NamedNodeMapImplT::throwIfReadOnly();
checkNotInUse(attr);
attr->setOwnerElement(ownerElement_);
return dynamic_cast<DOMAttr_implT*>(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<DOMAttr_implT*>(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<DOMAttr_implT*>(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<DOMAttr_implT*>(attr->cloneNode(true)));
}
}
} // getDefaults
DOMNamedNodeMap_implT* getDefaultAttrs()
{
if(!NamedNodeMapImplT::ownerDoc_)
return 0;
DocumentTypeImplT* docType = dynamic_cast<DocumentTypeImplT*>(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