/*
* Copyright © 2014 YAOCHEN Corporation, All Rights Reserved
*/
package com.easyooo.framework.cache.config.impl;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.easyooo.framework.cache.CacheLevel;
import com.easyooo.framework.cache.ConfigurationException;
import com.easyooo.framework.cache.annotations.Cache;
import com.easyooo.framework.cache.annotations.Group;
import com.easyooo.framework.cache.annotations.KeyProperty;
import com.easyooo.framework.cache.annotations.Merging;
import com.easyooo.framework.cache.annotations.MergingList;
import com.easyooo.framework.cache.annotations.MiniTable;
import com.easyooo.framework.cache.annotations.Refrence;
import com.easyooo.framework.cache.annotations.Refrences;
import com.easyooo.framework.cache.annotations.ThreadSafety;
import com.easyooo.framework.cache.annotations.Transient;
import com.easyooo.framework.cache.config.CacheBean;
import com.easyooo.framework.cache.config.Configuration;
import com.easyooo.framework.cache.config.GroupBean;
import com.easyooo.framework.cache.config.KeyPropertyBean;
import com.easyooo.framework.cache.config.MergingBean;
import com.easyooo.framework.cache.config.ModelField;
import com.easyooo.framework.cache.config.RefrenceBean;
import com.easyooo.framework.common.util.ListUtil;
/**
* 该类主要实现了基于注解的方式解析缓存配置
*
* @see Cache
* @see Merging
* @see com.yaochen.KeyPropertyBean.common.cache.annotations.KeyProperty
* @see com.yaochen.GroupBean.common.cache.annotations.Group
* @see Transient
*
* @author Killer
*/
@ThreadSafety
public class AnnotationConfiguration extends AbstractConfiguration{
public AnnotationConfiguration(){
super();
}
/**
*
* 解析实体Class缓存注解,它并不会判断检查Cache Class是否存在,
*
* @param type 需要实现 {@link PropertyMapper}接口
* @return
* @throws ConfigurationException
*/
@Override
public CacheBean parserConfiguration(
Class<?> type)throws ConfigurationException {
if(type == null)
return null;
logger.debug(" Load the " + type.getName() +"- annotation configuration");
CacheBean target = new ParserAnnotation(type).parseAndGet();
return super.validate(target);
}
/**
* 解析缓存注解具体实现
* @author Killer
*/
private static class ParserAnnotation{
private Class<?> type;
private CacheBean target = new CacheBean();
private ArrayList<Field> fields;
public ParserAnnotation(Class<?> type){
this.type = type;
}
public CacheBean parseAndGet()throws ConfigurationException{
this.prepare();
parseCache();
if(target.getXbeanClass() == null)
return null;
parseMiniTable();
parseMergings();
// parse fields
// & exclude Transient field
parseFields();
parseKeyProperty();
parseGroup();
if(needAppendInnerGroup()){
appendInnerGroup();
}
return this.target;
}
private void prepare(){
// clear transient fields
Field[] _fields = type.getDeclaredFields();
this.fields = new ArrayList<Field>(_fields.length);
for (Field field : _fields) {
Transient t = field.getAnnotation(Transient.class);
if(null == t){
this.fields.add(field);
}
}
this.fields.trimToSize();
}
private void parseGroup()throws ConfigurationException{
List<GroupBean> groups = new ArrayList<GroupBean>();
for (Field field : fields) {
Group group = field.getAnnotation(Group.class);
if(group != null){
String groupName = group.name();
if("".equals(groupName)){
groupName = Configuration.DEFAULT_GROUP_NAME;
}
groups.add(new GroupBean(groupName, field.getName(), group.value()));
}
}
Map<String, List<GroupBean>> groupMap = ListUtil.grouping(groups);
Set<String> keySet = groupMap.keySet();
for (String groupName : keySet) {
Collections.sort(groupMap.get(groupName));
}
this.target.setGroups(groupMap);
}
private void parseFields() throws ConfigurationException{
List<ModelField> fieldList = new ArrayList<ModelField>(fields.size());
for (Field field : fields) {
fieldList.add(new ModelField(field.getName()));
}
target.setFields(fieldList);
}
private void parseKeyProperty() throws ConfigurationException{
List<KeyPropertyBean> keys = new ArrayList<KeyPropertyBean>();
for (Field field : fields) {
KeyProperty kp = field.getAnnotation(KeyProperty.class);
if(kp != null){
keys.add(new KeyPropertyBean(field.getName(), kp.value()));
}
}
Collections.sort(keys);
this.target.setKeyPropertyList(keys);
}
private void parseMergings() throws ConfigurationException{
List<Merging> mergingList = new ArrayList<Merging>();
Merging merging = type.getAnnotation(Merging.class);
if(merging != null){
mergingList.add(merging);
}else{
MergingList ml = type.getAnnotation(MergingList.class);
if(ml == null)
return;
mergingList.addAll(Arrays.asList(ml.value()));
}
Map<Class<?>, List<RefrenceBean>> refrences = ListUtil
.grouping(_parseRefrence());
Map<Class<?>, MergingBean> mapMg = new HashMap<Class<?>, MergingBean>();
for (Merging mg : mergingList) {
Class<?> dtoClass = mg.value();
mapMg.put(dtoClass, _parseMerging(mg, refrences));
}
this.target.setMergings(mapMg);
}
private MergingBean _parseMerging(Merging mg, Map<Class<?>, List<RefrenceBean>> refrences) throws ConfigurationException{
MergingBean mbean = new MergingBean();
mbean.setTargetClass(mg.value());
Class<?>[] rfClass = mg.refrenceClass();
Map<Class<?>, List<RefrenceBean>> target = new HashMap<Class<?>, List<RefrenceBean>>();
for (Class<?> rfc : rfClass) {
List<RefrenceBean> lrs = refrences.get(rfc);
if(lrs != null && lrs.size() > 0){
target.put(rfc, lrs);
}
}
mbean.setRefrences(target);
return mbean;
}
private List<RefrenceBean> _parseRefrence(){
List<RefrenceBean> refrences = new ArrayList<RefrenceBean>();
for (Field field : fields) {
Refrence rf = field.getAnnotation(Refrence.class);
if(rf != null)
refrences.add(new RefrenceBean(field.getName(), rf));
Refrences rfs = field.getAnnotation(Refrences.class);
if(rfs != null){
List<Refrence> refs = Arrays.asList(rfs.value());
for (Refrence refrence : refs) {
refrences.add(new RefrenceBean(field.getName(), refrence));
}
}
}
return refrences;
}
private void parseCache() throws ConfigurationException{
Cache cache = type.getAnnotation(Cache.class);
if(cache == null)
return;
// parse prefix
String prefix = cache.value();
if(null == prefix || "".equals(prefix)){
prefix = type.getSimpleName();
}
target.setXbeanClass(type);
// TODO
// 手工修改数据造成JVM数据不一致的情况,
// 因此这里暂时将JVM标志视为REDIS级别
// target.setLevel(cache.level());
target.setLevel(CacheLevel.REDIS);
target.setKeyBuilder(cache.keyBuilder());
target.setPrefix(prefix);
}
private void parseMiniTable(){
MiniTable mt = type.getAnnotation(MiniTable.class);
target.setMiniTable(mt == null ? false : true );
}
private boolean needAppendInnerGroup(){
return target.isMiniTable();
}
private void appendInnerGroup(){
Map<String, List<GroupBean>> groups = target.getGroups();
List<GroupBean> innerGroups = new ArrayList<>();
innerGroups.add(new GroupBean(Configuration.DEFAULT_MINI_TABLE, null, 0));
groups.put(Configuration.DEFAULT_MINI_TABLE, innerGroups);
}
}
}