package jdepend.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import jdepend.framework.log.LogUtil;
import jdepend.metadata.JavaClass;
import jdepend.metadata.JavaClassRelationItem;
import jdepend.metadata.JavaPackage;
import jdepend.model.result.AnalysisResult;
/**
* 一个JavaClassUnit代表作为评价体系中的一个单元.
*
* @author <b>Abner</b>
*
*/
public class JavaClassUnit extends AbstractSubJDependUnit {
/**
*
*/
private static final long serialVersionUID = 3619193239851101008L;
protected JavaClass javaClass;
protected Component component;
protected List<JavaClassUnit> innerClassUnits = new ArrayList<JavaClassUnit>();
protected Boolean abstractClassQualification;// 是否具有抽象类资格
protected boolean stable = false;
protected transient Collection<JavaClassUnit> caList = null;
protected transient Collection<JavaClassUnit> ceList = null;
protected transient Collection<JavaClassUnit> relationList = null;
protected transient Collection<JavaClassUnit> afferents = null;
protected transient Collection<JavaClassUnit> efferents = null;
public static final String Place = "JavaClass_Place";
public static final String isPrivateElement = "JavaClass_isPrivateElement";
public static final String Stable = "JavaClass_Stable";
public static final String State = "JavaClass_State";
public static final String ClassType = "JavaClass_Type";
protected JavaClassUnit() {
}
public JavaClassUnit(JavaClass javaClass) {
this.javaClass = javaClass;
for (JavaClass innerClass : javaClass.getInnerClasses()) {
this.innerClassUnits.add(new JavaClassUnit(innerClass));
}
}
public JavaClassUnit(JavaClassUnit unit) {
super(unit);
this.javaClass = unit.javaClass;
this.component = unit.component;
this.innerClassUnits = unit.innerClassUnits;
this.abstractClassQualification = unit.abstractClassQualification;
this.stable = unit.stable;
this.caList = unit.caList;
this.ceList = unit.ceList;
this.relationList = unit.relationList;
this.afferents = unit.afferents;
this.efferents = unit.efferents;
}
public JavaClass getJavaClass() {
return javaClass;
}
@Override
public Collection<JavaClassUnit> getClasses() {
Collection<JavaClassUnit> javaClasses = new ArrayList<JavaClassUnit>();
javaClasses.add(this);
return javaClasses;
}
public String getId() {
return this.javaClass.getId();
}
@Override
public String getName() {
return this.javaClass.getName();
}
@Override
public String getPath() {
return javaClass.getPackageName();
}
public List<JavaClassUnit> getInnerClassUnits() {
return innerClassUnits;
}
@Override
public int getLineCount() {
return this.javaClass.getLineCount();
}
@Override
public boolean isInner() {
return this.javaClass.isInner();
}
/**
* 是否为私有Class,与组件外部的Class没有关系
*
* @return
*/
public boolean isPrivateElement() {
return this.getAfferents().size() == 0 && this.getEfferents().size() == 0;
}
/**
* 是否被其他组件使用
*
* @return
*/
public boolean isUsedByExternal() {
return this.getAfferents().size() != 0;
}
/**
* 在组件中是否孤立,与组件中的其他Class都没有关系
*
* @return
*/
public boolean isAlone() {
for (JavaClassUnit relationClass : this.getRelationList()) {
if (this.getComponent().containsClass(relationClass)) {
return false;
}
}
return true;
}
@Override
public AnalysisResult getResult() {
return this.getComponent().getResult();
}
public int getAbstractClassCount() {
if (this.abstractClassQualification == null) {
return this.javaClass.isAbstract() ? 1 : 0;
} else {
return this.abstractClassQualification ? 1 : 0;
}
}
public void setAbstractClassQualification(boolean abstractClassQualification) {
this.abstractClassQualification = abstractClassQualification;
}
public int getConcreteClassCount() {
if (getAbstractClassCount() == 1) {
return 0;
} else {
return 1;
}
}
@Override
public Float getAbstractness() {
return new Float(this.getAbstractClassCount());
}
@Override
public Collection<JavaPackage> getJavaPackages() {
Collection<JavaPackage> javaPackages = new ArrayList<JavaPackage>();
javaPackages.add(this.javaClass.getJavaPackage());
return javaPackages;
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
for (JavaClassUnit innerClass : this.innerClassUnits) {
innerClass.setComponent(component);
}
}
public boolean containedComponent() {
return this.component != null;
}
public void setStable(boolean b) {
this.stable = b;
}
public boolean isStable() {
return stable;
}
@Override
public int getClassCount() {
return 1;
}
@Override
public boolean containsClass(JavaClassUnit javaClass) {
return this.equals(javaClass);
}
@Override
public boolean containsClass(JavaClass javaClass) {
return this.getJavaClass().equals(javaClass);
}
public synchronized Collection<JavaClassUnit> getCeList() {
if (this.ceList == null) {
Collection<JavaClassUnit> javaClasses = new HashSet<JavaClassUnit>();
for (JavaClassRelationItem item : this.javaClass.getCeItems()) {
JavaClassUnit javaClassUnit = this.getResult().getTheClass(item.getTarget().getId());
if (javaClassUnit != null) {
javaClasses.add(javaClassUnit);
}
}
this.ceList = javaClasses;
}
return this.ceList;
}
public synchronized Collection<JavaClassUnit> getCaList() {
if (this.caList == null) {
Collection<JavaClassUnit> javaClasses = new HashSet<JavaClassUnit>();
for (JavaClassRelationItem item : this.javaClass.getCaItems()) {
JavaClassUnit javaClassUnit = this.getResult().getTheClass(item.getSource().getId());
if (javaClassUnit != null) {
javaClasses.add(javaClassUnit);
}
}
this.caList = javaClasses;
}
return this.caList;
}
public synchronized Collection<JavaClassUnit> getRelationList() {
if (this.relationList == null) {
Collection<JavaClassUnit> javaClasses = this.getCaList();
for (JavaClassUnit javaClass : this.getCeList()) {
if (!javaClasses.contains(javaClass)) {
javaClasses.add(javaClass);
}
}
this.relationList = javaClasses;
}
return this.relationList;
}
@Override
public synchronized Collection<JavaClassUnit> getAfferents() {
if (this.afferents == null) {
Collection<JavaClassUnit> afferents = new HashSet<JavaClassUnit>();
for (JavaClassUnit javaClass : this.getCaList()) {
if (!this.component.containsClass(javaClass)) {
afferents.add(javaClass);
}
}
this.afferents = afferents;
}
return this.afferents;
}
@Override
public synchronized Collection<JavaClassUnit> getEfferents() {
if (this.efferents == null) {
Collection<JavaClassUnit> efferents = new HashSet<JavaClassUnit>();
for (JavaClassUnit javaClass : this.getCeList()) {
if (!this.component.containsClass(javaClass)) {
efferents.add(javaClass);
}
}
this.efferents = efferents;
}
return this.efferents;
}
@Override
public RelationDetail ceCouplingDetail(JDependUnit dependUnit) {
RelationDetail detail = new RelationDetail();
if (this.equals(dependUnit)) {
return detail;
}
float intensity = 0;
for (JavaClassRelationItem relationItem : this.javaClass.getCeItems()) {
if (dependUnit.containsClass(relationItem.getTarget())) {
detail.addItem(relationItem);
intensity += relationItem.getRelationIntensity();
}
}
detail.setIntensity(intensity);
return detail;
}
@Override
public RelationDetail caCouplingDetail(JDependUnit dependUnit) {
RelationDetail detail = new RelationDetail();
if (this.equals(dependUnit)) {
return detail;
}
float intensity = 0;
for (JavaClassRelationItem relationItem : this.javaClass.getCaItems()) {
if (dependUnit.containsClass(relationItem.getSource())) {
detail.addItem(relationItem);
intensity += relationItem.getRelationIntensity();
}
}
detail.setIntensity(intensity);
return detail;
}
@Override
public float caCoupling() {
float intensity = 0;
for (JavaClassRelationItem relationItem : this.javaClass.getCaItems()) {
if (!this.component.containsClass(relationItem.getSource())) {
intensity += relationItem.getRelationIntensity();
}
}
return intensity;
}
@Override
public float ceCoupling() {
float intensity = 0;
for (JavaClassRelationItem relationItem : this.javaClass.getCeItems()) {
if (!this.component.containsClass(relationItem.getTarget())) {
intensity += relationItem.getRelationIntensity();
}
}
return intensity;
}
/**
* 计算在特定context环境下的内聚性
*
* @param context
* @return
*/
@Override
public float getCohesion() {
return this.getGroupCohesionInfo().getCohesion();
}
@Override
public Float getBalance() {
return this.getGroupInfoCalculator().getBalance();
}
@Override
protected GroupInfoCalculator createGroupInfoCalculator() {
return new GroupInfoCalculator(this);
}
@Override
public int collectCycle(List<JDependUnit> list, Map<JDependUnit, Integer> knowledge) {
if (!this.getComponent().getContainsCycle()) {
return NoCycle;// 当类所在的组件不存在循环依赖时,类也不会存在循环依赖
}
if (list.size() > 20) {
LogUtil.getInstance(JavaClassUnit.class).systemWarning(
"JavaClass[" + list.get(0).getName() + "] [" + this.getName() + "]collectCycle 搜索深度大于20停止搜索");
return StopCheckCycle;// 搜索深度大于20时停止
}
if (list.contains(this)) {
if (list.get(0).equals(this)) {
for (JDependUnit unit : list) {
if (!this.component.containsClass((JavaClassUnit) unit)) {
return Cycle;// 存在循环依赖
}
}
knowledge.put(this, LocalCycle);
return LocalCycle;// 存在局部循环依赖
} else {
// 通知其他组件存在循环依赖
int index;
L: for (index = 1; index < list.size(); index++) {
if (list.get(index).equals(this)) {
break L;
}
}
List<JavaClassUnit> otherCycles = new ArrayList<JavaClassUnit>();
Collection<Component> otherCycleComponents = new HashSet<Component>();
for (int pos = index; pos < list.size(); pos++) {
otherCycles.add((JavaClassUnit) list.get(pos));
otherCycleComponents.add(((JavaClassUnit) list.get(pos)).getComponent());
}
if (otherCycleComponents.size() > 1) {
for (JavaClassUnit unit : otherCycles) {
unit.setCycles(otherCycles);
}
}
knowledge.put(this, LocalCycle);
return LocalCycle;// 存在局部循环依赖
}
}
list.add(this);// 将当前分析单元入栈
if (this.getCeList().contains(list.get(0))) {// 直接依赖进行广度搜索
for (JDependUnit unit : list) {
if (!this.component.containsClass((JavaClassUnit) unit)) {
return Cycle;// 存在循环依赖
}
}
}
L: for (JavaClassUnit efferent : this.getCeList()) {
Integer rtnInteger = (Integer) knowledge.get(efferent);// 获取历史扫描数据
if (rtnInteger == null) {// 没有扫描过的区域进行深度扫描
int rtn = efferent.collectCycle(list, knowledge);// 深度搜索该区域
if (rtn == Cycle) {// 存在循环依赖
// 通知其他组件存在循环依赖
for (int index = 1; index < list.size(); index++) {
((JavaClassUnit) list.get(index)).setCycles(list);
}
return Cycle;
} else if (rtn == StopCheckCycle) {
break L;// 搜索深度大于20时停止
}
}
}
list.remove(this);// 将当前分析单元出栈
knowledge.put(this, NoCycle);// 记录该对象扫描过的结果
return NoCycle;// 不存在循环依赖
}
public JavaClassUnit clone() {
JavaClassUnit obj = new JavaClassUnit(this.javaClass.clone());
obj.abstractClassQualification = this.abstractClassQualification;
obj.stable = this.stable;
obj.setType(this.getType());
return obj;
}
@Override
public int compareTo(JDependUnit o) {
return this.javaClass.compareTo(((JavaClassUnit) o).javaClass);
}
@Override
public int hashCode() {
return this.javaClass.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof JavaClassUnit) {
return javaClass.equals(((JavaClassUnit) obj).javaClass);
} else {
return false;
}
}
@Override
public String toString() {
return this.javaClass.toString();
}
@Override
public void clear() {
super.clear();
this.javaClass.clear();
caList = null;
ceList = null;
relationList = null;
afferents = null;
efferents = null;
}
@Override
public Object getValue(String metrics) {
switch (metrics) {
case JavaClassUnit.Place:
return this.javaClass.getPlace();
case JavaClassUnit.State:
if (this.javaClass.isState()) {
return MetricsMgr.HaveState;
} else {
return MetricsMgr.NoValue;
}
case JavaClassUnit.Stable:
if (this.isStable()) {
return MetricsMgr.Stability;
} else {
return MetricsMgr.NoValue;
}
case JavaClassUnit.isPrivateElement:
if (!this.isUsedByExternal()) {
return MetricsMgr.Private;
} else {
return MetricsMgr.NoValue;
}
case JavaClassUnit.ClassType:
return this.javaClass.getClassType();
case MetricsMgr.Cycle:
if (this.getResult().getRunningContext().isCalJavaClassCycle()) {
if (this.getContainsCycle()) {
return MetricsMgr.Cyclic;
} else {
return MetricsMgr.NoValue;
}
} else {
return MetricsMgr.NoValue;
}
default:
return super.getValue(metrics);
}
}
}