// 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;
/*
 * Copyright 2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package biz.paluch.spinach.cluster;




/**
 * This mechanism allows to set a preferred node Id for next {@code HELLO} handshake. If the
 * {@link #setPreferredNodeIdPrefix(String)} is set, the selection mechanism tries to provide a {@link SocketAddress} from the
 * preferred node.
 *
 * @see biz.paluch.spinach.impl.HelloClusterSocketAddressSupplier
 */
public class NodeIdAwareSocketAddressSupplier extends HelloClusterSocketAddressSupplier {
    private transient String currentNodeId;
    private transient InetSocketAddress currentSocketAddress;
    private String preferredNodeIdPrefix;

    /**
     *
     * @param bootstrap bootstrap/fallback {@link SocketAddressSupplier} for bootstrapping before any communication is done.
     */
// 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;

/*
 * Copyright 2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package biz.paluch.spinach.cluster;




/**
 * This mechanism allows to set a preferred node Id for next {@code HELLO} handshake. If the
 * {@link #setPreferredNodeIdPrefix(String)} is set, the selection mechanism tries to provide a {@link SocketAddress} from the
 * preferred node.
 *
 * @see biz.paluch.spinach.impl.HelloClusterSocketAddressSupplier
 */
public class NodeIdAwareSocketAddressSupplier extends HelloClusterSocketAddressSupplier {
    private transient String currentNodeId;
    private transient InetSocketAddress currentSocketAddress;
    private String preferredNodeIdPrefix;

    /**
     *
     * @param bootstrap bootstrap/fallback {@link SocketAddressSupplier} for bootstrapping before any communication is done.
     */
    public NodeIdAwareSocketAddressSupplier(SocketAddressSupplier bootstrap) {