de.cau.cs.kieler.klay.layered.JsonDebugUtil.java Source code

Java tutorial

Introduction

Here is the source code for de.cau.cs.kieler.klay.layered.JsonDebugUtil.java

Source

/*
 * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient
 *
 * http://www.informatik.uni-kiel.de/rtsys/kieler/
 *
 * Copyright 2014 by
 * + Christian-Albrechts-University of Kiel
 *   + Department of Computer Science
 *     + Real-Time and Embedded Systems Group
 *
 * This code is provided under the terms of the Eclipse Public License (EPL).
 * See the file epl-v10.html for the license text.
 */
package de.cau.cs.kieler.klay.layered;

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;

import de.cau.cs.kieler.core.math.KVector;
import de.cau.cs.kieler.core.math.KVectorChain;
import de.cau.cs.kieler.core.properties.IProperty;
import de.cau.cs.kieler.klay.layered.graph.*;
import de.cau.cs.kieler.klay.layered.graph.LNode.NodeType;
import de.cau.cs.kieler.klay.layered.p4nodes.LinearSegmentsNodePlacer.LinearSegment;
import de.cau.cs.kieler.klay.layered.p5edges.OrthogonalRoutingGenerator.Dependency;
import de.cau.cs.kieler.klay.layered.p5edges.OrthogonalRoutingGenerator.HyperNode;
import de.cau.cs.kieler.klay.layered.properties.InternalProperties;

/**
 * A utility class for debugging of KLay Layered.
 *
 * @author msp
 * @author cds
 * @author csp
 */
public final class JsonDebugUtil {

    private static final String INDENT = "  ";

    /**
     * Hidden constructor to avoid instantiation.
     */
    private JsonDebugUtil() {
    }

    /**
     * Output a representation of the given graph in JSON format.
     *
     * @param lgraph
     *            the layered graph
     * @param slotIndex
     *            the slot before whose execution the graph is written.
     * @param name
     *            the name the slot before whose execution the graph is written.
     */
    public static void writeDebugGraph(final LGraph lgraph, final int slotIndex, final String name) {
        try {
            final ConsoleWriter ConsoleWriter = createConsoleWriter(lgraph, slotIndex, name);

            final List<LEdge> edges = Lists.newLinkedList();

            beginGraph(ConsoleWriter, lgraph);

            // Write layerless nodes and collect edges
            edges.addAll(writeLayer(ConsoleWriter, -1, lgraph.getLayerlessNodes(), 2));

            // Go through the layers
            int layerNumber = -1;
            final Iterator<Layer> layersIterator = lgraph.iterator();
            if (!lgraph.getLayerlessNodes().isEmpty() && layersIterator.hasNext()) {
                ConsoleWriter.write(",");
            }
            while (layersIterator.hasNext()) {
                final Layer layer = layersIterator.next();
                layerNumber++;

                // Write the nodes and collect edges
                edges.addAll(writeLayer(ConsoleWriter, layerNumber, layer.getNodes(), 2));

                if (layersIterator.hasNext()) {
                    ConsoleWriter.write(",");
                }
            }

            endChildNodeList(ConsoleWriter);

            writeEdges(ConsoleWriter, edges, 1);

            // Close the graph and the ConsoleWriter.
            endGraph(ConsoleWriter);
        } catch (final IOException exception) {
            exception.printStackTrace();
        }
    }

    /**
     * Writes a debug graph for the given linear segments and their
     * dependencies.
     *
     * @param layeredGraph
     *            the layered graph.
     * @param segmentList
     *            the list of linear segments.
     * @param outgoingList
     *            the list of successors for each linear segment.
     */
    public static void writeDebugGraph(final LGraph layeredGraph, final List<LinearSegment> segmentList,
            final List<List<LinearSegment>> outgoingList) {

        try {
            final ConsoleWriter ConsoleWriter = createConsoleWriter(layeredGraph);

            beginGraph(ConsoleWriter, layeredGraph);

            final String indent1 = Strings.repeat(INDENT, 2);
            final String indent2 = Strings.repeat(INDENT, 3); // SUPPRESS
            // CHECKSTYLE
            // MagicNumber
            int edgeId = 0;

            final Iterator<LinearSegment> segmentIterator = segmentList.iterator();
            final Iterator<List<LinearSegment>> successorsIterator = outgoingList.iterator();

            final StringBuffer edges = new StringBuffer();

            while (segmentIterator.hasNext()) {
                final LinearSegment segment = segmentIterator.next();
                ConsoleWriter.write("\n" + indent1 + "{\n" + indent2 + "\"id\": \"n" + segment.hashCode() + "\",\n"
                        + indent2 + "\"labels\": [ { \"text\": \"" + segment + "\" } ],\n" + indent2
                        + "\"width\": 50,\n" + indent2 + "\"height\": 25\n" + indent1 + "}");
                if (segmentIterator.hasNext()) {
                    ConsoleWriter.write(",");
                }

                final Iterator<LinearSegment> succIterator = successorsIterator.next().iterator();

                while (succIterator.hasNext()) {
                    final LinearSegment successor = succIterator.next();
                    edges.append("\n" + indent1 + "{\n" + indent2 + "\"id\": \"e" + edgeId++ + "\",\n" + indent2
                            + "\"source\": \"n" + segment.hashCode() + "\",\n" + indent2 + "\"target\": \"n"
                            + successor.hashCode() + "\",\n" + indent1 + "},");
                }
            }

            endChildNodeList(ConsoleWriter);

            if (edges.length() > 0) {
                edges.deleteCharAt(edges.length() - 1);
            }
            ConsoleWriter.write(INDENT + "\"edges\": [" + edges + "\n" + indent1 + "]");

            endGraph(ConsoleWriter);
        } catch (final Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * Writes a debug graph for the given list of hypernodes.
     *
     * @param layeredGraph
     *            the layered graph
     * @param layerIndex
     *            the currently processed layer's index
     * @param hypernodes
     *            a list of hypernodes
     * @param debugPrefix
     *            prefix of debug output files
     * @param label
     *            a label to append to the output files
     */
    public static void writeDebugGraph(final LGraph layeredGraph, final int layerIndex,
            final List<HyperNode> hypernodes, final String debugPrefix, final String label) {

        try {
            final ConsoleWriter ConsoleWriter = createConsoleWriter(layeredGraph, layerIndex, debugPrefix, label);
            beginGraph(ConsoleWriter, layeredGraph);

            final String indent1 = Strings.repeat(INDENT, 2);
            final String indent2 = Strings.repeat(INDENT, 3); // SUPPRESS
            // CHECKSTYLE
            // MagicNumber
            int edgeId = 0;

            final Iterator<HyperNode> hypernodeIterator = hypernodes.iterator();

            final StringBuffer edges = new StringBuffer();

            while (hypernodeIterator.hasNext()) {
                final HyperNode hypernode = hypernodeIterator.next();
                ConsoleWriter.write("\n" + indent1 + "{\n" + indent2 + "\"id\": \"n"
                        + System.identityHashCode(hypernode) + "\",\n" + indent2 + "\"labels\": [ { \"text\": \""
                        + hypernode.toString() + "\" } ],\n" + indent2 + "\"width\": 50,\n" + indent2
                        + "\"height\": 25\n" + indent1 + "}");
                if (hypernodeIterator.hasNext()) {
                    ConsoleWriter.write(",");
                }

                final Iterator<Dependency> dependencyIterator = hypernode.getOutgoing().iterator();

                while (dependencyIterator.hasNext()) {
                    final Dependency dependency = dependencyIterator.next();
                    edges.append("\n" + indent1 + "{\n" + indent2 + "\"id\": \"e" + edgeId++ + "\",\n" + indent2
                            + "\"source\": \"n" + System.identityHashCode(hypernode) + "\",\n" + indent2
                            + "\"target\": \"n" + System.identityHashCode(dependency.getTarget()) + "\"\n" + indent1
                            + "},");
                }
            }

            endChildNodeList(ConsoleWriter);

            if (edges.length() > 0) {
                edges.deleteCharAt(edges.length() - 1);
            }
            ConsoleWriter.write(INDENT + "\"edges\": [" + edges + "\n" + INDENT + "]");

            endGraph(ConsoleWriter);
        } catch (final Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * Begins a new graph by writing the root node, the graphs properties and
     * the start of the child node list to the ConsoleWriter.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @param lgraph
     *            the graph to begin
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void beginGraph(final ConsoleWriter ConsoleWriter, final LGraph lgraph) throws IOException {
        final KVectorChain graphSize = calculateGraphSize(lgraph);
        ConsoleWriter.write("{\n" + INDENT + "\"id\": \"root\",\n" + INDENT + "\"x\": " + graphSize.getFirst().x
                + ",\n" + INDENT + "\"y\": " + graphSize.getFirst().y + ",\n" + INDENT + "\"width\": "
                + graphSize.getLast().x + ",\n" + INDENT + "\"height\": " + graphSize.getLast().y + ",\n");
        writeProperties(ConsoleWriter, lgraph.getAllProperties(), 1);
        ConsoleWriter.write(",\n" + INDENT + "\"children\": [");
    }

    /**
     * Calculate the overall size of the given graph. Returns a
     * {@link KVectorChain} with two elements where the first one represents the
     * minimal coordinates used by any node, edge or port contained in the graph
     * and the second one represents the maximal coordinates.
     *
     * @param lgraph
     *            the graph to calculate the size for.
     * @return a {@link KVectorChain} with two elements, the minimal and the
     *         maximal coordinates.
     */
    private static KVectorChain calculateGraphSize(final LGraph lgraph) {
        final KVector min = new KVector();
        final KVector max = new KVector();
        for (final LNode node : lgraph.getLayerlessNodes()) {
            calculateMinMaxPositions(min, max, node);
        }
        for (final Layer layer : lgraph) {
            for (final LNode node : layer) {
                calculateMinMaxPositions(min, max, node);
            }
        }
        max.x -= min.x;
        max.y -= min.y;
        return new KVectorChain(min, max);
    }

    /**
     * Inspects the given node, its outgoing edges and its ports for minimal and
     * maximal coordinates and adjusts the given vectors {@code min} and
     * {@code max} if necessary.
     *
     * @param min
     *            the minimal coordinates used by the graph.
     * @param max
     *            the maximal coordinates used by the graph.
     * @param node
     *            the current node to inspect.
     */
    private static void calculateMinMaxPositions(final KVector min, final KVector max, final LNode node) {
        min.x = Math.min(min.x, node.getPosition().x - node.getMargin().left);
        max.x = Math.max(max.x, node.getPosition().x + node.getSize().x + node.getMargin().right);
        min.y = Math.min(min.y, node.getPosition().y - node.getMargin().top);
        max.y = Math.max(max.y, node.getPosition().y + node.getSize().y + node.getMargin().bottom);
        for (final LPort port : node.getPorts()) {
            min.x = Math.min(min.x, (node.getPosition().x + port.getPosition().x) - port.getMargin().left);
            max.x = Math.max(max.x,
                    node.getPosition().x + port.getPosition().x + port.getSize().x + port.getMargin().right);
            min.y = Math.min(min.y, (node.getPosition().y + port.getPosition().y) - port.getMargin().top);
            max.y = Math.max(max.y,
                    node.getPosition().y + port.getPosition().y + port.getSize().y + port.getMargin().bottom);
        }
        for (final LEdge edge : node.getOutgoingEdges()) {
            for (final KVector bendpoint : edge.getBendPoints()) {
                min.x = Math.min(min.x, bendpoint.x);
                max.x = Math.max(max.x, bendpoint.x);
                min.y = Math.min(min.y, bendpoint.y);
                max.y = Math.max(max.y, bendpoint.y);
            }
        }
    }

    /**
     * Ends the list of child nodes.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void endChildNodeList(final ConsoleWriter ConsoleWriter) throws IOException {
        ConsoleWriter.write("\n" + INDENT + "],\n");
    }

    /**
     * Ends the graph.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void endGraph(final ConsoleWriter ConsoleWriter) throws IOException {
        ConsoleWriter.write("\n}\n");

        ConsoleWriter.close();
    }

    /**
     * Writes the given list of nodes and collects their edges.
     *
     * @param ConsoleWriter
     *            ConsoleWriter to write to.
     * @param layerNumber
     *            the layer number. {@code -1} for layerless nodes.
     * @param nodes
     *            the nodes in the layer.
     * @param indentation
     *            the indentation level to use.
     * @return list of edges that need to be added to the graph.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static List<LEdge> writeLayer(final ConsoleWriter ConsoleWriter, final int layerNumber,
            final List<LNode> nodes, final int indentation) throws IOException {

        if (nodes.isEmpty()) {
            return Lists.newLinkedList();
        }

        writeNodes(ConsoleWriter, nodes, indentation, layerNumber);

        final List<LEdge> edges = Lists.newLinkedList();

        // Collect the edges
        for (final LNode node : nodes) {
            // Go through all edges and collect those that have this node as
            // their source
            for (final LPort port : node.getPorts()) {
                edges.addAll(port.getOutgoingEdges());
            }
        }

        return edges;
    }

    /**
     * Writes the nodes edges as JSON formatted string to the given
     * ConsoleWriter.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @param nodes
     *            the nodes to write.
     * @param indentation
     *            the indentation level to use.
     * @param layerNumber
     *            the layer number. {@code -1} for layerless nodes.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void writeNodes(final ConsoleWriter ConsoleWriter, final List<LNode> nodes,
            final int indentation, final int layerNumber) throws IOException {

        final String indent0 = Strings.repeat(INDENT, indentation);
        final String indent1 = Strings.repeat(INDENT, indentation + 1);
        int nodeNumber = -1;
        final Iterator<LNode> nodesIterator = nodes.iterator();
        while (nodesIterator.hasNext()) {
            nodeNumber++;
            final LNode node = nodesIterator.next();
            ConsoleWriter.write("\n" + indent0 + "{\n" + indent1 + "\"id\": \"n" + node.hashCode() + "\",\n"
                    + indent1 + "\"labels\": [ { \"text\": \"" + getNodeName(node, layerNumber, nodeNumber)
                    + "\" } ],\n" + indent1 + "\"width\": " + node.getSize().x + ",\n" + indent1 + "\"height\": "
                    + node.getSize().y + ",\n" + indent1 + "\"x\": " + node.getPosition().x + ",\n" + indent1
                    + "\"y\": " + node.getPosition().y + ",\n");
            writeProperties(ConsoleWriter, node.getAllProperties(), indentation + 1);
            ConsoleWriter.write(",\n");
            writePorts(ConsoleWriter, node.getPorts(), indentation + 1);
            ConsoleWriter.write("\n" + indent0 + "}");
            if (nodesIterator.hasNext()) {
                ConsoleWriter.write(",");
            }
        }
    }

    /**
     * Writes the given edges as JSON formatted string to the given
     * ConsoleWriter.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @param edges
     *            the edges to write.
     * @param indentation
     *            the indentation level to use.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void writeEdges(final ConsoleWriter ConsoleWriter, final List<LEdge> edges,
            final int indentation) throws IOException {

        final String indent0 = Strings.repeat(INDENT, indentation);
        final String indent1 = Strings.repeat(INDENT, indentation + 1);
        final String indent2 = Strings.repeat(INDENT, indentation + 2);
        ConsoleWriter.write(indent0 + "\"edges\": [");
        final Iterator<LEdge> edgesIterator = edges.iterator();
        while (edgesIterator.hasNext()) {
            final LEdge edge = edgesIterator.next();
            ConsoleWriter.write("\n" + indent1 + "{\n" + indent2 + "\"id\": \"e" + edge.hashCode() + "\",\n"
                    + indent2 + "\"source\": \"n" + edge.getSource().getNode().hashCode() + "\",\n" + indent2
                    + "\"target\": \"n" + edge.getTarget().getNode().hashCode() + "\",\n" + indent2
                    + "\"sourcePort\": \"p" + edge.getSource().hashCode() + "\",\n" + indent2
                    + "\"targetPort\": \"p" + edge.getTarget().hashCode() + "\",\n" + indent2
                    + "\"sourcePoint\": { \"x\": " + edge.getSource().getAbsoluteAnchor().x + ", \"y\": "
                    + edge.getSource().getAbsoluteAnchor().y + " },\n" + indent2 + "\"targetPoint\": { \"x\": "
                    + edge.getTarget().getAbsoluteAnchor().x + ", \"y\": " + edge.getTarget().getAbsoluteAnchor().y
                    + " },\n");
            // + indent2 + "\"bendPoints\": \"" +
            // edge.getBendPoints().toString() + "\",\n");
            writeBendPoints(ConsoleWriter, edge.getBendPoints(), indentation + 2);
            ConsoleWriter.write(",\n");
            writeProperties(ConsoleWriter, edge.getAllProperties(), indentation + 2);
            ConsoleWriter.write("\n" + indent1 + "}");
            if (edgesIterator.hasNext()) {
                ConsoleWriter.write(",");
            }
        }
        ConsoleWriter.write("\n" + indent0 + "]");
    }

    /**
     * Writes the given bendpoints as JSON formatted string to the given
     * ConsoleWriter.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @param bendPoints
     *            the bendpoints to write.
     * @param indentation
     *            the indentation level to use.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void writeBendPoints(final ConsoleWriter ConsoleWriter, final KVectorChain bendPoints,
            final int indentation) throws IOException {

        final String indent0 = Strings.repeat(INDENT, indentation);
        final String indent1 = Strings.repeat(INDENT, indentation + 1);
        ConsoleWriter.write(indent0 + "\"bendPoints\": [");
        final Iterator<KVector> pointsIterator = bendPoints.iterator();
        while (pointsIterator.hasNext()) {
            final KVector point = pointsIterator.next();
            ConsoleWriter.write("\n" + indent1 + "{ \"x\": " + point.x + ", \"y\": " + point.y + "}");
            if (pointsIterator.hasNext()) {
                ConsoleWriter.write(",");
            }
        }
        ConsoleWriter.write("\n" + indent0 + "]");
    }

    /**
     * Writes the given ports as JSON formatted string to the given
     * ConsoleWriter.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @param ports
     *            the ports to write.
     * @param indentation
     *            the indentation level to use.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void writePorts(final ConsoleWriter ConsoleWriter, final List<LPort> ports,
            final int indentation) throws IOException {

        final String indent0 = Strings.repeat(INDENT, indentation);
        final String indent1 = Strings.repeat(INDENT, indentation + 1);
        final String indent2 = Strings.repeat(INDENT, indentation + 2);
        ConsoleWriter.write(indent0 + "\"ports\": [");
        final Iterator<LPort> portsIterator = ports.iterator();
        while (portsIterator.hasNext()) {
            final LPort port = portsIterator.next();
            ConsoleWriter.write("\n" + indent1 + "{\n" + indent2 + "\"id\": \"p" + port.hashCode() + "\",\n"
                    + indent2 + "\"width\": " + port.getSize().x + ",\n" + indent2 + "\"height\": "
                    + port.getSize().y + ",\n" + indent2 + "\"x\": " + port.getPosition().x + ",\n" + indent2
                    + "\"y\": " + port.getPosition().y + ",\n");
            writeProperties(ConsoleWriter, port.getAllProperties(), indentation + 2);
            ConsoleWriter.write("\n" + indent1 + "}");
            if (portsIterator.hasNext()) {
                ConsoleWriter.write(",");
            }
        }
        ConsoleWriter.write("\n" + indent0 + "]");
    }

    /**
     * Writes the given properties as JSON formatted string to the given
     * ConsoleWriter.
     *
     * @param ConsoleWriter
     *            the ConsoleWriter to write to.
     * @param properties
     *            the properties to write.
     * @param indentation
     *            the indentation level to use.
     * @throws IOException
     *             if anything goes wrong with the ConsoleWriter.
     */
    private static void writeProperties(final ConsoleWriter ConsoleWriter,
            final Map<IProperty<?>, Object> properties, final int indentation) throws IOException {

        final String indent0 = Strings.repeat(INDENT, indentation);
        final String indent1 = Strings.repeat(INDENT, indentation + 1);
        ConsoleWriter.write(indent0 + "\"properties\": {");
        final Iterator<Entry<IProperty<?>, Object>> propertiesIterator = properties.entrySet().iterator();
        while (propertiesIterator.hasNext()) {
            final Entry<IProperty<?>, Object> property = propertiesIterator.next();
            final String id = property.getKey().getId();
            // Test whether the given id is a registered layout option. If not,
            // prefix the id with
            // DEBUG_ID_PREFIX
            final String val = getValueRepresentation(property.getKey(), property.getValue());
            ConsoleWriter.write("\n" + indent1 + "\"" + id + "\": \"" + val.replace("\"", "\\\"") + "\"");
            if (propertiesIterator.hasNext()) {
                ConsoleWriter.write(",");
            }
        }
        ConsoleWriter.write("\n" + indent0 + "}");
    }

    /**
     * Returns the value of the given property formatted for debug output. For
     * example for layout processors, only the class' simple name instead of the
     * qualified name is returned.
     *
     * @param property
     *            the property whose value to get.
     * @param value
     *            the value to format.
     * @return the formatted value.
     */
    @SuppressWarnings("unchecked")
    private static String getValueRepresentation(final IProperty<?> property, final Object value) {
        if (property.getId().equals(InternalProperties.PROCESSORS.getId())) {
            final Iterator<ILayoutProcessor> processors = ((List<ILayoutProcessor>) value).iterator();
            final StringBuffer result = new StringBuffer("[");
            while (processors.hasNext()) {
                final ILayoutProcessor processor = processors.next();
                result.append(processor.getClass().getSimpleName());
                if (processors.hasNext()) {
                    result.append(", ");
                }
            }
            result.append("]");
            return result.toString();
        }
        return value.toString();
    }

    /**
     * Returns the name of the node. The layer and index in the layer is added
     * in parentheses. If its a dummy node, it get a suffix
     * {@code DUMMY: <NodeType>}.
     *
     * @param node
     *            the node whose name to get.
     * @param layer
     *            the layer of the node.
     * @param index
     *            the index inside the layer.
     * @return the nodes name.
     */
    private static String getNodeName(final LNode node, final int layer, final int index) {
        String name = "";
        if (node.getNodeType() == NodeType.NORMAL) {
            // Normal nodes display their name, if any
            if (node.getName() != null) {
                name = node.getName().replace("\"", "\\\"");
            }
            name += " (" + layer + "," + index + ")";
        } else {
            // Dummy nodes show their name (if set), or their node ID
            if (node.getName() != null) {
                name = node.getName().replace("\"", "\\\"");
            } else {
                name = "n_" + node.id;
            }
            if (node.getNodeType() == NodeType.NORTH_SOUTH_PORT) {
                final Object origin = node.getProperty(InternalProperties.ORIGIN);
                if (origin instanceof LNode) {
                    name += "(" + ((LNode) origin).toString() + ")";
                }
            }
            name += " (" + layer + "," + index + ")";
            name += "\\n DUMMY: " + node.getNodeType().name();
        }
        return name;
    }

    /**
     * Creates a ConsoleWriter for debug output.
     *
     * @param layeredGraph
     *            the layered graph.
     * @return a file ConsoleWriter for debug output.
     * @throws IOException
     *             if creating the output file fails.
     */
    private static ConsoleWriter createConsoleWriter(final LGraph layeredGraph) throws IOException {
        final String debugFileName = getDebugOutputFileBaseName(layeredGraph) + "linseg-dep";
        return new ConsoleWriter(debugFileName + ".dot");
    }

    /**
     * Creates a ConsoleWriter for the given graph. The file name to be written
     * to is assembled from the graph's hash code and the slot index.
     *
     * @param graph
     *            the graph to be written.
     * @param slotIndex
     *            the slot before whose execution the graph is written.
     * @param name
     *            the name the slot before whose execution the graph is written.
     * @return file ConsoleWriter.
     * @throws IOException
     *             if anything goes wrong.
     */
    private static ConsoleWriter createConsoleWriter(final LGraph graph, final int slotIndex, final String name)
            throws IOException {

        final String debugFileName = getDebugOutputFileBaseName(graph) + "fulldebug-slot" + slotIndex + "-" + name;
        return new ConsoleWriter(debugFileName + ".json");
    }

    /**
     * Create a ConsoleWriter for debug output.
     *
     * @param layeredGraph
     *            the layered graph
     * @param layerIndex
     *            the currently processed layer's index
     * @param debugPrefix
     *            prefix of debug output files
     * @param label
     *            a label to append to the output files
     * @return a file ConsoleWriter for debug output
     * @throws IOException
     *             if creating the output file fails
     */
    private static ConsoleWriter createConsoleWriter(final LGraph layeredGraph, final int layerIndex,
            final String debugPrefix, final String label) throws IOException {
        final String debugFileName = getDebugOutputFileBaseName(layeredGraph) + debugPrefix + "-l" + layerIndex
                + "-" + label;
        return new ConsoleWriter(debugFileName + ".json");
    }

    /**
     * Returns the beginning of the file name used for debug output graphs while
     * layouting the given layered graph. This will look something like
     * {@code "143293-"}.
     *
     * @param graph
     *            the graph to return the base debug file name for.
     * @return the base debug file name for the given graph.
     */
    private static String getDebugOutputFileBaseName(final LGraph graph) {
        return "graph-";
    }

}