package bluej.views;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

import bluej.debugger.gentype.GenTypeDeclTpar;
import bluej.utility.JavaNames;
import bluej.utility.JavaUtils;
import threadchecker.OnThread;
import threadchecker.Tag;


| A representation of a Java class in BlueJ. | | <p>The methods in this class are generally thread-safe. | | @author Michael Cahill | @OnThread(Tag.FXPlatform) public class View {
| The class that this view is for | protected Class<?> cl; protected FieldView[] fields; protected FieldView[] allFields; protected ConstructorView[] constructors; protected MethodView[] methods; protected MethodView[] allMethods; protected TypeParamView[] typeParams; protected Comment comment; private static Map<Class<?>,View> views = new HashMap<Class<?>,View>();
| Return a view of a class. | This is the only way to obtain a View object. | This method is thread-safe. | public static View getView(Class<?> cl) { if (cl == null) return null; synchronized (views) { View v = views.get(cl); if (v == null) { v = new View(cl); views.put(cl, v); } return v; } }
| Remove from the view cache, all views of classes | which were loaded by the given class loader. | This method is thread-safe. | public static void removeAll(ClassLoader loader) { synchronized (views) { Iterator<View> it = views.values().iterator(); while (it.hasNext()) { View v = it.next(); if (v.getClassLoader() == loader) { it.remove(); } } } } private View(Class<?> cl) { this.cl = cl; } private ClassLoader getClassLoader() { return cl.getClassLoader(); } public String getQualifiedName() { return cl.getName(); } public String getPackageName() { String clName = cl.getName(); int i = clName.lastIndexOf('.'); if (i == -1) return ""; else{ return clName.substring(0, i); } }
| Gets the Class this view is looking into. | This is used to know the exact return type of a method and is consistent | with the Java Reflection API. Damiano | public Class getViewClass() { return cl; } public String getBaseName() { return JavaNames.getBase(cl.getName()); } public View getSuper() { return getView(cl.getSuperclass()); } public View[] getInterfaces() { Class<?>[] interfaces = cl.getInterfaces(); View[] interfaceViews = new View[interfaces.length]; for (int i = 0; i < interfaces.length; i++) interfaceViews[i] = getView(interfaces[i]); return interfaceViews; } public final boolean isInterface() { return cl.isInterface(); } public final boolean isGeneric() { return getTypeParams().length>0; }
| Returns all the formal type parameters. | | @return Type parameters. Empty array if none exist. | public TypeParamView[] getTypeParams() { if (typeParams == null) { List<GenTypeDeclTpar> genTypeParams = JavaUtils.getJavaUtils().getTypeParams(this.cl); typeParams = new TypeParamView[genTypeParams.size()]; for (int i = 0; i < typeParams.length; i++) { typeParams[i] = new TypeParamView(this, genTypeParams.get(i)); } } return typeParams; }
| Return views of all methods of this class (including inherited ones). | Walk superclasses + interfaces for methods. Method definitions higher | up in the inheritance hierarchy are first in the array, with the latest | redefinition last. | public synchronized MethodView[] getAllMethods() { if (allMethods == null) { HashMap<String,MemberElement> map = new HashMap<String,MemberElement>(); getAllMethods(map, 0); List<MemberElement> methods = new ArrayList<MemberElement>(map.values()); Collections.sort(methods, new ElementComparer()); int numMethods = methods.size(); allMethods = new MethodView[numMethods]; for (int i = 0; i < numMethods; i++) { MemberElement elem = (MemberElement)methods.get(i); allMethods[i] = (MethodView)elem.member; } } return allMethods; }
| Walk superclasses + interfaces for fields. | All fields are inherited (+ overridden) from everywhere. | public FieldView[] getAllFields() { if (allFields == null) { HashMap<String,MemberElement> map = new HashMap<String,MemberElement>(); getAllFields(map, 0); List<MemberElement> fields = new ArrayList<MemberElement>(map.values()); Collections.sort(fields, new ElementComparer()); int numFields = fields.size(); allFields = new FieldView[numFields]; for (int i = 0; i < numFields; i++) { MemberElement elem = (MemberElement)fields.get(i); allFields[i] = (FieldView)elem.member; } } return allFields; }
| (Attempt at an) efficient implementation of getAllMethods + getAllFields | The old version had shocking performance - this one uses a HashMap | to notice the conflicts | class MemberElement { int index; MemberView member; MemberElement(int index, MemberView member) { this.index = index; this.member = member; } } class ElementComparer implements Comparator<MemberElement> {
| Return {}-1, 0, 1 } to represent <a> {}<, ==, > } <b> | public final int compare(MemberElement a, MemberElement b) { int cmp = a.index - b.index; return (cmp < 0) ? -1 : ((cmp > 0) ? 1 : 0); } }
| Helper method to get all methods from the class represented by this | view and all its superclasses. If all methods have already been cached | (in "allMethods"), simply returns the cached list. |* * @param h The hashmap into which to put all the methods * @param methnum The number of methods presently in the map * @return The number of methods in the map at completion protected int getAllMethods(HashMap<String,MemberElement> h, int methnum) { if (allMethods != null) { methnum = addMembers(h, allMethods, methnum); return methnum; } View sView = getSuper(); if (sView != null) methnum = sView.getAllMethods(h, methnum); if (isInterface()) { View[] ifaces = getInterfaces(); for (int i = 0; i < ifaces.length; i++) methnum = ifaces[i].getAllMethods(h, methnum); } methnum = addMembers(h, getDeclaredMethods(), methnum); return methnum; } protected int getAllFields(HashMap<String,MemberElement> h, int fieldnum) { if (allFields != null) { fieldnum = addMembers(h, allFields, fieldnum); return fieldnum; } View sView = getSuper(); if (sView != null) fieldnum = sView.getAllFields(h, fieldnum); View[] ifaces = getInterfaces(); for (int i = 0; i < ifaces.length; i++) fieldnum = ifaces[i].getAllFields(h, fieldnum); fieldnum = addMembers(h, getDeclaredFields(), fieldnum); return fieldnum; } private int addMembers(HashMap<String,MemberElement> h, MemberView[] members, int num) { for (int i = members.length - 1; i >= 0; i--) { h.put(members[i].toString(), new MemberElement(num++, members[i])); } return num; } public MethodView[] getDeclaredMethods() { if (methods == null) { int count = 0; try { Method[] cl_methods = cl.getDeclaredMethods(); for (int i = 0; i < cl_methods.length; i++) { if (!cl_methods[i].isSynthetic()) { count++; } } methods = new MethodView[count]; count = 0; for (int i = 0; i < cl_methods.length; i++) { if (!cl_methods[i].isSynthetic()) { try { methods[count] = new MethodView(this, cl_methods[i]); } catch (Throwable t) { t.printStackTrace(); if (t instanceof ClassNotFoundException) { throw (ClassNotFoundException) t; } } count++; } } } catch (LinkageError le) { methods = new MethodView[0]; } catch (ClassNotFoundException cnfe) { methods = new MethodView[0]; } } return methods; } public FieldView[] getDeclaredFields() { if (fields == null) { try { Field[] cl_fields= cl.getDeclaredFields(); fields = new FieldView[cl_fields.length]; for (int i = 0; i < cl_fields.length; i++) fields[i] = new FieldView(this, cl_fields[i]); } catch (LinkageError le) { fields = new FieldView[0]; } } return fields; } public ConstructorView[] getConstructors() { if (constructors == null) { try { Constructor<?>[] cl_constrs = cl.getDeclaredConstructors(); constructors = new ConstructorView[cl_constrs.length]; for (int i = 0; i < constructors.length; i++) constructors[i] = new ConstructorView(this, cl_constrs[i]); } catch (LinkageError le) { return new ConstructorView[0]; } } return constructors; } public Comment getComment() { loadComments(); return comment; } public void setComment(Comment comment) { this.comment = comment; } boolean comments_loaded = false; protected void loadComments() { if (comments_loaded) return; comments_loaded = true; Map<String,MemberView> table = new HashMap<String,MemberView>(); addMembers(table, getAllFields()); addMembers(table, getConstructors()); addMembers(table, getAllMethods()); loadClassComments(this, table); } protected void loadClassComments(View curview, Map<String,MemberView> table) { if (curview.getSuper() != null) loadClassComments(curview.getSuper(), table); CommentList comments = null; String filename = curview.getQualifiedName().replace('.', '/') + ".ctxt"; try { InputStream in = null; if (curview.cl.getClassLoader() == null) { in = ClassLoader.getSystemResourceAsStream(filename); } else { in = curview.cl.getClassLoader().getResourceAsStream(filename); } if (in != null) { comments = new CommentList(); comments.load(in); in.close(); } } catch(Exception e) { e.printStackTrace(); } if (comments != null) { for (Iterator<Comment> it = comments.getComments(); it.hasNext(); ) { Comment c = it.next(); if (c.getTarget().startsWith("class ") || c.getTarget().startsWith("interface ")) { if (curview == this) setComment(c); continue; } MemberView m = table.get(c.getTarget()); if (m == null) { continue; } else { m.setComment(c); } } } } private void addMembers(Map<String,MemberView> table, MemberView[] members) { for (int i = 0; i < members.length; i++) { table.put(members[i].getSignature(), members[i]); } } public String getTypeName() { return getTypeName(cl); } static String getTypeName(Class<?> type) { if (type.isArray()) { try { Class<?> primtype = type; int dimensions = 0; while (primtype.isArray()) { dimensions++; primtype = primtype.getComponentType(); } StringBuffer sb = new StringBuffer(); sb.append(JavaNames.stripPrefix(primtype.getName())); for (int i = 0; i < dimensions; i++) sb.append("[]"); return sb.toString(); } catch (Throwable e) { } } return JavaNames.stripPrefix(type.getName()); } }
top, use, map, class View

.   getView
.   removeAll
.   View
.   getClassLoader
.   getQualifiedName
.   getPackageName
.   getViewClass
.   getBaseName
.   getSuper
.   getInterfaces
.   isInterface
.   isGeneric
.   getTypeParams
.   getAllMethods
.   getAllFields

top, use, map, class View . MemberElement

.   compare
.   getAllMethods
.   getAllFields
.   addMembers
.   getDeclaredMethods
.   getDeclaredFields
.   getConstructors
.   getComment
.   setComment
.   loadComments
.   loadClassComments
.   addMembers
.   getTypeName
.   getTypeName




606 neLoCode + 28 LoComm