Networks { public static <NodeT, EdgeT> void replaceDirectedNetworkNodes( MutableNetwork<NodeT, EdgeT> network, Function<NodeT, NodeT> function) { checkArgument(network.isDirected(), "Only directed networks are supported, given %s", network); checkArgument( !network.allowsSelfLoops(), "Only networks without self loops are supported, given %s", network); Map<NodeT, NodeT> oldNodesToNewNodes = new HashMap<>(network.nodes().size()); for (NodeT currentNode : network.nodes()) { NodeT newNode = function.apply(currentNode); if (!currentNode.equals(newNode)) { oldNodesToNewNodes.put(currentNode, newNode); } } for (Map.Entry<NodeT, NodeT> entry : oldNodesToNewNodes.entrySet()) { NodeT oldNode = entry.getKey(); NodeT newNode = entry.getValue(); network.addNode(newNode); for (NodeT predecessor : ImmutableSet.copyOf(network.predecessors(oldNode))) { for (EdgeT edge : ImmutableSet.copyOf(network.edgesConnecting(predecessor, oldNode))) { network.removeEdge(edge); network.addEdge(predecessor, newNode, edge); } } for (NodeT successor : ImmutableSet.copyOf(network.successors(oldNode))) { for (EdgeT edge : ImmutableSet.copyOf(network.edgesConnecting(oldNode, successor))) { network.removeEdge(edge); network.addEdge(newNode, successor, edge); } } network.removeNode(oldNode); } } private  Networks(); static void replaceDirectedNetworkNodes(
      MutableNetwork<NodeT, EdgeT> network, Function<NodeT, NodeT> function); static Set<NodeT> reachableNodes(
      Network<NodeT, EdgeT> network, Set<NodeT> startNodes, Set<NodeT> endNodes); static Iterable<NodeT> topologicalOrder(Network<NodeT, ?> network); static Iterable<NodeT> topologicalOrder(
      Network<NodeT, EdgeT> network, Comparator<NodeT> nodeOrder); static String toDot(Network<NodeT, EdgeT> network); static List<List<NodeT>> allPathsFromRootsToLeaves(
      Network<NodeT, EdgeT> network);  }
@Test public void testNodeReplacementInEmptyNetwork() { MutableNetwork<String, String> network = createEmptyNetwork(); Networks.replaceDirectedNetworkNodes(network, String::toLowerCase); assertThat(network.nodes(), empty()); }
@Test public void testNodeReplacement() { Function<String, String> function = input -> { if ("E".equals(input) || "J".equals(input) || "M".equals(input) || "O".equals(input)) { return input.toLowerCase(); } checkArgument( !input.toLowerCase().equals(input), "All inputs should be in upper case, got %s. " + "This may indicate calling the function on multiple inputs", input); return input; }; MutableNetwork<String, String> network = createNetwork(); Networks.replaceDirectedNetworkNodes(network, function); MutableNetwork<String, String> originalNetwork = createNetwork(); for (String node : originalNetwork.nodes()) { assertEquals( originalNetwork.successors(node).stream() .map(function) .collect(Collectors.toCollection(HashSet::new)), network.successors(function.apply(node))); } assertEquals( network.nodes(), originalNetwork.nodes().stream() .map(function) .collect(Collectors.toCollection(HashSet::new))); }