/* ================================================================== * 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); } } }