/* * (C) Copyright The MITRE Corporation 1999 All rights reserved. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * The program provided "as is" without any warranty express or * implied, including the warranty of non-infringement and the implied * warranties of merchantibility and fitness for a particular purpose. * The Copyright owner will not be liable for any damages suffered by * you as a result of using the Program. In no event will the Copyright * owner be liable for any special, indirect or consequential damages or * lost profits even if the Copyright owner has been advised of the * possibility of their occurrence. * * Please see release.txt distributed with this file for more information. * */ // Tom Kneeland (01/18/2000) // // Implementation of the Mozilla Wrapper class for the Document Object. // // Modification History: // Who When What // TK 02/11/2000 Added default constructor. If no NS object is provided // simply create an nsXMLDocument to use. // TK 02/15/2000 Fixed bug in Create Wrapper. We must check to see if the // the nsIDOM* object is NULL. If it is, then we don't need // a wrapper. // Also fixed the same problem with the other factory methods // that create wrappers for Mozilla objects. // #include "mozilladom.h" #include "nsXMLDocument.h" #include "iostream.h" // //Construct a Document Wrapper object without specificy a nsIDOMDocument //object. We will create an ns // Document::Document() { nsDocument = new nsXMLDocument(); Node::setNSObj(nsDocument, this); } // //Construct a Document Wrapper object with a nsIDOMDocument object // Document::Document(nsIDOMDocument* document) : Node(document, this) { nsDocument = document; } // //Clean up the private data members // Document::~Document() { } // //Provide an nsIDOMDocument object for wrapping // void Document::setNSObj(nsIDOMDocument* document) { Node::setNSObj(document); nsDocument = document; } // //Call nsIDOMDocument::GetDocumentElement to retreive the element for this //document. Then call the createElement factory method to retreive an element //wrapper for this object. // Element* Document::getDocumentElement() { nsIDOMElement* theElement = NULL; Element* elemWrapper = NULL; nsresult retval = 5; if (nsDocument == NULL) return NULL; //retval = nsDocument->GetDocumentElement(&theElement); //if (retval == NS_OK) if ((retval = nsDocument->GetDocumentElement(&theElement)) == NS_OK) { cout << "Document::getDocumentElement - Mozilla Call ok" << endl; return createElement(theElement); } else { cout << "Document::getDocumentElement - Mozilla Call not ok(" << hex <GetDoctype(&theDocType) == NS_OK) return createDocumentType(theDocType); else return NULL; } // //Return a constant reference to the DOM's Implementation // DOMImplementation* Document::getImplementation() { nsIDOMDOMImplementation* theImpl = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->GetImplementation(&theImpl) == NS_OK) return createDOMImplementation(theImpl); else return NULL; } // // DEFFER this functionality to the NODE parent class //Ensure that no Element node is inserted if the document already has an //associated Element child. // /* Node* Document::insertBefore(Node* newChild, Node* refChild) { Node* returnVal = NULL; NodeDefinition* pCurrentNode = NULL; NodeDefinition* pNextNode = NULL; //Convert to a NodeDefinition Pointer NodeDefinition* pNewChild = (NodeDefinition*)newChild; NodeDefinition* pRefChild = (NodeDefinition*)refChild; //Check to see if the reference node is a child of this node if ((refChild != NULL) && (pRefChild->getParentNode() != this)) return NULL; switch (pNewChild->getNodeType()) { case Node::DOCUMENT_FRAGMENT_NODE : pCurrentNode = (NodeDefinition*)pNewChild->getFirstChild(); while (pCurrentNode) { pNextNode = (NodeDefinition*)pCurrentNode->getNextSibling(); //Make sure that if the current node is an Element, the document //doesn't already have one. if ((pCurrentNode->getNodeType() != Node::ELEMENT_NODE) || ((pCurrentNode->getNodeType() == Node::ELEMENT_NODE) && (documentElement == NULL))) { pCurrentNode = (NodeDefinition*)pNewChild->removeChild(pCurrentNode); implInsertBefore(pCurrentNode, pRefChild); if (pCurrentNode->getNodeType() == Node::ELEMENT_NODE) documentElement = (Element*)pCurrentNode; } pCurrentNode = pNextNode; } returnVal = newChild; break; case Node::PROCESSING_INSTRUCTION_NODE : case Node::COMMENT_NODE : case Node::DOCUMENT_TYPE_NODE : returnVal = implInsertBefore(pNewChild, pRefChild); break; case Node::ELEMENT_NODE : if (!documentElement) { documentElement = (Element*)pNewChild; returnVal = implInsertBefore(pNewChild, pRefChild); } else returnVal = NULL; break; default: returnVal = NULL; } return returnVal; } */ // // DEFFER this functionality to the NODE implementation //Ensure that if the newChild is an Element and the Document already has an //element, then oldChild should be specifying the existing element. If not //then the replacement can not take place. // /* Node* Document::replaceChild(Node* newChild, Node* oldChild) { Node* replacedChild = NULL; if (newChild->getNodeType() != Node::ELEMENT_NODE) { //The new child is not an Element, so perform replacement replacedChild = NodeDefinition::replaceChild(newChild, oldChild); //If old node was an Element, then the document's element has been //replaced with a non-element node. Therefore clear the documentElement //pointer if (replacedChild && (oldChild->getNodeType() == Node::ELEMENT_NODE)) documentElement = NULL; return replacedChild; } else { //A node is being replaced with an Element. If the document does not //have an elemet yet, then just allow the replacemetn to take place. if (!documentElement) replacedChild = NodeDefinition::replaceChild(newChild, oldChild); else if (oldChild->getNodeType() == Node::ELEMENT_NODE) replacedChild = NodeDefinition::replaceChild(newChild, oldChild); if (replacedChild) documentElement = (Element*)newChild; return replacedChild; } } */ // // DEFFER this functionality to the NODE Implementation //Update the documentElement pointer if the associated Element node is being //removed. // /* Node* Document::removeChild(Node* oldChild) { Node* removedChild = NULL; removedChild = NodeDefinition::removeChild(oldChild); if (removedChild && (removedChild->getNodeType() == Node::ELEMENT_NODE)) documentElement = NULL; return removedChild; } */ // //Call the nsIDOMDocument::CreateDocumentFragment function, then create or //retrieve a wrapper class for it. // DocumentFragment* Document::createDocumentFragment() { nsIDOMDocumentFragment* fragment = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateDocumentFragment(&fragment) == NS_OK) return createDocumentFragment(fragment); else return NULL; } // //Check the wrapperHashTable for a preexisting wrapper object. If it does not // exists, create one and store it in the hash table. If it does exist, simply // return it to the caller. // DocumentFragment* Document::createDocumentFragment(nsIDOMDocumentFragment* fragment) { DocumentFragment* docFragWrapper = NULL; if (fragment) { docFragWrapper = (DocumentFragment*)wrapperHashTable.retrieve((Int32)fragment); if (!docFragWrapper) { docFragWrapper = new DocumentFragment(fragment, this); wrapperHashTable.add(docFragWrapper, (Int32)fragment); } } return docFragWrapper; } // //Call the nsIDOMDocument::CreateElement function, and retrieve or create //a wrapper object for it. // Element* Document::createElement(const DOMString& tagName) { nsIDOMElement* element = NULL; if (nsDocument->CreateElement(tagName.getConstNSString(), &element) == NS_OK) return createElement(element); else return NULL; } // //Check the wrapperHashTable for a precreated wrapper object. If one exists, //return it to the caller. If it doens't exist, create one, store it in the //hash, and return it to the caller. // Element* Document::createElement(nsIDOMElement* element) { Element* elemWrapper = NULL; if (element) { elemWrapper = (Element*)wrapperHashTable.retrieve((Int32)element); if (!elemWrapper) { elemWrapper = new Element(element, this); wrapperHashTable.add(elemWrapper, (Int32)element); } } return elemWrapper; } // //Call the nsIDOMDocument::CreateAttribute function, then create or retrieve a //wrapper object for it. // Attr* Document::createAttribute(const DOMString& name) { nsIDOMAttr* attr = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateAttribute(name.getConstNSString(), &attr) == NS_OK) return createAttribute(attr); else return NULL; } // //Check the wrapperHashTable for a precreated object. If one exists, return it, //else, create one, store it in the table, and return it. // Attr* Document::createAttribute(nsIDOMAttr* attr) { Attr* attrWrapper = NULL; if (attr) { attrWrapper = (Attr*)wrapperHashTable.retrieve((Int32)attr); if (!attrWrapper) { attrWrapper = new Attr(attr, this); wrapperHashTable.add(attrWrapper, (Int32)attr); } } return attrWrapper; } // //Call the nsIDOMDocument::CreateTextNode function, then create, or retrieve a //wrapper object for it. // Text* Document::createTextNode(const DOMString& theData) { nsIDOMText* text = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateTextNode(theData.getConstNSString(), &text) == NS_OK) return createTextNode(text); else return NULL; } // //Check the wrapperHashTable to see if a precreated object exists. If it does //then return it. Else, create a new one, insert it into the hash table, and //then return it. // Text* Document::createTextNode(nsIDOMText* text) { Text* textWrapper = NULL; if (text) { textWrapper = (Text*)wrapperHashTable.retrieve((Int32)text); if (!textWrapper) { textWrapper = new Text(text, this); wrapperHashTable.add(textWrapper, (Int32)text); } } return textWrapper; } // //Call the nsIDOMDocument::CreateComment function, then create or retrieve a //wrapper object to return to the caller. // Comment* Document::createComment(const DOMString& theData) { nsIDOMComment* comment = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateComment(theData.getConstNSString(), &comment) == NS_OK) return createComment(comment); else return NULL; } // //Check the wrapperHashTable for a precreated object to return to the caller. //If one does not exist, create it, store it in the hash, and return it to the //caller. Comment* Document::createComment(nsIDOMComment* comment) { Comment* commentWrapper = NULL; if (comment) { commentWrapper = (Comment*)wrapperHashTable.retrieve((Int32)comment); if (!commentWrapper) { commentWrapper = new Comment(comment, this); wrapperHashTable.add(commentWrapper, (Int32)comment); } } return commentWrapper; } // //Call the nsIDOMDocument::CreateCDATASection function, then create or retrieve //a wrapper object to return to the caller. // CDATASection* Document::createCDATASection(const DOMString& theData) { nsIDOMCDATASection* cdata = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateCDATASection(theData.getConstNSString(), &cdata) == NS_OK) return createCDATASection(cdata); else return NULL; } // //Check to see if a precreated object exists in the wrapperHashTable. If so //simply return it to the caller. If not, creat one, store it in the hash, and //return it to the caller. // CDATASection* Document::createCDATASection(nsIDOMCDATASection* cdata) { CDATASection* cdataWrapper = NULL; if (cdata) { cdataWrapper = (CDATASection*)wrapperHashTable.retrieve((Int32)cdata); if (!cdataWrapper) { cdataWrapper = new CDATASection(cdata, this); wrapperHashTable.add(cdataWrapper, (Int32)cdata); } } return cdataWrapper; } // //Call the nsIDOMDocument::CreateProcessingInstruction function, then find or //create a wrapper class to return to the caller. // ProcessingInstruction* Document::createProcessingInstruction(const DOMString& target, const DOMString& data) { nsIDOMProcessingInstruction* pi = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateProcessingInstruction(target.getConstNSString(), data.getConstNSString(), &pi) == NS_OK) return createProcessingInstruction(pi); else return NULL; } // //Check the wrapperHashTable for a precreated object. If one exists, return //it to the caller. If not, create one, store it in the hash table, and then //return it to the caller. // ProcessingInstruction* Document::createProcessingInstruction(nsIDOMProcessingInstruction* pi) { ProcessingInstruction* piWrapper = NULL; if (pi) { piWrapper = (ProcessingInstruction*)wrapperHashTable.retrieve((Int32)pi); if (!piWrapper) { piWrapper = new ProcessingInstruction(pi, this); wrapperHashTable.add(piWrapper, (Int32)pi); } } return piWrapper; } // //Call the nsIDOMDocument::CreateEntityReference function, then obtain a wrapper //class to return to the user. // EntityReference* Document::createEntityReference(const DOMString& name) { nsIDOMEntityReference* entityRef = NULL; if (nsDocument == NULL) return NULL; if (nsDocument->CreateEntityReference(name.getConstNSString(), &entityRef) == NS_OK) return createEntityReference(entityRef); else return NULL; } // //Check the wrapperHashTable for a wrapper class. If one exists, simply return //it to the caller. Else, create one, place it in the hash, and return it to //the caller. // EntityReference* Document::createEntityReference(nsIDOMEntityReference* entityRef) { EntityReference* entityWrapper = NULL; if (entityRef) { entityWrapper = (EntityReference*) wrapperHashTable.retrieve((Int32)entityRef); if (!entityWrapper) { entityWrapper = new EntityReference(entityRef, this); wrapperHashTable.add(entityWrapper, (Int32)entityRef); } } return entityWrapper; } // //Check the wrapperHashTable for a wrapper class. If one exists, simply return //it to the caller. Else create one, place it in the hash table, and then return //it to the caller. Entity* Document::createEntity(nsIDOMEntity* entity) { Entity* entityWrapper = NULL; if (entity) { entityWrapper = (Entity*)wrapperHashTable.retrieve((Int32) entity); if (!entity) { entityWrapper = new Entity(entity, this); wrapperHashTable.add(entityWrapper, (Int32)entity); } } return entityWrapper; } // //Factory function for creating and hashing generic Node wrapper classes. //Check the wrapperHashTable to see if a wrapper object already exists. If it //does then return it. If one does not exist, then creat one, hash it, and //return it to the caller. // Node* Document::createNode(nsIDOMNode* node) { Node* nodeWrapper = NULL; if (node) { nodeWrapper = (Node*)wrapperHashTable.retrieve((Int32)node); if (!nodeWrapper) { nodeWrapper = new Node(node, this); wrapperHashTable.add(nodeWrapper, (Int32)node); } } return nodeWrapper; } // //Factory function for creating and hashing a DOMString object. Note that it //is specifically for wrapping nsString objects with MozillaString objects. //Once the object is created it is stored in the hash table. // DOMString* Document::createDOMString(nsString* str) { DOMString* strWrapper = NULL; if (str) { strWrapper = (DOMString*)wrapperHashTable.retrieve((Int32)str); if (!strWrapper) { strWrapper = new DOMString(str); wrapperHashTable.add(strWrapper, (Int32)str); } } return strWrapper; } // //Factory function for creating and hashing a Notation object. // Notation* Document::createNotation(nsIDOMNotation* notation) { Notation* notationWrapper = NULL; if (notation) { notationWrapper = (Notation*)wrapperHashTable.retrieve((Int32) notation); if (!notationWrapper) { notationWrapper = new Notation(notation, this); wrapperHashTable.add(notationWrapper, (Int32)notation); } } return notationWrapper; } // //Factory function for creating and hashing DOM Implementation objects // DOMImplementation* Document::createDOMImplementation(nsIDOMDOMImplementation* impl) { DOMImplementation* implWrapper = NULL; if (impl) { implWrapper = (DOMImplementation*)wrapperHashTable.retrieve((Int32)impl); if (!implWrapper) { implWrapper = new DOMImplementation(impl, this); wrapperHashTable.add(implWrapper, (Int32)impl); } } return implWrapper; } // //Factory function for creating and hashing DOM DocumentType objects. // DocumentType* Document::createDocumentType(nsIDOMDocumentType* doctype) { DocumentType* doctypeWrapper = NULL; if (doctype) { doctypeWrapper = (DocumentType*)wrapperHashTable.retrieve((Int32)doctype); if (!doctypeWrapper) { doctypeWrapper = new DocumentType(doctype, this); wrapperHashTable.add(doctypeWrapper, (Int32)doctype); } } return doctypeWrapper; } // //Factory function for creating and hashing NodeList objects // NodeList* Document::createNodeList(nsIDOMNodeList* list) { NodeList* listWrapper = NULL; if (list) { listWrapper = (NodeList*)wrapperHashTable.retrieve((Int32)list); if (!listWrapper) { listWrapper = new NodeList(list, this); wrapperHashTable.add(listWrapper, (Int32)list); } } return listWrapper; } // //Factory function for creating and hashing NamedNodeMap objects // NamedNodeMap* Document::createNamedNodeMap(nsIDOMNamedNodeMap* map) { NamedNodeMap* mapWrapper = NULL; if (map) { mapWrapper = (NamedNodeMap*)wrapperHashTable.retrieve((Int32)map); if (!mapWrapper) { mapWrapper = new NamedNodeMap(map, this); wrapperHashTable.add(mapWrapper, (Int32)map); } } return mapWrapper; } // //Remove the specified hashed object from wrapperHashTable and return it to the //caller. // MITREObject* Document::removeWrapper(Int32 hashValue) { return wrapperHashTable.remove(hashValue); } // //Add the specified wrapper to the hash table using the specified hash value // void Document::addWrapper(MITREObject* obj, Int32 hashValue) { wrapperHashTable.add(obj, hashValue); } // //Determine what kind of node this is, and create the appropriate wrapper for it // Node* Document::createWrapper(nsIDOMNode* node) { unsigned short nodeType = 0; // //TK 02/15/2000 - Must make sure node is not null. if (!node) return NULL; node->GetNodeType(&nodeType); switch (nodeType) { case nsIDOMNode::ELEMENT_NODE: return createElement((nsIDOMElement*)node); break; case nsIDOMNode::ATTRIBUTE_NODE: return createAttribute((nsIDOMAttr*)node); break; case nsIDOMNode::TEXT_NODE: return createTextNode((nsIDOMText*)node); break; case nsIDOMNode::CDATA_SECTION_NODE: return createCDATASection((nsIDOMCDATASection*)node); break; case nsIDOMNode::COMMENT_NODE: return createComment((nsIDOMComment*)node); break; case nsIDOMNode::ENTITY_REFERENCE_NODE: return createEntityReference((nsIDOMEntityReference*)node); break; case nsIDOMNode::ENTITY_NODE: return createEntity((nsIDOMEntity*)node); break; case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: return createProcessingInstruction((nsIDOMProcessingInstruction*)node); break; case nsIDOMNode::DOCUMENT_TYPE_NODE: return createDocumentType((nsIDOMDocumentType*)node); break; case nsIDOMNode::DOCUMENT_FRAGMENT_NODE: return createDocumentFragment((nsIDOMDocumentFragment*)node); break; case nsIDOMNode::NOTATION_NODE: return createNotation((nsIDOMNotation*)node); break; default: return createNode(node); } }