@SuppressWarnings("unchecked")
  public static <NodeType extends ZyGraphNode<?>> void selectPath(
      final AbstractZyGraph<NodeType, ?> graph,
      final ArrayList<NodeType> alreadySelectedNodes,
      final NodeType newlySelectedNode) {
    final Function<NodeType, Node> function =
        new Function<NodeType, Node>() {
          @Override
          public Node apply(final NodeType input) {
            return input.getNode();
          }
        };

    final Collection<Node> foo = Collections2.transform(alreadySelectedNodes, function);

    final NodeList startNodes = new NodeList(foo.iterator());
    final NodeList endNodes = new NodeList(newlySelectedNode.getNode());

    final Set<Node> startSuccSet = new HashSet<Node>();
    final NodeList[] nodeListsStartSucc =
        Bfs.getLayers(
            graph.getGraph(),
            startNodes,
            Bfs.DIRECTION_SUCCESSOR,
            graph.getGraph().createNodeMap(),
            0);
    for (final NodeList nodeList : nodeListsStartSucc) {
      startSuccSet.addAll(nodeList);
    }
    final Set<Node> endPredSet = new HashSet<Node>();
    final NodeList[] nodeListsEndPred =
        Bfs.getLayers(
            graph.getGraph(),
            endNodes,
            Bfs.DIRECTION_PREDECESSOR,
            graph.getGraph().createNodeMap(),
            0);
    for (final NodeList nodeList : nodeListsEndPred) {
      endPredSet.addAll(nodeList);
    }

    final SetView<Node> startBeforeEndSetView = Sets.intersection(startSuccSet, endPredSet);
    if (!startBeforeEndSetView.isEmpty()) {
      for (final Node node : startBeforeEndSetView) {
        graph.getGraph().setSelected(node, true);
      }
    }

    final Set<Node> startPredSet = new HashSet<Node>();
    final NodeList[] nodeListsStartPred =
        Bfs.getLayers(
            graph.getGraph(),
            startNodes,
            Bfs.DIRECTION_PREDECESSOR,
            graph.getGraph().createNodeMap(),
            0);
    for (final NodeList nodeList : nodeListsStartPred) {
      startPredSet.addAll(nodeList);
    }

    final Set<Node> endSuccSet = new HashSet<Node>();
    final NodeList[] nodeListsEndSucc =
        Bfs.getLayers(
            graph.getGraph(),
            endNodes,
            Bfs.DIRECTION_SUCCESSOR,
            graph.getGraph().createNodeMap(),
            0);
    for (final NodeList nodeList : nodeListsEndSucc) {
      endSuccSet.addAll(nodeList);
    }

    final SetView<Node> endBeforeStartSetView = Sets.intersection(startPredSet, endSuccSet);
    if (!endBeforeStartSetView.isEmpty()) {
      for (final Node node : endBeforeStartSetView) {
        graph.getGraph().setSelected(node, true);
      }
    }
  }
Function which handles the selection of nodes in a path finding scenario. The function performs
four BFS runs: BFS 1 searches for all successors of the start nodes. BFS 2 searches for all
predecessors of the end nodes. BFS 2 searches for all predecessors of the start nodes. BFS 4
searches for all successors of the end nodes.

<p>These four BFS runs are used in two sets: Set 1 is intersect of nodes reached through (BFS
1, BFS 2). Set 2 is intersect of nodes reached through (BFS 3, BFS 4).

<p>Therefore Set 1 represents all nodes on paths if the set of start nodes contains parents of
the newly selected node and Set 2 represents all nodes on paths if the set of start nodes
contains child nodes of the newly selected node.

@param graph The graph in which the selection takes place.
@param alreadySelectedNodes The List of nodes already selected.
@param newlySelectedNode The node which is newly selected.
java/zylib/src/main/java/com/google/security/zynamics/zylib/yfileswrap/gui/zygraph/editmode/helpers/CGraphSelector.java