From 24a39d91b2c990eb209af6dda9590915259c27c7 Mon Sep 17 00:00:00 2001 From: "kvisco%ziplink.net" Date: Tue, 22 Feb 2000 11:12:57 +0000 Subject: [PATCH] Initial check in of DOMHelper.cpp, used to overcome some DOM related deficiencies. git-svn-id: svn://10.0.0.236/trunk@61430 18797224-902f-48f8-a5cc-f745e15eee43 --- .../source/xml/util/DOMHelper.cpp | 327 ++++++++++++++++++ .../transformiix/source/xml/util/DOMHelper.h | 179 ++++++++++ .../transformiix/source/xml/util/Makefile | 11 + 3 files changed, 517 insertions(+) create mode 100644 mozilla/extensions/transformiix/source/xml/util/DOMHelper.cpp create mode 100644 mozilla/extensions/transformiix/source/xml/util/DOMHelper.h create mode 100644 mozilla/extensions/transformiix/source/xml/util/Makefile diff --git a/mozilla/extensions/transformiix/source/xml/util/DOMHelper.cpp b/mozilla/extensions/transformiix/source/xml/util/DOMHelper.cpp new file mode 100644 index 00000000000..5e00ce093a6 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xml/util/DOMHelper.cpp @@ -0,0 +1,327 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (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/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is TransforMiiX XSLT processor. + * + * The Initial Developer of the Original Code is Keith Visco. + * Portions created by Keith Visco (C) 1999 Keith Visco. + * All Rights Reserved.. + * + * Contributor(s): + * Keith Visco, kvisco@ziplink.net + * -- original author. + * + * $Id: DOMHelper.cpp,v 1.1 2000-02-22 11:12:57 kvisco%ziplink.net Exp $ + */ + +/** + * A class used to overcome DOM 1.0 deficiencies + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-02-22 11:12:57 $ +**/ + +#include "DOMHelper.h" + + +/** + * Creates a new DOMHelper +**/ +DOMHelper::DOMHelper() {}; + +/** + * Delets this DOMHelper +**/ +DOMHelper::~DOMHelper() { + ListIterator* iter = indexes.iterator(); + while (iter->hasNext()) { + IndexState* idxState = (IndexState*)iter->next(); + delete idxState; + } + delete iter; +} //-- ~DOMHelper + + +/** + * Returns the node which appears first in the document + * If this method is called with nodes from a different + * document, node1 will be returned. + * @return the node which appears first in document order +**/ +Node* DOMHelper::appearsFirst(Node* node1, Node* node2) { + + if (!node2) return node1; + if (!node1) return node2; + + if (node1->getOwnerDocument() != node2->getOwnerDocument()) + return node1; + + OrderInfo* orderInfo1 = getDocumentOrder(node1); + OrderInfo* orderInfo2 = getDocumentOrder(node2); + + int compare = orderInfo1->compareTo(orderInfo2); + if (compare > 0) return node2; + return node1; + +} //-- compareDocumentOrders + +/** + * Returns the parent of the given node. This method is available + * mainly to compensate for the fact that Attr nodes in DOM 1.0 + * do not have parents. (Why??) + * @param node the Node to return the parent of +**/ +Node* DOMHelper::getParentNode(Node* node) { + + if (!node) return 0; + if (node->getNodeType() != Node::ATTRIBUTE_NODE) + return node->getParentNode(); + + Int32 key = (Int32)node; + MITREObjectWrapper* wrapper = 0; + + wrapper = (MITREObjectWrapper*) parents.retrieve(key); + if (!wrapper) { + continueIndexing(node); + wrapper = (MITREObjectWrapper*) parents.retrieve(key); + } + + if (wrapper) return (Node*)wrapper->object; + return 0; + +} //-- getParentNode + + +//-------------------/ +//- Private Methods -/ +//-------------------/ + +/** + * Adds the given child/parent mapping +**/ +void DOMHelper::addParentReference(Node* child, Node* parent) { + + Int32 key = (Int32)child; + MITREObjectWrapper* wrapper = (MITREObjectWrapper*) parents.retrieve(key); + if (!wrapper) { + wrapper = new MITREObjectWrapper(); + parents.add(wrapper, key); + } + wrapper->object = parent; + +} //-- addParentReference + +/** + * Continues indexing until the given node has been indexed + * @param node the target Node +**/ +void DOMHelper::continueIndexing(Node* node) { + if (!node) return; + + + + MITREObjectWrapper* wrapper = 0; + + //-- get indexing information + Document* doc = node->getOwnerDocument(); + ListIterator* iter = indexes.iterator(); + IndexState* idxState = 0; + while (iter->hasNext()) { + idxState = (IndexState*)iter->next(); + if (idxState->document == doc) break; + idxState = 0; + } + + if (!idxState) { + idxState = new IndexState(); + indexes.add(idxState); + idxState->document = doc; + idxState->next = doc->getDocumentElement(); + if (!idxState->next) idxState->done = MB_TRUE; + } + + if (idxState->done) return; + + MBool found = MB_FALSE; + MBool alreadyProcessed = MB_FALSE; + + while (!found) { + + if (!idxState->next) { + idxState->done = MB_TRUE; + break; + } + + if (!alreadyProcessed) { + //-- index attributes + if (idxState->next->getNodeType() == Node::ELEMENT_NODE) { + Element* element = (Element*)idxState->next; + NamedNodeMap* atts = element->getAttributes(); + if (atts) { + for (int i = 0; i < atts->getLength(); i++) { + Node* tmpNode = atts->item(i); + addParentReference(tmpNode, element); + if (node == tmpNode) found = MB_TRUE; + } + } + } + } + + //-- set next node to check + if ((!alreadyProcessed) && (idxState->next->hasChildNodes())) { + Node* child = idxState->next->getFirstChild(); + idxState->next = child; + } + else if (idxState->next->getNextSibling()) { + idxState->next = idxState->next->getNextSibling(); + alreadyProcessed = MB_FALSE; + } + else { + idxState->next = getParentNode(idxState->next); + alreadyProcessed = MB_TRUE; + } + } + +} //-- continueIndexing + + +/** + * Returns the child number of the given node. Numbering + * starts at 1 for all nodes except the Document node and + * attribute nodes which has child numbers of 0. The child + * number is calculated by counting the number of times + * Node#getPreviousSibling can be called. + * @param node a pointer to the node in which to return the + * child number of. + * @return the child number for the given node +**/ +int DOMHelper::getChildNumber(Node* node) { + + if (!node) return -1; + + int c = 0; + Node* tmp = node; + switch (node->getNodeType()) { + case Node::DOCUMENT_NODE: + case Node::ATTRIBUTE_NODE: + break; + default: + while (tmp = tmp->getPreviousSibling()) ++c; + break; + } + + + return c; +} //-- getChildNumber + +/** + * Returns the DocumentOrder for the given Node + * @param node a pointer to the Node in which to return the + * DocumentOrder of + * @return the DocumentOrder for the given Node +**/ +OrderInfo* DOMHelper::getDocumentOrder(Node* node) { + + if (!node) return 0; + + Int32 key = (Int32)node; + OrderInfo* orderInfo = (OrderInfo*)orders.retrieve(key); + + if (!orderInfo) { + if (node->getNodeType() == Node::DOCUMENT_NODE) { + orderInfo = new OrderInfo(); + orderInfo->size = 1; + orderInfo->order = new int[1]; + orderInfo->order[0] = 0; + } + else { + Node* parent = getParentNode(node); + OrderInfo* parentOrder = getDocumentOrder(parent); + orderInfo = new OrderInfo(); + + if (parentOrder) { + orderInfo->size = parentOrder->size+1; + orderInfo->order = new int[orderInfo->size]; + int c = 0; + for ( ; c < parentOrder->size; c++) + orderInfo->order[c] = parentOrder->order[c]; + orderInfo->order[c] = getChildNumber(node); + } + else { + orderInfo->size = 1; + orderInfo->order = new int[1]; + orderInfo->order[0] = 0; + } + } + orders.add(orderInfo, key); + } + + return orderInfo; + +} //-- getDocumentOrder + +//--------------------------------/ +//- implementation of IndexState -/ +//--------------------------------/ + +/** + * Creates a new IndexState +**/ +IndexState::IndexState() { + document = 0; + done = MB_FALSE; + next = 0; +} //-- IndexState + +/** + * Deletes this IndexState +**/ +IndexState::~IndexState() {}; + +//-------------------------------/ +//- Implementation of OrderInfo -/ +//-------------------------------/ + +/** + * Creates a new OrderInfo +**/ +OrderInfo::OrderInfo() : MITREObject() { + order = 0; + size = 0; +} //-- OrderInfo + +/** + * Deletes this OrderInfo +**/ +OrderInfo::~OrderInfo() { + if (order) delete [] order; +} //-- ~OrderInfo + + +/** + * Compares this OrderInfo with the given OrderInfo + * @return -1 if this OrderInfo is less than the given OrderInfo; + * 0 if they are equal; 1 if this OrderInfo is greater. +**/ +int OrderInfo::compareTo(OrderInfo* orderInfo) { + + if (!orderInfo) return -1; + + int c = 0; + while ( (c < size) && (c < orderInfo->size)) { + if (order[c] < orderInfo->order[c]) return -1; + else if (order[c] > orderInfo->order[c]) return 1; + ++c; + } + if (c < size) return 1; + else if (c < orderInfo->size) return -1; + return 0; + +} //-- compareTo diff --git a/mozilla/extensions/transformiix/source/xml/util/DOMHelper.h b/mozilla/extensions/transformiix/source/xml/util/DOMHelper.h new file mode 100644 index 00000000000..6985aec78e5 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xml/util/DOMHelper.h @@ -0,0 +1,179 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (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/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is TransforMiiX XSLT processor. + * + * The Initial Developer of the Original Code is Keith Visco. + * Portions created by Keith Visco (C) 1999 Keith Visco. + * All Rights Reserved.. + * + * Contributor(s): + * Keith Visco, kvisco@ziplink.net + * -- original author. + * + * $Id: DOMHelper.h,v 1.1 2000-02-22 11:12:57 kvisco%ziplink.net Exp $ + */ + +#ifndef TRANSFRMX_DOMHELPER_H +#define TRANSFRMX_DOMHELPER_H + +#include "baseutils.h" +#include "String.h" +#include "List.h" +#include "dom.h" +#include "HashTable.h" +#include "MITREObject.h" + + + +//----------------------/ +//- Class declarations -/ +//----------------------/ + +/** + * A class used by DOMHelper to hold document order information + * for DOM Nodes +**/ +class OrderInfo : public MITREObject { + + public: + + OrderInfo(); + virtual ~OrderInfo(); + + int compareTo(OrderInfo* orderInfo); + + int* order; + int size; + +}; //-- OrderInfo + +/** + * A class used to overcome DOM 1.0 deficiencies + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-02-22 11:12:57 $ +**/ +class DOMHelper { + +public: + + /** + * Creates a new DOMHelper + **/ + DOMHelper(); + + /** + * Deletes this DOMHelper + **/ + virtual ~DOMHelper(); + + /** + * Returns the node which appears first in the document + * (ie. has lower document order). + * If this method is called with nodes from a different + * document, node1 will be returned. + * @return the node which appears first in document order + **/ + Node* appearsFirst(Node* node1, Node* node2); + + /** + * Returns the child number of the given node. Numbering + * starts at 1 for all nodes except the Document node and + * attribute nodes which has child numbers of 0. The child + * number is calculated by counting the number of times + * Node#getPreviousSibling can be called. + * @param node a pointer to the node in which to return the + * child number of. + * @return the child number for the given node + **/ + int getChildNumber(Node* node); + + /** + * Returns the parent of the given node. This method is available + * mainly to compensate for the fact that Attr nodes in DOM 1.0 + * do not have parents. (Why??) + * @param node the Node to return the parent of + **/ + Node* getParentNode(Node* node); + + +private: + + + /** + * Adds the given child/parent mapping to the list of parents + **/ + void addParentReference(Node* child, Node* parent); + + /** + * Indexes until the given node has been indexed + **/ + void continueIndexing(Node* node); + + + /** + * Returns the DocumentOrder for the given Node + * @param node a pointer to the Node in which to return the + * DocumentOrder of + * @return the DocumentOrder for the given Node + **/ + OrderInfo* getDocumentOrder(Node* node); + + + /** + * A Hashtable of attribute's parent nodes + **/ + HashTable parents; + + /** + * A Hashtable of Node/OrderInfo mappings + **/ + HashTable orders; + + /** + * A list of IndexState objects (one for each Document) + **/ + List indexes; + + +}; //-- DOMHelper + +/** + * A class which holds information about the current state of + * indexing +**/ +class IndexState { + + public: + + IndexState(); + ~IndexState(); + + /** + * The Document that this IndexState is for + **/ + Document* document; + + /** + * The next node to index + **/ + Node* next; + + /** + * A boolean indicating if the indexing has completed + **/ + MBool done; + +}; //-- IndexState + + +#endif + diff --git a/mozilla/extensions/transformiix/source/xml/util/Makefile b/mozilla/extensions/transformiix/source/xml/util/Makefile new file mode 100644 index 00000000000..28f49c73267 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xml/util/Makefile @@ -0,0 +1,11 @@ + +INCLUDE_PATH = -I../../base -I../dom + + +ALL_OBJS = DOMHelper.o + + +target: $(ALL_OBJS) + +DOMHelper.o: DOMHelper.h DOMHelper.cpp + $(CC) $(INCLUDE_PATH) -c DOMHelper.cpp