public void changeEdgeNode(int direction, StatEdge edge, Statement value) {

    Map<Integer, List<StatEdge>> mapEdges =
        direction == DIRECTION_BACKWARD ? mapPredEdges : mapSuccEdges;
    Map<Integer, List<Statement>> mapStates =
        direction == DIRECTION_BACKWARD ? mapPredStates : mapSuccStates;

    int type = edge.getType();

    int[] arrtypes;
    if (type == StatEdge.TYPE_EXCEPTION) {
      arrtypes = new int[] {STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
    } else {
      arrtypes = new int[] {STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
    }

    for (int edgetype : arrtypes) {
      List<StatEdge> lst = mapEdges.get(edgetype);
      if (lst != null) {
        int index = lst.indexOf(edge);
        if (index >= 0) {
          mapStates.get(edgetype).set(index, value);
        }
      }
    }

    if (direction == DIRECTION_BACKWARD) {
      edge.setSource(value);
    } else {
      edge.setDestination(value);
    }
  }
  // TODO: make obsolete and remove
  public void removeAllSuccessors(Statement stat) {

    if (stat == null) {
      return;
    }

    for (StatEdge edge : getAllSuccessorEdges()) {
      if (edge.getDestination() == stat) {
        removeSuccessor(edge);
      }
    }
  }
  public void removeSuccessor(StatEdge edge) {

    if (edge == null) {
      return;
    }

    removeEdgeInternal(DIRECTION_FORWARD, edge);

    if (edge.closure != null) {
      edge.closure.getLabelEdges().remove(edge);
    }

    if (edge.getDestination() != null) { // TODO: redundant?
      edge.getDestination().removePredecessor(edge);
    }
  }
  public void addLabeledEdge(StatEdge edge) {

    if (edge.closure != null) {
      edge.closure.getLabelEdges().remove(edge);
    }
    edge.closure = this;
    this.getLabelEdges().add(edge);
  }
  public void addSuccessor(StatEdge edge) {
    addEdgeInternal(DIRECTION_FORWARD, edge);

    if (edge.closure != null) {
      edge.closure.getLabelEdges().add(edge);
    }

    edge.getDestination().addPredecessor(edge);
  }
  private void addEdgeDirectInternal(int direction, StatEdge edge, int edgetype) {

    Map<Integer, List<StatEdge>> mapEdges =
        direction == DIRECTION_BACKWARD ? mapPredEdges : mapSuccEdges;
    Map<Integer, List<Statement>> mapStates =
        direction == DIRECTION_BACKWARD ? mapPredStates : mapSuccStates;

    List<StatEdge> lst = mapEdges.get(edgetype);
    if (lst == null) {
      mapEdges.put(edgetype, lst = new ArrayList<StatEdge>());
    }
    lst.add(edge);

    List<Statement> lstStates = mapStates.get(edgetype);
    if (lstStates == null) {
      mapStates.put(edgetype, lstStates = new ArrayList<Statement>());
    }
    lstStates.add(direction == DIRECTION_BACKWARD ? edge.getSource() : edge.getDestination());
  }
  private static void addToReversePostOrderListIterative(Statement root, List<Statement> lst) {

    LinkedList<Statement> stackNode = new LinkedList<Statement>();
    LinkedList<Integer> stackIndex = new LinkedList<Integer>();
    HashSet<Statement> setVisited = new HashSet<Statement>();

    stackNode.add(root);
    stackIndex.add(0);

    while (!stackNode.isEmpty()) {

      Statement node = stackNode.getLast();
      int index = stackIndex.removeLast();

      setVisited.add(node);

      List<StatEdge> lstEdges = node.getAllSuccessorEdges();

      for (; index < lstEdges.size(); index++) {
        StatEdge edge = lstEdges.get(index);
        Statement succ = edge.getDestination();

        if (!setVisited.contains(succ)
            && (edge.getType() == StatEdge.TYPE_REGULAR
                || edge.getType() == StatEdge.TYPE_EXCEPTION)) { // TODO: edge filter?

          stackIndex.add(index + 1);

          stackNode.add(succ);
          stackIndex.add(0);

          break;
        }
      }

      if (index == lstEdges.size()) {
        lst.add(0, node);

        stackNode.removeLast();
      }
    }
  }
  public void changeEdgeType(int direction, StatEdge edge, int newtype) {

    int oldtype = edge.getType();
    if (oldtype == newtype) {
      return;
    }

    if (oldtype == StatEdge.TYPE_EXCEPTION || newtype == StatEdge.TYPE_EXCEPTION) {
      throw new RuntimeException("Invalid edge type!");
    }

    removeEdgeDirectInternal(direction, edge, oldtype);
    addEdgeDirectInternal(direction, edge, newtype);

    if (direction == DIRECTION_FORWARD) {
      edge.getDestination().changeEdgeType(DIRECTION_BACKWARD, edge, newtype);
    }

    edge.setType(newtype);
  }
  public HashSet<Statement> buildContinueSet() {
    continueSet.clear();

    for (Statement st : stats) {
      continueSet.addAll(st.buildContinueSet());
      if (st != first) {
        continueSet.remove(st.getBasichead());
      }
    }

    for (StatEdge edge : getEdges(StatEdge.TYPE_CONTINUE, DIRECTION_FORWARD)) {
      continueSet.add(edge.getDestination().getBasichead());
    }

    if (type == TYPE_DO) {
      continueSet.remove(first.getBasichead());
    }

    return continueSet;
  }
  private static void addToPostReversePostOrderList(
      Statement stat, List<Statement> lst, HashSet<Statement> setVisited) {

    if (setVisited.contains(
        stat)) { // because of not considered exception edges, s. isExitComponent. Should be
                 // rewritten, if possible.
      return;
    }
    setVisited.add(stat);

    for (StatEdge prededge :
        stat.getEdges(StatEdge.TYPE_REGULAR | StatEdge.TYPE_EXCEPTION, DIRECTION_BACKWARD)) {
      Statement pred = prededge.getSource();
      if (!setVisited.contains(pred)) {
        addToPostReversePostOrderList(pred, lst, setVisited);
      }
    }

    lst.add(0, stat);
  }
  public void replaceStatement(Statement oldstat, Statement newstat) {

    for (StatEdge edge : oldstat.getAllPredecessorEdges()) {
      oldstat.removePredecessor(edge);
      edge.getSource().changeEdgeNode(DIRECTION_FORWARD, edge, newstat);
      newstat.addPredecessor(edge);
    }

    for (StatEdge edge : oldstat.getAllSuccessorEdges()) {
      oldstat.removeSuccessor(edge);
      edge.setSource(newstat);
      newstat.addSuccessor(edge);
    }

    int statindex = stats.getIndexByKey(oldstat.id);
    stats.removeWithKey(oldstat.id);
    stats.addWithKeyAndIndex(statindex, newstat, newstat.id);

    newstat.setParent(this);
    newstat.post = oldstat.post;

    if (first == oldstat) {
      first = newstat;
    }

    List<StatEdge> lst = new ArrayList<StatEdge>(oldstat.getLabelEdges());

    for (int i = lst.size() - 1; i >= 0; i--) {
      StatEdge edge = lst.get(i);
      if (edge.getSource() != newstat) {
        newstat.addLabeledEdge(edge);
      } else {
        if (this == edge.getDestination() || this.containsStatementStrict(edge.getDestination())) {
          edge.closure = null;
        } else {
          this.addLabeledEdge(edge);
        }
      }
    }

    oldstat.getLabelEdges().clear();
  }
  private void removeEdgeInternal(int direction, StatEdge edge) {

    int type = edge.getType();

    int[] arrtypes;
    if (type == StatEdge.TYPE_EXCEPTION) {
      arrtypes = new int[] {STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
    } else {
      arrtypes = new int[] {STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
    }

    for (int edgetype : arrtypes) {
      removeEdgeDirectInternal(direction, edge, edgetype);
    }
  }
  public void collapseNodesToStatement(Statement stat) {

    Statement head = stat.getFirst();
    Statement post = stat.getPost();

    VBStyleCollection<Statement, Integer> setNodes = stat.getStats();

    // post edges
    if (post != null) {
      for (StatEdge edge : post.getEdges(STATEDGE_DIRECT_ALL, DIRECTION_BACKWARD)) {
        if (stat.containsStatementStrict(edge.getSource())) {
          edge.getSource().changeEdgeType(DIRECTION_FORWARD, edge, StatEdge.TYPE_BREAK);
          stat.addLabeledEdge(edge);
        }
      }
    }

    // regular head edges
    for (StatEdge prededge : head.getAllPredecessorEdges()) {

      if (prededge.getType() != StatEdge.TYPE_EXCEPTION
          && stat.containsStatementStrict(prededge.getSource())) {
        prededge.getSource().changeEdgeType(DIRECTION_FORWARD, prededge, StatEdge.TYPE_CONTINUE);
        stat.addLabeledEdge(prededge);
      }

      head.removePredecessor(prededge);
      prededge.getSource().changeEdgeNode(DIRECTION_FORWARD, prededge, stat);
      stat.addPredecessor(prededge);
    }

    if (setNodes.containsKey(first.id)) {
      first = stat;
    }

    // exception edges
    Set<Statement> setHandlers =
        new HashSet<Statement>(head.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD));
    for (Statement node : setNodes) {
      setHandlers.retainAll(node.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD));
    }

    if (!setHandlers.isEmpty()) {

      for (StatEdge edge : head.getEdges(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)) {
        Statement handler = edge.getDestination();

        if (setHandlers.contains(handler)) {
          if (!setNodes.containsKey(handler.id)) {
            stat.addSuccessor(new StatEdge(stat, handler, edge.getExceptions()));
          }
        }
      }

      for (Statement node : setNodes) {
        for (StatEdge edge : node.getEdges(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)) {
          if (setHandlers.contains(edge.getDestination())) {
            node.removeSuccessor(edge);
          }
        }
      }
    }

    if (post != null
        && !stat.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)
            .contains(post)) { // TODO: second condition redundant?
      stat.addSuccessor(new StatEdge(StatEdge.TYPE_REGULAR, stat, post));
    }

    // adjust statement collection
    for (Statement st : setNodes) {
      stats.removeWithKey(st.id);
    }

    stats.addWithKey(stat, stat.id);

    stat.setAllParent();
    stat.setParent(this);

    stat.buildContinueSet();
    // monitorenter and monitorexit
    stat.buildMonitorFlags();

    if (stat.type == TYPE_SWITCH) {
      // special case switch, sorting leaf nodes
      ((SwitchStatement) stat).sortEdgesAndNodes();
    }
  }