/* * JBoss, Home of Professional Open Source * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.seam.bpm; import java.lang.reflect.Method; import org.jboss.seam.annotations.bpm.BeginTask; import org.jboss.seam.annotations.bpm.CreateProcess; import org.jboss.seam.annotations.bpm.EndTask; import org.jboss.seam.annotations.bpm.ResumeProcess; import org.jboss.seam.annotations.bpm.StartTask; import org.jboss.seam.annotations.intercept.AroundInvoke; import org.jboss.seam.annotations.intercept.Interceptor; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.core.BijectionInterceptor; import org.jboss.seam.core.Expressions; import org.jboss.seam.core.Init; import org.jboss.seam.intercept.AbstractInterceptor; import org.jboss.seam.intercept.InvocationContext; import org.jboss.seam.log.LogProvider; import org.jboss.seam.log.Logging; import org.jboss.seam.util.Strings; import org.jboss.seam.web.Parameters; /** * Implements annotation-based business-process demarcation. * * @author <a href="mailto:steve@hibernate.org">Steve Ebersole</a> * @author Gavin King */ @Interceptor(stateless=true, around=BijectionInterceptor.class) public class BusinessProcessInterceptor extends AbstractInterceptor { private static final long serialVersionUID = 758197867958840918L; private static final LogProvider log = Logging.getLogProvider( BusinessProcessInterceptor.class ); @AroundInvoke public Object aroundInvoke(InvocationContext invocation) throws Exception { if ( !beforeInvocation(invocation) ) { return null; } else { return afterInvocation( invocation, invocation.proceed() ); } } private boolean beforeInvocation(InvocationContext invocationContext) { Method method = invocationContext.getMethod(); if ( method.isAnnotationPresent(StartTask.class) ) { log.trace( "encountered @StartTask" ); StartTask tag = method.getAnnotation(StartTask.class); Long taskId = getProcessOrTaskId( tag.taskIdParameter(), tag.taskId() ); return BusinessProcess.instance().resumeTask(taskId); } else if ( method.isAnnotationPresent(BeginTask.class) ) { log.trace( "encountered @BeginTask" ); BeginTask tag = method.getAnnotation(BeginTask.class); Long taskId = getProcessOrTaskId( tag.taskIdParameter(), tag.taskId() ); return BusinessProcess.instance().resumeTask(taskId); } else if ( method.isAnnotationPresent(ResumeProcess.class) ) { log.trace( "encountered @ResumeProcess" ); ResumeProcess tag = method.getAnnotation(ResumeProcess.class); if ( tag.processKey().equals("") ) { Long processId = getProcessOrTaskId( tag.processIdParameter(), tag.processId() ); return BusinessProcess.instance().resumeProcess(processId); } else { return BusinessProcess.instance().resumeProcess( tag.definition(), getProcessKey( tag.processKey() ) ); } } if ( method.isAnnotationPresent(EndTask.class) ) { log.trace( "encountered @EndTask" ); return BusinessProcess.instance().validateTask(); } else { return true; } } private Object afterInvocation(InvocationContext invocation, Object result) { Method method = invocation.getMethod(); if ( result!=null || method.getReturnType().equals(void.class) ) //interpreted as "redisplay" { if ( method.isAnnotationPresent(CreateProcess.class) ) { log.trace( "encountered @CreateProcess" ); CreateProcess tag = method.getAnnotation(CreateProcess.class); if ( tag.processKey().equals("") ) { BusinessProcess.instance().createProcess( tag.definition() ); } else { BusinessProcess.instance().createProcess( tag.definition(), getProcessKey( tag.processKey() ) ); } } if ( method.isAnnotationPresent(StartTask.class) ) { log.trace( "encountered @StartTask" ); BusinessProcess.instance().startTask(); } if ( method.isAnnotationPresent(EndTask.class) ) { log.trace( "encountered @EndTask" ); BusinessProcess.instance().endTask( method.getAnnotation(EndTask.class).transition() ); } if ( method.isAnnotationPresent(org.jboss.seam.annotations.bpm.Transition.class) ) { log.trace( "encountered @Transition" ); String transitionName = method.getAnnotation(org.jboss.seam.annotations.bpm.Transition.class).value(); if ( "".equals(transitionName) ) transitionName = method.getName(); BusinessProcess.instance().transition(transitionName); } } return result; } private String getProcessKey(String el) { Object key = Expressions.instance().createValueExpression(el).getValue(); if (key==null) { throw new IllegalStateException("process business key may not be null"); } return key.toString(); } private Long getProcessOrTaskId(String paramName, String el) { Object id; if ( Strings.isEmpty(paramName) ) { id = Expressions.instance().createValueExpression(el).getValue(); } else { String[] values = Parameters.instance().getRequestParameters().get(paramName); id = values!=null && values.length==1 ? values[0] : null; } if (id==null) { throw new IllegalStateException("task/process id may not be null"); } else if (id instanceof Long) { return (Long) id; } else if (id instanceof String) { return new Long( (String) id ); } else { throw new IllegalArgumentException("task/process id must be a string or long"); } } public boolean isInterceptorEnabled() { return Contexts.isApplicationContextActive() && Init.instance().isJbpmInstalled(); } }