package jdepend.util.analyzer.element;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import jdepend.metadata.InvokeItem;
import jdepend.metadata.JavaClass;
import jdepend.metadata.JavaClassRelationItem;
import jdepend.metadata.Method;
import jdepend.model.Component;
import jdepend.model.Relation;
import jdepend.model.result.AnalysisResult;
import jdepend.util.analyzer.framework.AbstractAnalyzer;
import jdepend.util.analyzer.framework.Analyzer;
import jdepend.util.analyzer.framework.AnalyzerException;
public class DIPPrinciple extends AbstractAnalyzer {
/**
*
*/
private static final long serialVersionUID = 792778276091284397L;
private transient List<DIPInfo> dipInfos;
public DIPPrinciple() {
super("DIP检查", Analyzer.Attention, "识别违反依赖倒置原则的地方");
}
protected void doExecute(AnalysisResult result) throws AnalyzerException {
Collection<Component> components = result.getComponents();
this.printDIPs(components);
}
private void printDIPs(Collection<Component> components) {
this.dipInfos = new ArrayList<DIPInfo>();
Iterator<Component> i = components.iterator();
while (i.hasNext()) {
collectDIP(i.next());
}
for (DIPInfo info : this.dipInfos) {
this.printTable("current", info.current);
this.printTable("depend", info.depend);
this.printTable("dependInterface", info.Interface);
}
}
private void collectDIP(Component component) {
boolean found;
for (Relation relation : component.getRelations()) {
for (JavaClassRelationItem item : relation.getDetail().getItems()) {
if (item.getType().canAbstraction()) {
JavaClass current = item.getSource();
JavaClass depend = item.getTarget();
// 识别组件外依赖的JavaClass是否是抽象的
if (!depend.isAbstract() && depend.getSupers().size() > 0) {
found = true;
L: for (Method method : current.getSelfMethods()) {
if (method.getReturnClassTypes().contains(depend)) {
found = false;
break L;
}
for (InvokeItem invokeItem : method.getInvokeItems()) {
if (invokeItem.getCallee().getArgClassTypes().contains(depend)) {
found = false;
break L;
}
if (invokeItem.getCallee().getJavaClass().equals(depend)) {
if (depend.getSelfMethods().contains(invokeItem.getCallee())) {
found = false;
break L;
}
}
}
}
if (found) {
this.dipInfos.add(new DIPInfo(current.getName(), depend.getName(), this
.getSuperNames(depend.getSupers())));
}
}
}
}
}
}
@Override
public String getExplain() {
StringBuilder explain = new StringBuilder();
explain.append("识别组件间的依赖【属性和参数】关系中,被依赖的类存在接口而依赖了具体类的情况。<br>");
explain.append("注:建议将该接口进行精化设计(从使用者角度命名),并打包在使用者所在的组件中。<br>");
return explain.toString();
}
private String getSuperNames(Collection<JavaClass> source) {
StringBuilder buf = new StringBuilder(100);
for (JavaClass item : source) {
buf.append(item.getName());
buf.append(" ");
}
return buf.toString();
}
class DIPInfo {
public String current;
public String depend;
public String Interface;
public DIPInfo(String current, String depend, String interface1) {
super();
this.current = current;
this.depend = depend;
Interface = interface1;
}
@Override
public String toString() {
return current + " " + depend + " " + Interface;
}
}
}