aboutsummaryrefslogtreecommitdiffstats
path: root/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters
diff options
context:
space:
mode:
Diffstat (limited to 'aspectj-attic/testing-src/org/aspectj/testing/compare/adapters')
-rw-r--r--aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/GenericTreeNodeFactoryI.java33
-rw-r--r--aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/JTreeNodeGenericTreeNodeFactory.java102
-rw-r--r--aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/Structure.java438
-rw-r--r--aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/StructureGenericTreeNodeFactory.java308
-rw-r--r--aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/SubTypeComparator.java224
-rw-r--r--aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/package.html50
6 files changed, 1155 insertions, 0 deletions
diff --git a/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/GenericTreeNodeFactoryI.java b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/GenericTreeNodeFactoryI.java
new file mode 100644
index 000000000..adee3d3ee
--- /dev/null
+++ b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/GenericTreeNodeFactoryI.java
@@ -0,0 +1,33 @@
+/* *******************************************************************
+ * Copyright (c) 1999-2001 Xerox Corporation,
+ * 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.testing.compare.adapters;
+
+import org.aspectj.testing.compare.GenericTreeNode;
+/**
+ * Encapsulate the implementation of an factory to create
+ * a GenericTreeNode tree from a given input type, to permit
+ * a general, pluggable factory to operate based on source type.
+ */
+public interface GenericTreeNodeFactoryI {
+ /** @return the expected Class of the root node supported by this factory */
+ public Class getRootClass();
+
+ /**
+ * Create a wrapped generic tree with the input root tree as delegates.
+ * @param root the {rootClass} root of the tree to convert - never null
+ * @throws IllegalArgumentException if root is null or not assignable to rootClass
+ */
+ public GenericTreeNode createGenericTreeNode(Object root, GenericTreeNode parent);
+}
+
diff --git a/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/JTreeNodeGenericTreeNodeFactory.java b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/JTreeNodeGenericTreeNodeFactory.java
new file mode 100644
index 000000000..5f48eef40
--- /dev/null
+++ b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/JTreeNodeGenericTreeNodeFactory.java
@@ -0,0 +1,102 @@
+/* *******************************************************************
+ * Copyright (c) 1999-2001 Xerox Corporation,
+ * 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.testing.compare.adapters;
+
+import org.aspectj.testing.compare.GenericTreeNode;
+import org.aspectj.testing.compare.*;
+
+import javax.swing.tree.*; // sample uses TreeModel...
+import java.util.*;
+
+/**
+ * Factory for adapting Swing TreeNode to GenericTreeNode
+ */
+public class JTreeNodeGenericTreeNodeFactory implements GenericTreeNodeFactoryI {
+ public static final GenericTreeNodeFactoryI SINGLETON
+ = new JTreeNodeGenericTreeNodeFactory();
+ private JTreeNodeGenericTreeNodeFactory() {}
+ public Class getRootClass() {
+ return TreeNode.class;
+ }
+
+ /**
+ * Adapt swing TreeModel to tree rooted at GenericTreeNode
+ * Only takes the current state of a TreeModel which does not
+ * change during the construction of the adapter. If the
+ * TreeModel changes, you can ask the adapter for a newly
+ * wrapped tree.
+ * Recursively convert entire tree from root to a wrapped tree
+ * Note this takes a snapshot of the tree such that changes to
+ * the TreeModel after the constructor returns are ignored.
+ * Changes during the constructor produce undetermined results.
+ * @param root the TreeNode taken as root of a tree to wrap
+ * @param parent the parent of the resulting GenericTreeNode
+ * @throws IllegalArgumentException if root is null
+ * or if children are not instanceof TreeNode.
+ */
+ public GenericTreeNode createGenericTreeNode(Object root, GenericTreeNode parent) {
+ if (null == root) {
+ throw new IllegalArgumentException("null root");
+ }
+ if (! (root instanceof TreeNode)) {
+ throw new IllegalArgumentException("not TreeNode: " + root);
+ }
+ TreeNode rootNode = (TreeNode) root;
+ final int numKids = rootNode.getChildCount();
+ ArrayList kids = new ArrayList(numKids);
+ Enumeration children = rootNode.children();
+ Object child;
+ GenericTreeNode result = new GenericTreeNode();
+ for (int i = 0; i < numKids; i++) {
+ if (! children.hasMoreElements()) {
+ throw new Error("(! children.hasNext())");
+ }
+ child = children.nextElement();
+ if (! (child instanceof TreeNode)) {
+ throw new Error("! (child instanceof TreeNode)): " + child );
+ }
+ kids.add(createGenericTreeNode((TreeNode) child, result));
+ }
+ //result.init(parent, GenericTreeNode.COMPARATOR, rootNode, kids, null);
+ result.init(parent, JTreeNodeComparator.SINGLETON, rootNode, kids, null);
+ return result;
+ }
+
+ /** Comparator for swing TreeNode todo convert from TreeNode to DefaultMutableTreeNode */
+ static class JTreeNodeComparator implements Comparator {
+ public static Comparator SINGLETON = new JTreeNodeComparator();
+ private JTreeNodeComparator () {}
+ public int compare(Object lhs, Object rhs) {
+ int result = CompareUtil.compare(lhs, rhs);
+ if (Integer.MAX_VALUE == result) {
+ Class lhClass = lhs.getClass() ;
+ Class rhClass = rhs.getClass() ;
+ if ((DefaultMutableTreeNode.class.isAssignableFrom(lhClass))
+ && (DefaultMutableTreeNode.class.isAssignableFrom(rhClass))) {
+ DefaultMutableTreeNode lh = (DefaultMutableTreeNode) lhs ;
+ DefaultMutableTreeNode rh = (DefaultMutableTreeNode) rhs ;
+ Object lhObject = lh.getUserObject();
+ Object rhObject = rh.getUserObject();
+ result = CompareUtil.compare(lhs, rhs);
+ if (Integer.MAX_VALUE == result) {
+ result = lhObject.toString().compareTo(rhObject.toString());
+ }
+ } else { // urk - broken unless wrapper
+ result = lhs.toString().compareTo(rhs.toString());
+ }
+ }
+ return result;
+ }
+ }
+}
diff --git a/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/Structure.java b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/Structure.java
new file mode 100644
index 000000000..b669f7c6b
--- /dev/null
+++ b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/Structure.java
@@ -0,0 +1,438 @@
+/* *******************************************************************
+ * Copyright (c) 1999-2001 Xerox Corporation,
+ * 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.testing.compare.adapters;
+
+import org.aspectj.testing.compare.GenericTreeNode;
+import org.aspectj.testing.compare.GenericTreeNodesVisitorI;
+import org.aspectj.testing.compare.GenericTreeNodeListOrdererFactoryI;
+import org.aspectj.testing.compare.GenericTreeNodeListOrdererI;
+import org.aspectj.testing.compare.adapters.StructureGenericTreeNodeFactory;
+
+// XXX compiler import org.aspectj.asm.StructureNode;
+// XXX wes move to ajde tests import org.aspectj.tools.ajde.StructureUtilities;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Compare or print (serialized) structure tree/graph(s).
+ * Mostly thread-safe, except that (todo for now) PRINT_SINK is a mutable static
+ * variable settable by the arguments.
+ * See {@link #main(String[]) main} for usage.
+ */
+public class Structure {
+ // ---------------------------------- static fields
+ // PRINT_SINK as static permits static inner class singleton visitors to reflect output sink policy
+ /** WARNING: print sink changeable at runtime (affects all instances of class!) */
+ public static PrintStream PRINT_SINK = System.err;
+
+ /** singleton factory to sort by string */
+ protected static final GenericTreeNodeListOrdererFactoryI STRING_SORTER_FACTORY
+ = new StringSortFactory();
+ /** singleton factory to sort by string */
+ protected static final GenericTreeNodeListOrdererI STRING_SORTER
+ = new StringSort();
+ /** singleton to sort by string */
+ protected static final Comparator STRING_COMP = new StringComparator();
+ /** default visitor printer expects only one of pair and render each parent as tab */
+ protected static final GenericTreeNodesVisitorI PRINT_EACH = new PrintEach();
+ /** visitor printer prints long version of both input (todo: not redirected by toOut) */
+ protected static final GenericTreeNodesVisitorI PRINT_ALL = GenericTreeNode.PRINTALL;
+ /** visitor printer prints long version of both input if non-matching (todo: not redirected by toOut) */
+ protected static final GenericTreeNodesVisitorI PRINT_ERR = GenericTreeNode.PRINTERR;
+ /** parms: default list of files used if no files given */
+ public static final String DEFAULT_LST = "default.lst";
+ /** parms: default argument list if none given */
+ public static final String[] DEFAULT_ARGS = new String[]
+ { "-d" , "classes" , "-workingdir", "ajworkingdir", "-argfile", DEFAULT_LST};
+
+ // ---------------------------------- static methods
+ /**
+ * Print and/or compare Structure trees.
+ * One (actual) can be compiled at the same time;
+ * either (expected or actual) may be read in from a serialized tree.
+ * Supported arguments:
+ * <table>
+ * <tr><td>{ajc compiler args}</td>
+ * <td>The set of compiler arguments, to compile a new tree</td></tr>
+ * <tr><td>-expect {file}.ser</td>
+ * <td>The old Structure tree to read in and compare with new</td></tr>
+ * <tr><td>-actual {file}.ser</td>
+ * <td>The new Structure tree to read in (i.e., no compile)</td></tr>
+ * <tr><td>-save {file}.ser</td>
+ * <td>Serialize the results of the compile to {file}.ser.</td></tr>
+ * <tr><td>-printall</td>
+ * <td>Print all pairs in long format</td></tr>
+ * <tr><td>-printeach</td>
+ * <td>Print each item in short format
+ * - used when only one tree is available</td></tr>
+ * <tr><td>-printerr</td>
+ * <td>Print pairs of items that do not match
+ * - used when only both trees are available</td></tr>
+ * <tr><td>-sortString</td>
+ * <td>before comparing, do a string-sort on each child list.</td></tr>
+ * <tr><td>-toOut</td>
+ * <td>Redirect output from System.err to System.out (for all instances of this class)</td></tr>
+ * <tr><td>-notest</td>
+ * <td>Do not run test (e.g., just compile and save)</td></tr>
+ * </table>
+ * @param args the String[] of arguments for this test - defaults supplied if empty.
+ */
+ public static void main(String[] args) {
+ new Structure().runTest(args);
+ }
+
+ // ---------------------------------- static util
+ protected static final void log(String s) {
+ final PrintStream sink = PRINT_SINK;
+ if ((null != s) && (null != sink)) {
+ sink.println("Structure: " + s);
+ }
+ }
+
+ protected static void signal(String message) {
+ log(message);
+ }
+ protected static void signal(String context, String event) {
+ log(context + ": " + event);
+ }
+ protected static void signal(String context, Throwable event) {
+ if (null == event) {
+ log(context);
+ } else {
+ String msg = event.getMessage();
+ log(context + ": " + msg);
+ event.printStackTrace(PRINT_SINK);
+ }
+ }
+
+ // ---------------------------------- instance fields
+ /** args result: path to serialize actual tree to */
+ protected String actualSavePath = null;
+ /** args result: path of actual serialized tree */
+ protected String actualPath = null;
+ /** args result: path of expected serialized tree */
+ protected String expectedPath = null;
+ /** args result: false if not running comparisons */
+ protected boolean doComparison = true;
+
+ /** visitor to run - print or test (default is PRINT_ALL) */
+ protected GenericTreeNodesVisitorI visitor = PRINT_ALL;
+ /** this determines for each set of children whether/how to sort them */
+ protected GenericTreeNodeListOrdererFactoryI sorter = null;
+
+ // ---------------------------------- instance methods
+ /** no-arg (default) constructor */
+ public Structure() { }
+
+ /**
+ * Clear settings before running.
+ * Use this unless you want to inherit settings from
+ * a prior run. You can specify new arguments that
+ * overwrite the old settings.
+ * @param args the String[] used for runTest(String[])
+ * @see #clear()
+ * @see #runTest(String[])
+ */
+ public synchronized void clearAndRunTest(String[] args) {
+ actualSavePath = null;
+ actualPath = null;
+ expectedPath = null;
+ doComparison = true;
+ visitor = PRINT_ALL;
+ runTest(args);
+ }
+
+ /**
+ * Read and/or write and/or compare structure trees.
+ * Any results are delivered by the comparison visitors.
+ * The test process is as follows:
+ * <li>processArgs(..)</li>
+ * <li>saveActual(..) if saving actual to file</li>
+ * <li>doComparison(..) of actual and expected per visitor/sorter options</li>
+ * <p>If you run this consecutively, you'll inherit the values
+ * of the last run that you do not overwrite
+ * unless you invoke {@link #clear()}. The method synchronization
+ * will not prevent another thread from interrupting your
+ * @param args the String[] defined by <code>main(String[] args)</code>
+ */
+ public synchronized void runTest(String[] args) {
+ if (null == args) throw new IllegalArgumentException("null args");
+ args = processArgs(args);
+ if (null == args) throw new IllegalArgumentException("bad args");
+// XXX compiler
+//// StructureNode lhsRoot = loadStructureNode(expectedPath);
+//// StructureNode rhsRoot = loadStructureNode(actualPath);
+//// if (null == rhsRoot) { // not serialized - try compile
+//// // XXX wes move to ajde tests rhsRoot = StructureUtilities.buildStructureModel(args);
+//// }
+//// // save actual, if requested
+//// saveActual(rhsRoot);
+//// // do comparison (i.e., run test)
+//// doComparison(lhsRoot, rhsRoot);
+ }
+
+ /**
+ * Process arguments by extracting our arguments from callee arguments
+ * and initializing the class accordingly.
+ * {@link See main(String[])} for a list of valid arguments.
+ * @param args the String[] adopted, elements shifted down to remove ours
+ * @return a String[] containing args not relevant to us (i.e., for callee = compiler)
+ */
+ protected String[] processArgs(String[] args) {
+ if ((null == args) || (1 > args.length)) {
+ return processArgs(DEFAULT_ARGS);
+ }
+ int numFiles = 0;
+ int numArgFiles = 0;
+ final String SKIP = "skip";
+ String calleeArg;
+ int readIndex = 0;
+ int writeIndex = 0;
+ while (readIndex < args.length) {
+ final String arg = args[readIndex];
+ calleeArg = arg;
+ // assume valid arg for callee unless shown to be ours
+ if ((null == arg) || (0 == arg.length())) {
+ signal("processArgs", "empty arg at index "+ readIndex);
+ break;
+ } else if (arg.startsWith("@") || "-argfile".equals(arg)) {
+ numArgFiles++;
+ } else if (arg.endsWith(".java")) {
+ numFiles++;
+ } else if (arg.startsWith("-")) {
+ calleeArg = SKIP; // assume args are ours unless found otherwise
+ if ("-toOut".equals(arg)) {
+ Structure.PRINT_SINK = System.out;
+ } else if ("-notest".equals(arg)) {
+ doComparison = false;
+ } else if ("-printall".equals(arg)) {
+ visitor = PRINT_ALL;
+ } else if ("-printeach".equals(arg)) {
+ visitor = PRINT_EACH;
+ } else if ("-printerr".equals(arg)) {
+ visitor = PRINT_ERR;
+ } else if ("-sortString".equals(arg)) {
+ sorter = STRING_SORTER_FACTORY;
+ } else { // the rest of ours require a parm
+ readIndex++;
+ String next = ((readIndex < args.length)
+ ? args[readIndex] : null);
+ boolean nextIsOption
+ = ((null != next) && next.startsWith("-"));
+ if ("-expect".equals(arg)) {
+ expectedPath = next;
+ } else if ("-actual".equals(arg)) {
+ actualPath = next;
+ } else if ("-save".equals(arg)) {
+ actualSavePath = next;
+ } else {
+ readIndex--;
+ calleeArg = arg; // ok, not ours - save
+ }
+ if ((calleeArg == SKIP)
+ && ((null == next) || (nextIsOption))) {
+ signal("processArgs", arg + " requires a parameter");
+ break;
+ }
+ }
+ }
+ if (SKIP != calleeArg) {
+ args[writeIndex++] = calleeArg;
+ }
+ readIndex++;
+ } // end of reading args[]
+ if (readIndex < args.length) { // bad args[] - abort (see signals above)
+ return null;
+ }
+ // if no input specified, supply default list file
+ if ((0 == numFiles) && (0 == numArgFiles) && (null == actualPath)) {
+ if (writeIndex+3 > args.length) {
+ String[] result = new String[writeIndex+2];
+ System.arraycopy(args, 0, result, 0, writeIndex);
+ args = result;
+ }
+ args[writeIndex++] = "-argfile";
+ args[writeIndex++] = DEFAULT_LST;
+ }
+ // if some args clipped (ours), clip array to actual (callee)
+ if (writeIndex < args.length) {
+ String[] result = new String[writeIndex];
+ System.arraycopy(args, 0, result, 0, writeIndex);
+ args = result;
+ }
+ return args;
+ } // processArgs(String[])
+
+// XXX compiler
+// /**
+// * Load any StructureNode tree at path, if possible
+// * @param path the String path to a serialized StructureNode
+// */
+// protected StructureNode loadStructureNode(String path) {
+// if (null == path) return null;
+// StructureNode result = null;
+// try {
+// FileInputStream stream = new FileInputStream(path);
+// ObjectInputStream ois = new ObjectInputStream(stream);
+// Object o = ois.readObject();
+// Class oClass = (null == o ? null : o.getClass());
+// if (StructureNode.class.isAssignableFrom(oClass)) {
+// result = (StructureNode) o;
+// } else {
+// signal("loadStructureNode(\"" + path
+// + "\") - wrong type: " + oClass);
+// }
+// } catch (Throwable t) {
+// signal("loadStructureNode(\"" + path + "\")", t);
+// }
+// return result;
+// }
+//
+// /**
+// * Save any StructureNode tree to actualSavePath, if possible
+// * @param actual the StructureNode root of the actual tree to save
+// * (ignored if null)
+// */
+// protected void saveActual(StructureNode actual) {
+// if ((null != actual) && (null != actualSavePath)) {
+// ObjectOutputStream p = null;
+// FileOutputStream ostream = null;
+// try {
+// ostream = new FileOutputStream(actualSavePath);
+// p = new ObjectOutputStream(ostream);
+// p.writeObject(actual);
+// } catch (Throwable e) {
+// signal("saveActual(\"" + actual + "\") -> "
+// + actualSavePath, e);
+// } finally {
+// try {
+// if (null != p) p.flush();
+// if (null != ostream) ostream.close();
+// } catch (IOException o) {} // ignored
+// }
+// }
+// }
+
+ /**
+ * Compare two trees based on the settings for
+ * the visitor and sorter. All results should be
+ * delivered by the visitor.
+ * @param expected the StructureNode actual tree to compare
+ * @param actual the StructureNode actual tree to compare
+ */
+ // XXX compiler
+// protected void doComparison(StructureNode expected, StructureNode actual) {
+// if (doComparison) {
+// final GenericTreeNodeFactoryI fact =
+// StructureGenericTreeNodeFactory.SINGLETON;
+// GenericTreeNode lhs = null;
+// if (expected != null) {
+// lhs = fact.createGenericTreeNode(expected, null);
+// }
+// GenericTreeNode rhs = null;
+// if (actual != null) {
+// rhs = fact.createGenericTreeNode(actual, null);
+// }
+// GenericTreeNode.traverse(lhs, rhs, sorter, visitor);
+// }
+// }
+
+ /**
+ * A visitor which prints each to the sink (if any).
+ * If only one of the pair is not null,
+ * render it using GenericTreeNode.shortString()
+ */
+ static class PrintEach implements GenericTreeNodesVisitorI {
+ private PrintEach() {}
+ public boolean visit(GenericTreeNode lhs,GenericTreeNode rhs) {
+ PrintStream sink = PRINT_SINK;
+ if (null != sink) {
+ if ((lhs != null) && (rhs != null)) { // both
+ sink.println("[lhs=" + lhs + "] [rhs=" + rhs + "]");
+ } else {
+ GenericTreeNode gtn = (null == lhs ? rhs : lhs);
+ if (null != gtn) { // one
+ sink.println(gtn.shortString());
+ }
+ }
+ }
+ return true;
+ }
+ } // class PrintEach
+
+ static class StringSortFactory implements GenericTreeNodeListOrdererFactoryI {
+ /**
+ * Produce the correct orderer for the children of the given GenericTreeNodes
+ * This always produces the same StringSorter.
+ * @return GenericTreeNodeListOrdererI for children, or null if none to be used
+ */
+ public GenericTreeNodeListOrdererI produce(GenericTreeNode lhs, GenericTreeNode rhs,
+ GenericTreeNodesVisitorI visitor) {
+ return STRING_SORTER;
+ }
+ } // class StringSortFactory
+
+ /**
+ * sort input lists by Comparator <code>Structure.STRING_COMP</code>.
+ */
+ static class StringSort implements GenericTreeNodeListOrdererI {
+ /**
+ * Order input lists (not copies)
+ * using the Comparator <code>Structure.STRING_COMP</code>.
+ * @param lhs the List representing the left-hand-side
+ * which contains only GenericTreeNode
+ * @param rhs the List representing the right-hand-side
+ * which contains only GenericTreeNode
+ * @return two lists List[] (0 => lhs, 1 => rhs)
+ */
+ public List[] produceLists(List lhs, List rhs) {
+ if (null != lhs) Collections.sort(lhs, STRING_COMP);
+ if (null != rhs) Collections.sort(rhs, STRING_COMP);
+ List[] result = new List[2];
+ result[0] = lhs;
+ result[1] = rhs;
+ return result;
+ }
+ } // class CompSort
+
+ /**
+ * Comparator that imposes case-sensitive String order
+ * based on GenericTreeNode.shortString() if both are
+ * GenericTreeNode, or toString() otherwise.
+ * If both are null, considered equal.
+ * If one is null, the other is considered larger.
+ */
+ static class StringComparator implements Comparator {
+ public int compare(Object lhs, Object rhs) {
+ if (null == lhs) {
+ return (null == rhs ? 0 : -1);
+ } else if (null == rhs) {
+ return 1;
+ } else if ((lhs instanceof GenericTreeNode)
+ && (rhs instanceof GenericTreeNode)) {
+ String lhsString = ((GenericTreeNode) lhs).shortString();
+ String rhsString = ((GenericTreeNode) rhs).shortString();
+ if (null == lhsString) {
+ return (null == rhsString ? 0 : rhsString.compareTo(lhsString));
+ } else {
+ return lhsString.compareTo(rhsString);
+ }
+ } else {
+ return lhs.toString().compareTo(rhs.toString());
+ }
+ }
+ } // class StringComparator
+} // class Structure
+
diff --git a/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/StructureGenericTreeNodeFactory.java b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/StructureGenericTreeNodeFactory.java
new file mode 100644
index 000000000..1f5883d2c
--- /dev/null
+++ b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/StructureGenericTreeNodeFactory.java
@@ -0,0 +1,308 @@
+/* *******************************************************************
+ * Copyright (c) 1999-2001 Xerox Corporation,
+ * 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.testing.compare.adapters;
+//
+//import org.aspectj.asm.SourceLocation;
+import org.aspectj.testing.compare.GenericTreeNode;
+//import org.aspectj.testing.compare.*;
+//import org.aspectj.asm.StructureNode;
+//import org.aspectj.asm.LinkNode;
+//import org.aspectj.asm.RelationNode;
+//import org.aspectj.asm.Relation;
+//import org.aspectj.asm.ProgramElementNode;
+//import java.util.*;
+//
+///**
+// * Factory for adapting StructureNode trees to GenericTreeNode
+// */
+// XXX compiler
+public class StructureGenericTreeNodeFactory implements GenericTreeNodeFactoryI {
+ public GenericTreeNode createGenericTreeNode(Object root,
+ GenericTreeNode parent) {
+ return null;
+ }
+ /**
+ * @see org.aspectj.testing.compare.adapters.GenericTreeNodeFactoryI#getRootClass()
+ */
+ public Class getRootClass() {
+ return null;
+ }
+
+}
+// protected static final String[] MODIFIERS = new String[]
+// { "strictfp", "abstract", "synchronized", "native",
+// "final", "transient", "static", "volatile" };
+// protected static final List MODIFIERS_LIST = Arrays.asList(MODIFIERS);
+// protected static final String[] ACCESS = new String[]
+// { "private", "protected", "package", "public", "privileged" };
+// protected static final List ACCESS_LIST = Arrays.asList(ACCESS);
+//
+// /** represent empty list of children (todo: use immutable instead) */
+// public static final List EMPTY_LIST = new ArrayList();
+// public static final GenericTreeNodeFactoryI SINGLETON
+// = new StructureGenericTreeNodeFactory();
+// /** delegate of the factory */
+// private static final Comparator NODE_COMPARATOR;
+//
+// static {
+// SubTypeComparator init = new SubTypeComparator();
+// init.addComparator(LinkNode.class, LinkNodeComparator.SINGLETON);
+// init.addComparator(RelationNode.class, RelationNodeComparator.SINGLETON);
+// init.addComparator(ProgramElementNode.class, ProgramElementNodeComparator.SINGLETON);
+// init.addComparator(StructureNode.class, StructureNodeComparator.SINGLETON);
+// GenericTreeNodeComparator gtnc = new GenericTreeNodeComparator(init);
+// NODE_COMPARATOR = gtnc;
+// }
+//
+// private StructureGenericTreeNodeFactory() {}
+// public Class getRootClass() {
+// return StructureNode.class;
+// }
+//
+// /**
+// * Adapt Structure model to tree rooted at GenericTreeNode.
+// * Only takes the current state of a model which does not
+// * change during the construction of the adapter. If the
+// * model changes, you can ask the adapter for a newly
+// * wrapped tree.
+// * @param root the TreeNode taken as root of a tree to wrap
+// * @param parent the parent of the resulting GenericTreeNode
+// * @throws IllegalArgumentException if root is null
+// * or if children are not instanceof TreeNode.
+// */
+// public GenericTreeNode createGenericTreeNode(Object root,
+// GenericTreeNode parent) {
+// if (null == root) {
+// throw new IllegalArgumentException("null root");
+// }
+// if (! (root instanceof StructureNode)) {
+// throw new IllegalArgumentException("not StructureNode: " + root);
+// }
+// GenericTreeNode result = new GenericTreeNode();
+// StructureNode rootNode = (StructureNode) root;
+// List kidList = rootNode.getChildren();
+// List kids = EMPTY_LIST;
+// // get kids of result
+// if (null != kidList) {
+// final int numKids = kidList.size();
+// ArrayList newKids = new ArrayList(numKids);
+// ListIterator kidIter = kidList.listIterator();
+// Object child;
+// for (int i = 0; i < numKids; i++) {
+// if (! kidIter.hasNext()) { // items removed from list while iterating
+// throw new Error("(! hasNext())");
+// }
+// child = kidIter.next();
+// if (! (child instanceof StructureNode)) {
+// throw new Error("! (child instanceof StructureNode)): " + child );
+// }
+// newKids.add(createGenericTreeNode((StructureNode) child, result));
+// }
+// kids = newKids;
+// }
+// // todo: select comparator here - avoids type checking at run time
+// //result.init(parent, StructureComparator.SINGLETON, rootNode, kids, null);
+// result.init(parent, NODE_COMPARATOR, rootNode, kids, null);
+// return result;
+// }
+//
+// /** Comparator for GenericTreeNode delegates to handler for nodes... */
+// static final class GenericTreeNodeComparator implements Comparator {
+// private final Comparator delegate;
+// private GenericTreeNodeComparator (Comparator delegate) {
+// this.delegate = delegate;
+// }
+// public final int compare(Object lhs, Object rhs) {
+// return delegate.compare(((GenericTreeNode)lhs).getNode()
+// , ((GenericTreeNode)lhs).getNode());
+// }
+// }
+//
+// /**
+// * Comparator for RelationNode delegates to String & boolean comparison of public attributes.
+// */
+// static class RelationNodeComparator implements Comparator {
+// public static Comparator SINGLETON = new RelationNodeComparator();
+// private RelationNodeComparator () {}
+// /**
+// * Comparator for RelationNode uses String & boolean comparison of public attributes
+// * forwardNavigationName, backNavigationName, associationName, symmetrical, associative.
+// */
+// public int compare(Object lhs, Object rhs) {
+// int result = CompareUtil.compare(lhs, rhs);
+// if (Integer.MAX_VALUE == result) {
+// RelationNode lh = (RelationNode) lhs ;
+// RelationNode rh = (RelationNode) rhs ;
+// Relation leftRelation = lh.getRelation();
+// Relation rightRelation = rh.getRelation();
+// String left = null;
+// String right = null;
+// result = CompareUtil.compare(leftRelation, rightRelation);
+// if (0 == result) {
+// left = leftRelation.getForwardNavigationName();
+// right = rightRelation.getForwardNavigationName();
+// result = CompareUtil.compare(left, right);
+// }
+// if (0 == result) {
+// left = leftRelation.getBackNavigationName();
+// right = rightRelation.getBackNavigationName();
+// result = CompareUtil.compare(left, right);
+// }
+// if (0 == result) {
+// left = leftRelation.getAssociationName();
+// right = rightRelation.getAssociationName();
+// result = CompareUtil.compare(left, right);
+// }
+// boolean l = false;
+// boolean r = false;
+// if (0 == result) {
+// l = leftRelation.isSymmetrical();
+// r = rightRelation.isSymmetrical();
+// result = CompareUtil.compare(l, r);
+// }
+// if (0 == result) {
+// l = leftRelation.isTransitive();
+// r = rightRelation.isTransitive();
+// result = CompareUtil.compare(l, r);
+// }
+// }
+// return result;
+// }
+// }
+//
+// /** Comparator for ProgramElementNode. */
+// static class ProgramElementNodeComparator implements Comparator {
+// public static Comparator SINGLETON = new ProgramElementNodeComparator();
+// private ProgramElementNodeComparator () {}
+// public int compare(Object lhs, Object rhs) {
+// int result = CompareUtil.compare(lhs, rhs);
+// if (Integer.MAX_VALUE == result) {
+// ProgramElementNode lh = (ProgramElementNode) lhs ;
+// ProgramElementNode rh = (ProgramElementNode) rhs ;
+//
+// boolean rhStmntKind = rh.isCode();
+// boolean lhStmntKind = lh.isCode();
+// if (lhStmntKind != rhStmntKind) {
+// return (lhStmntKind ? 1 : -1);
+// }
+// String left= lh.getKind();
+// String right= rh.getKind();
+// // boilerplate
+// result = CompareUtil.compare(left, right);
+// if (Integer.MAX_VALUE == result) {
+// result = left.compareTo(right);
+// if (0 != result) return result;
+// }
+// right = rh.getSignature();
+// left = lh.getSignature();
+// result = CompareUtil.compare(left, right);
+// if (Integer.MAX_VALUE == result) {
+// result = left.compareTo(right);
+// if (0 != result) return result;
+// }
+// List rightList = rh.getModifiers();
+// List leftList = lh.getModifiers();
+// result = CompareUtil.compare(leftList, rightList, MODIFIERS_LIST);
+// if (0 != result) return result;
+//
+// result = compare(rh.getAccessibility(), lh.getAccessibility());
+// if (0 != result) return result;
+//
+// right = rh.getDeclaringType();
+// left = lh.getDeclaringType();
+// result = CompareUtil.compare(left, right);
+// if (Integer.MAX_VALUE == result) {
+// result = left.compareTo(right);
+// if (0 != result) return result;
+// }
+//
+// SourceLocation leftSourceLocation = rh.getSourceLocation();
+// SourceLocation rightSourceLocation = rh.getSourceLocation();
+// int iright= rightSourceLocation.getLineNumber();
+// int ileft= leftSourceLocation.getLineNumber();
+// if (iright != ileft) return (ileft-iright);
+// iright= rightSourceLocation.getColumnNumber();
+// ileft= leftSourceLocation.getColumnNumber();
+// if (iright != ileft) return (ileft-iright);
+//
+// right= rh.getFormalComment();
+// left= lh.getFormalComment();
+// if (Integer.MAX_VALUE == result) {
+// result = left.compareTo(right);
+// if (0 != result) return result;
+// }
+//
+// right = rh.toString(); // ignored? super
+// left = lh.toString(); // ignored? super
+// if (Integer.MAX_VALUE == result) {
+// result = left.compareTo(right);
+// if (0 != result) return result;
+// }
+// // ignore source file path - may change?
+// // lhSourceFilePath = lh.getSourceFilePath(); // ignored
+// // lh.sourceFilePath = lh.getSourceFilePath(); // ignored
+// // List rhRelations= rh.getRelations() ; // ignored
+// // List lhRelations= lh.getRelations(); // ignored
+// return 0;
+// }
+// return result;
+// }
+// }
+//
+// /** Comparator for LinkNode. */
+// static class LinkNodeComparator implements Comparator {
+// public static Comparator SINGLETON = new LinkNodeComparator();
+// private LinkNodeComparator () {}
+// public int compare(Object lhs, Object rhs) {
+// int result = CompareUtil.compare(lhs, rhs);
+// if (Integer.MAX_VALUE == result) {
+// LinkNode lh = (LinkNode) lhs ;
+// LinkNode rh = (LinkNode) rhs ;
+// // LinkNode only has child and lexical name in toString
+// result = lh.toString().compareTo(rh.toString());
+// }
+// return result;
+// }
+// } // class LinkNodeComparator
+//
+// /**
+// * Comparator for StructureNode.
+// * <li>todo: implement comparators for each StructureNode subtype</li>
+// */
+// static class StructureNodeComparator implements Comparator {
+// public static Comparator SINGLETON = new StructureNodeComparator();
+// private StructureNodeComparator () {}
+// public int compare(Object lhs, Object rhs) {
+// int result = CompareUtil.compare(lhs, rhs);
+// if (Integer.MAX_VALUE == result) {
+// Class lhClass = lhs.getClass() ;
+// Class rhClass = rhs.getClass() ;
+// if ((StructureNode.class.isAssignableFrom(lhClass))
+// && (StructureNode.class.isAssignableFrom(rhClass))) {
+// StructureNode lh = (StructureNode) lhs ;
+// StructureNode rh = (StructureNode) rhs ;
+// Object lhObject = lh.getName(); // todo: weak name-based comparison
+// Object rhObject = rh.getName();
+// result = CompareUtil.compare(lhs, rhs);
+// if (Integer.MAX_VALUE == result) {
+// result = lhObject.toString().compareTo(rhObject.toString());
+// }
+// } else { // urk - broken unless wrapper
+// result = lhs.toString().compareTo(rhs.toString());
+// }
+// }
+// return result;
+// }
+// }
+//}
diff --git a/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/SubTypeComparator.java b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/SubTypeComparator.java
new file mode 100644
index 000000000..3094fdb64
--- /dev/null
+++ b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/SubTypeComparator.java
@@ -0,0 +1,224 @@
+/* *******************************************************************
+ * Copyright (c) 1999-2001 Xerox Corporation,
+ * 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.testing.compare.adapters;
+
+import org.aspectj.testing.compare.CompareUtil;
+import java.util.Comparator;
+
+// for testing code
+import java.util.*;
+import java.text.Collator;
+
+/**
+ * This adopts pairs of [Class, Comparator]
+ * and implements compare by delegation thereto,
+ * selecting the first added where the classes of the both inputs
+ * are assignable to the pair Class.
+ * It first applies the null-semantics of CompareUtil.compare(..),
+ * which holds that null values are less-than non-null values,
+ * and that two nulls are equal.
+ * Note that this class uses Object.equals(..)'s default reference
+ * equality, so two SubTypeComparator with the same list
+ * of delegates will NOT be considered equal.
+ * <p>todo: This class is not thread-safe.
+ * <p>todo: immutable: final list copy on construction to implement equals??
+ */
+public class SubTypeComparator implements Comparator {
+ /** order-sensitive comparators collection */
+ private Vector comparators;
+ /** copy of comparators for compare method */
+ private Struct[] cache;
+
+ /** default constructor */
+ public SubTypeComparator () {
+ comparators = new Vector();
+ }
+
+ /**
+ * Return true if the Class is in the list of comparators
+ * as of the initial execution of the method.
+ * @param c the Class to look for a comparator
+ * @return true of comparator exists for c
+ */
+ private boolean contains(Class c) {
+ final int size = comparators.size();
+ for (int i = 0; i < size; i++) {
+ if (c == ((Struct) comparators.elementAt(i)).accepts) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get copy of comparators for compare operation.
+ */
+ private Struct[] getComparators() { // todo: sync on comparators
+ if ((null == cache) || (cache.length < comparators.size())) {
+ cache = new Struct[comparators.size()];
+ comparators.copyInto(cache);
+ }
+ return cache;
+ }
+
+ /**
+ * Add a Class, Comparator pair as delegate when
+ * both input are assignable to Class.
+ * Note that additions are checked in the order they are added,
+ * so add the lowest subtypes first. (i.e., if you add
+ * a comparator for Class Object first, none of the others
+ * will ever match.)
+ * @param accepts the Class supertype of objects to accept
+ * @param comparator the Comparator to use on such objects
+ * @return false if not added, because either input is null
+ * or because the Class is represented already.
+ */
+ public final boolean addComparator(Class accepts, Comparator comparator) {
+ if ((null == accepts) || (null == comparator)
+ || (contains(accepts))) {
+ return false;
+ }
+ comparators.addElement(new Struct(accepts, comparator));
+ return true;
+ }
+
+ /**
+ * This implements compare by delegating
+ * to the first input Comparator
+ * where the class of the both input
+ * is assignable to the pair Class.
+ * It first enforces the null-semantics of CompareUtil.compare(..).
+ * @throws ClassCastException if both input are not null and
+ * they are not assignable to any registered Comparator.
+ */
+ public final int compare(Object lhs, Object rhs) {
+ int result = CompareUtil.compare(lhs, rhs);
+ if (Integer.MAX_VALUE == result) {
+ Class lhClass = lhs.getClass() ;
+ Class rhClass = rhs.getClass() ;
+ Struct[] comp = getComparators();
+ Class compClass;
+ for (int i = 0; i < comp.length; i++) {
+ compClass = comp[i].accepts;
+ if ((compClass.isAssignableFrom(lhClass))
+ && (compClass.isAssignableFrom(lhClass))) {
+ return comp[i].comparator.compare(lhs, rhs);
+ }
+ }
+ // not found - throw ClassCastException
+ String mssg = "Unable to find Comparator for "
+ + "lhs Class: " + lhClass.getName()
+ + " rhs Class: " + rhClass.getName();
+ throw new ClassCastException(mssg);
+ }
+ return result;
+ }
+
+ /**
+ * (unnecessary) Struct to hold class-comparator pair
+ * is preparation for using collections
+ */
+ static class Struct {
+ public final Class accepts;
+ public final Comparator comparator;
+ /**
+ * @param accepts the Class to accept input for - not null
+ * @param comparator the Comparator to compare input with - not null
+ */
+ public Struct(Class accepts,Comparator comparator) {
+ this.accepts = accepts;
+ this.comparator = comparator;
+ }
+ /** delegate to accept hashcode */
+ public int hashCode() { return accepts.hashCode() ; }
+ /** WARNING: fast comparison based only on accept key reference identity */
+ public boolean equals(Object o) {
+ return ((null != o) && (o instanceof Struct)
+ && (accepts == ((Struct)o).accepts));
+ }
+ } // class Struct
+
+ //----------------------------------------------- test code
+ /** test code */
+ static class Test { // todo move elsewhere
+ public void runTest(String[] args) {
+ if ((null == args) || (1 > args.length)) {
+ args = new String[] { "one", "two", "THREE", "FOUR", "fIVE", "6" };
+ }
+ SubTypeComparator me = new SubTypeComparator();
+ String[] copy = new String[args.length];
+ System.arraycopy(args, 0, copy, 0, copy.length);
+ List list = Arrays.asList(args);
+ Throwable result = test(me, list);
+ if ((null == result)
+ && (!ClassCastException.class.isAssignableFrom(result.getClass()))) {
+ System.err.println("FAIL: expected cce: " + result);
+ }
+ me.addComparator(String.class, Collator.getInstance());
+ me.addComparator(Object.class, new Comparator () {
+ public int compare (Object lhs, Object rhs) {
+ throw new Error("never used");
+ }});
+ result = test(me, list);
+ if (null != result) {
+ if (ClassCastException.class.isAssignableFrom(result.getClass())) {
+ System.err.println("FAIL: unexpected cce: " + result);
+ } else {
+ System.err.println("FAIL: unexpected Throwable: " + result);
+ }
+ }
+ // heterogeneous - pick Object
+ Object[] temp = new Object[] { "string", new Integer(1) };
+ result = test(me, Arrays.asList(temp));
+ if ((null == result)
+ && (!Error.class.isAssignableFrom(result.getClass()))) {
+ System.err.println("FAIL: expected Error: " + result);
+ }
+
+ StringBuffer toPrint = print(Arrays.asList(copy), null);
+ toPrint.append("\n");
+ print(list, toPrint);
+ System.err.println(toPrint.toString());
+ }
+
+ StringBuffer print(List list, StringBuffer sb) {
+ if (null == sb) sb = new StringBuffer();
+ sb.append("[");
+ ListIterator iter = list.listIterator();
+ while (iter.hasNext()) {
+ sb.append(iter.next().toString());
+ if (iter.hasNext()) sb.append(", ");
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ /**
+ * run comparison, return true if got expected exception
+ */
+ Throwable test(Comparator c, List l) {
+ try {
+ Collections.sort(l,c);
+ return null;
+ } catch (Throwable r) {
+ return r;
+ }
+ }
+ } // class Test
+
+ /** invoke Test.runTest(args) todo remove */
+ public static void main(String[] args) {
+ new Test().runTest(args);
+ }
+} // class SubTypeComparator
diff --git a/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/package.html b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/package.html
new file mode 100644
index 000000000..c2d839ed1
--- /dev/null
+++ b/aspectj-attic/testing-src/org/aspectj/testing/compare/adapters/package.html
@@ -0,0 +1,50 @@
+<html>
+<body>
+These adapters facilitate using the GenericTreeNode
+comparison utilities on different types of trees.
+The classes currently in this package support Swing
+<code>TreeNode</code> and AspectJ compiler <code>StructureNode</code>.
+
+<p>
+<code>Structure</code> supports a command-line interface for
+compiling <code>StructureNode</code> trees using
+<code>AspectJCompiler</code> and saving
+or loading them using serialization. Once loaded, two trees
+can be compared using the <code>GenericTreeNode.traverse(..)</code> method,
+providing it the appropriate visitors and comparators to implement
+a comparison of the expected and actual structure trees and
+report on any differences. (This is used to validate that
+changes to the structure tree are backwards compatible with
+trees from previous compiles, since the structure tree is
+effectively exported from the compiler to the IDE tools.)
+
+<p>
+If you want to support new trees,
+<code>GenericTreeNodeFactoryI</code> is the interface to implement.
+It specifies a factory to provide a <code>Comparator</code> based
+on a given pair to be compared. This means that you can
+use (or generate) comparators based on specific pairs.
+Usually you will implement only for the target type,
+so your factory may be final and always return a
+singleton <code>Comparator.</code>
+<p>
+The <code>SubTypeComparator</code> implements a <code>Comparator</code>
+container that acts as a <code>Comparator</code> by delegating to
+contained <code>Comparator</code>s registered along with the class of the input
+they accept. This permits you to write type-specific
+<code>Comparator</code>s for heterogeneous trees. It does require
+both members of the comparison be assignable to the
+target class.
+
+<p>
+<code>StructureGenericTreeNodeFactory</code> is an implementation of
+<code>GenericTreeNodeFactoryI</code> for StructureNode trees. It
+contains comparator classes for <code>RelationNode</code>, <code>LinkNode,</code>
+and <code>ProgramElementNode</code>,
+combined using a <code>SubTypeComparator.</code>
+<p>
+<code>JTreeNodeGenericTreeNodeFactory</code> is an implementation of
+<code>GenericTreeNodeFactoryI</code> for Swing <code>TreeNode</code>'s, done only
+for testing purposes.
+</body>
+</html>