diff options
Diffstat (limited to 'sdo-java/trunk-cts/sdo2.1/src/main/java/test/sdo21/tests/util/XMLEqualityChecker.java')
-rw-r--r-- | sdo-java/trunk-cts/sdo2.1/src/main/java/test/sdo21/tests/util/XMLEqualityChecker.java | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/sdo-java/trunk-cts/sdo2.1/src/main/java/test/sdo21/tests/util/XMLEqualityChecker.java b/sdo-java/trunk-cts/sdo2.1/src/main/java/test/sdo21/tests/util/XMLEqualityChecker.java new file mode 100644 index 0000000000..dee5f84ea9 --- /dev/null +++ b/sdo-java/trunk-cts/sdo2.1/src/main/java/test/sdo21/tests/util/XMLEqualityChecker.java @@ -0,0 +1,324 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package test.sdo21.tests.util; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * Provides a series of methods for comparing output from the XMLHelper with an + * expected XML file. + */ +public class XMLEqualityChecker { + + private static final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance"; + + /** + * Places the nodes in nodeList into a indexed list. + * + * @param nodeList + * @param nodes + */ + private static void getAllNodes(NodeList nodeList, List nodes) { + int length = nodeList.getLength(); + if (length == 0) + return; + + for (int i = 0; i < length; i++) { + Node node = nodeList.item(i); + nodes.add(node); + getAllNodes(node.getChildNodes(), nodes); + } // for + } + + /** + * Compares two NamedNodeMap instances and throws an exception if they are not equivalent. + * + * @param mapA + * @param mapB + */ + private static void compareNamedNodeMap(NamedNodeMap mapA, NamedNodeMap mapB) throws XMLDifferenceException { + if (mapA == null) { + if (mapB == null) { + return; + } + throw new XMLDifferenceException( "mapA was null, mapB wasn't" ); + } + if (mapA.getLength() != mapB.getLength()) { + throw new XMLDifferenceException( "map length", mapA.getLength(), mapB.getLength() ); + } + for (int i = 0; i < mapA.getLength(); i++) { + Node trialNode = mapA.item(i); + if (trialNode == null) { + throw new XMLDifferenceException("mapB did not contain value at index " + i); + } + if (trialNode.getNodeName().startsWith("xmlns:")) { + // ignore namespace declarations since these will be checked on each element + // using the namespace + continue; + } + Node checkNode = mapB.getNamedItem(trialNode.getNodeName()); + if (checkNode == null) { + throw new XMLDifferenceException("mapB did not contain value named '" + trialNode.getNodeName() + "'"); + } + compareNode(trialNode, checkNode); + } + } + + /** + * Compares two Node instances and throws an exception if they are not equivalent. + * + * @param nodeA + * @param nodeB + */ + private static void compareNode(Node nodeA, Node nodeB) throws XMLDifferenceException { + if (nodeA == null) { + if (nodeB == null) { + return; + } + throw new XMLDifferenceException( "nodeA was null, nodeB wasn't" ); + } + // following is intended to provide same function as 1.5 isEqualNode() + if (nodeA.getNodeType() != nodeB.getNodeType()) { + throw new XMLDifferenceException( "node type", nodeA.getNodeType(), nodeB.getNodeType() ); + } + if (!equalString(nodeA.getLocalName(), nodeB.getLocalName())) { + throw new XMLDifferenceException( "local name", nodeA.getLocalName(), nodeB.getLocalName() ); + } + if (!equalString(nodeA.getNamespaceURI(), nodeB.getNamespaceURI())) { + throw new XMLDifferenceException( "namespace URI", nodeA.getNamespaceURI(), nodeB.getNamespaceURI() ); + } + + // special handling for xsi:type + if (XSI_NAMESPACE_URI.equals(nodeA.getNamespaceURI()) + && nodeA.getLocalName().equals("type")) { + + // because the gold xml file might use a different namespace prefix + // than the sdo implementation under test, we need to ignore the + // prefix used in any xsi:type attribute + + String nodeValueA = nodeA.getNodeValue(); + String nodeValueB = nodeB.getNodeValue(); + + int posA = nodeValueA.indexOf(':'); + int posB = nodeValueB.indexOf(':'); + + if (posA != -1 && posB != -1 && nodeValueA.substring(posA+1).equals(nodeValueB.substring(posB+1))) { + // the type name does match + } + else { + if (!equalString(nodeA.getNodeValue(), nodeB.getNodeValue())) { + throw new XMLDifferenceException ("node value", nodeA.getNodeValue(), nodeB.getNodeValue() ); + } + } + } + else { + if (!equalString(nodeA.getNodeValue(), nodeB.getNodeValue())) { + throw new XMLDifferenceException( + "value of node '" + nodeA.getLocalName() + "' in namespace '" + nodeA.getNamespaceURI() + "'", + nodeA.getNodeValue(), nodeB.getNodeValue() ); + } + + compareNamedNodeMap(nodeA.getAttributes(), nodeB.getAttributes()); + compareNodeList( nodeA.getChildNodes(), nodeB.getChildNodes()); + if (nodeA.getNodeType() == Node.DOCUMENT_TYPE_NODE) { + DocumentType documentTypeA = (DocumentType)nodeA; + DocumentType documentTypeB = (DocumentType)nodeB; + if (!equalString(documentTypeA.getPublicId(), documentTypeB.getPublicId())) { + throw new XMLDifferenceException( "public ID", documentTypeA.getPublicId(), documentTypeB.getPublicId() ); + } + if (!equalString(documentTypeA.getSystemId(), documentTypeB.getSystemId())) { + throw new XMLDifferenceException( "system ID", documentTypeA.getSystemId(), documentTypeB.getSystemId() ); + } + if (!equalString(documentTypeA.getInternalSubset(), documentTypeB.getInternalSubset())) { + throw new XMLDifferenceException( "internal subset", documentTypeA.getInternalSubset(), documentTypeB.getInternalSubset() ); + } + compareNamedNodeMap(documentTypeA.getEntities(), documentTypeB.getEntities()); + compareNamedNodeMap(documentTypeA.getNotations(), documentTypeB.getNotations()); + } + } + } + + /** + * Compares two NodeList instances and throws an exception if they are not equivalent. + * + * @param nodeListA + * @param nodeListB + */ + private static void compareNodeList(NodeList nodeListA, NodeList nodeListB) throws XMLDifferenceException { + if (nodeListA == null) { + if (nodeListB == null) { + return; + } + throw new XMLDifferenceException( "nodeListA was null, nodeListB wasn't" ); + } + compareNodes(nodeListA, nodeListB); + } + + /** + * Returns true of the two Strings are equivalent, false otherwise. + * + * @param stringA + * @param stringB + */ + private static boolean equalString(String stringA, String stringB) { + if (stringA == null) { + if (stringB == null) { + return true; + } + return false; + } + return stringA.equals(stringB); + } + + /** + * Returns true if the two NodeLists are equivalent, false otherwise. + * + * @param sourceNodeList + * @param targetNodeList + */ + private static void compareNodes(NodeList sourceNodeList, NodeList targetNodeList) + throws XMLDifferenceException { + + ArrayList sourceNodes = new ArrayList(); + ArrayList targetNodes = new ArrayList(); + + getAllNodes(sourceNodeList, sourceNodes); + getAllNodes(targetNodeList, targetNodes); + + int sourceLength = sourceNodes.size(); + int targetLength = targetNodes.size(); + + if (sourceLength != targetLength) { + throw new XMLDifferenceException( + "node count", + sourceLength, + targetLength + ); + } + + for (int i = 0; i < sourceLength; i++) { + Node sourceNode = (Node)sourceNodes.get(i); + Node targetNode = (Node)targetNodes.get(i); + + compareNode(sourceNode, targetNode); + } // for + } + + /** + * Throws exception if the two XML files are not equivalent. + * Accepts as input two URLs which identify the XML files, and calls + * equalXMLFiles(InputStream, InputStream). + * + * @param source + * @param target + */ + public static void compareXmlFiles(URL source, URL target) + throws XMLDifferenceException, IOException { + compareXmlFiles(source.openStream(), target.openStream()); + } + + /** + * Throws exception if the two XML files are not equivalent. + * Accepts as input an InputStream and a URL which identify the XML files, + * and calls equalXMLFiles(InputStream, InputStream). + * + * @param sourceStream + * @param target + */ + public static void compareXmlFiles(InputStream sourceStream, URL target) + throws XMLDifferenceException, IOException { + compareXmlFiles(sourceStream, target.openStream()); + } + + /** + * Throws exception if the two XML files are not equivalent. + * Accepts as input a URL and an InputStream which identify the XML files, + * and calls equalXMLFiles(InputStream, InputStream). + * + * @param source + * @param targetStream + */ + public static void compareXmlFiles(URL source, InputStream targetStream) + throws XMLDifferenceException, IOException { + compareXmlFiles(source.openStream(), targetStream); + } + + /** + * Throws exception if the two XML files are not equivalent. + * Accepts as input two InputStreams which identify the XML files. + * + * @param sourceStream + * @param targetStream + */ + public static void compareXmlFiles(InputStream sourceStream, InputStream targetStream) + throws XMLDifferenceException, IOException { + + DocumentBuilder builder; + Document sourceDocument; + Document targetDocument; + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + builder = factory.newDocumentBuilder(); + sourceDocument = builder.parse(sourceStream); + targetDocument = builder.parse(targetStream); + } catch (IOException ie) { + throw ie; + } catch (Exception e) { + throw new XMLDifferenceException( "Failed to parse files", e ); + } + + sourceDocument.normalize(); + targetDocument.normalize(); + + /* + * remove comment when migrated to Java 1.5 if + * (!sourceDocument.getXmlVersion().equals(targetDocument.getXmlVersion())) + * return false; String sourceXmlEncoding = + * sourceDocument.getXmlEncoding(); String targetXmlEncoding = + * targetDocument.getXmlEncoding(); if (sourceXmlEncoding != null && + * targetXmlEncoding != null && + * sourceXmlEncoding.equalsIgnoreCase(targetXmlEncoding)) { // continue } + * else { return false; } + */ + + NodeList sourceNodes = sourceDocument.getChildNodes(); + NodeList targetNodes = targetDocument.getChildNodes(); + + compareNodes(sourceNodes, targetNodes); + } +} |