org.codetracker.GraphImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of code-tracker Show documentation
Show all versions of code-tracker Show documentation
A refactoring-aware tool that can generate the commit change history of code elements with a very high accuracy.
package org.codetracker;
import com.google.common.graph.*;
import org.refactoringminer.api.RefactoringType;
import org.codetracker.api.CodeElement;
import org.codetracker.api.Edge;
import org.codetracker.api.Graph;
import java.util.*;
/**
* @param Node Type
* @param Edge Type
*/
public class GraphImpl implements org.codetracker.api.Graph {
private static final List CTR = Arrays.asList(RefactoringType.CHANGE_ATTRIBUTE_TYPE.getDisplayName(),
RefactoringType.CHANGE_PARAMETER_TYPE.getDisplayName(), RefactoringType.CHANGE_RETURN_TYPE.getDisplayName(), RefactoringType.CHANGE_VARIABLE_TYPE.getDisplayName());
private final MutableValueGraph graph;
/**
* @param graph
*/
private GraphImpl(ValueGraph graph) {
this.graph = Graphs.copyOf(graph);
}
public GraphImpl() {
this.graph = ValueGraphBuilder.directed().allowsSelfLoops(true).build();
}
public static GraphImpl of(ValueGraph graph) {
return new GraphImpl<>(graph);
}
public static Graph subGraph(ValueGraph graph, N startNode) {
if (graph == null || startNode == null)
return null;
Set connectedNodes = new HashSet<>();
Queue queue = new LinkedList<>();
queue.add(startNode);
while (!queue.isEmpty()) {
N visitingNode = queue.poll();
if (!connectedNodes.contains(visitingNode)) {
connectedNodes.add(visitingNode);
queue.addAll(graph.successors(visitingNode));
queue.addAll(graph.predecessors(visitingNode));
}
}
return new GraphImpl(Graphs.inducedSubgraph(graph, connectedNodes));
}
public static Set> setOf(ValueGraph graph) {
Set> graphs = new HashSet<>();
for (Set nodes : induceDisconnectedSubGraphs(graph)) {
graphs.add(new GraphImpl(Graphs.inducedSubgraph(graph, nodes)));
}
return graphs;
}
public static Set> setOf(Graph graph) {
Set> graphs = new HashSet<>();
for (Set nodes : induceDisconnectedSubGraphs(((GraphImpl) graph).graph)) {
graphs.add(new GraphImpl(Graphs.inducedSubgraph(((GraphImpl) graph).graph, nodes)));
}
return graphs;
}
public static List> induceDisconnectedSubGraphs(ValueGraph graph) {
List> inducedSubGraphNodes = new ArrayList<>();
HashMap> visitedNodes = new HashMap<>();
for (N node : graph.nodes()) {
if (graph.predecessors(node).isEmpty()) {
if (!visitedNodes.containsKey(node)) {
Set reachable = findReachable(graph, node);
reachable.add(node);
Set relatedReachable = null;
for (N reachableNode : reachable) {
if (visitedNodes.containsKey(reachableNode)) {
relatedReachable = visitedNodes.get(reachableNode);
break;
}
}
if (relatedReachable == null) {
inducedSubGraphNodes.add(reachable);
relatedReachable = reachable;
}
for (N reachableNode : reachable) {
visitedNodes.put(reachableNode, relatedReachable);
}
}
}
}
return inducedSubGraphNodes;
}
private static Set findReachable(ValueGraph graph, N node) {
Set reachable = new HashSet<>();
Traverser.forGraph(graph).breadthFirst(node).forEach(reachable::add);
return reachable;
}
// public static Map getEdgesContainingCTR(GraphImpl graph) {
// return graph.graph.edges().stream()
// .filter(x -> graph.graph.edgeValue(x).get().numberOfRefactoring() > 1)
// .filter(x -> Arrays.stream(graph.graph.edgeValue(x).get().toString().split(",")).anyMatch(r -> CTR.contains(r)))
// .collect(toMap(x -> x.nodeU(), x -> graph.graph.edgeValue(x).get(), (e1, e2) -> e1));
// }
public void merge(GraphImpl toMergeGraph) {
for (EndpointPair edge : toMergeGraph.graph.edges()) {
E e = toMergeGraph.graph.edgeValueOrDefault(edge, null);
if (e != null)
graph.putEdgeValue(edge, e);
}
}
@Override
public Set getNodeList() {
return graph.nodes();
}
@Override
public Set> getEdges() {
return graph.edges();
}
@Override
public Optional getEdgeValue(EndpointPair e) {
return graph.edgeValue(e);
}
/**
* @return true if the chain is empty
*/
public boolean isEmpty() {
return graph.nodes().isEmpty();
}
@Override
public Set predecessors(N n) {
return graph.predecessors(n);
}
@Override
public Set successors(N n) {
return graph.successors(n);
}
// public boolean isMultiContainer() {
// return graph.nodes().stream().map(n -> n.getContainerName()).collect(Collectors.toSet()).size() > 1;
// }
}