package com.yiqiniu.easytrans.queue.consumer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yiqiniu.easytrans.config.EasyTransConifg;
import com.yiqiniu.easytrans.filter.EasyTransFilter;
import com.yiqiniu.easytrans.filter.EasyTransFilterChain;
import com.yiqiniu.easytrans.filter.EasyTransFilterChainFactory;
import com.yiqiniu.easytrans.filter.EasyTransResult;
import com.yiqiniu.easytrans.protocol.BusinessIdentifer;
import com.yiqiniu.easytrans.protocol.BusinessProvider;
import com.yiqiniu.easytrans.protocol.EasyTransRequest;
import com.yiqiniu.easytrans.protocol.MessageBusinessProvider;
import com.yiqiniu.easytrans.provider.factory.ListableProviderFactory;
import com.yiqiniu.easytrans.util.ReflectUtil;
/**
* register the message handlers,wire the filters,dispatch handlers
*/
public class EasyTransMsgInitializer implements EasyTransMsgListener {
private ConcurrentHashMap<Class<? extends EasyTransRequest<?, ?>>, EasyTransFilter> mapHandler = new ConcurrentHashMap<Class<? extends EasyTransRequest<?, ?>>, EasyTransFilter>();
@Resource
private ListableProviderFactory serviceWareHouse;
@Resource
private EasyTransMsgConsumer consumer;
@Resource
private EasyTransFilterChainFactory filterChainFactory;
@Resource
private EasyTransConifg config;
private Logger LOG = LoggerFactory.getLogger(this.getClass());
@SuppressWarnings({ "unchecked" })
@PostConstruct
private void init(){
HashMap<String,List<String>> map = new HashMap<String, List<String>>();
//do initial
Set<Class<?>> transactionTypeSet = serviceWareHouse.getServiceTransactionTypeSet(MessageBusinessProvider.class);
for(Class<?> transactionType:transactionTypeSet){
List<Object> serviceMap = serviceWareHouse.getServices(MessageBusinessProvider.class, transactionType);
for(Object handler:serviceMap){
BusinessProvider<?> messageHandler = (BusinessProvider<?>) handler;
wrapToFilter(messageHandler);
Class<? extends EasyTransRequest<?, ?>> clazz = ReflectUtil.getRequestClass((Class<? extends BusinessProvider<?>>) messageHandler.getClass());
BusinessIdentifer businessIdentifer = ReflectUtil.getBusinessIdentifer(clazz);
List<String> list = map.get(businessIdentifer.appId());
if(list == null){
list = new ArrayList<String>();
map.put(businessIdentifer.appId(), list);
}
list.add(businessIdentifer.busCode());
}
}
//register listener to queue
for(Entry<String, List<String>> e:map.entrySet()){
consumer.subscribe(e.getKey(), e.getValue(), this);
}
}
@Override
public EasyTransConsumeAction consume(EasyTransRequest<?, ?> message) {
EasyTransFilter easyTransFilter = getFilter(message);
BusinessIdentifer businessIdentifer = ReflectUtil.getBusinessIdentifer(message.getClass());
EasyTransFilterChain filterChain = filterChainFactory.getDefaultFilterChain(config.getAppId()/*should use consumer's appId*/, businessIdentifer.busCode(), EasyTransFilterChain.MESSAGE_BUSINESS_FLAG);
filterChain.addFilter(easyTransFilter);
EasyTransResult result = filterChain.invokeFilterChain(message);
try {
return (EasyTransConsumeAction) result.recreate();
} catch (Throwable e) {
LOG.error("Consume Error!",e);
throw new RuntimeException(e);
}
}
private EasyTransFilter getFilter(EasyTransRequest<?, ?> message) {
return mapHandler.get(message.getClass());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void wrapToFilter(final BusinessProvider<?> handler) {
List<Class<?>> result = ReflectUtil.getTypeArguments(MessageBusinessProvider.class, (Class)handler.getClass());
if(result != null){
Class<? extends EasyTransRequest<?, ?>> requestClass = (Class<? extends EasyTransRequest<?, ?>>) result.get(0);
EasyTransFilter easyTransFilter = new EasyTransFilter() {
@Override
public EasyTransResult invoke(EasyTransFilterChain filterChain,
EasyTransRequest<?, ?> request) {
EasyTransResult easyTransResult = new EasyTransResult();
try {
easyTransResult.setValue(((MessageBusinessProvider<?>)handler).consume(request));
} catch (Throwable e) {
easyTransResult.setException(e);
}
return easyTransResult;
}
};
mapHandler.put(requestClass, easyTransFilter);
}
}
}