class FreeIpaTopologyService {

    @VisibleForTesting
    Set<UnorderedPair> generateTopology(Set<String> nodes) {
        LOGGER.debug("Generating topology for FreeIPA [{}}", nodes);
        Map<String, Integer> connectionRemaining = nodes.stream()
                .sorted()
                .collect(Collectors.toMap(n -> n, n -> MAX_REPLICATION_CONNECTIONS, (k, v) -> v, LinkedHashMap::new));
        Set<UnorderedPair> ret = new HashSet<>();
        Iterator<String> itr2 = null;
        for (Map.Entry<String, Integer> entry : connectionRemaining.entrySet()) {
            String node = entry.getKey();
            Integer remainingConnectionsForNode = entry.getValue();
            for (int i = remainingConnectionsForNode; i > 0; i--) {
                // Note: It is not possible for itr2 to reference on object with 0 remaining connections
                // because itr2 is after the node iterator and the node iterator is checked for
                // remaining connections.
                if (itr2 == null || !itr2.hasNext()) {
                    itr2 = getIteratorAfterCurrentNode(node, connectionRemaining.keySet());
                    if (!itr2.hasNext()) {
                        break;
                    }
                }
                String node2 = itr2.next();
                connectionRemaining.put(node2, connectionRemaining.get(node2) - 1);
                ret.add(new UnorderedPair(node, node2));
            }
        }
        return ret;
    }

}