// Path: trpc-client/src/main/java/com/github/sofn/trpc/client/config/ServiceKey.java
// @Data
// @AllArgsConstructor
// public class ServiceKey {
//     private String remoteKey;
//     private String service;
// }
// 
// Path: trpc-client/src/main/java/com/github/sofn/trpc/client/config/TrpcServiceNode.java
// @Getter
// @ToString
// @AllArgsConstructor
// @EqualsAndHashCode(of = {"ip", "port"})
// public class TrpcServiceNode implements Comparable<TrpcServiceNode> {
//     private String ip;
//     private int port;
//     private int weight;
//     private int timeout;
// 
//     public static List<TrpcServiceNode> fromRegistryConfig(RegistryConfig registryConfig) {
//         ThriftServerInfo server = registryConfig.getServerInfo();
//         return registryConfig.getServers().stream()
//                 .map(s -> new TrpcServiceNode(server.getIp(), server.getPort(), s.getWeight(), s.getTimeout()))
//                 .collect(Collectors.toList());
//     }
// 
//     public ThriftServerInfo toThriftServerInfo() {
//         return new ThriftServerInfo(this.ip, this.port);
//     }
// 
//     @Override
//     public int compareTo(TrpcServiceNode other) {
//         int result = this.ip.compareTo(other.ip);
//         return result != 0 ? result : this.port - other.port;
//     }
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/AbstractMonitor.java
// public abstract class AbstractMonitor {
// 
//     /**
//      * 返回remoteKey下所有节点数据，并监控变化
//      *
//      * @param monitor 消息listener
//      * @return 返回现在的数据
//      */
//     public abstract List<RegistryConfig> monitorRemoteKey(RegistryConfigListener monitor);
// 
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/config/RegistryConfig.java
// @Setter
// @Getter
// @Builder
// @EqualsAndHashCode(of = {"serverInfo", "appKey"}, callSuper = false)
// public class RegistryConfig extends AbstractConfig {
//     @Singular
//     private List<ServiceConfig> servers = Collections.emptyList();
//     private ThriftServerInfo serverInfo;
//     private String appKey;
//     private String registry;
//     private String hostName;
//     private int weight; //权重
// 
//     public RegistryConfig() {
//         super("registry");
//     }
// 
//     public RegistryConfig(List<ServiceConfig> servers, ThriftServerInfo serverInfo, String appKey, String registry, String hostName, int weight) {
//         this();
//         this.servers = servers;
//         this.serverInfo = serverInfo;
//         this.appKey = appKey;
//         this.registry = registry;
//         this.hostName = hostName;
//         this.weight = weight;
//     }
// 
//     public String toJsonString() {
//         this.servers.stream().forEach(AbstractConfig::fillId);
//         this.fillId();
//         return JsonUtils.toJson(this);
//     }
// 
//     public static RegistryConfig parse(String json) {
//         return JsonUtils.fromJson(json, RegistryConfig.class);
//     }
// 
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/config/ThriftServerInfo.java
// @Data
// @AllArgsConstructor
// @EqualsAndHashCode
// public class ThriftServerInfo {
//     private String ip;
//     private int port;
// 
//     public ThriftServerInfo(String ipPort) {
//         checkNotNull(ipPort);
//         String[] splits = ipPort.split(":");
//         checkArgument(splits.length == 2, "ipPort format error");
//         this.ip = splits[0];
//         this.port = NumberUtils.toInt(splits[1]);
//     }
// 
//     @Override
//     public String toString() {
//         return ip + ":" + port;
//     }
// 
//     public static ThriftServerInfo parse(String info) {
//         String[] splits = StringUtils.split(info, ":");
//         if (splits == null || splits.length != 2) {
//             return null;
//         }
//         return new ThriftServerInfo(splits[0], NumberUtils.toInt(splits[1]));
//     }
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/monitor/RegistryConfigListener.java
// @Getter
// @AllArgsConstructor
// public abstract class RegistryConfigListener {
//     private String remoteKey;
// 
//     public abstract void addServer(RegistryConfig config);
// 
//     public abstract void removeServer(ThriftServerInfo serverInfo);
// 
//     public abstract void updateServer(RegistryConfig config);
// }


import com.github.sofn.trpc.client.config.ServiceKey;
import com.github.sofn.trpc.client.config.TrpcServiceNode;
import com.github.sofn.trpc.core.AbstractMonitor;
import com.github.sofn.trpc.core.config.RegistryConfig;
import com.github.sofn.trpc.core.config.ThriftServerInfo;
import com.github.sofn.trpc.core.monitor.RegistryConfigListener;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
package com.github.sofn.trpc.client.monitor;



/**
 * 根据服务信息，获取节点信息，有监控机制保证数据实时同步
 * Authors: sofn
 * Version: 1.0  Created at 2016-09-28 23:02.
 */
@Slf4j
public class ServiceFactory {
    private static Map<ServiceKey, Set<TrpcServiceNode>> servicesMap = new ConcurrentHashMap<>();

    /**
     * 获取节点信息
     */
    public static Set<TrpcServiceNode> getServiceKeys(ServiceKey serviceKey, AbstractMonitor monitor) {
        return getServiceKeys(serviceKey, ImmutableList.of(monitor));
    }

// Path: trpc-client/src/main/java/com/github/sofn/trpc/client/config/ServiceKey.java
// @Data
// @AllArgsConstructor
// public class ServiceKey {
//     private String remoteKey;
//     private String service;
// }
// 
// Path: trpc-client/src/main/java/com/github/sofn/trpc/client/config/TrpcServiceNode.java
// @Getter
// @ToString
// @AllArgsConstructor
// @EqualsAndHashCode(of = {"ip", "port"})
// public class TrpcServiceNode implements Comparable<TrpcServiceNode> {
//     private String ip;
//     private int port;
//     private int weight;
//     private int timeout;
// 
//     public static List<TrpcServiceNode> fromRegistryConfig(RegistryConfig registryConfig) {
//         ThriftServerInfo server = registryConfig.getServerInfo();
//         return registryConfig.getServers().stream()
//                 .map(s -> new TrpcServiceNode(server.getIp(), server.getPort(), s.getWeight(), s.getTimeout()))
//                 .collect(Collectors.toList());
//     }
// 
//     public ThriftServerInfo toThriftServerInfo() {
//         return new ThriftServerInfo(this.ip, this.port);
//     }
// 
//     @Override
//     public int compareTo(TrpcServiceNode other) {
//         int result = this.ip.compareTo(other.ip);
//         return result != 0 ? result : this.port - other.port;
//     }
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/AbstractMonitor.java
// public abstract class AbstractMonitor {
// 
//     /**
//      * 返回remoteKey下所有节点数据，并监控变化
//      *
//      * @param monitor 消息listener
//      * @return 返回现在的数据
//      */
//     public abstract List<RegistryConfig> monitorRemoteKey(RegistryConfigListener monitor);
// 
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/config/RegistryConfig.java
// @Setter
// @Getter
// @Builder
// @EqualsAndHashCode(of = {"serverInfo", "appKey"}, callSuper = false)
// public class RegistryConfig extends AbstractConfig {
//     @Singular
//     private List<ServiceConfig> servers = Collections.emptyList();
//     private ThriftServerInfo serverInfo;
//     private String appKey;
//     private String registry;
//     private String hostName;
//     private int weight; //权重
// 
//     public RegistryConfig() {
//         super("registry");
//     }
// 
//     public RegistryConfig(List<ServiceConfig> servers, ThriftServerInfo serverInfo, String appKey, String registry, String hostName, int weight) {
//         this();
//         this.servers = servers;
//         this.serverInfo = serverInfo;
//         this.appKey = appKey;
//         this.registry = registry;
//         this.hostName = hostName;
//         this.weight = weight;
//     }
// 
//     public String toJsonString() {
//         this.servers.stream().forEach(AbstractConfig::fillId);
//         this.fillId();
//         return JsonUtils.toJson(this);
//     }
// 
//     public static RegistryConfig parse(String json) {
//         return JsonUtils.fromJson(json, RegistryConfig.class);
//     }
// 
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/config/ThriftServerInfo.java
// @Data
// @AllArgsConstructor
// @EqualsAndHashCode
// public class ThriftServerInfo {
//     private String ip;
//     private int port;
// 
//     public ThriftServerInfo(String ipPort) {
//         checkNotNull(ipPort);
//         String[] splits = ipPort.split(":");
//         checkArgument(splits.length == 2, "ipPort format error");
//         this.ip = splits[0];
//         this.port = NumberUtils.toInt(splits[1]);
//     }
// 
//     @Override
//     public String toString() {
//         return ip + ":" + port;
//     }
// 
//     public static ThriftServerInfo parse(String info) {
//         String[] splits = StringUtils.split(info, ":");
//         if (splits == null || splits.length != 2) {
//             return null;
//         }
//         return new ThriftServerInfo(splits[0], NumberUtils.toInt(splits[1]));
//     }
// }
// 
// Path: trpc-core/src/main/java/com/github/sofn/trpc/core/monitor/RegistryConfigListener.java
// @Getter
// @AllArgsConstructor
// public abstract class RegistryConfigListener {
//     private String remoteKey;
// 
//     public abstract void addServer(RegistryConfig config);
// 
//     public abstract void removeServer(ThriftServerInfo serverInfo);
// 
//     public abstract void updateServer(RegistryConfig config);
// }


// Path: trpc-client/src/main/java/com/github/sofn/trpc/client/monitor/ServiceFactory.java
import com.github.sofn.trpc.client.config.ServiceKey;
import com.github.sofn.trpc.client.config.TrpcServiceNode;
import com.github.sofn.trpc.core.AbstractMonitor;
import com.github.sofn.trpc.core.config.RegistryConfig;
import com.github.sofn.trpc.core.config.ThriftServerInfo;
import com.github.sofn.trpc.core.monitor.RegistryConfigListener;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;

package com.github.sofn.trpc.client.monitor;



/**
 * 根据服务信息，获取节点信息，有监控机制保证数据实时同步
 * Authors: sofn
 * Version: 1.0  Created at 2016-09-28 23:02.
 */
@Slf4j
public class ServiceFactory {
    private static Map<ServiceKey, Set<TrpcServiceNode>> servicesMap = new ConcurrentHashMap<>();

    /**
     * 获取节点信息
     */
    public static Set<TrpcServiceNode> getServiceKeys(ServiceKey serviceKey, AbstractMonitor monitor) {
        return getServiceKeys(serviceKey, ImmutableList.of(monitor));
    }

    public static Set<TrpcServiceNode> getServiceKeys(ServiceKey serviceKey, List<AbstractMonitor> monitors) {