package jdepend.model.result;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jdepend.framework.util.MetricsFormat;
import jdepend.model.Component;
import jdepend.model.MetricsInfo;
import jdepend.model.MetricsMgr;
import jdepend.model.ObjectMeasured;
import jdepend.model.profile.model.AnalysisResultProfile;
public class AnalysisResultSummary extends ObjectMeasured implements Serializable {
private static final long serialVersionUID = -5109171634600473818L;
public static final String Name = "小结";
private String path;
private int afferentCoupling;
private int efferentCoupling;
private float cohesion;
private float coupling;
private Float balance;
private Float distance;
private Float encapsulation;
private Float normalRelation;
private int abstractClassCount;
private int classCount;
private int concreteClassCount;
private int lineCount;
private Float abstractness;
private Float stability;
private Float volatility;
private int javaPackageCount;
private int componentCount;
private int relationCount;
public AnalysisResultSummary() {
}
public AnalysisResultSummary(AnalysisResultSummary summary) {
this.path = summary.path;
this.afferentCoupling = summary.afferentCoupling;
this.efferentCoupling = summary.efferentCoupling;
this.cohesion = summary.cohesion;
this.coupling = summary.coupling;
this.balance = summary.balance;
this.distance = summary.distance;
this.encapsulation = summary.encapsulation;
this.normalRelation = summary.normalRelation;
this.abstractClassCount = summary.abstractClassCount;
this.classCount = summary.classCount;
this.concreteClassCount = summary.concreteClassCount;
this.lineCount = summary.lineCount;
this.abstractness = summary.abstractness;
this.stability = summary.stability;
this.volatility = summary.volatility;
this.javaPackageCount = summary.javaPackageCount;
this.componentCount = summary.componentCount;
this.relationCount = summary.relationCount;
}
@Override
public Float getAbstractness() {
return this.abstractness;
}
@Override
public int getAfferentCoupling() {
return this.afferentCoupling;
}
@Override
public int getEfferentCoupling() {
return this.efferentCoupling;
}
@Override
public Float getBalance() {
return this.balance;
}
@Override
public float getCohesion() {
return this.cohesion;
}
@Override
public boolean getContainsCycle() {
return false;
}
@Override
public float getCoupling() {
return this.coupling;
}
@Override
public Float getDistance() {
return this.distance;
}
@Override
public Float getEncapsulation() {
return this.encapsulation;
}
@Override
public MetricsInfo extendMetrics(String metrics) {
return null;
}
@Override
public int getAbstractClassCount() {
return this.abstractClassCount;
}
@Override
public int getClassCount() {
return this.classCount;
}
@Override
public int getConcreteClassCount() {
return this.concreteClassCount;
}
@Override
public int getLineCount() {
return this.lineCount;
}
@Override
public Float getStability() {
return this.stability;
}
@Override
public Float getVolatility() {
return this.volatility;
}
@Override
public String getName() {
return Name;
}
public void setAbstractness(Float abstractness) {
this.abstractness = abstractness;
}
public void setAfferentCoupling(int afferentCoupling) {
this.afferentCoupling = afferentCoupling;
}
public void setEfferentCoupling(int efferentCoupling) {
this.efferentCoupling = efferentCoupling;
}
public void setBalance(Float balance) {
this.balance = balance;
}
public void setCohesion(float cohesion) {
this.cohesion = cohesion;
}
public void setCoupling(float coupling) {
this.coupling = coupling;
}
public void setDistance(Float distance) {
this.distance = distance;
}
public void setEncapsulation(Float encapsulation) {
this.encapsulation = encapsulation;
}
public void setStability(Float stability) {
this.stability = stability;
}
public void setVolatility(Float volatility) {
this.volatility = volatility;
}
public void setAbstractClassCount(int abstractClassCount) {
this.abstractClassCount = abstractClassCount;
}
public void setClassCount(int classCount) {
this.classCount = classCount;
}
public void setConcreteClassCount(int concreteClassCount) {
this.concreteClassCount = concreteClassCount;
}
public void setLineCount(int lineCount) {
this.lineCount = lineCount;
}
public int getJavaPackageCount() {
return javaPackageCount;
}
public void setJavaPackageCount(int javaPackageCount) {
this.javaPackageCount = javaPackageCount;
}
public int getComponentCount() {
return componentCount;
}
public void setComponentCount(int componentCount) {
this.componentCount = componentCount;
}
public int getRelationCount() {
return relationCount;
}
public void setRelationCount(int relationCount) {
this.relationCount = relationCount;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Float getNormalRelation() {
return normalRelation;
}
public void setNormalRelation(Float attentionRelation) {
this.normalRelation = attentionRelation;
}
public AnalysisResultSummary(AnalysisResult result) {
MetricsSummaryInfo[] metricsSummaryInfos = getMetricsSummaryInfo(result);
// 计算内部分析单元
List<Object[]> objs = new ArrayList<Object[]>();
Object[] rowData;
for (Component unit : result.getComponents()) {
if (unit.isInner()) {
rowData = new Object[metricsSummaryInfos.length];
for (int i = 0; i < metricsSummaryInfos.length; i++) {
rowData[i] = unit.getValue(metricsSummaryInfos[i].name);
}
objs.add(rowData);
}
}
if (objs.size() > 0) {
// 初始化summry
Object[] summry = new Object[metricsSummaryInfos.length];
for (int i = 0; i < metricsSummaryInfos.length; i++) {
if (metricsSummaryInfos[i].type.equals(MetricsSummaryInfo.TypeInteger)) {
summry[i] = 0;
} else if (metricsSummaryInfos[i].type.equals(MetricsSummaryInfo.TypeFloat)) {
summry[i] = 0F;
}
}
// 初始化参与计算的组件个数
Integer[] calComponents = new Integer[metricsSummaryInfos.length];
for (int col = 0; col < metricsSummaryInfos.length; col++) {
calComponents[col] = 0;
}
// 初始化参与计算的组件代码行数总和
Integer[] componentSizes = new Integer[metricsSummaryInfos.length];
for (int col = 0; col < metricsSummaryInfos.length; col++) {
componentSizes[col] = 0;
}
// 计算参与计算的组件个数和代码行数总和
for (int row = 0; row < objs.size(); row++) {
for (int col = 0; col < metricsSummaryInfos.length; col++) {
if (objs.get(row)[col] != null) {
calComponents[col]++;
componentSizes[col] = componentSizes[col] + (Integer) objs.get(row)[0];
}
}
}
// 当指定指标的代码行总数为0时,采用LogicAVE计算汇总值
for (int col = 0; col < metricsSummaryInfos.length; col++) {
if (componentSizes[col] == 0) {
metricsSummaryInfos[col].logic = MetricsSummaryInfo.LogicAVE;
}
}
// 计算汇总数据第一步(求和)
for (int row = 0; row < objs.size(); row++) {
for (int col = 0; col < metricsSummaryInfos.length; col++) {
if (objs.get(row)[col] != null) {
if (metricsSummaryInfos[col].logic.equals(MetricsSummaryInfo.LogicAVE_WEIGHT)) {
if (metricsSummaryInfos[col].type.equals(MetricsSummaryInfo.TypeFloat)) {
summry[col] = (Float) summry[col] + (Float) objs.get(row)[col]
* (Integer) objs.get(row)[0];
} else if (metricsSummaryInfos[col].type.equals(MetricsSummaryInfo.TypeInteger)) {
summry[col] = (Integer) summry[col] + (Integer) objs.get(row)[col]
* (Integer) objs.get(row)[0];
}
} else {
if (metricsSummaryInfos[col].type.equals(MetricsSummaryInfo.TypeFloat)) {
summry[col] = (Float) summry[col] + (Float) objs.get(row)[col];
} else if (metricsSummaryInfos[col].type.equals(MetricsSummaryInfo.TypeInteger)) {
summry[col] = (Integer) summry[col] + (Integer) objs.get(row)[col];
}
}
}
}
}
// 计算汇总数据第二步(求均)
for (int col = 0; col < metricsSummaryInfos.length; col++) {
if (calComponents[col] != 0) {
if (metricsSummaryInfos[col].logic.equals(MetricsSummaryInfo.LogicAVE)) {
if (metricsSummaryInfos[col].type.equals(MetricsSummaryInfo.TypeInteger)) {
summry[col] = (Integer) ((Integer) summry[col] / calComponents[col]);
} else {
summry[col] = ((Float) summry[col]) / calComponents[col];
}
} else if (metricsSummaryInfos[col].logic.equals(MetricsSummaryInfo.LogicAVE_WEIGHT)) {
if (componentSizes[col] != 0) {
if (metricsSummaryInfos[col].type.equals(MetricsSummaryInfo.TypeInteger)) {
summry[col] = (Integer) ((Integer) summry[col] / (Integer) componentSizes[col]);
} else {
summry[col] = ((Float) summry[col]) / new Float((Integer) componentSizes[col]);
}
} else {
summry[col] = null;
}
}
} else {
summry[col] = null;
}
}
this.setJavaPackageCount(result.getJavaPackages().size());
this.setLineCount((Integer) summry[0]);
this.setClassCount((Integer) summry[1]);
this.setConcreteClassCount((Integer) summry[2]);
this.setAbstractClassCount((Integer) summry[3]);
this.setAfferentCoupling((Integer) summry[4]);
this.setEfferentCoupling((Integer) summry[5]);
this.setAbstractness(MetricsFormat.toFormattedMetrics((Float) summry[6]));
this.setVolatility(MetricsFormat.toFormattedMetrics((Float) summry[7]));
this.setStability(MetricsFormat.toFormattedMetrics((Float) summry[8]));
this.setDistance(MetricsFormat.toFormattedMetrics((Float) summry[9]));
this.setCoupling(MetricsFormat.toFormattedMetrics((Float) summry[10]) / 2);
this.setCohesion(MetricsFormat.toFormattedMetrics((Float) summry[11]));
this.setBalance(MetricsFormat.toFormattedMetrics((Float) summry[12]));
this.setEncapsulation(MetricsFormat.toFormattedMetrics((Float) summry[13]));
this.setComponentCount(objs.size());
this.setRelationCount(result.getRelations().size());
this.setPath(result.getRunningContext().getPath());
this.setNormalRelation(MetricsFormat.toFormattedMetrics(result.getNormalRelation()));
}
}
private static MetricsSummaryInfo[] getMetricsSummaryInfo(AnalysisResult result) {
// 得到summry部分指标(A、V、I、D、Balance、Encapsulation)计算规则
AnalysisResultProfile analysisResultProfile = result.getRunningContext().getProfileFacade()
.getAnalysisResultProfile();
String logic = null;
if (analysisResultProfile.isComponentWeight()) {
logic = MetricsSummaryInfo.LogicAVE_WEIGHT;
} else {
logic = MetricsSummaryInfo.LogicAVE;
}
MetricsSummaryInfo[] metricsSummaryInfos;
metricsSummaryInfos = new MetricsSummaryInfo[14];
metricsSummaryInfos[0] = new MetricsSummaryInfo(MetricsMgr.LC, MetricsSummaryInfo.TypeInteger,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[1] = new MetricsSummaryInfo(MetricsMgr.CN, MetricsSummaryInfo.TypeInteger,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[2] = new MetricsSummaryInfo(MetricsMgr.CC, MetricsSummaryInfo.TypeInteger,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[3] = new MetricsSummaryInfo(MetricsMgr.AC, MetricsSummaryInfo.TypeInteger,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[4] = new MetricsSummaryInfo(MetricsMgr.Ca, MetricsSummaryInfo.TypeInteger,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[5] = new MetricsSummaryInfo(MetricsMgr.Ce, MetricsSummaryInfo.TypeInteger,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[6] = new MetricsSummaryInfo(MetricsMgr.A, MetricsSummaryInfo.TypeFloat, logic);
metricsSummaryInfos[7] = new MetricsSummaryInfo(MetricsMgr.V, MetricsSummaryInfo.TypeFloat, logic);
metricsSummaryInfos[8] = new MetricsSummaryInfo(MetricsMgr.I, MetricsSummaryInfo.TypeFloat, logic);
metricsSummaryInfos[9] = new MetricsSummaryInfo(MetricsMgr.D, MetricsSummaryInfo.TypeFloat, logic);
metricsSummaryInfos[10] = new MetricsSummaryInfo(MetricsMgr.Coupling, MetricsSummaryInfo.TypeFloat,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[11] = new MetricsSummaryInfo(MetricsMgr.Cohesion, MetricsSummaryInfo.TypeFloat,
MetricsSummaryInfo.LogicSUM);
metricsSummaryInfos[12] = new MetricsSummaryInfo(MetricsMgr.Balance, MetricsSummaryInfo.TypeFloat, logic);
metricsSummaryInfos[13] = new MetricsSummaryInfo(MetricsMgr.Encapsulation, MetricsSummaryInfo.TypeFloat, logic);
return metricsSummaryInfos;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((path == null) ? 0 : path.hashCode());
result = prime * result + abstractClassCount;
result = prime * result + ((abstractness == null) ? 0 : Float.floatToIntBits(abstractness));
result = prime * result + afferentCoupling;
result = prime * result + ((balance == null) ? 0 : Float.floatToIntBits(balance));
result = prime * result + classCount;
result = prime * result + Float.floatToIntBits(cohesion);
result = prime * result + componentCount;
result = prime * result + concreteClassCount;
result = prime * result + Float.floatToIntBits(coupling);
result = prime * result + ((distance == null) ? 0 : Float.floatToIntBits(distance));
result = prime * result + efferentCoupling;
result = prime * result + ((encapsulation == null) ? 0 : Float.floatToIntBits(encapsulation));
result = prime * result + ((normalRelation == null) ? 0 : Float.floatToIntBits(normalRelation));
result = prime * result + ((stability == null) ? 0 : Float.floatToIntBits(stability));
result = prime * result + javaPackageCount;
result = prime * result + lineCount;
result = prime * result + relationCount;
result = prime * result + ((volatility == null) ? 0 : Float.floatToIntBits(volatility));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AnalysisResultSummary other = (AnalysisResultSummary) obj;
if (path == null && other.path != null)
return false;
if (path != null && other.path == null)
return false;
if (path != other.path)
return false;
if (abstractClassCount != other.abstractClassCount)
return false;
if (abstractness == null && other.abstractness != null)
return false;
if (abstractness != null && other.abstractness == null)
return false;
if (abstractness != null && other.abstractness != null)
if (Float.floatToIntBits(abstractness) != Float.floatToIntBits(other.abstractness))
return false;
if (afferentCoupling != other.afferentCoupling)
return false;
if (balance == null && other.balance != null)
return false;
if (balance != null && other.balance == null)
return false;
if (balance != null && other.balance != null)
if (Float.floatToIntBits(balance) != Float.floatToIntBits(other.balance))
return false;
if (classCount != other.classCount)
return false;
if (Float.floatToIntBits(cohesion) != Float.floatToIntBits(other.cohesion))
return false;
if (componentCount != other.componentCount)
return false;
if (concreteClassCount != other.concreteClassCount)
return false;
if (Float.floatToIntBits(coupling) != Float.floatToIntBits(other.coupling))
return false;
if (Float.floatToIntBits(distance) != Float.floatToIntBits(other.distance))
return false;
if (efferentCoupling != other.efferentCoupling)
return false;
if (encapsulation == null && other.encapsulation != null)
return false;
if (encapsulation != null && other.encapsulation == null)
return false;
if (encapsulation != null && other.encapsulation != null)
if (Float.floatToIntBits(encapsulation) != Float.floatToIntBits(other.encapsulation))
return false;
if (normalRelation == null && other.normalRelation != null)
return false;
if (normalRelation != null && other.normalRelation == null)
return false;
if (normalRelation != null && other.normalRelation != null)
if (Float.floatToIntBits(normalRelation) != Float.floatToIntBits(other.normalRelation))
return false;
if (stability == null && other.stability != null)
return false;
if (stability != null && other.stability == null)
return false;
if (stability != null && other.stability != null)
if (Float.floatToIntBits(stability) != Float.floatToIntBits(other.stability))
return false;
if (javaPackageCount != other.javaPackageCount)
return false;
if (lineCount != other.lineCount)
return false;
if (relationCount != other.relationCount)
return false;
if (volatility == null && other.volatility != null)
return false;
if (volatility != null && other.volatility == null)
return false;
if (volatility != null && other.volatility != null)
if (Float.floatToIntBits(volatility) != Float.floatToIntBits(other.volatility))
return false;
return true;
}
@Override
public String toString() {
StringBuilder info = new StringBuilder();
info.append("共分析" + this.getComponentCount() + "个分析单元,得到" + this.getJavaPackageCount() + "个packages,"
+ this.getClassCount() + "个javaclass,代码行数为" + this.getLineCount() + "行。\n");
info.append("其中具有抽象类计数资格的类" + this.getAbstractClassCount() + "个\n");
info.append(" 具体类" + this.getConcreteClassCount() + "个\n");
info.append(" 关系" + this.getAfferentCoupling() + "个。\n");
info.append(" 抽象程度" + MetricsFormat.toFormattedMetrics(this.getAbstractness())
+ " [具有抽象类计数资格的类数量/类总数,值越大越抽象]\n");
info.append(" 易变性" + MetricsFormat.toFormattedMetrics(this.getVolatility()) + " [稳定的类数量/类总数,值越大越不易变]\n");
info.append(" 不稳定性" + MetricsFormat.toFormattedMetrics(this.getStability())
+ " [传出数量/(传出数量 + 传入数量),值越小越稳定]\n");
info.append(" 合理性" + MetricsFormat.toFormattedMetrics(this.getDistance())
+ " [1 - abs(抽象程度 + 不稳定性 - 1),值越大越理想]\n");
info.append(" 耦合值" + MetricsFormat.toFormattedMetrics(this.getCoupling())
+ " [sum(依赖的JavaClass * Relation强度),值越小越好]\n");
info.append(" 内聚值" + MetricsFormat.toFormattedMetrics(this.getCohesion())
+ " [sum(内部的JavaClass * Relation强度),值越大越好]\n");
info.append(" 内聚性指数" + MetricsFormat.toFormattedMetrics(this.getBalance())
+ " [内聚值/(内聚值+分组耦合最大顺序差值),值越大越好]\n");
info.append(" 封装性" + MetricsFormat.toFormattedMetrics(this.getEncapsulation()) + " [私有类比例,值越大越好]\n");
return info.toString();
}
static class MetricsSummaryInfo {
private static final String LogicAVE = "AVE";// 求平均
private static final String LogicSUM = "SUM";// 求和
private static final String LogicAVE_WEIGHT = "AVE_WEIGHT";// 加权求平均
private static final String TypeInteger = "Integer";
private static final String TypeFloat = "Float";
String name;
String type;
String logic;
public MetricsSummaryInfo(String name, String type, String logic) {
super();
this.name = name;
this.type = type;
this.logic = logic;
}
}
}