package jdepend.model; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import jdepend.framework.util.MathUtil; import jdepend.framework.util.MetricsFormat; import jdepend.metadata.JavaClassRelationItem; import jdepend.model.profile.model.RelationProfile; import jdepend.model.result.AnalysisResult; /** * 两个Element间的关系对象 * * @author <b>Abner</b> * */ public final class Relation implements Comparable<Relation>, Serializable { /** * */ private static final long serialVersionUID = -6078087861336926293L; private Element current = null; private Element depend = null; private RelationDetail detail; private transient boolean isAttention = true;// 是否值得注意,可以通过外部设置为不关注 private transient String attentionType;// 缓存 private transient Float attentionLevel;// 缓存 private transient boolean normality = true; public static final String DefaultAttentionType = "DefaultAttentionType"; public static final String CycleDependAttentionType = "CycleDependAttentionType";// 循环依赖的关系 public static final String SDPAttentionType = "SDPAttentionType";// 违反稳定依赖原则的关系 public static final String ComponentLayerAttentionType = "ComponentLayerAttentionType";// 下层组件依赖了上层组件的关系 public static final String MutualDependAttentionType = "MutualDependAttentionType";// 彼此依赖的关系 public static final Map<String, String> AttentionTypeList = new HashMap<String, String>(); static { AttentionTypeList.put(DefaultAttentionType, ""); AttentionTypeList.put(CycleDependAttentionType, "循环依赖"); AttentionTypeList.put(SDPAttentionType, "违反稳定依赖原则"); AttentionTypeList.put(ComponentLayerAttentionType, "下层组件依赖了上层组件"); AttentionTypeList.put(MutualDependAttentionType, "彼此依赖"); } public static final String CurrentName = "Relation_CurrentName"; public static final String DependName = "Relation_DependName"; public static final String CurrentCohesion = "Relation_CurrentCohesion"; public static final String DependCohesion = "Relation_DependCohesion"; public static final String Intensity = "Relation_Intensity"; public static final String AttentionType = "Relation_AttentionType"; public static final String AttentionLevel = "Relation_AttentionLevel"; public static final String Balance = "Relation_Balance"; public static final String isProblem = "Relation_isProblem"; public Relation() { super(); } public void setCurrent(Element current) { this.current = current; } public void setDepend(Element depend) { this.depend = depend; } public float getIntensity() { return detail.getIntensity(); } public Collection<JavaClassRelationItem> getItems() { return this.detail.getItems(); } public void setDetail(RelationDetail detail) { this.detail = detail; } public RelationDetail getDetail() { return detail; } /** * 关系平衡指数 * * @return */ public float getBalance() { return this.current.getIntensity() + this.depend.getIntensity() - detail.getIntensity(); } public int size() { return this.getItems().size(); } public int compareTo(Relation obj) { return new Float(this.getBalance()).compareTo(obj.getBalance()); } public Element getCurrent() { return current; } public Element getDepend() { return depend; } public Component getOpposite(Component component) { if (this.current.getComponent().equals(component)) { return this.depend.getComponent(); } else if (this.depend.getComponent().equals(component)) { return this.current.getComponent(); } else { return null; } } public String getAttentionType() { if (!this.isAttention) { return DefaultAttentionType; } if (this.attentionType == null) { this.attentionType = this.calAttentionType(); } return this.attentionType; } /** * 得到关注程度 * * @param relations * @return */ public Float getAttentionLevel() { if (!this.isAttention) { return 0F; } if (this.attentionLevel == null) { this.attentionLevel = this.calAttentionLevel(); } return this.attentionLevel; } public String getAttentionTypeName() { return AttentionTypeList.get(this.getAttentionType()); } public boolean isNormality() { return normality; } public boolean isAttention() { return this.isAttention && !this.getAttentionType().equals(DefaultAttentionType); } public void setAttention(boolean isAttention) { this.isAttention = isAttention; } public Object getValue(String metrics) { if (metrics.equals(CurrentName)) { return this.current.getName(); } else if (metrics.equals(DependName)) { return this.depend.getName(); } else if (metrics.equals(CurrentCohesion)) { return MetricsFormat.toFormattedMetrics(this.current.getIntensity()); } else if (metrics.equals(DependCohesion)) { return MetricsFormat.toFormattedMetrics(this.depend.getIntensity()); } else if (metrics.equals(Balance)) { return MetricsFormat.toFormattedMetrics(this.getBalance()); } else if (metrics.equals(Intensity)) { return MetricsFormat.toFormattedMetrics(this.getIntensity()); } else if (metrics.equals(AttentionType)) { return this.getAttentionType(); } else if (metrics.equals(AttentionLevel)) { return this.getAttentionLevel(); } else if (metrics.equals(isProblem)) { return this.isNormality() ? "" : "是"; } else { return null; } } public void init() { this.attentionType = this.calAttentionType(); this.attentionLevel = this.calAttentionLevel(); } /** * 得到彼此依赖的对方关系 * * @param relation * @return */ private Relation getReverseRelation() { for (Relation relation : this.depend.getComponent().getRelations()) { if (this.current.equals(relation.getDepend()) && this.depend.equals(relation.getCurrent())) { return relation; } } return null; } private Float calAttentionLevel() { Float attentionLevel = 0F; String attentiontype = getAttentionType(); if (attentiontype.equals(MutualDependAttentionType)) {// 彼此依赖 Relation relation = this.getReverseRelation(); if (MathUtil.isEquals(relation.getIntensity(), this.getIntensity())) { attentionLevel = this.getAttentionWeight(attentiontype); } else { Float attention = 1 - this.getIntensity() / (this.getIntensity() + relation.getIntensity()); attentionLevel = this.getAttentionWeight(attentiontype) + attention; if (attention > 0.5) { this.normality = false; } } } else if (attentiontype.equals(SDPAttentionType)) {// 稳定性差的组件依赖稳定性高的组件 Float attention = this.getDepend().getComponent().getStability() - this.getCurrent().getComponent().getStability(); if (attention > 0) { attentionLevel = this.getAttentionWeight(attentiontype) + attention;// 按自动计算的稳定性计算attentionLevel } this.normality = false; } else if (attentiontype.equals(ComponentLayerAttentionType)) {// 下层组件依赖了上层组件 Float attention = 0F; if (this.current.getComponent().getAreaComponent() != null && this.depend.getComponent().getAreaComponent() != null) { attention = this.getDepend().getComponent().getAreaComponent().instability() - this.getCurrent().getComponent().getAreaComponent().instability(); } else { attention = new Float(this.getDepend().getComponent().getLayer() - this.getCurrent().getComponent().getLayer()); } attentionLevel = this.getAttentionWeight(attentiontype) + attention; this.normality = false; } else { attentionLevel = 0F; } return attentionLevel; } private String calAttentionType() { if (this.current.getComponent().isDefinedComponentLevel() && this.depend.getComponent().isDefinedComponentLevel() && this.current.getComponent().getLayer() < this.depend.getComponent().getLayer()) {// 检测组件层依赖(人工指定) return ComponentLayerAttentionType; } else if (this.current.getComponent().getAreaComponent() != null && this.depend.getComponent().getAreaComponent() != null && this.current.getComponent().getAreaComponent().instability() < this.depend.getComponent() .getAreaComponent().instability()) {// 检测组件层依赖(按着AreaComponent) return ComponentLayerAttentionType; } else if (this.depend.getComponent().getEfferents().contains(this.current.getComponent()) && // 检测反向关系不是ComponentLayerAttentionType (!(this.current.getComponent().isDefinedComponentLevel() && this.depend.getComponent().isDefinedComponentLevel() && this.depend.getComponent().getLayer() < this.current.getComponent().getLayer())) && !(this.current.getComponent().getAreaComponent() != null && this.depend.getComponent().getAreaComponent() != null && this.depend.getComponent().getAreaComponent().instability() < this.current.getComponent() .getAreaComponent().instability())) { return MutualDependAttentionType; } else if (this.current.getComponent().stability(this.depend.getComponent())) {// 检测稳定依赖(按着自动计算的稳定性) return SDPAttentionType; } else if (this.current.getComponent().collectCycle().contains(this.depend.getComponent())) {// 检测循环依赖 return CycleDependAttentionType; } else { return DefaultAttentionType; } } /** * 将问题类型转化成问题权值 * * @param attentiontype * @return */ public float getAttentionWeight(String attentiontype) { RelationProfile relationProfile = this.getResult().getRunningContext().getProfileFacade().getRelationProfile(); return relationProfile.getProblemRelations().get(attentiontype); } public AnalysisResult getResult() { return this.current.getComponent().getResult(); } public static Collection<Element> calElements(Collection<Relation> relations) { Collection<Element> elements = new ArrayList<Element>(); for (Relation relation : relations) { if (!elements.contains(relation.getCurrent())) { elements.add(relation.getCurrent()); } if (!elements.contains(relation.getDepend())) { elements.add(relation.getDepend()); } } return elements; } public void clear() { this.attentionLevel = null; this.attentionType = null; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((current == null) ? 0 : current.hashCode()); result = prime * result + ((depend == null) ? 0 : depend.hashCode()); return result; } public boolean equals(String current, String depend) { return this.current.getName().equals(current) && this.depend.getName().equals(depend); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final Relation other = (Relation) obj; if (current == null) { if (other.current != null) return false; } else if (!current.equals(other.current)) return false; if (depend == null) { if (other.depend != null) return false; } else if (!depend.equals(other.depend)) return false; return true; } @Override public String toString() { return "关系耦合值:" + MetricsFormat.toFormattedMetrics(this.getIntensity()) + " " + this.getAttentionTypeName(); } }