/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.component.recycle;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.aopalliance.intercept.MethodInvocation;
import com.jinhe.tss.component.recycle.entity.Recycle;
import com.jinhe.tss.component.support.persistence.entityaop.IDecodable;
import com.jinhe.tss.component.support.persistence.entityaop.MatchByDaoMethodNameInterceptor;
import com.jinhe.tss.core.persistence.IDao;
import com.jinhe.tss.core.persistence.IEntity;
import com.jinhe.tss.core.sso.Environment;
import com.thoughtworks.xstream.XStream;
/**
* <p> RecycleInterceptor.java </p>
* <p>
* 回收拦截器。
* 一般拦截应用中Dao对象,如果调用的dao方法名中含delete、remove等字样,且第一个参数为Recycleable接口实例
* 且当前线程的回收拦截器没有被关闭,则执行回收站操作。
*
* 本拦截器需要配置在拦截器列的最后一个,否则其后的拦截器不会被执行。
* </p>
*/
public class RecycleInterceptor extends MatchByDaoMethodNameInterceptor {
/* 控制当前线程中,回收站的拦截功能是否打开。(用以放行物理删除等操作) */
public static ThreadLocal<String> switchTL = new ThreadLocal<String>();
@SuppressWarnings("unchecked")
public Object invoke(MethodInvocation invocation) throws Throwable {
String methodName = invocation.getMethod().getName();
if (DELETE == judgeManipulateKind(methodName) && !SWITCH_CLOSE_TAG.equals(switchTL.get())) {
Object[] args = invocation.getArguments();
if( args[0] instanceof Recycleable && invocation.getThis() instanceof IDao ){
IDao<IEntity> dao = (IDao<IEntity>) invocation.getThis();
Recycleable deletedEntity = (Recycleable)args[0];
RecycleResource source = RecycleConfig.getRecycleSource(deletedEntity.getClass().getName());
//判断该类型的数据是否要进行回收操作
if (source.getToRecycle() == 1) {
//创建垃圾回收记录
Recycle recycle = createRecycleInfo(deletedEntity, source, invocation);
dao.create(recycle);
//执行逻辑删除
logicDelete(deletedEntity, source, recycle, dao);
return deletedEntity;
}
}
}
return invocation.proceed();
}
/**
* 创建一条垃圾回收信息
* @param deletedEntity
* @param source
* @param invocation
* @return
*/
Recycle createRecycleInfo(Recycleable deletedEntity, RecycleResource source, MethodInvocation invocation){
Recycle recycle = new Recycle();
recycle.setNodeId(deletedEntity.getId());
recycle.setNodeName(deletedEntity.getName());
recycle.setTypeId(source.getId());
recycle.setTypeName(source.getName());
recycle.setEntityClass(deletedEntity.getClass().getName());
recycle.setBeanId(source.getBeanId()); //被拦截的Dao对象ID
recycle.setMethodName(invocation.getMethod().getName()); //被拦截的方法名称
List<Object> params = new ArrayList<Object>();
params.add(invocation.getArguments());
params.add(invocation.getMethod().getParameterTypes());
recycle.setParams(new XStream().toXML(params)); //被拦截方法的参数和参数类型
recycle.setUserId(Environment.getOperatorId());
recycle.setUserName(Environment.getOperatorName());
recycle.setDeleteDate(new Date());
return recycle;
}
/**
* 逻辑删除
*
* @param deletedEntity
* @param resource
* @param recycle
* @param template
*/
private void logicDelete(Recycleable deletedEntity, RecycleResource resource, Recycle recycle, IDao<IEntity> dao) {
/* primary(update) */
deletedEntity.setRecycleId(recycle.getId()); //设置删除实体对应回收站的记录
deletedEntity.setDeleted(Recycle.TRUE); //打上删除标记
dao.update((IEntity) deletedEntity);
//如果被删除实体是多层结构,则删除其子节点
if ( resource.isMultiLayer() ) {
logicDeleteChild(deletedEntity, dao);
}
}
/**
* 逻辑删除子节点
* @param deletedEntity
* @param template
*/
private void logicDeleteChild(Recycleable deletedEntity, IDao<IEntity> dao) {
IDecodable node = (IDecodable) deletedEntity; //层次结构一定继承IDecodable接口
String hqlGetchild = "from " + deletedEntity.getClass().getName() + " where decode like ? ";
List<?> list = dao.getEntities(hqlGetchild, node.getDecode() + "%");
for (Iterator<?> it = list.iterator(); it.hasNext();) {
Recycleable child = (Recycleable) it.next();
child.setRecycleId(deletedEntity.getRecycleId()); //将子节点的删除原因和其父节点一致
child.setDeleted(Recycle.TRUE);
dao.update((IEntity) child);
}
}
}