Package org.jboss.seam.interceptors

Source Code of org.jboss.seam.interceptors.ConversationInterceptor

//$Id: ConversationInterceptor.java,v 1.61 2007/02/26 23:56:05 gavin Exp $
package org.jboss.seam.interceptors;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.jboss.seam.annotations.AroundInvoke;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.BeginTask;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.EndTask;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.Interceptor;
import org.jboss.seam.annotations.StartTask;
import org.jboss.seam.core.ConversationEntries;
import org.jboss.seam.core.ConversationEntry;
import org.jboss.seam.core.Interpolator;
import org.jboss.seam.core.Manager;
import org.jboss.seam.core.Pageflow;
import org.jboss.seam.core.PersistenceContexts;
import org.jboss.seam.intercept.InvocationContext;

/**
* After the end of the invocation, begin or end a long running
* conversation, if necessary.
*
* @author Gavin King
*/
@Interceptor(stateless=true,
             around={ValidationInterceptor.class, BijectionInterceptor.class},
             within=BusinessProcessInterceptor.class)
public class ConversationInterceptor extends AbstractInterceptor
{
   private static final long serialVersionUID = -5405533438107796414L;

   @AroundInvoke
   public Object aroundInvoke(InvocationContext invocation) throws Exception
   {
      Method method = invocation.getMethod();
      if ( getComponent().isConversationManagementMethod(method) ) //performance optimization
      {
  
         if ( isMissingJoin(method) )
         {
            throw new IllegalStateException("begin method invoked from a long running conversation, try using @Begin(join=true) on method: " + method.getName());
         }
        
         if ( redirectToExistingConversation(method) )
         {
            return null;
         }
         else
         {
            Object result = invocation.proceed();  
            beginConversationIfNecessary(method, result);
            endConversationIfNecessary(method, result);
            return result;
         }
        
      }
      else
      {
         return invocation.proceed();
      }
   }
  
   public boolean redirectToExistingConversation(Method method)
   {
      if ( !Manager.instance().isLongRunningConversation() )
      {
         String id = null;
         if ( method.isAnnotationPresent(Begin.class) )
         {
            id = method.getAnnotation(Begin.class).id();
         }
         else if ( method.isAnnotationPresent(BeginTask.class) )
         {
            id = method.getAnnotation(BeginTask.class).id();
         }
         else if ( method.isAnnotationPresent(StartTask.class) )
         {
            id = method.getAnnotation(StartTask.class).id();
         }
        
         if ( id!=null && !"".equals(id) )
         {
            id = Interpolator.instance().interpolate(id);
            ConversationEntry ce = ConversationEntries.instance().getConversationEntry(id);
            if (ce==null)
            {
               Manager.instance().updateCurrentConversationId(id);
            }
            else
            {
               return ce.switchConversation();
            }
         }
      }
     
      return false;
   }

   private boolean isMissingJoin(Method method) {
      return Manager.instance().isLongRunningOrNestedConversation() && (
            (
                  method.isAnnotationPresent(Begin.class) &&
                  !method.getAnnotation(Begin.class).join() &&
                  !method.getAnnotation(Begin.class).nested()
            ) ||
            method.isAnnotationPresent(BeginTask.class) ||
            method.isAnnotationPresent(StartTask.class)
         );
   }

   private void beginConversationIfNecessary(Method method, Object result)
   {
     
      boolean simpleBegin =
            method.isAnnotationPresent(StartTask.class) ||
            method.isAnnotationPresent(BeginTask.class) ||
            ( method.isAnnotationPresent(Begin.class) && method.getAnnotation(Begin.class).ifOutcome().length==0 );
      if ( simpleBegin )
      {
         if ( result!=null || method.getReturnType().equals(void.class) )
         {
            boolean nested = false;
            if ( method.isAnnotationPresent(Begin.class) )
            {
               nested = method.getAnnotation(Begin.class).nested();
            }
            beginConversation( nested, getProcessDefinitionName(method) );
            setFlushMode(method); //TODO: what if conversation already exists? Or a nested conversation?
         }
      }
      else if ( method.isAnnotationPresent(Begin.class) )
      {
         String[] outcomes = method.getAnnotation(Begin.class).ifOutcome();
         if ( outcomes.length==0 || Arrays.asList(outcomes).contains(result) )
         {
            beginConversation(
                  method.getAnnotation(Begin.class).nested(),
                  getProcessDefinitionName(method)
               );
            setFlushMode(method); //TODO: what if conversation already exists? Or a nested conversation?
         }
      }
     
   }
  
   private void setFlushMode(Method method)
   {
      FlushModeType flushMode;
      if (method.isAnnotationPresent(Begin.class))
      {
         flushMode = method.getAnnotation(Begin.class).flushMode();
      }
      else if (method.isAnnotationPresent(BeginTask.class))
      {
         flushMode = method.getAnnotation(BeginTask.class).flushMode();
      }
      else if (method.isAnnotationPresent(StartTask.class))
      {
         flushMode = method.getAnnotation(StartTask.class).flushMode();
      }
      else
      {
         return;
      }
     
      PersistenceContexts.instance().changeFlushMode(flushMode);
   }

   private String getProcessDefinitionName(Method method) {
      if ( method.isAnnotationPresent(Begin.class) )
      {
         return method.getAnnotation(Begin.class).pageflow();
      }
      if ( method.isAnnotationPresent(BeginTask.class) )
      {
         return method.getAnnotation(BeginTask.class).pageflow();
      }
      if ( method.isAnnotationPresent(StartTask.class) )
      {
         return method.getAnnotation(StartTask.class).pageflow();
      }
      //TODO: let them pass a pageflow name as a request parameter
      return "";
   }

   private void beginConversation(boolean nested, String pageflowName)
   {
      if ( !Manager.instance().isLongRunningOrNestedConversation() )
      {
         Manager.instance().beginConversation( getComponent().getName() );
         beginNavigation(pageflowName);
      }
      else if (nested)
      {
         Manager.instance().beginNestedConversation( getComponent().getName() );
         beginNavigation(pageflowName);
      }
   }
  
   private void beginNavigation(String pageflowName)
   {
      if ( !pageflowName.equals("") )
      {
         Pageflow.instance().begin(pageflowName);
      }
   }

   private void endConversationIfNecessary(Method method, Object result)
   {
      boolean isEndAnnotation = method.isAnnotationPresent(End.class);
      boolean isEndTaskAnnotation = method.isAnnotationPresent(EndTask.class);
     
      boolean beforeRedirect = ( isEndAnnotation && method.getAnnotation(End.class).beforeRedirect() ) ||
            ( isEndTaskAnnotation && method.getAnnotation(EndTask.class).beforeRedirect() );
     
      boolean simpleEnd =
            ( isEndAnnotation && method.getAnnotation(End.class).ifOutcome().length==0 ) ||
            ( isEndTaskAnnotation && method.getAnnotation(EndTask.class).ifOutcome().length==0 );
      if ( simpleEnd )
      {
         if ( result!=null || method.getReturnType().equals(void.class) ) //null outcome interpreted as redisplay
         {
            endConversation(beforeRedirect);
         }
      }
      else if ( isEndAnnotation )
      {
         String[] outcomes = method.getAnnotation(End.class).ifOutcome();
         if ( Arrays.asList(outcomes).contains(result) )
         {
            endConversation(beforeRedirect);
         }
      }
      else if ( isEndTaskAnnotation )
      {
         //TODO: fix minor code duplication
         String[] outcomes = method.getAnnotation(EndTask.class).ifOutcome();
         if ( Arrays.asList(outcomes).contains(result) )
         {
            endConversation(beforeRedirect);
         }
      }
   }

   private void endConversation(boolean beforeRedirect)
   {
      Manager.instance().endConversation(beforeRedirect);
   }

}
TOP

Related Classes of org.jboss.seam.interceptors.ConversationInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.