package jane.core;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.mina.core.session.IoSession;
/**
* RPC类型的bean(抽象类)
* <p>
* 包含请求和回复的两个bean
*/
public abstract class RpcBean<A extends Bean<A>, R extends Bean<R>, B extends RpcBean<A, R, B>> extends Bean<B>
{
private static final long serialVersionUID = 1L;
private static final AtomicInteger RPCID = new AtomicInteger(); // RPC的ID分配器
private transient int _rpcId = RPCID.getAndIncrement() & 0x7fffffff; // RPC的ID. 用于匹配请求和回复的RPC
private transient int _reqTime; // 发送请求的时间戳(秒)
private transient IoSession _session; // 请求时绑定的session
private transient RpcHandler<A, R, B> _onClient; // 回复的回调
protected A _arg; // 请求bean
protected R _res; // 回复bean
int getReqTime()
{
return _reqTime;
}
void setReqTime(int time)
{
_reqTime = time;
}
IoSession getSession()
{
return _session;
}
void setSession(IoSession session)
{
_session = session;
}
public RpcHandler<A, R, B> getOnClient()
{
return _onClient;
}
public void setOnClient(RpcHandler<A, R, B> handler)
{
_onClient = handler;
}
/**
* 当前RPC的ID
* <p>
* 用于标识当前唯一的RPC,并和RPC的回复相配
*/
public int getRpcId()
{
return _rpcId & 0x7fffffff;
}
void setRpcId(int rpcId)
{
_rpcId = rpcId;
}
/**
* 判断当前的RPC是否是请求RPC
* <p>
* RPC的ID最高位如果是0则表示请求RPC,否则是回复RPC
*/
public boolean isRequest()
{
return _rpcId >= 0;
}
/**
* 设置当前的RPC为请求RPC
*/
public void setRequest()
{
_rpcId &= 0x7fffffff;
}
/**
* 设置当前的RPC为回复RPC
*/
public void setResponse()
{
_rpcId |= 0x80000000;
}
public A getArg()
{
return _arg;
}
public void setArg(A a)
{
_arg = a;
}
public R getRes()
{
return _res;
}
public void setRes(R r)
{
_res = r;
}
/**
* 获取超时时间(秒)
* <p>
* 当RPC的请求发出之后,如果一段时间没有收到此RPC的回复,就会出现超时<br>
* 子类应该实现这个方法返回合适的值,默认是10秒
*/
@SuppressWarnings("static-method")
public int getTimeout()
{
return 10;
}
/**
* 创建一个新的请求bean实例
* <p>
* 子类的实现一般是new A(),返回对象的所有字段只有初始的默认值
*/
public abstract A createArg();
/**
* 创建一个新的回复bean实例
* <p>
* 子类的实现一般是new R(),返回对象的所有字段只有初始的默认值
*/
public abstract R createRes();
@Override
public void reset()
{
if(_arg != null) _arg.reset();
if(_res != null) _res.reset();
}
@Override
public B clone()
{
B b = create();
b.setRpcId(_rpcId);
b.setReqTime(_reqTime);
b.setSession(_session);
b.setOnClient(_onClient);
if(_arg != null) b._arg = _arg.clone();
if(_res != null) b._res = _res.clone();
return b;
}
@Override
public OctetsStream marshal(OctetsStream os)
{
os.marshal(_rpcId);
return _rpcId >= 0 ? os.marshalProtocol(_arg != null ? _arg : (_arg = createArg())) : os.marshalProtocol(_res != null ? _res : (_res = createRes()));
}
@Override
public OctetsStream unmarshal(OctetsStream os) throws MarshalException
{
_rpcId = os.unmarshalInt();
if(_rpcId >= 0)
{
if(_arg == null) _arg = createArg();
os.unmarshalProtocol(_arg);
}
else
{
if(_res == null) _res = createRes();
os.unmarshalProtocol(_res);
}
return os;
}
@Override
public int hashCode()
{
int h = 0;
if(_arg != null) h += _arg.hashCode();
if(_res != null) h += _res.hashCode();
return h;
}
@Override
public boolean equals(Object o)
{
if(o == this) return true;
if(!(o instanceof RpcBean)) return false;
RpcBean<?, ?, ?> b = (RpcBean<?, ?, ?>)o;
return (_arg == b._arg || _arg != null && _arg.equals(b._arg)) &&
(_res == b._res || _res != null && _res.equals(b._res)) &&
getClass() == o.getClass();
}
@Override
public String toString()
{
return "{arg=" + _arg + ",res=" + _res + "}";
}
@Override
public StringBuilder toJson(StringBuilder s)
{
s.append("{\"arg\":");
if(_arg != null)
_arg.toJson(s);
else
s.append("null");
s.append(",\"res\":");
if(_arg != null)
_arg.toJson(s);
else
s.append("null");
return s.append('}');
}
@Override
public StringBuilder toLua(StringBuilder s)
{
s.append("{arg=");
if(_arg != null)
_arg.toLua(s);
else
s.append("nil");
s.append(",res=");
if(_arg != null)
_arg.toLua(s);
else
s.append("nil");
return s.append('}');
}
}