@@ -0,0 +1,2474 @@
+/**%0A * %0A */%0Apackage com.github.ansell.abstractserviceloader;%0A%0Aimport java.util.Collection;%0Aimport java.util.Collections;%0Aimport java.util.ServiceConfigurationError;%0Aimport java.util.concurrent.ConcurrentHashMap;%0A%0A/**%0A * @author Peter Ansell p_ansell@yahoo.com%0A * %0A */%0Apublic abstract class AbstractUniqueServiceLoader%3CK, S%3E extends AbstractServiceLoader%3CK, S%3E%0A%7B%0A    %0A    /**%0A     * @param serviceClass%0A     */%0A    public AbstractUniqueServiceLoader(Class%3CS%3E serviceClass)%0A    %7B%0A        super(serviceClass);%0A        // TODO Auto-generated constructor stub%0A    %7D%0A    %0A    /**%0A     * @param serviceClass%0A     * @param classLoader%0A     */%0A    public AbstractUniqueServiceLoader(Class%3CS%3E serviceClass, ClassLoader classLoader)%0A    %7B%0A        super(serviceClass, classLoader);%0A        // TODO Auto-generated constructor stub%0A    %7D%0A    %0A    @Override%0A    public void add(final S service)%0A    %7B%0A        final K key = this.getKey(service);%0A        %0A        Collection%3CS%3E set = this.services.get(key);%0A        %0A        if(set == null)%0A        %7B%0A            set = Collections.newSetFromMap(new ConcurrentHashMap%3CS, Boolean%3E(2, 0.75f, 2));%0A            %0A            final Collection%3CS%3E existingSet = this.services.putIfAbsent(key, set);%0A            %0A            if(existingSet != null)%0A            %7B%0A                this.log.error(%22Failing due to a duplicate service with key: %7B%7D for class %7B%7D%22, key, service);%0A                throw new ServiceConfigurationError(%22Found a duplicate service with key: %22 + key + %22 for class: %22%0A                        + service);%0A            %7D%0A        %7D%0A        else%0A        %7B%0A            this.log.error(%22Failing due to a duplicate service with key: %7B%7D for class %7B%7D%22, key, service);%0A            throw new ServiceConfigurationError(%22Found a duplicate service with key: %22 + key + %22 for class: %22 + service);%0A        %7D%0A        %0A        set.add(service);%0A        %0A        if(this.log.isDebugEnabled())%0A        %7B%0A            this.log.debug(%22Added service with key: %7B%7D%22, key);%0A        %7D%0A    %7D%0A    %0A    public S getUnique(K key)%0A    %7B%0A        Collection%3CS%3E results = this.services.get(key);%0A        %0A        if(results.isEmpty())%0A        %7B%0A            return null;%0A        %7D%0A        else if(results.size() == 1)%0A        %7B%0A            return results.iterator().next();%0A        %7D%0A        %0A        this.log.error(%22Failing due to a duplicate service with key: %7B%7D%22, key);%0A        throw new ServiceConfigurationError(%22Found a duplicate service with key: %22 + key);%0A    %7D%0A%7D%0A

add initial AbstractUniqueServiceLoader to support cases where a single key refers to a single service