Skip to content
Snippets Groups Projects
DOMDocumentImpl.cpp 37 KiB
Newer Older
                srcdoctype->getSystemId());
            // Values are on NamedNodeMaps
            DOMNamedNodeMap *smap = srcdoctype->getEntities();
            DOMNamedNodeMap *tmap = newdoctype->getEntities();
            if(smap != 0) {
                for(XMLSize_t i = 0; i < smap->getLength(); i++) {
                    tmap->setNamedItem(importNode(smap->item(i), true, false));
                }
            }
            smap = srcdoctype->getNotations();
            tmap = newdoctype->getNotations();
            if (smap != 0) {
                for(XMLSize_t i = 0; i < smap->getLength(); i++) {
                    tmap->setNamedItem(importNode(smap->item(i), true, false));
                }
            }
            // NOTE: At this time, the DOM definition of DocumentType
            // doesn't cover Elements and their Attributes. domimpl's
            // extentions in that area will not be preserved, even if
            // copying from domimpl to domimpl. We could special-case
            // that here. Arguably we should. Consider. ?????
            newnode = newdoctype;
        }
        break;
    case DOMNode::DOCUMENT_FRAGMENT_NODE :
        newnode = createDocumentFragment();
        // No name, kids carry value
        break;
    case DOMNode::NOTATION_NODE :
        {
            DOMNotation *srcnotation=(DOMNotation *)source;
            DOMNotationImpl *newnotation = (DOMNotationImpl *)createNotation(source->getNodeName());
            newnotation->setPublicId(srcnotation->getPublicId());
            newnotation->setSystemId(srcnotation->getSystemId());
            // Kids carry additional value
            newnode=newnotation;
            // No name, no value
            break;
        }

    case DOMNode::DOCUMENT_NODE : // Document can't be child of Document
    default:                       // Unknown node type
        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
    }

    // If deep, replicate and attach the kids.
    if (deep)
        for (DOMNode *srckid = source->getFirstChild();
             srckid != 0;
             srckid = srckid->getNextSibling())
        {
            newnode->appendChild(importNode(srckid, true, false));
        }

    if (newnode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE
        || newnode->getNodeType() == DOMNode::ENTITY_NODE) {
        castToNodeImpl(newnode)->setReadOnly(true, true);
        errorChecking = oldErrorCheckingFlag;
    }

    if (!cloningDoc)
        fNode.callUserDataHandlers(DOMUserDataHandler::NODE_IMPORTED, source, newnode);

    return newnode;
}

// user data utility
void* DOMDocumentImpl::setUserData(DOMNodeImpl* n, const XMLCh* key, void* data, DOMUserDataHandler* handler)
{
    void* oldData = 0;
    DOMNode_UserDataTable* node_userDataTable = 0;

    if (!fUserDataTable) {
        // create the table on heap so that it can be cleaned in destructor
        fUserDataTable = new (this) RefHashTableOf<DOMNode_UserDataTable>(29, true, new HashPtr());
    }
    else {
        node_userDataTable = fUserDataTable->get((void*)n);
        DOMUserDataRecord* oldDataRecord = 0;

        if (node_userDataTable) {
            oldDataRecord = node_userDataTable->get((void*)key);

            if (oldDataRecord) {
                oldData = oldDataRecord->getKey();
                node_userDataTable->removeKey((void*)key);
            }
        }
    }

    if (data) {

        // create the DOMNode_UserDataTable if not exists
        // create on the heap and adopted by the hashtable which will delete it upon removal.
        if (!node_userDataTable) {
            node_userDataTable  = new RefHashTableOf<DOMUserDataRecord>(29, true);
            fUserDataTable->put(n, node_userDataTable);
        }

        // clone the key first, and create the DOMUserDataRecord
        // create on the heap and adopted by the hashtable which will delete it upon removal.
        node_userDataTable->put((void*)getPooledString(key), new DOMUserDataRecord(data, handler));
    }
    else {
        if (node_userDataTable->isEmpty())
            n->hasUserData(false);
    }

    return oldData;
}

void* DOMDocumentImpl::getUserData(const DOMNodeImpl* n, const XMLCh* key) const
{
    if (fUserDataTable) {
        DOMNode_UserDataTable*  node_userDataTable = fUserDataTable->get((void*)n);

        if (node_userDataTable) {
            DOMUserDataRecord* dataRecord = node_userDataTable->get((void*)key);
            if (dataRecord)
                return dataRecord->getKey();
        }
    }

    return 0;
}

void DOMDocumentImpl::callUserDataHandlers(const DOMNodeImpl* n, DOMUserDataHandler::DOMOperationType operation, const DOMNode* src, const DOMNode* dst) const
{
    if (fUserDataTable) {
        DOMNode_UserDataTable*  node_userDataTable = fUserDataTable->get((void*)n);

        if (node_userDataTable) {
            RefHashTableOfEnumerator<DOMUserDataRecord> userDataEnum(node_userDataTable);

            // walk through the entire node_userDataTable table
            while (userDataEnum.hasMoreElements()) {
                // get the key
                XMLCh* key = (XMLCh*) userDataEnum.nextElementKey();

                // get the DOMUserDataRecord
                DOMUserDataRecord* userDataRecord = node_userDataTable->get((void*)key);

                // get the handler
                DOMUserDataHandler* handler = userDataRecord->getValue();

                if (handler) {
                    // get the data
                    void* data = userDataRecord->getKey();
                    handler->handle(operation, key, data, src, dst);
                }
            }
        }
    }
}