// Path: src/main/java/biz/paluch/spinach/impl/HelloClusterSocketAddressSupplier.java
// public class HelloClusterSocketAddressSupplier extends ClusterAwareNodeSupport implements SocketAddressSupplier,
//         ConnectionAware {
// 
//     protected final SocketAddressSupplier bootstrap;
//     protected RoundRobin<DisqueNode> roundRobin;
// 
//     /**
//      * 
//      * @param bootstrap bootstrap/fallback {@link SocketAddressSupplier} for bootstrapping before any communication is done.
//      */
//     public HelloClusterSocketAddressSupplier(SocketAddressSupplier bootstrap) {
//         this.bootstrap = bootstrap;
//     }
// 
//     @Override
//     public SocketAddress get() {
// 
//         if (getNodes().isEmpty()) {
//             return bootstrap.get();
//         }
// 
//         DisqueNode disqueNode = roundRobin.next();
//         return InetSocketAddress.createUnresolved(disqueNode.getAddr(), disqueNode.getPort());
//     }
// 
//     @Override
//     public <K, V> void setConnection(DisqueConnection<K, V> disqueConnection) {
//         super.setConnection(disqueConnection);
//         reloadNodes();
//     }
// 
//     @Override
//     public void reloadNodes() {
//         super.reloadNodes();
//         roundRobin = new RoundRobin<DisqueNode>(getNodes());
//     }
// 
// }
// 
// Path: src/main/java/biz/paluch/spinach/impl/RoundRobin.java
// public class RoundRobin<V> {
// 
//     protected final Collection<? extends V> collection;
//     protected V offset;
// 
//     public RoundRobin(Collection<? extends V> collection) {
//         this(collection, null);
//     }
// 
//     public RoundRobin(Collection<? extends V> collection, V offset) {
//         this.collection = collection;
//         this.offset = offset;
//     }
// 
//     /**
//      * Returns the next item.
//      * 
//      * @return the next item
//      */
//     public V next() {
//         if (offset != null) {
//             boolean accept = false;
//             for (V element : collection) {
//                 if (element == offset) {
//                     accept = true;
//                     continue;
//                 }
// 
//                 if (accept) {
//                     return offset = element;
//                 }
//             }
//         }
// 
//         return offset = collection.iterator().next();
//     }
// 
// }
// 
// Path: src/main/java/biz/paluch/spinach/impl/SocketAddressSupplier.java
// public interface SocketAddressSupplier extends Supplier<SocketAddress> {
// 
// }


import java.net.InetSocketAddress;
import java.net.SocketAddress;
import com.lambdaworks.redis.internal.LettuceAssert;
import biz.paluch.spinach.impl.HelloClusterSocketAddressSupplier;
import biz.paluch.spinach.impl.RoundRobin;
import biz.paluch.spinach.impl.SocketAddressSupplier;
    /**
     * Set the id prefix of the preferred node.
     *
     * @param preferredNodeIdPrefix the id prefix of the preferred node
     */
    public void setPreferredNodeIdPrefix(String preferredNodeIdPrefix) {
        LettuceAssert.notNull(preferredNodeIdPrefix, "preferredNodeIdPrefix must not be null");
        boolean resetRoundRobin = false;

        if (this.preferredNodeIdPrefix == null || !preferredNodeIdPrefix.equals(this.preferredNodeIdPrefix)) {
            resetRoundRobin = true;
        }

        this.preferredNodeIdPrefix = preferredNodeIdPrefix;

        if (resetRoundRobin) {
            resetRoundRobin(preferredNodeIdPrefix);
        }
    }

    /**
     * Reset the {@link RoundRobin} to start with the node matching the {@code preferredNodeIdPrefix}.
     *
     * @param preferredNodeIdPrefix the id prefix of the preferred node
     */
    private void resetRoundRobin(String preferredNodeIdPrefix) {
        DisqueNode previous = null; // remember the previous node because the offset is a marker to start with the next
        // element
        for (DisqueNode disqueNode : getNodes()) {
            if (disqueNode.getNodeId().startsWith(preferredNodeIdPrefix)) {
// Path: src/main/java/biz/paluch/spinach/impl/HelloClusterSocketAddressSupplier.java
// public class HelloClusterSocketAddressSupplier extends ClusterAwareNodeSupport implements SocketAddressSupplier,
//         ConnectionAware {
// 
//     protected final SocketAddressSupplier bootstrap;
//     protected RoundRobin<DisqueNode> roundRobin;
// 
//     /**
//      * 
//      * @param bootstrap bootstrap/fallback {@link SocketAddressSupplier} for bootstrapping before any communication is done.
//      */
//     public HelloClusterSocketAddressSupplier(SocketAddressSupplier bootstrap) {
//         this.bootstrap = bootstrap;
//     }
// 
//     @Override
//     public SocketAddress get() {
// 
//         if (getNodes().isEmpty()) {
//             return bootstrap.get();
//         }
// 
//         DisqueNode disqueNode = roundRobin.next();
//         return InetSocketAddress.createUnresolved(disqueNode.getAddr(), disqueNode.getPort());
//     }
// 
//     @Override
//     public <K, V> void setConnection(DisqueConnection<K, V> disqueConnection) {
//         super.setConnection(disqueConnection);
//         reloadNodes();
//     }
// 
//     @Override
//     public void reloadNodes() {
//         super.reloadNodes();
//         roundRobin = new RoundRobin<DisqueNode>(getNodes());
//     }
// 
// }
// 
// Path: src/main/java/biz/paluch/spinach/impl/RoundRobin.java
// public class RoundRobin<V> {
// 
//     protected final Collection<? extends V> collection;
//     protected V offset;
// 
//     public RoundRobin(Collection<? extends V> collection) {
//         this(collection, null);
//     }
// 
//     public RoundRobin(Collection<? extends V> collection, V offset) {
//         this.collection = collection;
//         this.offset = offset;
//     }
// 
//     /**
//      * Returns the next item.
//      * 
//      * @return the next item
//      */
//     public V next() {
//         if (offset != null) {
//             boolean accept = false;
//             for (V element : collection) {
//                 if (element == offset) {
//                     accept = true;
//                     continue;
//                 }
// 
//                 if (accept) {
//                     return offset = element;
//                 }
//             }
//         }
// 
//         return offset = collection.iterator().next();
//     }
// 
// }
// 
// Path: src/main/java/biz/paluch/spinach/impl/SocketAddressSupplier.java
// public interface SocketAddressSupplier extends Supplier<SocketAddress> {
// 
// }


// Path: src/main/java/biz/paluch/spinach/cluster/NodeIdAwareSocketAddressSupplier.java
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import com.lambdaworks.redis.internal.LettuceAssert;
import biz.paluch.spinach.impl.HelloClusterSocketAddressSupplier;
import biz.paluch.spinach.impl.RoundRobin;
import biz.paluch.spinach.impl.SocketAddressSupplier;

    /**
     * Set the id prefix of the preferred node.
     *
     * @param preferredNodeIdPrefix the id prefix of the preferred node
     */
    public void setPreferredNodeIdPrefix(String preferredNodeIdPrefix) {
        LettuceAssert.notNull(preferredNodeIdPrefix, "preferredNodeIdPrefix must not be null");
        boolean resetRoundRobin = false;

        if (this.preferredNodeIdPrefix == null || !preferredNodeIdPrefix.equals(this.preferredNodeIdPrefix)) {
            resetRoundRobin = true;
        }

        this.preferredNodeIdPrefix = preferredNodeIdPrefix;

        if (resetRoundRobin) {
            resetRoundRobin(preferredNodeIdPrefix);
        }
    }

    /**
     * Reset the {@link RoundRobin} to start with the node matching the {@code preferredNodeIdPrefix}.
     *
     * @param preferredNodeIdPrefix the id prefix of the preferred node
     */
    private void resetRoundRobin(String preferredNodeIdPrefix) {
        DisqueNode previous = null; // remember the previous node because the offset is a marker to start with the next
        // element
        for (DisqueNode disqueNode : getNodes()) {
            if (disqueNode.getNodeId().startsWith(preferredNodeIdPrefix)) {
                roundRobin = new RoundRobin<DisqueNode>(getNodes(), previous);