live.document.mavenplugin.rootmethod.DuplicatedRootMethodRemover Maven / Gradle / Ivy
package live.document.mavenplugin.rootmethod;
import live.document.scanner.CallGraph;
import live.document.scanner.ClassObject;
import live.document.scanner.MethodObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class DuplicatedRootMethodRemover {
private final CallGraph callGraph;
public DuplicatedRootMethodRemover(CallGraph callGraph) {
this.callGraph = callGraph;
}
public List removeDuplicatedRootMethodOperator(List methodOperators) {
List results = new ArrayList<>(methodOperators);
List methods = methodOperators.stream()
.map(n -> new Method(n.getName()))
.collect(Collectors.toList());
Set distinctMethods = new HashSet<>(removeDuplicated(methods));
Iterator iterator = results.iterator();
while (iterator.hasNext()) {
RootMethodOperator next = iterator.next();
if (! distinctMethods.contains(new Method(next.getName()))) {
iterator.remove();
}
}
return results;
}
public List removeDuplicatedMethods(List rootMethodNames) {
List methods = rootMethodNames.stream()
.map(n -> new Method(n))
.collect(Collectors.toList());
List results = removeDuplicated(methods);
return results.stream().map(m -> m.fullMethodName).sorted().collect(Collectors.toList());
}
private List removeDuplicated(List methods) {
Map> callerCalleeMap = generateCallerCalleeMap(methods);
List results = new ArrayList<>(methods);
Iterator iterator = results.iterator();
while (iterator.hasNext()) {
Method method = iterator.next();
for (Map.Entry> methodSetEntry : callerCalleeMap.entrySet()) {
if (methodSetEntry.getKey().equals(method.fullMethodName)) {
continue;
}
Set methodObjects = new HashSet<>(findMethodObjects(method));
if (methodObjects.removeAll(methodSetEntry.getValue())) {
iterator.remove();
break;
}
}
}
return results;
}
private Map> generateCallerCalleeMap(List methods) {
Map> tmpResults = new HashMap<>();
for (Method method : methods) {
tmpResults.put(method.fullMethodName, new ArrayList<>());
List methodObjects = findMethodObjects(method);
for (MethodObject methodObject : methodObjects) {
List children = findChildren(methodObject, new HashSet());
tmpResults.get(method.fullMethodName).addAll(children);
}
}
Map> results = new HashMap<>();
for (Map.Entry> entry : tmpResults.entrySet()) {
results.put(entry.getKey(), new HashSet<>(entry.getValue()));
}
return results;
}
private List findChildren(MethodObject method, Set scannedMethods) {
if (scannedMethods.contains(method)) {
return new ArrayList<>();
}
scannedMethods.add(method);
List results = new ArrayList<>();
method.calleeStream(MethodObject.class)
.forEach(results::add);
method.calleeStream(MethodObject.class)
.forEach(callee ->
results.addAll(findChildren(callee, scannedMethods))
);
return results;
}
private List findMethodObjects(Method method) {
ClassObject calleeClass = callGraph.findClass(method.fullClassName);
List calleeMethods = calleeClass.findMethod(method.shortMethodName);
return calleeMethods;
}
static class Method {
String packageName;
String className;
String fullClassName;
String shortMethodName;
String fullMethodName;
public Method(String fullMethodName) {
this.fullMethodName = fullMethodName;
int i = fullMethodName.lastIndexOf(".");
this.fullClassName = fullMethodName.substring(0, i);
this.shortMethodName = fullMethodName.substring(i + 1);
int j = this.fullClassName.lastIndexOf(".");
this.packageName = this.fullClassName.substring(0, j);
this.className = this.fullClassName.substring(j + 1);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Method method = (Method) o;
return fullMethodName.equals(method.fullMethodName);
}
@Override
public int hashCode() {
return fullMethodName.hashCode();
}
}
}