class CaseManagementDrawCommand extends AbstractCanvasCommand {

    @SuppressWarnings("unchecked")
    void sortNodes(final Diagram<Graph<DefinitionSet, Node>, Metadata> diagram) {
        List<Node<View<?>, Edge>> nodes = StreamSupport.stream(diagram.getGraph().nodes().spliterator(), false)
                .map(n -> (Node<View<?>, Edge>) n).collect(Collectors.toList());

        nodes.stream()
                .filter(node -> node.getContent().getDefinition() instanceof CaseManagementDiagram)
                .findAny().ifPresent(root -> {

            // Sort the Stages by the SequenceFlow from StartNoneEvent to EndNoneEvent of the diagram
            Map<Node<View<?>, Edge>, Edge> childNodes = root.getOutEdges().stream()
                    .filter(childPredicate()).collect(Collectors.toMap(e -> (Node<View<?>, Edge>) e.getTargetNode(), identity()));

            Node<View<?>, Edge> startNode = root.getOutEdges().stream().map(Edge::getTargetNode)
                    .filter(n -> ((Node<View<?>, Edge>) n).getContent().getDefinition() instanceof StartNoneEvent).findAny()
                    .orElseGet(() -> childNodes.keySet().stream().filter(n -> n.getInEdges().size() == 1).findAny().orElse(null));

            if (startNode != null) {
                Node<View<?>, Edge> node = startNode;
                List<Edge> childEdges = new LinkedList<>();

                do {
                    childEdges.add(0, childNodes.get(node));
                    node = node.getOutEdges().stream().filter(sequencePredicate())
                            .map(Edge::getTargetNode).filter(childNodes::containsKey).findAny().orElse(null);
                } while (node != null);

                childEdges.forEach(e -> root.getOutEdges().remove(e));
                childEdges.forEach(e -> root.getOutEdges().add(0, e));
            }

            // Sort the child nodes in Stages by their coordinates
            Stream<Node<View<?>, Edge>> stageStream = root.getOutEdges().stream().filter(childPredicate()).map(Edge::getTargetNode);
            stageStream.filter(CaseManagementCommandUtil::isStageNode)
                    .forEach(n -> {
                        List<Edge> edges = n.getOutEdges().stream().filter(childPredicate()).collect(Collectors.toList());
                        Collections.sort(edges, (e1, e2) -> {
                            final double y1 = ((Node<View, Edge>) e1.getTargetNode()).getContent().getBounds().getY();
                            final double y2 = ((Node<View, Edge>) e2.getTargetNode()).getContent().getBounds().getY();
                            return Double.compare(y2, y1);
                        });

                        edges.forEach(e -> n.getOutEdges().remove(e));
                        edges.forEach(e -> n.getOutEdges().add(0, e));
                    });
        });
    }

    public  CaseManagementDrawCommand(final ChildrenTraverseProcessor childrenTraverseProcessor);

}