package jdepend.util.analyzer.element;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import jdepend.metadata.JavaClass;
import jdepend.metadata.Method;
import jdepend.metadata.tree.JavaClassNode;
import jdepend.metadata.tree.JavaClassTree;
import jdepend.metadata.tree.Node;
import jdepend.metadata.tree.TreeCreatorFacade;
import jdepend.model.result.AnalysisResult;
import jdepend.model.util.JavaClassUnitUtil;
import jdepend.util.analyzer.framework.AbstractAnalyzer;
import jdepend.util.analyzer.framework.Analyzer;
import jdepend.util.analyzer.framework.AnalyzerException;
public class OverrideCheck extends AbstractAnalyzer {
private transient List<Method> methods = new ArrayList<Method>();// 缓存在一次继承树扫描时的method集合
private Boolean isPrintNotOverrideMethod;
private Boolean isPrintOverrideMethod;
/**
*
*/
private static final long serialVersionUID = 6965754729091695315L;
public OverrideCheck() {
super("覆盖检查", Analyzer.Attention, "检查在继承树上覆盖父类方法的情况");
if (isPrintNotOverrideMethod == null) {
isPrintNotOverrideMethod = true;
}
if (isPrintOverrideMethod == null) {
isPrintOverrideMethod = true;
}
}
protected void doExecute(AnalysisResult result) throws AnalyzerException {
List<JavaClassTree> trees = TreeCreatorFacade.createJavaClassInheritTrees(JavaClassUnitUtil
.getJavaClasses(result.getClasses()));
for (JavaClassTree tree : trees) {
overrideCheck(tree);
}
}
private void overrideCheck(JavaClassTree tree) {
for (JavaClassNode node : tree.getNodes()) {
search(node.getJavaClass(), tree);
}
// 清空缓存
methods = new ArrayList<Method>();
}
private void search(JavaClass javaClass, JavaClassTree tree) {
boolean found;
boolean override;
ArrayList<Method> theMethods;
ArrayList<Method> overrideMethods;
Map<Method, ArrayList<Method>> printNotOverrideMethods = new LinkedHashMap<Method, ArrayList<Method>>();
Map<Method, ArrayList<Method>> printOverrideMethods = new LinkedHashMap<Method, ArrayList<Method>>();
// search
for (Method currentMethod : getCheckingMethods(javaClass)) {
found = false;
override = false;
overrideMethods = new ArrayList<Method>();
theMethods = this.getMethods(currentMethod, tree);
for (Method method : theMethods) {
found = true;
if (this.override(currentMethod, method)) {
override = true;
// 对于当前JavaClass,删除之前记录错误的未覆盖方法
for (Method printMethod : printNotOverrideMethods.keySet()) {
if (printMethod.getName().equals(currentMethod)) {
printNotOverrideMethods.remove(printMethod);
break;
}
}
// 记录覆盖的方法
if (isNoteOverrideMethod(method)) {
overrideMethods.add(method);
}
}
}
if (!found) {
this.methods.add(currentMethod);
} else if (!override) {
printNotOverrideMethods.put(currentMethod, theMethods);
} else if (overrideMethods.size() > 0) {
printOverrideMethods.put(currentMethod, overrideMethods);
}
}
// print
if (isPrintNotOverrideMethod) {
for (Method printMethod : printNotOverrideMethods.keySet()) {
this.print("JavaClass[" + printMethod.getJavaClass().getName() + "] Method[" + printMethod.getInfo()
+ "] not Override Super Method:\n");
for (Method method : printNotOverrideMethods.get(printMethod)) {
this.printTab();
this.print("JavaClass[" + method.getJavaClass().getName() + "] Method[" + method.getInfo() + "]\n");
}
this.print("\n");
}
}
if (isPrintOverrideMethod) {
for (Method printMethod : printOverrideMethods.keySet()) {
this.print("JavaClass[" + printMethod.getJavaClass().getName() + "] Method[" + printMethod.getInfo()
+ "] override Super Method:\n");
for (Method method : printOverrideMethods.get(printMethod)) {
this.printTab();
this.print("JavaClass[" + method.getJavaClass().getName() + "] Method[" + method.getInfo() + "]\n");
}
this.print("\n");
}
}
if (isPrintNotOverrideMethod) {
for (Method printMethod : printNotOverrideMethods.keySet()) {
for (Method method : printNotOverrideMethods.get(printMethod)) {
this.printTable("Type", "NotOverride");
this.printTable("JavaClass", printMethod.getJavaClass().getName());
this.printTable("Method", printMethod.getInfo());
this.printTable("SuperJavaClass", method.getJavaClass().getName());
this.printTable("SuperMethod", method.getInfo());
}
}
}
if (isPrintOverrideMethod) {
for (Method printMethod : printOverrideMethods.keySet()) {
for (Method method : printOverrideMethods.get(printMethod)) {
this.printTable("Type", "Override");
this.printTable("JavaClass", printMethod.getJavaClass().getName());
this.printTable("Method", printMethod.getInfo());
this.printTable("SuperJavaClass", method.getJavaClass().getName());
this.printTable("SuperMethod", method.getInfo());
}
}
}
}
/**
* 得到可能需要覆盖的方法集合
*
* @param name
* @return
*/
private ArrayList<Method> getMethods(Method currentMethod, JavaClassTree tree) {
ArrayList<Method> theMethods = new ArrayList<Method>();
for (Method method : this.methods) {
if (method.getName().equals(currentMethod.getName())
&& this.isSubJavaClass(currentMethod.getJavaClass(), method.getJavaClass(), tree)) {
theMethods.add(method);
}
}
return theMethods;
}
/**
* 判断current处于javaClass的下层
*
* @param javaClass
* @param current
* @return
*/
private boolean isSubJavaClass(JavaClass current, JavaClass javaClass, JavaClassTree tree) {
return this.getNode(current, tree).getLayer() > this.getNode(javaClass, tree).getLayer();
}
private Node getNode(JavaClass javaClass, JavaClassTree tree) {
for (JavaClassNode node : tree.getNodes()) {
if (node.getJavaClass().equals(javaClass)) {
return node;
}
}
return null;
}
private List<Method> getCheckingMethods(JavaClass javaClass) {
List<Method> theMethods = new ArrayList<Method>();
for (Method method : javaClass.getSelfMethods()) {
if (!method.isConstruction()// 初始化方法 不检查
&& !method.isPrivate()) {// 私有方法不检查
theMethods.add(method);
}
}
return theMethods;
}
private boolean override(Method subMethod, Method superMethod) {
return subMethod.equals(superMethod);
}
private boolean isNoteOverrideMethod(Method method) {
return !method.getJavaClass().isInterface() && method.getInfo().indexOf("abstract") == -1;
}
public Boolean getIsPrintNotOverrideMethod() {
return isPrintNotOverrideMethod;
}
public void setIsPrintNotOverrideMethod(Boolean isPrintNotOverrideMethod) {
this.isPrintNotOverrideMethod = isPrintNotOverrideMethod;
}
public Boolean getIsPrintOverrideMethod() {
return isPrintOverrideMethod;
}
public void setIsPrintOverrideMethod(Boolean isPrintOverrideMethod) {
this.isPrintOverrideMethod = isPrintOverrideMethod;
}
}