001: /*
002: * ClassInfo.java - part of the CodeAid plugin.
003: * Copyright (C) 1999 Jason Ginchereau
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019:
020: package org.acm.seguin.completer.info;
021:
022: import org.acm.seguin.ide.jedit.Navigator; //import anthelper.ClassNameCache;
023: import java.lang.reflect.Constructor;
024: import java.lang.reflect.Field;
025: import java.lang.reflect.Method;
026: import java.lang.reflect.Modifier;
027:
028: // Collections API
029: import java.util.SortedSet;
030: import java.util.TreeSet;
031:
032: /**
033: * Contains information about a class such as super classes, inner classes,
034: * fields, and methods.
035: *
036: * @author Jason Ginchereau
037: * @created December 11, 2002
038: * @see ClassInfoDatabase
039: */
040: public class ClassInfo extends MemberInfo {
041: static final Navigator.NavigatorLogger logger = Navigator
042: .getLogger(ClassInfo.class);
043: private boolean isInterface;
044: private String packageName;
045: private String super class;
046: private String[] interfaces;
047:
048: private SortedSet classes;
049: private SortedSet fields;
050: private SortedSet constructors;
051: private SortedSet methods;
052:
053: public ClassInfo(Class c) {
054: this (c, c.getDeclaringClass());
055: }
056:
057: /**
058: * Creates a new <code>ClassInfo</code> structure using reflection to
059: * determine information about superclasses, inner classes, fields, and
060: * methods.
061: *
062: * @param c Description of the Parameter
063: */
064: public ClassInfo(Class c, Class argDeclaringClass) {
065: super ((argDeclaringClass != null ? argDeclaringClass.getName()
066: : null), c.getModifiers(), getSimpleName(c.getName()),
067: null);
068:
069: this .isInterface = c.isInterface();
070:
071: if (isInterface) {
072: super class = "java.lang.Object";
073: } else {
074: super class = (c.getSuperclass() != null ? c.getSuperclass()
075: .getName() : null);
076: }
077:
078: Class[] ifs = c.getInterfaces();
079: interfaces = new String[ifs.length];
080: for (int i = 0; i < interfaces.length; i++) {
081: interfaces[i] = ifs[i].getName();
082: }
083:
084: //this.packageName = (c.getPackage() != null? c.getPackage().getName(): null);
085: //logger.msg("pkg.name", this.packageName);
086:
087: int dot = c.getName().lastIndexOf('.');
088: if (dot < 0) {
089: this .packageName = null;
090: } else {
091: this .packageName = c.getName().substring(0, dot); //c.getName().length());
092: }
093:
094: initSets();
095:
096: Class[] innerClasses = c.getDeclaredClasses();
097: for (int i = 0; i < innerClasses.length; i++) {
098: this .classes.add(new ClassInfo(innerClasses[i]));
099: }
100: try {
101: Field[] fields = c.getDeclaredFields();
102: for (int i = 0; i < fields.length; i++) {
103: this .fields.add(new FieldInfo(fields[i]));
104: }
105: } catch (NoClassDefFoundError e) {
106: logger.warning(e.toString());
107: }
108:
109: Constructor[] constructors = c.getDeclaredConstructors();
110: for (int i = 0; i < constructors.length; i++) {
111: this .constructors.add(new ConstructorInfo(constructors[i]));
112: }
113: try {
114: Method[] methods = c.getDeclaredMethods();
115: for (int i = 0; i < methods.length; i++) {
116: this .methods.add(new MethodInfo(methods[i]));
117: }
118: } catch (NoClassDefFoundError e) {
119: logger.warning(e.toString());
120: }
121: }
122:
123: /**
124: * Creates a new <code>ClassInfo</code> structure using all specified
125: * information.
126: *
127: * @param declaringClass Description of the Parameter
128: * @param modifiers Description of the Parameter
129: * @param isInterface Description of the Parameter
130: * @param name Description of the Parameter
131: * @param superclass Description of the Parameter
132: * @param interfaces Description of the Parameter
133: * @param packageName Description of the Parameter
134: * @param comment Description of the Parameter
135: */
136: public ClassInfo(String declaringClass, int modifiers,
137: boolean isInterface, String name, String super class,
138: String[] interfaces, String packageName, String comment) {
139: super (declaringClass, modifiers, name, comment);
140: this .isInterface = isInterface;
141: if (isInterface && super class == null) {
142: super class = "java.lang.Object";
143: }
144: if (interfaces == null) {
145: interfaces = new String[0];
146: }
147: this .super class = super class;
148: this .interfaces = interfaces;
149: this .packageName = packageName;
150:
151: initSets();
152: }
153:
154: /**
155: * Creates an empty <code>ClassInfo</code> structure that is a placeholder
156: * for when nothing about a class is yet known.
157: *
158: * @param name Description of the Parameter
159: * @param packageName Description of the Parameter
160: */
161: public ClassInfo(String name, String packageName) {
162: super (null, Modifier.PUBLIC, name, null);
163: this .isInterface = false;
164: if ((packageName + "." + name).equals("java.lang.Object")) {
165: this .super class = null;
166: } else {
167: this .super class = "java.lang.Object";
168: }
169: this .interfaces = new String[0];
170: this .packageName = packageName;
171: initSets();
172: }
173:
174: static String getSimpleName(String className) {
175: int i = className.lastIndexOf('$');
176: int j = className.lastIndexOf('.');
177: return className.substring(Math.max(i, j) + 1);
178: }
179:
180: private void initSets() {
181: classes = new TreeSet(new StringComparator());
182: fields = new TreeSet();
183: constructors = new TreeSet();
184: methods = new TreeSet();
185: //new
186: }
187:
188: /**
189: * Adds the class, field, constructor, or method info to the class.
190: *
191: * @param mi Description of the Parameter
192: */
193: public void add(MemberInfo mi) {
194: if (mi.getDeclaringClass() == null
195: || !mi.getDeclaringClass().equals(getFullName())) {
196: throw new IllegalArgumentException(
197: "Cannot add a member to a class that is not its declaring class.");
198: }
199:
200: if (mi instanceof ClassInfo) {
201: classes.add(((ClassInfo) mi).getName());
202: } else if (mi instanceof FieldInfo) {
203: fields.add(mi);
204: } else if (mi instanceof ConstructorInfo) {
205: constructors.add(mi);
206: } else if (mi instanceof MethodInfo) {
207: methods.add(mi);
208: } else {
209: throw new IllegalArgumentException(
210: "Unknown MemberInfo type.");
211: }
212: }
213:
214: /**
215: * Gets the type attribute of the ClassInfo object
216: *
217: * @return The type value
218: */
219: public String getType() {
220: return getFullName();
221: }
222:
223: /**
224: * Gets the fully-qualified name of the class.
225: *
226: * @return The fullName value
227: */
228: public String getFullName() {
229: if (getDeclaringClass() != null) {
230: return getDeclaringClass() + '$' + getName();
231: } else if (getPackage() != null) {
232: return getPackage() + '.' + getName();
233: } else {
234: return getName();
235: }
236: }
237:
238: /**
239: * Gets the interface attribute of the ClassInfo object
240: *
241: * @return The interface value
242: */
243: public boolean isInterface() {
244: return isInterface;
245: }
246:
247: /**
248: * Gets the line attribute of the ClassInfo object
249: *
250: * @return The line value
251: */
252: public String getLine() {
253: return modifiersToString(getModifiers())
254: + (isInterface ? "interface " : "class ") + getName();
255: }
256:
257: /**
258: * Gets the superclass of this class. If this class is an interface, the
259: * returned classes will be <code>Object</code>. If this class is <code>Object</code>
260: * , <code>null</code> will be returned.
261: *
262: * @return The superclass value
263: */
264: public String getSuperclass() {
265: return super class;
266: }
267:
268: /**
269: * Gets the set of interfaces which this class implements. If this class is
270: * an interface, the returned array will be the set of super-interfaces
271: * extended by this interface. If this class is implements no interfaces, an
272: * array of length 0 will be returned.
273: *
274: * @return The interfaces value
275: */
276: public String[] getInterfaces() {
277: return interfaces;
278: }
279:
280: /**
281: * Gets the name of the package this class is a part of, or <code>null</code>
282: * if this class is part of the unnamed package.
283: *
284: * @return The package value
285: */
286: public String getPackage() {
287: return packageName;
288: }
289:
290: /**
291: * Gets the set of inner classes that are declared by this class. Note that
292: * inner classes declared by a superclass are not included in this set.
293: *
294: * @return a <code>SortedSet</code> of <code>Strings</code> that are the
295: * simple names of inner classes of this class. This set should not be
296: * modified directly.
297: */
298: public SortedSet getClasses() {
299: return classes;
300: }
301:
302: /**
303: * Gets the set of fields that are declared by this class. Note that fields
304: * declared by a superclass are not included in this set.
305: *
306: * @return a <code>SortedSet</code> of <code>FieldInfo</code> objects.
307: * This set should not be modified directly.
308: */
309: public SortedSet getFields() {
310: return fields;
311: }
312:
313: /**
314: * Gets the set of constructors that are declared by this class.
315: *
316: * @return a <code>SortedSet</code> of <code>ConstructorInfo</code>
317: * objects. This set should not be modified directly.
318: */
319: public SortedSet getConstructors() {
320: return constructors;
321: }
322:
323: /**
324: * Gets the set of methods that are declared by this class. Note that
325: * methods declared by a superclass are not included in this set.
326: *
327: * @return a <code>SortedSet</code> of <code>MethodInfo</code> objects.
328: * This set should not be modified directly.
329: */
330: public SortedSet getMethods() {
331: return methods;
332: }
333:
334: /**
335: * Description of the Method
336: *
337: * @param mi Description of the Parameter
338: * @return Description of the Return Value
339: */
340: public int compareTo(MemberInfo mi) {
341: int nc = getName().compareTo(mi.getName());
342: if (nc != 0) {
343: return nc;
344: }
345:
346: if (mi instanceof ArrayClassInfo) {
347: return -1;
348: } else if (mi instanceof ClassInfo) {
349: return 0;
350: } else {
351: return -1;
352: }
353: }
354:
355: public static void main(String[] args) {
356: try {
357: String name = "ClassNameCache$ClassInfo";
358: String strClassName = name.substring(0, name.indexOf("$"));
359: logger.msg(strClassName);
360: if (1 == 1)
361: System.exit(0);
362: Class cls = org.gjt.sp.jedit.gui.DockableWindowManager.class;
363: Class[] classes = cls.getDeclaredClasses();
364: for (int i = 0, l = classes.length; i < l; i++) {
365: logger.msg(classes[i].getName());
366: ClassInfo ci = new ClassInfo(classes[i]);
367: }
368: } catch (Throwable t) {
369: t.printStackTrace();
370: }
371: }
372:
373: /*
374: * *
375: * Gets the list of members that are accessible from the specified class.
376: *
377: * @param accessFrom The class from which the members are being
378: * accessed from. If this parameter is null, only
379: * public members are returned.
380: * @param staticOnly If true, only include static members in the list.
381: *
382: * @return a sorted List of members (FieldInfos and MethodInfos).
383: * This list should not be modified by the caller.
384: */
385: /*
386: * public List getMemberList(ClassInfo accessFrom, boolean staticOnly) {
387: * if (memberCache == null) { memberCache = new HashMap(); }
388: * String key = getMemberListKey(accessFrom, staticOnly);
389: * List memberList = memberCache.get(key);
390: * if(memberList == null) {
391: * }
392: * return memberList;
393: * }
394: * private String getMemberListKey(ClassInfo accessFrom, boolean staticOnly) {
395: * return "" + (staticOnly? "!" : "")
396: * + (accessFrom != null? accessFrom.getFullName() : null);
397: * }
398: */
399: }
|