package com.a.eye.uniqueid.player;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

/**
 * {@link UniqueIDPlayer}'s RegisterCenter
 * Use SPI({@link ServiceLoader}) to get all IDGenerator implementations.
 * Also, provide {@link RegisterCenter#register(IDGenerator)} to register any implementations as your wish.
 * <p>
 * All implementations will stay and be hold by {@link RegisterCenter}.
 * <p>
 * Created by wusheng on 2016/12/29.
 */
public enum RegisterCenter {
    /**
     * stay in singleton.
     */
    INSTANCE;

    /**
     * all registered implementations.
     */
    private Map<String, IDGenerator> registeredGenerator = new HashMap<String, IDGenerator>();

    /**
     * In default mechanism,
     * {@link RegisterCenter} use SPI({@link ServiceLoader}) to get all IDGenerator implementations.
     */
    RegisterCenter() {
        Iterator<IDGenerator> generatorIterator = ServiceLoader.load(IDGenerator.class).iterator();
        while (generatorIterator.hasNext()) {
            IDGenerator next = generatorIterator.next();
            registeredGenerator.put(next.name().trim(), next);
        }
    }

    /**
     * register {@link IDGenerator} implementation manually.
     * This method should not be called concurrency, or in high-throughput processes.
     *
     * @param instance {@link IDGenerator} implementation.
     * @return {@link RegisterCenter#INSTANCE}
     */
    public synchronized RegisterCenter register(IDGenerator instance) {
        registeredGenerator.put(instance.name(), instance);
        return this;
    }

    /**
     * find a {@link UniqueIDPlayer} by name
     *
     * @param name {@link IDGenerator}'s register name.
     * @return {@link IDGenerator} instance.
     * @throws UnregisteredGeneratorException when register name not found.
     */
    public UniqueIDPlayer find(String name) throws UnregisteredGeneratorException {
        IDGenerator generator = registeredGenerator.get(name);
        if (generator != null) {
            return new UniqueIDPlayer(generator);
        }

        throw new UnregisteredGeneratorException("Register name:" + name + " not found");
    }

    /**
     * find a {@link UniqueIDPlayer} by named("uniqueid.player.config") config file.
     *
     * File contains the only {@link IDGenerator}'s register name.
     * If many names exist, use the first and ignore others.
     * Line comments start with '#' are supported in config file.
     *
     * @return
     * @throws UnregisteredGeneratorException
     */
    public UniqueIDPlayer find() throws UnregisteredGeneratorException {
        InputStream configResource = RegisterCenter.class.getResourceAsStream("/uniqueid.player.config");
        String generatorName = "default";
        if (configResource != null) {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(configResource));
            String line = null;
            try {
                while ((line = bufferedReader.readLine()) != null) {
                    String trim = line.trim();
                    if (trim.length() > 0 && !trim.startsWith("#")) {
                        generatorName = trim;
                    }
                }
            } catch (IOException e) {
                throw new UnregisteredGeneratorException("uniqueid.player.config can't provide the name", e);
            }
        }

        return find(generatorName);
    }
}

@@ -169,16 +169,65 @@
 .util.*;
+%0Aimport java.util.concurrent.locks.ReentrantLock;
 %0A%0A/**%0A *
@@ -813,16 +813,278 @@
 or%3E();%0A%0A
+    /**%0A     * default GeneratorName%0A     */%0A    private String defaultGeneratorName = null;%0A%0A    /**%0A     * the lock when initialize %7B@link RegisterCenter#defaultGeneratorName%7D.%0A     */%0A    private ReentrantLock defaultGeneratorFindLock = new ReentrantLock();%0A%0A
     /**%0A
@@ -2637,32 +2637,36 @@
 fig file.%0A     *
+ %3Cp%3E
 %0A     * File con
@@ -2985,32 +2985,80 @@
 atorException %7B%0A
+        if (defaultGeneratorName == null) %7B%0A    
         InputStr
@@ -3147,24 +3147,25 @@
 nfig%22);%0A
+%0A
         
 String g
@@ -3160,42 +3160,199 @@
     
-String generatorNam
+    // use lock and double checks to avoid lock after initialize.%0A            if (configResourc
 e 
+!
 = 
-%22default%22;%0A
+null) %7B%0A                defaultGeneratorFindLock.lock();%0A                try %7B%0A            
     
@@ -3377,32 +3377,44 @@
 urce != null) %7B%0A
+            
             Buff
@@ -3516,28 +3516,45 @@
     
-String line = null;%0A
+            String line;%0A            
     
@@ -3559,32 +3559,44 @@
           try %7B%0A
+            
                 
@@ -3664,24 +3664,36 @@
             
+      
+      
 String trim 
@@ -3703,24 +3703,103 @@
 ine.trim();%0A
+                                // ignore comments and empty line.%0A            
             
@@ -3880,17 +3880,36 @@
         
+           
-g
+ defaultG
 enerator
@@ -3933,38 +3933,32 @@
                 
-%7D%0A    
             %7D%0A  
@@ -3947,32 +3947,74 @@
               %7D%0A
+                            %7D%0A            
             %7D ca
@@ -4043,32 +4043,44 @@
                 
+  
+          
 throw new Unregi
@@ -4105,16 +4105,29 @@
 eption(%22
+Can not read 
 uniqueid
@@ -4144,37 +4144,587 @@
 nfig
- can't provide the name%22, e);
+%22, e);%0A                        %7D%0A%0A                        // if no generatorName in config file, implicit to set the generator to 'default', stead of throwing exception.%0A                        if(defaultGeneratorName == null) %7B%0A                            defaultGeneratorName = %22default%22;%0A                        %7D%0A                    %7D%0A                %7Dfinally%7B%0A                    defaultGeneratorFindLock.unlock();%0A                    try %7B%0A                        configResource.close();%0A                    %7D catch (IOException e) %7B%0A                    %7D%0A                %7D
 %0A   
@@ -4765,17 +4765,24 @@
 rn find(
-g
+defaultG
 enerator

Fix some issues from review. Avoid re-initialize.