/*
* Copyright © 2014 YAOCHEN Corporation, All Rights Reserved
*/
package com.easyooo.framework.cache.config.impl;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.easyooo.framework.cache.CacheException;
import com.easyooo.framework.cache.ConfigurationException;
import com.easyooo.framework.cache.IKeyValue;
import com.easyooo.framework.cache.annotations.ThreadSafety;
import com.easyooo.framework.cache.config.CacheBean;
import com.easyooo.framework.cache.config.Configuration;
import com.easyooo.framework.cache.config.MergingBean;
import com.easyooo.framework.common.util.ClassUtil;
/**
* <p>缓存配置抽象类实现,使用线程安全的Map,实现该类无需关心存储以及存储是否安全,
* 还具备缓存配置的合法性检查,扩展该类只需要完成具体的解析配置的过程</p>
*
* @see #parserConfiguration(Class)
* @see ConcurrentHashMap
*
* @author Killer
*/
@ThreadSafety
public abstract class AbstractConfiguration implements Configuration{
protected final Logger logger = LoggerFactory.getLogger(getClass());
private final ConcurrentHashMap<Class<?>, Future<CacheBean>> cache
= new ConcurrentHashMap<Class<?>, Future<CacheBean>>();
public AbstractConfiguration(){
super();
}
/**
* 从缓存配置中获取一个配置信息,如果不存在,则动态解析它,如何解析则取决于具体实现类
*
* @param type 实体类的Class
* @return 能正常返回就一定能返回一个正确的CacheBean
* @throws ConfigurationException
*/
@Override
public CacheBean get(final Class<?> type)
throws ConfigurationException {
if(type == null)
return null;
// Get from cacheMap
Future<CacheBean> future = cache.get(type);
if(future == null){
Callable<CacheBean> eval = new Callable<CacheBean>() {
@Override
public CacheBean call() throws Exception {
return parserConfiguration(type);
}
};
FutureTask<CacheBean> ft = new FutureTask<CacheBean>(eval);
future = cache.putIfAbsent(type, ft);
if(future == null){
future = ft;
ft.run();
}
}
try {
return future.get();
} catch (InterruptedException e) {
cache.remove(type);
throw new ConfigurationException(e);
} catch (ExecutionException e) {
cache.remove(type);
throw new ConfigurationException("Load [" + type.getName() + "] configuration error", e);
}
}
/**
* @see #get(Class)
* 区别在于,如果不存在,则直接返回NULL
* @throws CacheException 不包含自动配置的特性,故抛出 CacheException,
* 它仅仅是InterruptedException异常的薄包装
*/
public CacheBean getIfExist(final Class<?> type)throws CacheException{
Future<CacheBean> future = cache.get(type);
if(null == future){
return null;
}
if(future.isDone()){
try {
return future.get();
} catch (InterruptedException e) {
throw new CacheException(e);
} catch (ExecutionException igore) {
}
}
return null;
}
/**
* 卸载一个Cache Class,该方法一般不会主动调用,该方法只能与
* @param type
* @return
*/
public boolean unloadCacheClass(final Class<?> type){
if(null == cache.remove(type)){
return false;
}
return true;
}
/**
* 验证缓存配置是否正确
*
* @param target
* @throws ConfigurationException
*/
protected CacheBean validate(CacheBean target) throws ConfigurationException {
if (target == null || target.getXbeanClass() == null) {
throw new ConfigurationException("Cache annotation was not found");
}
if (target.getMergings() != null) {
Set<Entry<Class<?>, MergingBean>> entries = target.getMergings().entrySet();
for (Entry<Class<?>, MergingBean> entry : entries) {
if(entry.getValue().getRefrences().size() == 0){
throw new ConfigurationException(
"Merging annotation was found, but refrences size is zero");
}
}
}
if (target.getKeyPropertyList().size() == 0
&& !ClassUtil.hasInterface(target.getXbeanClass(), IKeyValue.class)) {
throw new ConfigurationException(
"KeyProperty and Key interface was not found");
}
if (target.getFields().size() == 0) {
throw new ConfigurationException(
"The field does not need to cache");
}
return target;
}
}