/** * This method converts the given tree completely into dot code. * * @param root The root of the tree. * @param ps The stream in which the dot code will be written. * @param includeWeights Determines whether to include weights or not. * @param includeEois Determines whether to include the execution order indices or not. * @param shortLabels Determines whether to use short labels or not. */ private static void dotFromCallingTree( final AbstractCallTreeNode<?> root, final PrintStream ps, final boolean includeWeights, final boolean includeEois, final boolean shortLabels) { // preamble: ps.println("digraph G {"); final StringBuilder edgestringBuilder = new StringBuilder(); final Map<AbstractCallTreeNode<?>, Integer> nodeIds = new Hashtable<AbstractCallTreeNode<?>, Integer>(); // NOPMD (not synchronized) AbstractCallTreeFilter.dotEdgesFromSubTree( root, nodeIds, new AtomicInteger(0), ps, shortLabels); AbstractCallTreeFilter.dotVerticesFromSubTree( root, includeEois ? new AtomicInteger(1) : null, nodeIds, ps, includeWeights); // NOPMD NOCS (null) ps.println(edgestringBuilder.toString()); ps.println("}"); }
public static <T> void writeDotForMessageTrace( final AbstractCallTreeNode<T> root, final IPairFactory<T> pairFactory, final MessageTrace msgTrace, final String outputFilename, final boolean includeWeights, final boolean shortLabels) throws FileNotFoundException, TraceProcessingException, UnsupportedEncodingException { AbstractCallTreeFilter.<T>addTraceToTree( root, msgTrace, pairFactory, false); // false: no aggregation AbstractCallTreeFilter.saveTreeToDotFile( root, outputFilename, includeWeights, true, shortLabels); // includeEois }
@SuppressWarnings("unchecked") // javac reports unchecked casts protected static final String nodeLabel( final AbstractCallTreeNode<?> node, final boolean shortLabels) { if (node.getEntity() instanceof AllocationComponentOperationPair) { return AbstractCallTreeFilter.allocationComponentOperationPairNodeLabel( (AbstractCallTreeNode<AllocationComponentOperationPair>) node, shortLabels); } else if (node.getEntity() instanceof AssemblyComponentOperationPair) { return AbstractCallTreeFilter.assemblyComponentOperationPairNodeLabel( (AbstractCallTreeNode<AssemblyComponentOperationPair>) node, shortLabels); } else { throw new UnsupportedOperationException( "Node type not supported: " + node.getEntity().getClass().getName()); } }
/** * Traverse tree recursively and generate dot code for vertices. * * @param n The root node. * @param eoiCounter The counter for the execution order index. * @param nodeIds The map containing the node IDs. * @param ps The stream on which the generated code will be printed. * @param includeWeights Determines whether to include weights or not. */ private static void dotVerticesFromSubTree( final AbstractCallTreeNode<?> n, final AtomicInteger eoiCounter, final Map<AbstractCallTreeNode<?>, Integer> nodeIds, final PrintStream ps, final boolean includeWeights) { final int thisId = nodeIds.get(n); for (final WeightedDirectedCallTreeEdge<?> child : n.getChildEdges()) { final StringBuilder strBuild = new StringBuilder(1024); final int childId = nodeIds.get(child.getTarget()); strBuild .append('\n') .append(thisId) .append("->") .append(childId) .append("[style=solid,arrowhead=none"); if (includeWeights) { strBuild.append(",label=\"").append(child.getTargetWeight().get()).append('"'); } else if (eoiCounter != null) { strBuild.append(",label=\"").append(eoiCounter.getAndIncrement()).append(".\""); } strBuild.append(" ]"); ps.println(strBuild.toString()); AbstractCallTreeFilter.dotVerticesFromSubTree( child.getTarget(), eoiCounter, nodeIds, ps, includeWeights); } }
/** * This method saves the given tree as valid dot code into the given file. * * @param root The root of the tree. * @param outputFn The file in which the code will be written. * @param includeWeights Determines whether to include weights or not. * @param includeEois Determines whether to include the execution order indices or not. * @param shortLabels Determines whether to use short labels or not. * @throws FileNotFoundException If the given file is somehow invalid. * @throws UnsupportedEncodingException If the default encoding is not supported. */ protected static void saveTreeToDotFile( final AbstractCallTreeNode<?> root, final String outputFn, final boolean includeWeights, final boolean includeEois, final boolean shortLabels) throws FileNotFoundException, UnsupportedEncodingException { final PrintStream ps = new PrintStream(new FileOutputStream(outputFn), false, ENCODING); AbstractCallTreeFilter.dotFromCallingTree(root, ps, includeWeights, includeEois, shortLabels); ps.flush(); ps.close(); }
/** * Traverse tree recursively and generate dot code for edges. * * @param n The root node to start with. * @param nodeIds The map containing the node IDs. * @param nextNodeId The counter for the IDs of the nodes. * @param ps The stream in which the dot code will be written. * @param shortLabels Determines whether to use short labels or not. */ private static void dotEdgesFromSubTree( final AbstractCallTreeNode<?> n, final Map<AbstractCallTreeNode<?>, Integer> nodeIds, final AtomicInteger nextNodeId, final PrintStream ps, final boolean shortLabels) { final StringBuilder strBuild = new StringBuilder(64); nodeIds.put(n, nextNodeId.get()); strBuild .append(nextNodeId.getAndIncrement()) .append("[label =\"") .append( n.isRootNode() ? SystemModelRepository.ROOT_NODE_LABEL // NOCS : AbstractCallTreeFilter.nodeLabel(n, shortLabels)) // NOCS .append("\",shape=" + DotFactory.DOT_SHAPE_NONE + "];"); ps.println(strBuild.toString()); for (final WeightedDirectedCallTreeEdge<?> child : n.getChildEdges()) { AbstractCallTreeFilter.dotEdgesFromSubTree( child.getTarget(), nodeIds, nextNodeId, ps, shortLabels); } }