package org.jfox.ejb.invoker;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.ejb.EJBObject;

import org.jfox.ejb.EJBObjectMethod;
import org.jfox.ejb.MethodHasher;
import org.jfox.ejb.ObjectId;
import org.jfox.ejb.ObjectMethod;

/**
 * 所有的基于某个协议的 InvocationHandler 的父类
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public abstract class ContainerInvokerSupport implements ClientContainerInvoker {
  protected ObjectId objectId;
  protected ContainerRemote invoker;

  public ContainerInvokerSupport(ObjectId objectId, ContainerRemote invoker) {
    this.objectId = objectId;
    this.invoker = invoker;
  }
  public ObjectId getObjectId() {
    return objectId;
  }

  public ContainerRemote getInvoker() {
    return invoker;
  }

  /**
   * 接收由 DelegateInvocationHandler 转发来的 invoke 请求
   *
   * 可以实现通用的 Object 方法,比如:toString, hashCode 等
   */
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if(method.equals(ObjectMethod.ToString)) {
      return ((ClientContainerInvoker)Proxy.getInvocationHandler(proxy)).getObjectId().toString();
    }
    else if(method.equals(ObjectMethod.HashCode)){
      return new Integer(objectId.hashCode());
    }
    else if(method.getName().equals(ObjectMethod.Equals)) {
      Object obj = args[0];
      if(objectId.isHome()){
        return new Boolean(objectId.equals(((ContainerInvokerSupport)Proxy.getInvocationHandler(proxy)).getObjectId()));
      }
      else if(obj instanceof EJBObject){
        return invokeBean(proxy, EJBObjectMethod.IsIdentical,args);
      }
      else {
        return Boolean.FALSE;
      }
    }

    if(objectId.isHome()) { // 一个 EJBHome 方法
      return invokeHome(proxy, method, args);
    }
    else {
      return invokeBean(proxy, method, args);
    }
  }

  /**
   * 来自 EJBHome 的方法
   * 注意:要注意拦截来自 EJBHome 的请求
   * 比如:create,这时,服务端返回的并不是一个 EJBObject 对象,
   * 而是这个 EJBObject 对象的 ObjectId,所以必须在这里手动生成代理对象   */
  protected abstract Object invokeHome(Object proxy, Method method, Object[] args) throws Exception;

  /**
   * 执行 Bean 的方法
   */
  protected abstract Object invokeBean(Object proxy, Method method, Object[] args) throws Exception;

  /**
   * 得到一个 method 的 hashCode ,可以唯一的标志一个 method
   * @param method
   * @return
   */
  protected static long getMethodHash(Method method) {
    return MethodHasher.getMethodHash(method);
  }

}