package dk.brics.xact.analysis.xmlgraph;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import dk.brics.xact.analysis.Debug;
import dk.brics.xact.analysis.flowgraph.Statement;
import dk.brics.xmlgraph.MultiContentNode;
import dk.brics.xmlgraph.Node;
import dk.brics.xmlgraph.SingleContentNode;
import dk.brics.xmlgraph.XMLGraph;
import dk.brics.xmlgraph.converter.XMLGraph2Dot;
public class XMLGraphDebug {
private static int dump_number = 0;
public static String getPathForStatement(Statement s) {
String name = s.getOpName();
String path = System.getProperty("java.io.tmpdir");
String sep = System.getProperty("file.separator");
if (!path.endsWith(sep))
path += sep;
path += ++dump_number + "-" + name + "-" + s.getOrigin().getFile().replace('.', '-').replace('$', '-').replace("<", "").replace(">", "")
+ "-" + s.getOrigin().getLine();
return path;
}
/**
* Dumps the XML graph to a file.
*/
public static void dumpXMLGraph(XMLGraph xg, Statement s) {
if (Debug.getLevel() >= 5) {
dumpXMLGraphAlways(xg, s);
}
}
public synchronized static void dumpXMLGraphAlways(XMLGraph xg, Statement s) {
try {
String path = getPathForStatement(s) + ".dot";
Debug.println(3, true, "Writing XML graph to: " + path);
FileOutputStream out = new FileOutputStream(path);
PrintStream pout = new PrintStream(out);
new XMLGraph2Dot(pout).print(xg, true);
pout.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public synchronized static void dumpXMLGraphAlways(XMLGraph xg, Statement s, int depth) {
try {
String path = getPathForStatement(s) + ".dot";
Debug.println(3, true, "Writing XML graph to: " + path);
System.err.println("Writing DOT file to " + path);
FileOutputStream out = new FileOutputStream(path);
PrintStream pout = new PrintStream(out);
new XMLGraph2Dot(pout).print(xg, getNodesWithinDepth(xg, depth));
pout.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public synchronized static void dumpXMLGraphObject(XMLGraph xg, Statement s) {
try {
String path = getPathForStatement(s) + ".object";
System.err.println("Writing OBJECT file to " + path);
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(path));
os.writeObject(xg);
os.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public synchronized static void dumpXMLGraphObjects(XMLGraphPair pair, Statement s) {
try {
String path = getPathForStatement(s) + ".object";
System.err.println("Writing OBJECT file to " + path);
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(path));
os.writeObject(pair);
os.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
static private class NodeDepthPair {
Node node;
int depth;
public NodeDepthPair(Node node, int depth) {
this.node = node;
this.depth = depth;
}
}
public static Set<Node> getNodesWithinDepth(XMLGraph xg, int depth) {
Set<Node> nodes = new HashSet<Node>();
LinkedList<NodeDepthPair> queue = new LinkedList<NodeDepthPair>();
for (int root : xg.getRoots()) {
nodes.add(xg.getNode(root));
queue.add(new NodeDepthPair(xg.getNode(root), 0));
}
while (!queue.isEmpty()) {
NodeDepthPair pair = queue.removeFirst();
Node node = pair.node;
int d = pair.depth;
for (int child : getSuccessors(node)) {
Node childnode = xg.getNode(child);
if (nodes.contains(childnode))
continue;
nodes.add(childnode);
if (d < depth) {
queue.add(new NodeDepthPair(childnode, d+1));
}
}
}
return nodes;
}
private static Collection<Integer> getSuccessors(Node node) {
if (node instanceof MultiContentNode) {
return ((MultiContentNode)node).getContents();
}
else if (node instanceof SingleContentNode) {
return Collections.singleton(((SingleContentNode)node).getContent());
}
else {
return Collections.emptySet();
}
}
}