|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.mdr.test; import java.util.*; import java.io.*; import java.net.URL; import org.xml.sax.*; import org.w3c.dom.*; import javax.xml.parsers.*; import org.netbeans.lib.jmi.util.*; import javax.jmi.reflect.*; import javax.jmi.model.*; public class XMIComparator extends Object { // a character used to mark start of an element name private static final char ELEMENT_START = '['; // a character used to mark end of an element name private static final char ELEMENT_END = ']'; // an auxiliar separator used to create code of a tree private static final char LEFT_SEPARATOR = '('; // an auxiliar separator used to create code of a tree private static final char RIGHT_SEPARATOR = ')'; // an auxiliar separator used to enclose a comment private static final char COMMENT_MARKER = '#'; private CodeComparator codeComparator = new CodeComparator (); // init ..................................................................... public XMIComparator() { } // methods .................................................................. /** * Compares content of two XMI files. Both files are parsed by DOM parser. * Nodes representing content sections are found in created structures and * their content is coded into a String value. The codes equals iff both trees * are isomorphous. Note that (for now) attribute values are not included in tree * codes and that whitespace characters are excluded when content of TEXT_NODE * is added as a part of a resulting code. * * @param streamOne InputSource providing the first XMI documnet * @param streamTwo InputSource providing the second XMI documnet * * @return null if both documents are logically identical, otherwise an error message */ public String compareDocuments (InputSource streamOne, InputSource streamTwo) { try { Document docOne = parse (streamOne, null); Document docTwo = parse (streamTwo, null); Node xmiNode = findSubnodeByName (docOne, "XMI"); Node contentNode = findSubnodeByName (xmiNode, "XMI.content"); String codeOne = treeCode (contentNode); xmiNode = findSubnodeByName (docTwo, "XMI"); contentNode = findSubnodeByName (xmiNode, "XMI.content"); String codeTwo = treeCode (contentNode); if (removeComments (codeOne).equals (removeComments (codeTwo))) return null; String el = findDifference (codeOne, codeTwo); return "Trees are not identical, element: " + el; } catch (Exception e) { e.printStackTrace (); return "Cannot parse documnet"; } } /** * Finds the first difference in two codes and detects the name of the nearest * element that encloses the detected position. */ private String findDifference (String c1, String c2) { int x = 0; int length = Math.min (c1.length (), c2.length ()); for (x = 0; x < c1.length (); x++) if (c1.charAt (x) != c2.charAt (x)) break; while (c1.charAt (x) != ELEMENT_START) x--; String name = ""; x++; while (c1.charAt (x) != ELEMENT_END) { name = name + c1.charAt (x); x++; } return name; } /** * Returns direct child node given by its name. */ private Node findSubnodeByName (Node node, String name) { NodeList subNodes = node.getChildNodes (); for (int x = 0; x < subNodes.getLength (); x++) { Node temp = subNodes.item (x); if (temp.getNodeName ().equals (name)) return temp; } // for return null; } /** * Returns a code for a tree given by its root node. */ private String treeCode (Node node) { if (node.getNodeType () == Node.TEXT_NODE) { String text = node.getNodeValue (); String res = ""; for (int x = 0; x < text.length (); x++) if (!Character.isWhitespace (text.charAt (x))) res = res + text.charAt (x); return res; } if (node.getNodeType () != Node.ELEMENT_NODE) return ""; // ignore non-text and non-element nodes List list = new LinkedList (); String nodeName = node.getNodeName (); NamedNodeMap attrs = node.getAttributes (); String xmiId = null; for (int x = 0; x < attrs.getLength (); x++) { Node attr = attrs.item (x); String name = attr.getNodeName (); if (name.equals ("xmi.id")) xmiId = attr.getNodeValue (); String value = attr.getNodeValue (); if (value.startsWith ("xmi.")) { value = "xmi."; } // if list.add (name); // [PENDING] value not added yet !!! } // for String attributesCode = listToString (list); list = new LinkedList (); NodeList subNodes = node.getChildNodes (); for (int x = 0; x < subNodes.getLength (); x++) { String s = treeCode (subNodes.item (x)); if (s.length () > 0) list.add (s); } // for String subNodesCode = listToString (list); String comment = ""; if (xmiId != null) comment = " " + COMMENT_MARKER + xmiId + COMMENT_MARKER; return LEFT_SEPARATOR + " " + ELEMENT_START + nodeName + comment + ELEMENT_END + attributesCode + " " + subNodesCode + RIGHT_SEPARATOR; } /** * Sorts all Strings in a List and returns their contatenation. */ private String listToString (List list) { Collections.sort (list, codeComparator); String res = ""; Iterator iter = list.iterator (); while (iter.hasNext ()) { res = res + " " + (String) iter.next (); } return res; } /** * Parses XMI document into DOM tree structure. */ private Document parse (InputSource is, String encoding) throws IOException, SAXException, ParserConfigurationException { Document result = null; DocumentBuilderFactory bfact = DocumentBuilderFactory.newInstance(); bfact.setValidating(false); DocumentBuilder docBuilder = bfact.newDocumentBuilder(); docBuilder.setEntityResolver(DummyER.getInstance()); if (encoding != null) is.setEncoding(encoding); result = docBuilder.parse(is); return result; } private static String removeComments (String code) { StringBuffer res = new StringBuffer (code.length ()); boolean inComment = false; for (int x = 0; x < code.length (); x++) { char c = code.charAt (x); if (c == COMMENT_MARKER) inComment = !inComment; else if (!inComment) res.append(c); } // for return res.toString (); } // (Dummy) entity resolver class private static class DummyER implements EntityResolver { private static EntityResolver instance = new DummyER(); public static EntityResolver getInstance() { return instance; } public InputSource resolveEntity(String publicID, String systemID) { return new InputSource(new StringReader("")); } } private static class CodeComparator implements Comparator { public int compare(Object obj1, Object obj2) { String s1 = removeComments ((String) obj1); String s2 = removeComments ((String) obj2); return s1.compareTo(s2); } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.