package dk.brics.xact.analysis.transformations;
import java.util.ArrayList;
import java.util.List;
import dk.brics.xact.analysis.flowgraph.Edge;
import dk.brics.xact.analysis.flowgraph.FlowGraph;
import dk.brics.xact.analysis.flowgraph.Statement;
import dk.brics.xact.analysis.flowgraph.VariableFilter;
import dk.brics.xact.analysis.util.UnionFindForest;
import dk.brics.xact.analysis.xmlgraph.XMLGraphChecker;
/**
* Finds disjoint components in the flow graph and creates a new flow graph for each component.
* Components without any XML operations are ignored.
*/
public class Splitter {
private static final class Component {
public boolean interesting = false;
public FlowGraph graph = null;
}
public List<FlowGraph> split(FlowGraph graph) {
UnionFindForest<Statement, Component> forest = new UnionFindForest<Statement, Component>() {
@Override
protected Component mergeNodeData(Component a, Component b) {
a.interesting |= b.interesting;
return a;
}
@Override
protected Component defaultNodeData() {
return new Component();
}
};
for (Statement stm : graph.getNodes()) {
for (Edge<Statement,VariableFilter> edge : graph.getInEdges(stm))
forest.merge(stm, edge.getFrom());
for (Edge<Statement,VariableFilter> edge : graph.getOutEdges(stm))
forest.merge(stm, edge.getTo());
if (XMLGraphChecker.isStatementChecked(stm)) {
forest.getData(stm).interesting = true;
}
}
List<FlowGraph> graphs = new ArrayList<FlowGraph>();
for (Statement stm : graph.getNodes()) {
Component comp = forest.getData(stm);
if (!comp.interesting)
continue;
if (comp.graph == null) {
comp.graph = new FlowGraph(graph.getSchemas(), graph.getNamespaces());
comp.graph.setXMLGraph(graph.getXMLGraph());
comp.graph.setTypemap(graph.getTypemap());
graphs.add(comp.graph);
}
comp.graph.addNode(stm);
}
for (Statement stm : graph.getNodes()) {
Component comp = forest.getData(stm);
if (!comp.interesting)
continue;
// only add ingoing edges. each outgoing edge will be added by the destination node as an ingoing edge
for (Edge<Statement,VariableFilter> edge : graph.getInEdges(stm))
comp.graph.addEdge(edge.getFrom(), edge.getTo(), edge.getData());
if (graph.getEntries().contains(stm))
comp.graph.addEntry(stm);
}
return graphs;
}
}