All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.bpmn.runtime.handler.GatewayORActivityHandler Maven / Gradle / Ivy

package jadex.bpmn.runtime.handler;

import jadex.bpmn.model.MActivity;
import jadex.bpmn.model.MSequenceEdge;
import jadex.bpmn.runtime.BpmnInterpreter;
import jadex.bpmn.runtime.IActivityHandler;
import jadex.bpmn.runtime.ProcessThread;
import jadex.bpmn.runtime.ProcessThreadValueFetcher;
import jadex.bridge.ComponentChangeEvent;
import jadex.bridge.IComponentChangeEvent;
import jadex.commons.IValueFetcher;
import jadex.commons.SUtil;
import jadex.javaparser.IParsedExpression;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;


/**
 *  Handler for or split and join gateways.
 */
public class GatewayORActivityHandler implements IActivityHandler
{
	/** The split id counter. */
	protected int splitidcnt;
	
	/**
	 *  Execute an activity.
	 *  @param activity	The activity to execute.
	 *  @param instance	The process instance.
	 *  @param thread	The process thread.
	 */
	public void execute(MActivity activity, BpmnInterpreter instance, ProcessThread thread)
	{
		// Notify listeners as gateways are not followed by step handler execution
		instance.notifyListeners(instance.createActivityEvent(IComponentChangeEvent.EVENT_TYPE_DISPOSAL, thread, activity));

		List	incoming	= activity.getIncomingSequenceEdges();
		List	outgoing	= activity.getOutgoingSequenceEdges();
		
		// Split
		if(incoming!=null && incoming.size()==1 && outgoing!=null && outgoing.size()>1)
		{
			List threads = new ArrayList();
			IValueFetcher fetcher = new ProcessThreadValueFetcher(thread, false, instance.getFetcher());
			for(int i=0; i1 && outgoing!=null && outgoing.size()==1)
		{
			// Try to find threads for all incoming edges.
			Set	edges	= new HashSet(incoming);
			Set	threads	= new LinkedHashSet();	// Threads to be deleted.
			edges.remove(thread.getLastEdge());	// Edge of current thread not required.
			
			// Find threads that belong to my split and have arrived at gate.
			for(Iterator it=thread.getThreadContext().getThreads().iterator(); !edges.isEmpty() && it.hasNext(); )
			{
				ProcessThread oldthread	= (ProcessThread)it.next();
				if(oldthread.getSplitId()==thread.getSplitId() && edges.contains(oldthread.getLastEdge()))
				{
					threads.add(oldthread);
					edges.remove(oldthread.getLastEdge());
				}
			}
			
			if(threads.size()==thread.getSplitCount()-1)
			{
				// Find surviving thread (incoming thread has deepest stack).
				ProcessThread tmp = thread;
				for(Iterator it=threads.iterator(); it.hasNext(); )
				{
					ProcessThread pt = (ProcessThread)it.next();
					if(pt.getSplitDepth()>tmp.getSplitDepth())
					{
						tmp = pt;
					}
				}
				if(!tmp.equals(thread))
				{
					thread.setSplitInfos(tmp.getSplitInfos());
//					threads.remove(tmp);
//					threads.add(thread);
//					thread = tmp;
				}
				
				// Reset split settings.
				thread.popSplitInfo();
				
				// Handle parameter merging of incoming values.
				Set	ignore	= null;
				if(thread.hasPropertyValue("ignore"))
				{
					ignore	= new HashSet();
					String	ignores	= (String)thread.getPropertyValue("ignore");
					StringTokenizer	stok	= new StringTokenizer(ignores, ", \t\r\n");
					while(stok.hasMoreTokens())
					{
						String	ign	= stok.nextToken();
						ignore.add(ign);
						thread.removeParameterValue(ign);
					}
				}
				
				thread.setLastEdge((MSequenceEdge)outgoing.get(0));
				for(Iterator it=threads.iterator(); it.hasNext(); )
				{
					ProcessThread pt = (ProcessThread)it.next();
					pt.popSplitInfo();
					
					Map data = pt.getData();
					if(data!=null)
					{
						for(Iterator keys=data.keySet().iterator(); keys.hasNext(); )
						{
							String key = (String)keys.next();
							if(ignore==null || !ignore.contains(key))
							{
								Object value = data.get(key);
								
								if(thread.hasParameterValue(key))
								{
									Object origval =thread.getParameterValue(key);
									if(!SUtil.equals(origval, value))
									{
		//								System.out.println("origact: "+thread.getModelElement());
		//								System.out.println("act: "+pt.getModelElement());
										throw new RuntimeException("Inconsistent parameter values from threads cannot be unified in AND join: "+key+" "+value+" "+origval);
									}
								}
								else
								{
									thread.setParameterValue(key, value);
								}
							}
						}
					}
					
					thread.getThreadContext().removeThread(pt);
	//				instance.notifyListeners(BpmnInterpreter.EVENT_THREAD_REMOVED, pt);
					ComponentChangeEvent cce = new ComponentChangeEvent(IComponentChangeEvent.EVENT_TYPE_DISPOSAL, BpmnInterpreter.TYPE_THREAD, thread.getClass().getName(), 
						thread.getId(), instance.getComponentIdentifier(), instance.getCreationTime(), instance.createProcessThreadInfo(pt));
					instance.notifyListeners(cce);
				}
			}
			else
			{
	//			thread.setWaitingState(ProcessThread.WAITING_FOR_JOIN);
				thread.setWaiting(true);
			}
		}
		else
		{
			throw new UnsupportedOperationException("Invalid number of edges for parallel split/join: "+activity+", "+instance);
		}
		
	}
	
	/**
	 *  Execute an activity.
	 *  @param activity	The activity to execute.
	 *  @param instance	The process instance.
	 *  @param thread The process thread.
	 *  @param info The info object.
	 */
	public void cancel(MActivity activity, BpmnInterpreter instance, ProcessThread thread)
	{
	}
	
	/**
	 *  Safely evaluate a branch expression.
	 */
	protected boolean isValid(ProcessThread thread, IParsedExpression exp, IValueFetcher fetcher)
	{
		boolean ret = false;
		try
		{
//			System.out.println("Evaluating: "+thread.getInstance()+", "+exp.getExpressionText());
			ret = ((Boolean)exp.getValue(fetcher)).booleanValue();
//			System.out.println("Evaluated: "+ret);
		}
		catch(Exception e)
		{
			thread.getInstance().getLogger().warning("Error in branch condition: "+thread+", "+exp+", "+e);
//			e.printStackTrace();
		}
		return ret;
	}
	
	/**
	 *  Get next split id.
	 */
	protected int getNextSplitId()
	{
		return ++splitidcnt;
	}
}
	




© 2015 - 2025 Weber Informatics LLC | Privacy Policy