KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > core > util > reflection > ClassTree


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.core.util.reflection;
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26
27 /**
28  * <p>This class creates a tree structure that maps inheritance hierarchies of
29  * classes. A developer can place any number of classes into this object and
30  * retrieve the closest super class or the class itself.</p>
31  *
32  *
33  * Copyright 2001 Sapient
34  * @since EJFW 2.7
35  * @author Greg Hinkle, January 2001
36  * @version $Revision: 1.4 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $)
37  */

38 public class ClassTree {
39
40     protected ClassTreeNode bottom;
41
42
43     /**
44      * Constructs a ClassTree that represents all classes and interfaces that
45      * are generalizations of the provided class. This ends up with a tree
46      * structure of the inheritance hierarchy for that provided class all the
47      * way up to java.lang.Object.
48      * @param specificClass The class to build the tree for.
49      */

50     public ClassTree(Class JavaDoc specificClass) {
51         this.bottom = ClassTreeNode.buildNode(specificClass);
52
53     }
54
55     public ClassTreeNode getBottom() {
56         return this.bottom;
57     }
58
59
60     /**
61      * Constructs an ordered list starting at the highest (most general) class
62      * in the tree and moving down the tree, ensuring no generalization comes
63      * after one of its specializations.
64      * @return a list ordered as above
65      */

66     public List JavaDoc getOrderedList() {
67         List JavaDoc list = new ArrayList JavaDoc();
68         list.add(getBottom());
69
70         buildList(getBottom(),list);
71
72         Collections.sort(list);
73
74         // Refactor list into a list of classes from a list of ClassTreeNodes
75
for (int i = 0; i < list.size(); i++) {
76             ClassTreeNode node = (ClassTreeNode) list.get(i);
77             list.set(i,node.getObjectClass());
78         }
79
80         // Reverse the list so that the top class in the hierarchy comes first
81
Collections.reverse(list);
82
83         return list;
84     }
85
86     /**
87      * <p>Build breadth first in order to maintain sudo ordering as per
88      * class declarations (i.e. if A implements B, C... B is closer in the
89      * chain to A than C is, because B comes first in the implements clause.</p>
90      *
91      * <p>Note that the list coming out here is preordered, but not natural
92      * ordered. (i.e. some classes are out of order in relation to classes
93      * they have direct relationships with. This is later fixed by a sort
94      * on the list by natural ordering. Collecitons.sort, does preserve
95      * the preordering for nodes that have no relationship.</p>
96      *
97      * @param node the node to be browsed.
98      * @param output this list is altered to add the contents as they are
99      * browsed in breadth-first order. Start with a list containing only
100      * the bottom node.
101      */

102     private void buildList(ClassTreeNode node, List JavaDoc output) {
103
104         for (int i = 0; i < node.getParents().size(); i++) {
105             ClassTreeNode parent = (ClassTreeNode) node.getParents().get(i);
106             if (!output.contains(parent)) {
107                 output.add(parent);
108             }
109         }
110
111         List JavaDoc parents = node.getParents();
112         for (int i = 0; i < parents.size(); i++) {
113             ClassTreeNode parent = (ClassTreeNode) parents.get(i);
114             buildList(parent, output);
115         }
116     }
117
118
119
120     /**
121      * <p>Inner class representing each node in the tree. Holds references to the
122      * nodes children, parent and provides the Comparable interface for sorting
123      * by inheritance hierarchy.</p>
124      */

125     public static class ClassTreeNode implements Comparable JavaDoc {
126         /** The class of this node */
127         protected Class JavaDoc objectClass;
128
129         /** The map of children classes to their class names */
130         protected List JavaDoc children;
131
132         /** A reference to the parent node of this node */
133         protected List JavaDoc parents;
134
135         /**
136          * <p>Constructs a ClassTreeNode with the given Class.</p>
137          *
138          * @param objectClass the Class of the node
139          */

140         public ClassTreeNode(Class JavaDoc objectClass) {
141             this.children = new ArrayList JavaDoc();
142             this.objectClass = objectClass;
143             this.parents = new ArrayList JavaDoc();
144
145
146         }
147
148         public static ClassTreeNode buildNode(Class JavaDoc objectClass) {
149             Map JavaDoc allNodes = new HashMap JavaDoc();
150             return buildNode(objectClass, allNodes);
151         }
152
153         protected static ClassTreeNode buildNode(Class JavaDoc objectClass, Map JavaDoc allNodes) {
154             ClassTreeNode node;
155             if (allNodes.containsKey(objectClass)) {
156                 node = (ClassTreeNode) allNodes.get(objectClass);
157             } else {
158                 node = new ClassTreeNode(objectClass);
159                 allNodes.put(objectClass, node);
160             }
161
162             // Add the implemented interfaces...
163
Class JavaDoc[] superInterfaces = objectClass.getInterfaces();
164             for (int i = 0; i < superInterfaces.length; i++) {
165                 Class JavaDoc superInterface = superInterfaces[i];
166                 ClassTreeNode parent = buildNode(superInterface);
167                 node.addParent(parent);
168             }
169
170             // Add the superclass after the interfaces...
171
Class JavaDoc superClass = objectClass.getSuperclass();
172             if (superClass != null) {
173                 ClassTreeNode parent = buildNode(superClass);
174                 node.addParent(parent);
175             }
176             return node;
177         }
178
179
180         public List JavaDoc getParents() {
181             return this.parents;
182         }
183
184         public void addParent(ClassTreeNode node) {
185             this.parents.add(node);
186             node.addChild(this);
187         }
188
189         public boolean removeChild(ClassTreeNode node) {
190             return this.children.remove(node);
191         }
192         public void addChild(ClassTreeNode node) {
193             this.children.add(node);
194         }
195
196         public List JavaDoc getChildren() {
197             return this.children;
198         }
199
200         public boolean equals(Object JavaDoc obj) {
201             return ((ClassTreeNode)obj).getObjectClass().equals(this.objectClass);
202         }
203
204         public Class JavaDoc getObjectClass() {
205             return this.objectClass;
206         }
207
208         public String JavaDoc getClassName() {
209             return this.objectClass.getName();
210         }
211
212
213         public int hashCode() {
214             return this.objectClass.hashCode();
215         }
216
217         /**
218          * <p>Compares one class to another class by their inheritance tree.</p>
219          *
220          * @return an integer representing the comparison results as follows:<br>
221          * 2 if this is a subclass of past in object<br>
222          * -2 if this is a superclass of past in object<br>
223          * 0 if they are not related (and in relation to sorting, equal)<br>
224          * 0 if they are the same<br>
225          */

226         public int compareTo(Object JavaDoc obj) {
227             Class JavaDoc objClass = ((ClassTreeNode)obj).getObjectClass();
228
229             if (objClass.equals(this.objectClass)) {
230                 return 0;
231             } else if (this.objectClass.isAssignableFrom(objClass)) {
232                 return 2;
233             } else if (objClass.isAssignableFrom(this.objectClass)) {
234                 return -2;
235             } else {
236                 return 0;
237             }
238         }
239     } // End of ClassTree$ClassTreeNode
240

241
242 }
243
244
Popular Tags