package jdepend.metadata; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import jdepend.framework.context.JDependContext; import jdepend.framework.context.Scope.SCOPE; import jdepend.metadata.annotation.Transactional; import jdepend.metadata.util.JavaClassCollection; import jdepend.metadata.util.JavaClassUtil; import jdepend.metadata.util.ParseUtil; /** * The <code>JavaClass</code> class represents a Java class or interface. * * @author <b>Abner</b> * */ public final class JavaClass extends AccessFlags implements Candidate, Comparable<JavaClass> { private static final long serialVersionUID = 5220907141997737077L; private String name; private String packageName; private Collection<String> imports; private int lineCount; private boolean isInner; private String place; public static final String Extend_PlaceName = "outer"; private JavaPackage javaPackage; private int haveState = UnCalculate;// 缓存是否存在状态 private JavaClassDetail detail; private Collection<JavaClassRelationItem> caItems = new ArrayList<JavaClassRelationItem>(); private Collection<JavaClassRelationItem> ceItems = new ArrayList<JavaClassRelationItem>(); private List<JavaClass> innerClasses = new ArrayList<JavaClass>(); private JavaClass hostClass; private transient String classType; public final static String Service_TYPE = "Service"; public final static String VO_TYPE = "VO"; public final static String Unensure_TYPE = "Unensure"; private transient Collection<Method> methods; private transient Map<Method, Collection<Method>> overrideMethods; private transient Map<Method, Collection<Method>> subOverrideMethods; private transient Collection<JavaClass> supers; private transient Collection<JavaClass> superClasses; private transient Collection<JavaClass> interfaces; private transient Collection<JavaClass> subClasses; private transient Collection<JavaClass> subAllClasses; private transient Collection<JavaClassRelationItem> allCaItems; private transient Collection<JavaClassRelationItem> allCeItems; private transient Collection<JavaClassRelationItem> relationItems; private transient Collection<JavaClass> allInnerClasses; private transient Collection<JavaClass> caList = null; private transient Collection<JavaClass> ceList = null; private transient Collection<JavaClass> relationList = null; private transient Boolean haveBusinessMethod; private final static int UnCalculate = -2; private final static int HaveState = 1; private final static int NoHaveState = 0; private final static int Searched = -1; private final static String haveStateJavaClasses = "haveStateJavaClasses"; private static final String InnerClassSymbol = "$"; public JavaClass(String name, boolean isInner, int access_flags) { this(name, isInner); this.access_flags = access_flags; } public JavaClass(String name, boolean isInner) { this.name = name; this.packageName = JavaPackage.Default; this.imports = new HashSet<String>(); this.detail = new JavaClassDetail(this); this.isInner = isInner; this.subClasses = new HashSet<JavaClass>(); } public String getPlace() { return place; } public void setPlace(String place) { this.place = place; } @Override public String getId() { return CandidateUtil.getId(this); } @Override public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Collection<JavaClass> getClasses() { Collection<JavaClass> javaClasses = new ArrayList<JavaClass>(); javaClasses.add(this); return javaClasses; } /** * 是否是内部类 * * @return */ public boolean isInnerClass() { if (this.getName().indexOf(InnerClassSymbol) > 0) { return true; } else { return false; } } public String getHostClassId() { int pos = this.getName().indexOf(InnerClassSymbol); if (pos != -1) { return CandidateUtil.getId(this.getPlace(), this.getName().substring(0, pos)); } else { return null; } } public boolean containsInnerClass(JavaClass javaClass) { if (!javaClass.isInnerClass()) { return false; } else { return javaClass.getName().startsWith(this.getName()); } } public boolean containedInnerClass(JavaClass javaClass) { if (!this.isInnerClass() || this.equals(javaClass)) { return false; } else { return this.getName().startsWith(javaClass.getName()); } } public synchronized void addInnerClass(JavaClass javaClass) { if (!this.innerClasses.contains(javaClass)) { this.innerClasses.add(javaClass); } javaClass.hostClass = this; } public synchronized JavaClass getHostClass() { if (this.hostClass != null && this.hostClass.isInnerClass()) { return this.hostClass.getHostClass(); } else { return hostClass; } } public synchronized Collection<JavaClass> getInnerClasses() { if (this.allInnerClasses == null) { this.allInnerClasses = new HashSet<JavaClass>(); this.allInnerClasses.addAll(this.innerClasses); for (JavaClass innerClass : this.innerClasses) { this.allInnerClasses.addAll(innerClass.getInnerClasses()); } } return this.allInnerClasses; } public void setPackageName(String name) { packageName = name; } public String getPackageName() { return packageName; } public Collection<String> getImportedPackages() { return imports; } /** * 是否是分析目标中包含的Class */ public boolean isInner() { return this.isInner; } public JavaClassDetail getDetail() { return detail; } public void setDetail(JavaClassDetail detail) { this.detail = detail; } public Collection<Attribute> getAttributes() { return this.detail.getAttributes(); } public Attribute getTheAttribute(String name) { return this.detail.getTheAttribute(name); } /** * 得到类本身的方法列表(不包含继承父类的方法) * * @return */ public Collection<Method> getSelfMethods() { return this.detail.getMethods(); } public Method getTheMethod(String info) { for (Method method : this.getMethods()) { if (method.getInfo().equals(info)) { return method; } } return null; } public synchronized String getClassType() { if (this.classType == null) { this.classType = JavaClassUtil.getType(this).getType(); } return this.classType; } /** * 得到覆盖了父类方法的方法列表 * * @return */ public synchronized Map<Method, Collection<Method>> calOverrideMethods() { if (this.overrideMethods == null) { this.overrideMethods = new HashMap<Method, Collection<Method>>(); for (JavaClass superClass : this.getSupers()) { for (Method method : superClass.getSelfMethods()) { if (!method.isConstruction() && (method.isPublic() || method.isProtected())) { for (Method selfMethod : this.getSelfMethods()) { if (selfMethod.isOverride(method)) { if (!this.overrideMethods.containsKey(selfMethod)) { this.overrideMethods.put(selfMethod, new HashSet<Method>()); } this.overrideMethods.get(selfMethod).add(method); } } } } } } return this.overrideMethods; } /** * 得到覆盖了父类方法的方法列表 * * @return */ public Collection<Method> getOverrideMethods() { return this.calOverrideMethods().keySet(); } /** * 得到指定方法覆盖的父类方法列表 * * @param method * @return */ public Collection<Method> getOverridedMethods(Method method) { Collection<Method> overridedMethods = this.calOverrideMethods().get(method); if (overridedMethods == null) { return new HashSet<Method>(); } else { return overridedMethods; } } /** * 得到全部方法覆盖的父类方法列表 * * @param callee * @return */ public Collection<Method> getOverridedMethods() { Collection<Method> overridedMethods = new HashSet<Method>(); Map<Method, Collection<Method>> overrideMethods = this.calOverrideMethods(); for (Method overrideMethod : overrideMethods.keySet()) { overridedMethods.addAll(overrideMethods.get(overrideMethod)); } return overridedMethods; } /** * 得到被子类覆盖的方法列表 * * @return */ public synchronized Map<Method, Collection<Method>> calSubOverrideMethods() { if (this.subOverrideMethods == null) { this.subOverrideMethods = new HashMap<Method, Collection<Method>>(); for (JavaClass subClass : this.getSubClasses()) { for (Method method : subClass.getSelfMethods()) { if (!method.isConstruction() && (method.isPublic() || method.isProtected())) { for (Method selfMethod : this.getSelfMethods()) { if (method.isOverride(selfMethod)) { if (!this.subOverrideMethods.containsKey(selfMethod)) { this.subOverrideMethods.put(selfMethod, new HashSet<Method>()); } this.subOverrideMethods.get(selfMethod).add(method); } } } } } } return this.subOverrideMethods; } /** * 得到子类覆盖了的方法列表 * * @return */ public Collection<Method> getSubOverridedMethods() { return this.calSubOverrideMethods().keySet(); } /** * 得到指定方法被子类覆盖的方法列表 * * @param method * @return */ public Collection<Method> getSubOverrideMethods(Method method) { Collection<Method> overridedMethods = this.calSubOverrideMethods().get(method); if (overridedMethods == null) { return new HashSet<Method>(); } else { return overridedMethods; } } /** * 得到覆盖的子类全部方法列表 * * @param callee * @return */ public Collection<Method> getSubOverrideMethods() { Collection<Method> overridedMethods = new HashSet<Method>(); Map<Method, Collection<Method>> overrideMethods = this.calSubOverrideMethods(); for (Method overrideMethod : overrideMethods.keySet()) { overridedMethods.addAll(overrideMethods.get(overrideMethod)); } return overridedMethods; } /** * 得到类的构造函数列表 * * @return */ public Collection<Method> getConstructorMethods() { Collection<Method> constructors = new HashSet<Method>(); for (Method method : this.getMethods()) { if (method.isConstruction()) { constructors.add(method); } } return constructors; } /** * 得到其他类可以使用的方法列表(包含继承父类的方法) * * @return */ public synchronized Collection<Method> getMethods() { if (this.methods == null) { boolean isOverride; this.methods = new HashSet<Method>(); for (JavaClass superClass : this.getSupers()) { for (Method method : superClass.getSelfMethods()) { if (!method.isConstruction() && (method.isPublic() || method.isProtected())) { isOverride = false; L: for (Method selfMethod : this.getSelfMethods()) { if (selfMethod.isOverride(method)) { isOverride = true; break L; } } if (!isOverride) { this.methods.add(method); } } } } this.methods.addAll(this.getSelfMethods()); } return this.methods; } public void addSelfMethod(Method method) { this.detail.addMethod(method); } public Collection<TableInfo> getTables() { return this.detail.getTables(); } /** * 得到所有的父类和接口列表 * * @return */ public synchronized Collection<JavaClass> getSupers() { if (this.supers == null) { supers = new HashSet<JavaClass>(); supers.addAll(this.getSuperClasses()); supers.addAll(this.getAllInterfaces()); } return this.supers; } /** * 得到所有的父类列表 * * @return */ private synchronized Collection<JavaClass> getSuperClasses() { if (this.superClasses == null) { this.superClasses = new HashSet<JavaClass>(); JavaClass superClass = this.getSuperClass(); if (superClass != null) { superClasses.add(superClass); superClasses.addAll(superClass.getSuperClasses()); } } return this.superClasses; } /** * 得到所有的接口列表 * * @return */ private synchronized Collection<JavaClass> getAllInterfaces() { if (this.interfaces == null) { this.interfaces = new HashSet<JavaClass>(); for (JavaClass interfaceClass : this.getInterfaces()) { this.interfaces.add(interfaceClass); Collection<JavaClass> interfaceClasses = interfaceClass.getInterfaces(); for (JavaClass interfaceClass1 : interfaceClasses) { this.interfaces.add(interfaceClass1); this.interfaces.addAll(interfaceClass1.getAllInterfaces()); } } } return this.interfaces; } /** * 得到父类和接口列表 * * @return */ public synchronized Collection<JavaClass> getSelfSupers() { Collection<JavaClass> selfSupers = new HashSet<JavaClass>(); selfSupers.add(this.getSuperClass()); selfSupers.addAll(this.getInterfaces()); return selfSupers; } public Collection<JavaClass> getInterfaces() { return this.detail.getInterfaces(); } public JavaClass getSuperClass() { return this.detail.getSuperClass(); } public synchronized Collection<JavaClass> getSubClasses() { if (this.subAllClasses == null) { this.subAllClasses = new HashSet<JavaClass>(); this.subAllClasses.addAll(this.subClasses); for (JavaClass subClass : subClasses) { this.subAllClasses.addAll(subClass.getSubClasses()); } } return this.subAllClasses; } public synchronized void addSubClass(JavaClass javaClass) { this.subClasses.add(javaClass); } public Collection<JavaClassRelationItem> getCaItems() { if (this.allCaItems == null) { this.allCaItems = new HashSet<JavaClassRelationItem>(this.caItems); for (JavaClass innerClass : this.getInnerClasses()) { for (JavaClassRelationItem item : innerClass.getSelfCaItems()) { this.allCaItems.add(item.clone2()); } } } return allCaItems; } public Collection<JavaClassRelationItem> getSelfCaItems() { return caItems; } public synchronized Collection<JavaClass> getCaList() { if (this.caList == null) { Collection<JavaClass> javaClasses = new HashSet<JavaClass>(); for (JavaClassRelationItem item : getCaItems()) { javaClasses.add(item.getSource()); } this.caList = javaClasses; } return this.caList; } public synchronized Collection<JavaClass> getRelationList() { if (this.relationList == null) { this.relationList = new HashSet<JavaClass>(); this.relationList.addAll(this.getCaList()); this.relationList.addAll(this.getCeList()); } return this.relationList; } public synchronized Collection<JavaClassRelationItem> getRelationItems() { if (this.relationItems == null) { this.relationItems = new HashSet<JavaClassRelationItem>(); this.relationItems.addAll(this.getCaItems()); this.relationItems.addAll(this.getCeItems()); } return this.relationItems; } public synchronized void addCaItems(JavaClassRelationItem caItem) { this.caItems.add(caItem); } public Collection<JavaClassRelationItem> getCeItems() { if (this.allCeItems == null) { this.allCeItems = new HashSet<JavaClassRelationItem>(this.ceItems); for (JavaClass innerClass : this.getInnerClasses()) { for (JavaClassRelationItem item : innerClass.getSelfCeItems()) { this.allCeItems.add(item.clone2()); } } } return allCeItems; } public Collection<JavaClassRelationItem> getSelfCeItems() { return ceItems; } public synchronized Collection<JavaClass> getCeList() { if (this.ceList == null) { Collection<JavaClass> javaClasses = new HashSet<JavaClass>(); for (JavaClassRelationItem item : getCeItems()) { javaClasses.add(item.getTarget()); } this.ceList = javaClasses; } return this.ceList; } public synchronized void addCeItems(JavaClassRelationItem ceItem) { this.ceItems.add(ceItem); } public int getLineCount() { if (this.isInnerClass()) { return 0; } else { return this.lineCount; } } public void setLineCount(int lineCount) { this.lineCount = lineCount; } public synchronized boolean isState() { if (this.haveState == UnCalculate) { this.haveState = this.searchState(); } return this.haveState == HaveState; } public void setState(boolean haveState) { if (haveState) { this.haveState = HaveState; } else { this.haveState = NoHaveState; } } public JavaPackage getJavaPackage() { return javaPackage; } public void setJavaPackage(JavaPackage javaPackage) { this.javaPackage = javaPackage; } public Transactional getTransactional() { return this.detail.getAnnotations().getTransactional(); } public boolean haveBusinessMethod() { if (this.haveBusinessMethod == null) { this.haveBusinessMethod = false; L: for (Method method : this.getMethods()) { if (method.isBusinessMethod()) { this.haveBusinessMethod = true; break L; } } } return this.haveBusinessMethod; } public JavaClass clone() { JavaClass obj = new JavaClass(this.getName(), this.isInner); obj.place = this.place; obj.access_flags = this.access_flags; obj.packageName = this.packageName; obj.lineCount = this.lineCount; obj.setState(this.isState()); for (String importPackage : this.getImportedPackages()) { obj.addImportedPackage(importPackage); } obj.setDetail(this.getDetail().clone(obj)); for (JavaClassRelationItem item : this.getSelfCaItems()) { JavaClassRelationItem newItem = item.clone(); if (!obj.caItems.contains(newItem)) { obj.caItems.add(newItem); } } for (JavaClassRelationItem item : this.getSelfCeItems()) { JavaClassRelationItem newItem = item.clone(); if (!obj.ceItems.contains(newItem)) { obj.ceItems.add(newItem); } } for (JavaClass innerClass : this.innerClasses) { obj.addInnerClass(innerClass.clone()); } return obj; } public void supplyDetail(JavaClassCollection javaClasses) { this.getDetail().supply(javaClasses); // 填充HostClass if (this.isInnerClass()) { JavaClass hostClass = javaClasses.getTheClass(this.getHostClassId()); if (hostClass != null) { hostClass.addInnerClass(this); } } } public void supplyJavaClassRelationItem(JavaClassCollection javaClasses) { Iterator<JavaClassRelationItem> it; JavaClassRelationItem relationItem; JavaClass dependClass; it = this.getSelfCaItems().iterator(); while (it.hasNext()) { relationItem = it.next(); dependClass = javaClasses.getTheClass(relationItem.getSourceJavaClassPlace(), relationItem.getSourceJavaClass()); if (dependClass != null) { relationItem.setTarget(this); relationItem.setSource(dependClass); relationItem.setType(javaClasses.getJavaClassRelationTypes().getType(relationItem.getTypeName())); } else { it.remove(); } } it = this.getSelfCeItems().iterator(); while (it.hasNext()) { relationItem = it.next(); dependClass = javaClasses.getTheClass(relationItem.getTargetJavaClassPlace(), relationItem.getTargetJavaClass()); if (dependClass != null) { relationItem.setTarget(dependClass); relationItem.setSource(this); relationItem.setType(javaClasses.getJavaClassRelationTypes().getType(relationItem.getTypeName())); } else { it.remove(); } } } /** * 删除没有包含在javaClasses中的JavaClass引用 * * @param javaClasses */ public void filterExternalJavaClass(Collection<JavaClass> javaClasses) { Iterator<JavaClassRelationItem> it; it = this.getSelfCaItems().iterator(); while (it.hasNext()) { if (!javaClasses.contains(it.next().getSource())) { it.remove(); } } it = this.getSelfCeItems().iterator(); while (it.hasNext()) { if (!javaClasses.contains(it.next().getTarget())) { it.remove(); } } } @Override public int compareTo(JavaClass o) { return this.getId().compareTo(o.getId()); } @Override public int hashCode() { final int prime = 32; int result = 1; result = prime * result + ((this.getId() == null) ? 0 : this.getId().hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (getClass() != obj.getClass()) return false; JavaClass other = (JavaClass) obj; if (!getId().equals(other.getId())) return false; return true; } @Override public String toString() { return this.detail.toString(); } public void clear() { caList = null; ceList = null; relationList = null; supers = null; superClasses = null; interfaces = null; subAllClasses = null; allCeItems = null; allCaItems = null; allInnerClasses = null; relationItems = null; classType = null; haveBusinessMethod = null; } /** * 是否存在可变基本类型 * * @param types * @return */ private boolean exitChangeBaseType() { for (Attribute attribute : this.getAttributes()) { if (!attribute.isFinal() && !attribute.isStatic()) { for (String type : attribute.getTypes()) { if (ParseUtil.isBaseType(type) || ParseUtil.isStateClassType(type)) { return true; } } } } return false; } @Override public int size() { return this.getLineCount(); } /** * 搜索该JavaClass是否存在状态 * * @return 1 存在;0 不存在; -1 该javaClass已经扫描过了。 */ private int searchState() { // 判断该javaClass是否扫描过 Collection<JavaClass> javaClasses = (Collection<JavaClass>) JDependContext.getInfo(SCOPE.THREAD_SCOPSE, haveStateJavaClasses); if (javaClasses == null) {// 建立历史列表 javaClasses = new HashSet<JavaClass>(); JDependContext.setInfo(SCOPE.THREAD_SCOPSE, haveStateJavaClasses, javaClasses); } else if (javaClasses.contains(this)) {// 扫描过 return Searched; } // 放入扫描列表 javaClasses.add(this); // 判断是否存在可变基本类型 if (exitChangeBaseType()) { // 清空扫描列表 JDependContext.setInfo(SCOPE.THREAD_SCOPSE, haveStateJavaClasses, null); return HaveState; } int result; // 判断属性 for (Attribute attribute : this.getAttributes()) { for (JavaClass javaClass : attribute.getTypeClasses()) { result = javaClass.searchState(); if (result != Searched) { return result; } } } // 判断父类是否存在状态 if (this.getSuperClass() != null) { result = this.getSuperClass().searchState(); if (result != Searched) { return result; } } if (javaClasses.iterator().next().equals(this)) {// 搜索完毕时,清空搜索列表 JDependContext.setInfo(SCOPE.THREAD_SCOPSE, haveStateJavaClasses, null); } return NoHaveState; } public boolean addImportedPackage(String jPackage) { if (jPackage != null && !jPackage.equals(packageName) && !imports.contains(jPackage)) { imports.add(jPackage); return true; } else { return false; } } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); this.subClasses = new HashSet<JavaClass>(); } }