/**
 * @author XiongJie, Date: 13-10-29
 */
package net.happyonroad.spring.support;

import net.happyonroad.spring.service.MutableServiceRegistry;
import net.happyonroad.spring.exception.ServiceConfigurationException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/** 缺省的服务注册表 */
@SuppressWarnings("unchecked")
public class DefaultServiceRegistry implements MutableServiceRegistry {
    protected Logger                          logger   = LoggerFactory.getLogger(getClass());
    private   Map<Class, Map<String, Object>> services = new HashMap<Class, Map<String, Object>>();

    ////////////////////////////////////////////////////////////////////////
    // Mutable Service Registry的实现
    ////////////////////////////////////////////////////////////////////////

    @Override
    public <T> void register(Class<T> interfaceClass, T service) {
        register(interfaceClass, service, DEFAULT_HINT);
    }

    @Override
    public <T> void register(Class<T> interfaceClass, T service, String hint) {
        String serviceName = service.getClass().getSimpleName();
        logger.info("Register {} by {} with hint {}", interfaceClass.getName(), serviceName, hint);
        Map<String, Object> instances = services.get(interfaceClass);
        if (instances == null) {
            instances = new HashMap<String, Object>(2);
            services.put(interfaceClass, instances);
        }
        instances.put(hint, service);
    }

    @Override
    public <T> void register(Class[] interfaceClasses, T service, String hint) {
        for (Class interfaceClass : interfaceClasses) {
            register(interfaceClass, service, hint);
        }
    }

    @Override
    public <T> T unRegister(Class<T> interfaceClass, String hint) {
        List<T> removes = new ArrayList<T>();
        Set<Class> keys = services.keySet();
        for (Class key : keys) {
            if (interfaceClass.isAssignableFrom(key)) {
                Map<String, Object> theMap = services.get(key);
                if (theMap != null) {
                    T removed = (T) theMap.remove(hint);
                    if (removed != null) removes.add(removed);
                }
            }
        }
        if (removes.size() == 1) {
            return removes.get(0);
        } else if (removes.isEmpty()) {
            return null;
        } else {
            logger.warn("I have unRegister multiple service {} with hint {}, {}",
                        interfaceClass, hint, StringUtils.join(removes, ","));
            return removes.get(0);
        }
    }

    @Override
    public <T> Map<String, T> unRegister(Class<T> interfaceClass) {
        Set<Class> keys = services.keySet();
        Map<String, T> removes = new HashMap<String, T>();
        for (Class key : keys) {
            if (interfaceClass.isAssignableFrom(key)) {
                Map<String, T> theMap = (Map<String, T>) services.remove(key);
                if (theMap != null) {
                    removes.putAll(theMap);
                }
            }
        }
        return removes;
    }

    ////////////////////////////////////////////////////////////////////////
    // Service Registry的实现
    ////////////////////////////////////////////////////////////////////////

    @Override
    public <T> T getService(Class<T> requiredType) {
        return getService(requiredType, ANY_HINT);
    }

    @Override
    public <T> T getService(Class<T> requiredType, String hint) {
        Map<String, Object> map = services.get(requiredType);
        T service = getServiceFromMap(map, hint);
        if (service == null) {
            //如果精确查找找不到，则进行模糊匹配，找到第一个算数
            map = digMaps(requiredType);
            service = getServiceFromMap(map, hint);
        }
        return service;
    }

    protected <T> T getServiceFromMap(Map<String, Object> map, String hint) {
        if(map == null || map.isEmpty()) return null;
        if(ANY_HINT.equals(hint)){
            return (T) map.values().iterator().next();
        }
        return (T) map.get(hint);
    }

    @Override
    public <T> T getService(Class[] requiredTypes, String hint) {
        Set<T> found = new HashSet<T>();
        for (Class type : requiredTypes) {
            T service = (T)getService(type, hint);
            found.add(service);
        }
        if( found.size() != 1 ){
            String types = StringUtils.join(requiredTypes, ",");
            throw new ServiceConfigurationException("The service with hint = " + hint +
                                                    " is not exported with multiple interfaces: " + types);
        }
        return found.iterator().next();
    }

    @Override
    public <T> Map<String, T> getServices(Class<T> requiredType) {
        Map<String, Object> map = digMaps(requiredType);
        return (Map<String, T>) map;
    }

    /**
     * 找到符合相应类型的服务map
     *
     * @param requiredType 服务类型
     * @param <T>          服务类型
     * @return 第一个找到的map
     */
    private <T> Map<String, Object> digMaps(Class<T> requiredType) {
        Map<String, Object> all = new HashMap<String, Object>();
        Set<Class> keys = services.keySet();
        for (Class serviceClass : keys) {
            if (requiredType.isAssignableFrom(serviceClass)) {
                //如果出现子类型中的服务与已有存在的冲突了怎么办？
                Map<String, Object> map = services.get(serviceClass);
                for (String key : map.keySet()) {
                    Object service = map.get(key);
                    Object exist = all.get(key);
                    if (exist != null) {
                        logger.warn("A service instance: {} override another: {} with hint = {}", service, exist, key);
                    }
                    all.put(key, service);
                }
            }
        }
        return all;
    }
}

@@ -337,16 +337,19 @@
 .*;%0A%0A/**
+%0A *
  %E7%BC%BA%E7%9C%81%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C
@@ -349,16 +349,17 @@
 %E7%BC%BA%E7%9C%81%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E8%A1%A8
+%0A
  */%0A@Sup
@@ -3926,16 +3926,17 @@
       if
+ 
 (map == 
@@ -3981,16 +3981,17 @@
       if
+ 
 (ANY_HIN
@@ -4005,16 +4005,17 @@
 s(hint))
+ 
 %7B%0A      
@@ -4305,16 +4305,17 @@
 ce = (T)
+ 
 getServi
@@ -4386,10 +4386,10 @@
   if
-(
  
+(
 foun
@@ -4405,10 +4405,10 @@
 != 1
- 
 )
+ 
 %7B%0A  
@@ -5655,101 +5655,247 @@
     
-logger.warn(%22A service instance: %7B%7D override another: %7B%7D with hint = %7B%7D%22, service, exist, key
+int n = 1;%0A                        String newKey;%0A                        do %7B%0A                            newKey = key + %22#%22 + n++;%0A                        %7D while (all.containsKey(newKey));%0A                        all.put(newKey, service
 );%0A 
@@ -5906,33 +5906,44 @@
                %7D
-%0A
+ else %7B%0A    
                 
@@ -5961,32 +5961,54 @@
 (key, service);%0A
+                    %7D%0A
                 

Fix bug about service registry