@SuppressWarnings("rawtypes")
  private static void removeMergeBeforeFlatten(StreamGraph streamGraph) {
    Set<Entry<Integer, StreamInvokable<?, ?>>> invokables = streamGraph.getInvokables();
    List<Integer> flatteners = new ArrayList<Integer>();

    for (Entry<Integer, StreamInvokable<?, ?>> entry : invokables) {
      if (entry.getValue() instanceof WindowFlattener) {
        flatteners.add(entry.getKey());
      }
    }

    for (Integer flattener : flatteners) {
      // Flatteners should have exactly one input
      Integer input = streamGraph.getInEdges(flattener).get(0);

      // Check whether the flatten is applied after a merge
      if (streamGraph.getInvokable(input) instanceof WindowMerger) {

        // Mergers should have exactly one input
        Integer mergeInput = streamGraph.getInEdges(input).get(0);
        streamGraph.setEdge(
            mergeInput, flattener, new DistributePartitioner(true), 0, new ArrayList<String>());

        // If the merger is only connected to the flattener we delete it
        // completely, otherwise we only remove the edge
        if (streamGraph.getOutEdges(input).size() > 1) {
          streamGraph.removeEdge(input, flattener);
        } else {
          streamGraph.removeVertex(input);
        }

        streamGraph.setParallelism(flattener, streamGraph.getParallelism(mergeInput));
      }
    }
  }
  private static void replaceDiscretizer(
      StreamGraph streamGraph, Integer toReplace, Integer replaceWith) {
    // Convert to array to create a copy
    List<Integer> outEdges = new ArrayList<Integer>(streamGraph.getOutEdges(toReplace));

    int numOutputs = outEdges.size();

    // Reconnect outputs
    for (int i = 0; i < numOutputs; i++) {
      Integer output = outEdges.get(i);

      streamGraph.setEdge(
          replaceWith,
          output,
          streamGraph.getOutPartitioner(toReplace, output),
          0,
          new ArrayList<String>());
      streamGraph.removeEdge(toReplace, output);
    }

    List<Integer> inEdges = new ArrayList<Integer>(streamGraph.getInEdges(toReplace));
    // Remove inputs
    for (Integer input : inEdges) {
      streamGraph.removeEdge(input, toReplace);
    }

    streamGraph.removeVertex(toReplace);
  }