| /* |
| * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.platform.xml; |
| |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Comment; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentFragment; |
| import org.w3c.dom.DocumentType; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.EntityReference; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.ProcessingInstruction; |
| import org.w3c.dom.Text; |
| |
| /** |
| * This class is used to compare if two DOM nodes are equal. |
| */ |
| public class XMLComparer { |
| |
| private boolean ignoreOrder; |
| |
| public XMLComparer() { |
| super(); |
| ignoreOrder = false; |
| } |
| |
| /** |
| * Compare two DOM nodes. |
| * @param control The first node in the comparison. |
| * @param test The second node in the comparison. |
| * @return Return true if the nodes are equal, else false. |
| */ |
| public boolean isNodeEqual(Node control, Node test) { |
| if (control == test) { |
| return true; |
| } else if ((null == control) || (null == test)) { |
| return false; |
| } else if (control.getNodeType() != test.getNodeType()) { |
| return false; |
| } |
| switch (control.getNodeType()) { |
| case (Node.ATTRIBUTE_NODE): |
| return isAttributeEqual((Attr)control, (Attr)test); |
| case (Node.CDATA_SECTION_NODE): |
| return isTextEqual((Text)control, (Text)test); |
| case (Node.COMMENT_NODE): |
| return isCommentEqual((Comment)control, (Comment)test); |
| case (Node.DOCUMENT_FRAGMENT_NODE): |
| return isDocumentFragmentEqual((DocumentFragment)control, (DocumentFragment)test); |
| case (Node.DOCUMENT_NODE): |
| return isDocumentEqual((Document)control, (Document)test); |
| case (Node.DOCUMENT_TYPE_NODE): |
| return isDocumentTypeEqual((DocumentType)control, (DocumentType)test); |
| case (Node.ELEMENT_NODE): |
| return isElementEqual((Element)control, (Element)test); |
| case (Node.ENTITY_NODE): |
| return false; |
| case (Node.ENTITY_REFERENCE_NODE): |
| return isEntityReferenceEqual((EntityReference)control, (EntityReference)test); |
| case (Node.NOTATION_NODE): |
| return false; |
| case (Node.PROCESSING_INSTRUCTION_NODE): |
| return isProcessingInstructionEqual((ProcessingInstruction)control, (ProcessingInstruction)test); |
| case (Node.TEXT_NODE): |
| return isTextEqual((Text)control, (Text)test); |
| default: |
| return true; |
| } |
| } |
| |
| protected boolean isAttributeEqual(Attr control, Attr test) { |
| if (!isStringEqual(control.getNamespaceURI(), test.getNamespaceURI())) { |
| return false; |
| } |
| if (!isStringEqual(control.getName(), test.getName())) { |
| return false; |
| } |
| if (!isStringEqual(control.getNodeValue(), test.getNodeValue())) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean isCommentEqual(Comment control, Comment test) { |
| if (!isStringEqual(control.getNodeValue(), test.getNodeValue())) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean isDocumentEqual(Document control, Document test) { |
| if (!isDocumentTypeEqual(control.getDoctype(), test.getDoctype())) { |
| return false; |
| } |
| |
| Element controlRootElement = control.getDocumentElement(); |
| Element testRootElement = test.getDocumentElement(); |
| if (controlRootElement == testRootElement) { |
| return true; |
| } else if ((null == controlRootElement) || (null == testRootElement)) { |
| return false; |
| } |
| return isElementEqual(controlRootElement, testRootElement); |
| } |
| |
| private boolean isDocumentFragmentEqual(DocumentFragment control, DocumentFragment test) { |
| return isNodeListEqual(control.getChildNodes(), test.getChildNodes()); |
| } |
| |
| private boolean isDocumentTypeEqual(DocumentType control, DocumentType test) { |
| if (control == test) { |
| return true; |
| } else if ((null == control) || (null == test)) { |
| return false; |
| } |
| |
| if (!isStringEqual(control.getName(), test.getName())) { |
| return false; |
| } |
| if (!isStringEqual(control.getPublicId(), test.getPublicId())) { |
| return false; |
| } |
| if (!isStringEqual(control.getSystemId(), test.getSystemId())) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| private boolean isElementEqual(Element control, Element test) { |
| if (!isStringEqual(control.getNamespaceURI(), test.getNamespaceURI())) { |
| return false; |
| } |
| if (!isStringEqual(control.getTagName(), test.getTagName())) { |
| return false; |
| } |
| |
| // COMPARE ATTRIBUTES |
| NamedNodeMap controlAttributes = control.getAttributes(); |
| NamedNodeMap testAttributes = test.getAttributes(); |
| int numberOfControlAttributes = controlAttributes.getLength(); |
| int numberOfTestAttributes = testAttributes.getLength(); |
| if (numberOfControlAttributes != numberOfTestAttributes) { |
| return false; |
| } |
| Attr controlAttribute; |
| Attr testAttribute; |
| for (int x = 0; x < numberOfControlAttributes; x++) { |
| controlAttribute = (Attr)controlAttributes.item(x); |
| if (null == controlAttribute.getNamespaceURI()) { |
| testAttribute = (Attr)testAttributes.getNamedItem(controlAttribute.getNodeName()); |
| } else { |
| testAttribute = (Attr)testAttributes.getNamedItemNS(controlAttribute.getNamespaceURI(), controlAttribute.getLocalName()); |
| } |
| if (null == testAttribute) { |
| return false; |
| } else if (!isAttributeEqual(controlAttribute, testAttribute)) { |
| return false; |
| } |
| } |
| |
| // COMPARE CHILD NODES |
| return isNodeListEqual(control.getChildNodes(), test.getChildNodes()); |
| } |
| |
| private boolean isEntityReferenceEqual(EntityReference control, EntityReference test) { |
| if (!isStringEqual(control.getNodeName(), test.getNodeName())) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean isProcessingInstructionEqual(ProcessingInstruction control, ProcessingInstruction test) { |
| if (!isStringEqual(control.getTarget(), test.getTarget())) { |
| return false; |
| } |
| if (!isStringEqual(control.getData(), test.getData())) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean isTextEqual(Text control, Text test) { |
| return isStringEqual(control.getNodeValue(), test.getNodeValue()); |
| } |
| |
| private boolean isNodeListEqual(NodeList control, NodeList test) { |
| int numberOfControlNodes = control.getLength(); |
| if (numberOfControlNodes != test.getLength()) { |
| return false; |
| } |
| if(ignoreOrder){ |
| for (int x = 0; x < numberOfControlNodes; x++) { |
| if(!isNodeInNodeList(control.item(x), test)){ |
| return false; |
| } |
| } |
| for (int x = 0; x < numberOfControlNodes; x++) { |
| if(!isNodeInNodeList(test.item(x), control)){ |
| return false; |
| } |
| } |
| }else{ |
| for (int x = 0; x < numberOfControlNodes; x++) { |
| if (!isNodeEqual(control.item(x), test.item(x))) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| private boolean isNodeInNodeList(Node node, NodeList nodeList){ |
| int length = nodeList.getLength(); |
| for (int x = 0; x < length; x++) { |
| Node nextNode = nodeList.item(x); |
| if(isNodeEqual(node, nextNode)){ |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private boolean isStringEqual(String control, String test) { |
| if (control == test) { |
| return true; |
| } else if (null == control) { |
| return false; |
| } else { |
| return control.equals(test); |
| } |
| } |
| |
| public boolean isIgnoreOrder() { |
| return ignoreOrder; |
| } |
| |
| public void setIgnoreOrder(boolean ignoreOrder) { |
| this.ignoreOrder = ignoreOrder; |
| } |
| } |