diff --git a/projects/viztool/src/java/com/samskivert/viztool/Visualizer.java b/projects/viztool/src/java/com/samskivert/viztool/Visualizer.java new file mode 100644 index 00000000..d16b795d --- /dev/null +++ b/projects/viztool/src/java/com/samskivert/viztool/Visualizer.java @@ -0,0 +1,8 @@ +// +// $Id: Visualizer.java,v 1.1 2001/07/04 18:24:07 mdb Exp $ + +package com.samskivert.viztool.viz; + +public class Visualizer +{ +} diff --git a/projects/viztool/src/java/com/samskivert/viztool/hierarchy/Chain.java b/projects/viztool/src/java/com/samskivert/viztool/hierarchy/Chain.java new file mode 100644 index 00000000..b94d9d30 --- /dev/null +++ b/projects/viztool/src/java/com/samskivert/viztool/hierarchy/Chain.java @@ -0,0 +1,128 @@ +// +// $Id: Chain.java,v 1.1 2001/07/04 18:24:07 mdb Exp $ + +package com.samskivert.viztool.viz; + +import java.util.ArrayList; +import java.awt.Dimension; +import java.awt.Point; + +/** + * A chain is used by the hierarchy visualizer to represent inheritance + * chains. + */ +public class Chain +{ + /** + * Constructs a chain with the specified class as its root. + */ + public Chain (Class root) + { + _root = root; + } + + /** + * Returns a Dimension instance representing the size of + * this chain (and all contained subchains) in whatever coordinates + * are being used to diagram this chain. + */ + public Dimension getSize () + { + return _size; + } + + /** + * Returns the location of this chain in whatever coordinate system + * that is being used to diagram this chain. + */ + public Point getLocation () + { + return _location; + } + + /** + * Sets the size of this chain. + * + * @see #getSize + */ + public void setSize (int width, int height) + { + _size = new Dimension(width, height); + } + + /** + * Sets the location of this chain. + * + * @see #getLocation + */ + public void setLocation (int x, int y) + { + _location = new Point(x, y); + } + + /** + * Adds a child to this chain. The specified class is assumed to + * directly inherit from the class that is the root of this chain. + */ + public void addClass (Class child) + { + Chain chain = new Chain(child); + if (!_children.contains(chain)) { + _children.add(chain); + } + } + + /** + * Locates the chain for the specified target class and returns it if + * it is a registered child of this chain. Returns null if no child + * chain of this chain contains the specified target class. + */ + public Chain getChain (Class target) + { + if (_root.equals(target)) { + return this; + } + + // just do a depth first search because it's fun + for (int i = 0; i < _children.size(); i++) { + Chain chain = ((Chain)_children.get(i)).getChain(target); + if (chain != null) { + return chain; + } + } + + return null; + } + + public boolean equals (Object other) + { + if (other == null) { + return false; + } else if (other instanceof Chain) { + return ((Chain)other)._root.equals(_root); + } else { + return false; + } + } + + public String toString () + { + StringBuffer out = new StringBuffer(); + toString("", out); + return out.toString(); + } + + protected void toString (String indent, StringBuffer out) + { + out.append(indent).append(_root.getName()).append("\n"); + for (int i = 0; i < _children.size(); i++) { + Chain child = (Chain)_children.get(i); + child.toString(indent + " ", out); + } + } + + protected Class _root; + protected ArrayList _children = new ArrayList(); + protected Dimension _size = new Dimension(0, 0); + protected Point _location = new Point(0, 0); +} diff --git a/projects/viztool/src/java/com/samskivert/viztool/hierarchy/ChainUtil.java b/projects/viztool/src/java/com/samskivert/viztool/hierarchy/ChainUtil.java new file mode 100644 index 00000000..1f0f9d40 --- /dev/null +++ b/projects/viztool/src/java/com/samskivert/viztool/hierarchy/ChainUtil.java @@ -0,0 +1,158 @@ +// +// $Id: ChainUtil.java,v 1.1 2001/07/04 18:24:07 mdb Exp $ + +package com.samskivert.viztool.viz; + +import java.util.ArrayList; + +import com.samskivert.viztool.Log; +import com.samskivert.viztool.enum.Enumerator; + +/** + * Chain related utility functions. + */ +public class ChainUtil +{ + /** + * Builds a list of chains for all the classes enumerated by the + * supplied enumerator. Classes outside the specified package root + * will be ignored except where they are the direct parent of an + * enumerated class inside the package root. + * + * @return an array list containing all of the root chains. + */ + public static ArrayList buildChains (String pkgroot, Enumerator enum) + { + ArrayList roots = new ArrayList(); + computeRoots(pkgroot, enum, roots); + return roots; + } + + /** + * Looks up the chain that contains the specified target class as it's + * root class in the supplied array list of chains. + * + * @return the matching chain or null if no chain could be found. + */ + public static Chain getChain (ArrayList roots, Class target) + { + // figure out which of our root chains (if any) contains the + // specified class + for (int i = 0; i < roots.size(); i++) { + Chain root = (Chain)roots.get(i); + Chain chain = root.getChain(target); + if (chain != null) { + return chain; + } + } + + return null; + } + + /** + * Dumps the classes in the supplied array list of chain instances to + * stdout. + */ + public static void dumpClasses (ArrayList roots) + { + for (int i = 0; i < roots.size(); i++) { + Chain root = (Chain)roots.get(i); + System.out.print(root.toString()); + } + System.out.flush(); + } + + /** + * Scans the list of classes provided by the supplied enumerator and + * constructs a hierarchical representation of those classes. + */ + protected static + void computeRoots (String pkgroot, Enumerator enum, ArrayList roots) + { + while (enum.hasMoreClasses()) { + insertClass(roots, pkgroot, enum.nextClass()); + } + } + + /** + * Loads the supplied class and inserts it into the appropriate + * position in the hierarchy based on its inheritance properties. + */ + protected static + void insertClass (ArrayList roots, String pkgroot, String clazz) + { + try { + // sanity check + if (!clazz.startsWith(pkgroot)) { + Log.warning("Requested to process class not in target " + + "package [class=" + clazz + + ", pkgroot=" + pkgroot + "]."); + return; + } + + // load and insert the class + insertClass(roots, pkgroot, Class.forName(clazz)); + + } catch (Exception e) { + Log.warning("Unable to process class [class=" + clazz + + ", error=" + e + "]."); + } + } + + /** + * Inserts the specified class into the appropriate position in the + * hierarchy based on its inheritance properties. + */ + protected static + void insertClass (ArrayList roots, String pkgroot, Class target) + { + // insert the parent of this class into the hierarchy + Class parent = target.getSuperclass(); + + // if we have no parent, we want to insert ourselves as a root + // class + if (parent == null || parent.equals(Object.class)) { + insertRoot(roots, target); + + } else { + // if our parent is not in this package, we want to insert it + // into the hierarchy as a root class + if (!parent.getName().startsWith(pkgroot)) { + insertRoot(roots, parent); + } + + // and now hang ourselves off of our parent class + Chain chain = getChain(roots, parent); + if (chain == null) { + // if there's no chain for our parent class, we'll need to + // insert it into the hierarchy + insertClass(roots, pkgroot, parent); + // and refetch our chain + chain = getChain(roots, parent); + // sanity check + if (chain == null) { + Log.warning("Chain still doesn't exist even though " + + "we inserted our parent " + + "[class=" + target.getName() + + ", parent=" + parent.getName() + "]."); + return; + } + } + // add class will ignore our request if this class was already + // added due to some previous operation + chain.addClass(target); + } + } + + protected static boolean insertRoot (ArrayList roots, Class root) + { + Chain chroot = new Chain(root); + // make sure no chain already exists for this root + if (!roots.contains(chroot)) { + roots.add(chroot); + return true; + } else { + return false; + } + } +} diff --git a/projects/viztool/src/java/com/samskivert/viztool/hierarchy/HierarchyVisualizer.java b/projects/viztool/src/java/com/samskivert/viztool/hierarchy/HierarchyVisualizer.java new file mode 100644 index 00000000..69b9afdc --- /dev/null +++ b/projects/viztool/src/java/com/samskivert/viztool/hierarchy/HierarchyVisualizer.java @@ -0,0 +1,55 @@ +// +// $Id: HierarchyVisualizer.java,v 1.1 2001/07/04 18:24:07 mdb Exp $ + +package com.samskivert.viztool.viz; + +import java.util.ArrayList; + +import com.samskivert.viztool.Log; +import com.samskivert.viztool.enum.Enumerator; + +/** + * The hierarchy visualizer displays inheritance hierarchies in a compact + * representation so that an entire package can be displayed on a single + * page (or small number of pages). + */ +public class HierarchyVisualizer +{ + /** + * Constructs a hierarchy visualizer with the supplied enumerator as + * its source of classes. If the hierarchy enumerator should be + * limited to a particular set of classes, a filter enumerator should + * be supplied that returns only the classes to be visualized. + * + * @param pkgroot The name of the package that is being visualized. + * @param enum The enumerator that will return the names of all of the + * classes in the specified package. + */ + public HierarchyVisualizer (String pkgroot, Enumerator enum) + { + // keep track of these + _pkgroot = pkgroot; + _enum = enum; + + // process the classes provided by our enumerator + _roots = ChainUtil.buildChains(pkgroot, enum); + } + + /** + * Processes the hierarchy of class chains assigning coordinates to + * all of the chains and subchains so that they can be used to + * generate a visualization. + */ + public void layoutChains (int pointSize) + { + } + + public void dumpClasses () + { + ChainUtil.dumpClasses(_roots); + } + + protected String _pkgroot; + protected Enumerator _enum; + protected ArrayList _roots; +}