/**
   * Returns Adapter Descriptor mapped class instance based on adapter descriptor name.
   *
   * @param adapterDescriptorName Name of Adapter Descriptor.
   * @return Adapter Class Instance.
   */
  public IAdapter getAdapterInstance(String adapterDescriptorName) {
    AdapterDescriptor adapterDescriptor =
        resourceManager.getAdapterDescriptor(adapterDescriptorName);
    String mapTo = adapterDescriptor.getMapTo();

    return (IAdapter) ClassUtils.createClassInstance(mapTo);
  }
  /**
   * Returns Handler mapped method instance based on adapter name, handler name and its handler
   * parameter types.
   *
   * @param adapterDescriptorName Name of Adapter.
   * @param handlerName Name of Handler.
   * @param handlerParameterTypes Type of Parameters.
   * @return Handler Method Instance.
   */
  public Method getHandlerInstance(
      String adapterDescriptorName, String handlerName, Class<?>... handlerParameterTypes) {

    AdapterDescriptor adapterDescriptor =
        resourceManager.getAdapterDescriptor(adapterDescriptorName);
    Handler handler = adapterDescriptor.getHandler(handlerName);

    return ClassUtils.createMethodBasedOnClassName(
        adapterDescriptor.getMapTo(), handler.getMapTo(), handlerParameterTypes);
  }
 private AdapterFactory() {
   resourceManager.setAdapterFactory(adapterFactory);
 }
/** It caches Adapter Instance and based on requirement server request. */
public class AdapterFactory {

  private Map<String, IAdapter> adapters = new HashMap<String, IAdapter>();
  private Map<String, Method> handlers = new HashMap<String, Method>();

  private ResourceManager resourceManager = ResourceManager.getInstance();

  private static AdapterFactory adapterFactory = null;

  private AdapterFactory() {
    resourceManager.setAdapterFactory(adapterFactory);
  }

  /**
   * It provides an instance of AdapterResources class.
   *
   * @return AdapterResources instance.
   */
  public static final AdapterFactory getInstance() {
    if (adapterFactory == null) {
      adapterFactory = new AdapterFactory();
    }

    return adapterFactory;
  }

  /**
   * Returns Adapter Descriptor mapped class instance based on adapter descriptor name.
   *
   * @param adapterDescriptorName Name of Adapter Descriptor.
   * @return Adapter Class Instance.
   */
  public IAdapter getAdapterInstance(String adapterDescriptorName) {
    AdapterDescriptor adapterDescriptor =
        resourceManager.getAdapterDescriptor(adapterDescriptorName);
    String mapTo = adapterDescriptor.getMapTo();

    return (IAdapter) ClassUtils.createClassInstance(mapTo);
  }

  /**
   * Returns Adapter mapped class instance based on adapter name. If adapter instance is not cache
   * it will create new instance of that class.
   *
   * @param adapterName Name of Adapter.
   * @return Adapter Class Instance.
   */
  public IAdapter requireAdapterInstance(String adapterName) {
    boolean contain = adapters.containsValue(adapterName);
    if (contain) {
      return adapters.get(adapterName);
    }

    IAdapter adapterObject = getAdapterInstance(adapterName);
    adapters.put(adapterName, adapterObject);

    return adapterObject;
  }

  /**
   * Returns Handler mapped method instance based on adapter name, handler name and its handler
   * parameter types.
   *
   * @param adapterDescriptorName Name of Adapter.
   * @param handlerName Name of Handler.
   * @param handlerParameterTypes Type of Parameters.
   * @return Handler Method Instance.
   */
  public Method getHandlerInstance(
      String adapterDescriptorName, String handlerName, Class<?>... handlerParameterTypes) {

    AdapterDescriptor adapterDescriptor =
        resourceManager.getAdapterDescriptor(adapterDescriptorName);
    Handler handler = adapterDescriptor.getHandler(handlerName);

    return ClassUtils.createMethodBasedOnClassName(
        adapterDescriptor.getMapTo(), handler.getMapTo(), handlerParameterTypes);
  }

  /**
   * Returns Handler mapped method instance based on adapter name, handler name and its handler
   * parameter types. If instance is not cached it will create new instance for handler.
   *
   * @param adapterDescriptorName Name of Adapter.
   * @param handlerName Name of Handler.
   * @param handlerParameterTypes Type of Parameters.
   * @return
   */
  public Method requireHandlerInstance(
      String adapterDescriptorName, String handlerName, Class<?>... handlerParameterTypes) {

    boolean contain = handlers.containsKey(handlerName);
    if (contain) {
      return handlers.get(handlerName);
    }

    Method handler = getHandlerInstance(adapterDescriptorName, handlerName, handlerParameterTypes);
    handlers.put(handlerName, handler);

    return handler;
  }
}