/**
 *  Layer factory (Singleton)
 *  
 *  @author     ETSI / STF424
 *  @version    $URL: svn+ssh://vcs.etsi.org/TTCN3/TOOL/ITS_TestPlatform/trunk/javasrc/adapter/org/etsi/its/adapter/layers/LayerFactory.java $
 *              $Id: LayerFactory.java 182 2011-04-27 08:01:07Z berge $
 *
 */
package org.etsi.its.uppertester;


import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.TreeMap;

/**
 *  Layer factory (Singleton)
 */
public class UpperTesterFactory {

    /**
     * Unique instance of the factory
     */
	private static UpperTesterFactory instance = new UpperTesterFactory();
	
	/**
     * List of the registered layer types 
     */
	protected Map<String, Class<? extends IUpperTester>> upperTesters = new TreeMap<String, Class<? extends IUpperTester>>();
	protected Map<String, IUpperTester> upperTesterInstances = new TreeMap<String, IUpperTester>();
	
	/**
     * Private constructor (Singleton pattern)
     */
	private UpperTesterFactory() {
	    
		// Register the upperTester
	    upperTesters.put("Operator", org.etsi.its.uppertester.operator.ItsUpperTester.class);
	    upperTesters.put("Yes", org.etsi.its.uppertester.yes.ItsUpperTester.class);
	    upperTesters.put("HitachiCam", org.etsi.its.uppertester.hitachi.CamUpperTester.class);
	    upperTesters.put("HitachiDenm", org.etsi.its.uppertester.hitachi.DenmUpperTester.class);
	    upperTesters.put("HitachiNwt", org.etsi.its.uppertester.hitachi.NwtUpperTester.class);
	    upperTesters.put("NecNwt", org.etsi.its.uppertester.nec.NwtUpperTester.class);
	    upperTesters.put("ITriCam", org.etsi.its.uppertester.itri.CamUpperTester.class);
	    upperTesters.put("ITriDenm", org.etsi.its.uppertester.itri.DenmUpperTester.class);
	    upperTesters.put("ITriNwt", org.etsi.its.uppertester.itri.NwtUpperTester.class);
	}

	/**
     * Gets the unique factory instance
     * @return LayerFactory instance
     */
	public static UpperTesterFactory getInstance(){
		return instance;
	}

    /**
     * Retrieves an upper tester instance of the desired type
     * @param  utName    Name of the upper tester
     * @return Upper tester instance
     */
	public IUpperTester getUpperTester(String utName) {
	    IUpperTester upperTester = upperTesterInstances.get(utName);
	    if(upperTester == null) {
	        upperTester = createUpperTester(utName);
	        upperTesterInstances.put(utName, upperTester);
	    }
	    return upperTester;
	}
	
	/**
     * Creates an upper tester of the desired type
     * @param  utName    Name of the upper tester
     * @return Upper tester instance
     */
	private IUpperTester createUpperTester(String utName) {
	    IUpperTester upperTester = null;
		Class<?>[] ctorParams = {};
		
   		try {		
	        Class<? extends IUpperTester> cls = upperTesters.get(utName);
	        if (cls == null) {
	        	throw new RuntimeException("No class registered under " + utName);
	        }
            Constructor<? extends IUpperTester> ctor = cls.getConstructor(ctorParams);
            upperTester = ctor.newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return upperTester;
	}

	public void dispose() {
		for (String key : upperTesterInstances.keySet()) {
			upperTesterInstances.get(key).uninitialize();
		} // End of 'for' statement
	}
}
