001: /* HierarchyTreeModel Copyright (C) 1999-2002 Jochen Hoenicke.
002: *
003: * This program is free software; you can redistribute it and/or modify
004: * it under the terms of the GNU General Public License as published by
005: * the Free Software Foundation; either version 2, or (at your option)
006: * any later version.
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU General Public License for more details.
012: *
013: * You should have received a copy of the GNU General Public License
014: * along with this program; see the file COPYING. If not, write to
015: * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
016: *
017: * $Id: HierarchyTreeModel.java.in,v 1.2.2.1 2002/05/28 17:34:19 hoenicke Exp $
018: */
019:
020: package jode.swingui;
021:
022: import jode.bytecode.ClassInfo;
023:
024: import javax.swing.JProgressBar;
025: import javax.swing.tree.TreeModel;
026: import javax.swing.tree.TreePath;
027: import javax.swing.event.TreeModelListener;
028: import javax.swing.event.TreeModelEvent;
029:
030: import java.lang.Comparable;
031: import java.util.TreeSet;
032: import java.util.Collection;
033: import java.util.Iterator;
034: import java.util.HashMap;
035: import java.util.Set;
036: import java.util.HashSet;
037:
038: import java.util.Enumeration;
039: import java.util.NoSuchElementException;
040:
041: public class HierarchyTreeModel implements TreeModel, Runnable {
042: static final int MAX_PACKAGE_LEVEL = 10;
043: TreeElement root = new TreeElement("");
044: Set listeners = new HashSet();
045: JProgressBar progressBar;
046: Main main;
047:
048: class TreeElement implements Comparable {
049: String fullName;
050: TreeSet childs;
051: boolean inClassPath = false;
052:
053: public TreeElement(String fqn) {
054: this .fullName = fqn;
055: childs = new TreeSet();
056: }
057:
058: public String getFullName() {
059: return fullName;
060: }
061:
062: public void addChild(TreeElement child) {
063: childs.add(child);
064: }
065:
066: public Collection getChilds() {
067: return childs;
068: }
069:
070: public String toString() {
071: return fullName;
072: }
073:
074: public int compareTo(Object o) {
075: TreeElement other = (TreeElement) o;
076: return fullName.compareTo(other.fullName);
077: }
078:
079: public boolean equals(Object o) {
080: return (o instanceof TreeElement)
081: && fullName.equals(((TreeElement) o).fullName);
082: }
083:
084: public int hashCode() {
085: return fullName.hashCode();
086: }
087: }
088:
089: private TreeElement handleClass(HashMap classes, ClassInfo clazz) {
090: if (clazz == null)
091: return root;
092: TreeElement elem = (TreeElement) classes.get(clazz);
093: if (elem != null)
094: return elem;
095:
096: elem = new TreeElement(clazz.getName());
097: classes.put(clazz, elem);
098:
099: if (!clazz.isInterface()) {
100: ClassInfo super Clazz = clazz.getSuperclass();
101: handleClass(classes, super Clazz).addChild(elem);
102: }
103: ClassInfo[] ifaces = clazz.getInterfaces();
104: for (int i = 0; i < ifaces.length; i++)
105: handleClass(classes, ifaces[i]).addChild(elem);
106: if (ifaces.length == 0 && clazz.isInterface())
107: root.addChild(elem);
108: return elem;
109: }
110:
111: public int readPackage(int depth, HashMap classes, String packageName,
112: int count) {
113: if (depth++ >= MAX_PACKAGE_LEVEL)
114: return count;
115: String prefix = packageName.length() == 0 ? "" : packageName + ".";
116: Enumeration enum =
117: ClassInfo.getClassesAndPackages(packageName);
118: while (enum.hasMoreElements()) {
119: //insert sorted and remove double elements;
120: String name = (String)enum.nextElement();
121: String fqn = prefix + name;
122: if (ClassInfo.isPackage(fqn)) {
123: count = readPackage(depth, classes, fqn, count);
124: } else {
125: TreeElement elem = handleClass(classes,
126: ClassInfo.forName(fqn));
127: if (progressBar != null)
128: progressBar.setValue(++count);
129:
130: elem.inClassPath = true;
131: }
132: }
133: return count;
134: }
135:
136: public int countClasses(int depth, String packageName) {
137: if (depth++ >= MAX_PACKAGE_LEVEL)
138: return 0;
139: int number = 0;
140: String prefix = packageName.length() == 0 ? "" : packageName + ".";
141: Enumeration enum =
142: ClassInfo.getClassesAndPackages(packageName);
143: while (enum.hasMoreElements()) {
144: //insert sorted and remove double elements;
145: String name = (String)enum.nextElement();
146: String fqn = prefix + name;
147: if (ClassInfo.isPackage(fqn)) {
148: number += countClasses(depth, fqn);
149: } else {
150: number++;
151: }
152: }
153: return number;
154: }
155:
156: public HierarchyTreeModel(Main main) {
157: this .main = main;
158: this .progressBar = null;
159: rebuild();
160: }
161:
162: public HierarchyTreeModel(Main main, JProgressBar progressBar) {
163: this .main = main;
164: this .progressBar = progressBar;
165: rebuild();
166: }
167:
168: public void rebuild() {
169: Thread t = new Thread(this );
170: t.setPriority(Thread.MIN_PRIORITY);
171: t.start();
172: }
173:
174: public void run() {
175: if (progressBar != null) {
176: progressBar.setMinimum(0);
177: progressBar.setMaximum(countClasses(0, ""));
178: }
179: readPackage(0, new HashMap(), "", 0);
180:
181: TreeModelListener[] ls;
182: synchronized (listeners) {
183: ls = (TreeModelListener[]) listeners
184: .toArray(new TreeModelListener[listeners.size()]);
185: }
186: TreeModelEvent ev = new TreeModelEvent(this ,
187: new Object[] { root });
188: for (int i = 0; i < ls.length; i++)
189: ls[i].treeStructureChanged(ev);
190:
191: main.reselect();
192: }
193:
194: public void addTreeModelListener(TreeModelListener l) {
195: listeners.add(l);
196: }
197:
198: public void removeTreeModelListener(TreeModelListener l) {
199: listeners.remove(l);
200: }
201:
202: public void valueForPathChanged(TreePath path, Object newValue) {
203: // we don't allow values
204: }
205:
206: public Object getChild(Object parent, int index) {
207: Iterator iter = ((TreeElement) parent).getChilds().iterator();
208: for (int i = 0; i < index; i++)
209: iter.next();
210: return iter.next();
211: }
212:
213: public int getChildCount(Object parent) {
214: return ((TreeElement) parent).getChilds().size();
215: }
216:
217: public int getIndexOfChild(Object parent, Object child) {
218: Iterator iter = ((TreeElement) parent).getChilds().iterator();
219: int i = 0;
220: while (iter.next() != child)
221: i++;
222: return i;
223: }
224:
225: public Object getRoot() {
226: return root;
227: }
228:
229: public boolean isLeaf(Object node) {
230: return ((TreeElement) node).getChilds().isEmpty();
231: }
232:
233: public boolean isValidClass(Object node) {
234: return ((TreeElement) node).inClassPath;
235: }
236:
237: public String getFullName(Object node) {
238: return ((TreeElement) node).getFullName();
239: }
240:
241: public TreePath getPath(String fullName) {
242: if (fullName == null || fullName.length() == 0)
243: return new TreePath(root);
244:
245: int length = 2;
246: ClassInfo ci = ClassInfo.forName(fullName);
247: while (ci.getSuperclass() != null) {
248: length++;
249: ci = ci.getSuperclass();
250: }
251:
252: TreeElement[] path = new TreeElement[length];
253: path[0] = root;
254: int nr = 0;
255: next_component: while (nr < length - 1) {
256: ci = ClassInfo.forName(fullName);
257: for (int i = 2; i < length - nr; i++)
258: ci = ci.getSuperclass();
259: Iterator iter = path[nr].getChilds().iterator();
260: while (iter.hasNext()) {
261: TreeElement te = (TreeElement) iter.next();
262: if (te.getFullName().equals(ci.getName())) {
263: path[++nr] = te;
264: continue next_component;
265: }
266: }
267: return null;
268: }
269: return new TreePath(path);
270: }
271: }
|