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

jadex.bdiv3.actions.ExecutePlanStepAction Maven / Gradle / Ivy

package jadex.bdiv3.actions;

import java.util.Collections;

import jadex.bdiv3.features.impl.BDILifecycleAgentFeature;
import jadex.bdiv3.features.impl.IInternalBDIAgentFeature;
import jadex.bdiv3.model.MPlan;
import jadex.bdiv3.runtime.impl.IPlanBody;
import jadex.bdiv3.runtime.impl.RGoal;
import jadex.bdiv3.runtime.impl.RPlan;
import jadex.bdiv3.runtime.impl.RProcessableElement;
import jadex.bridge.IConditionalComponentStep;
import jadex.bridge.IInternalAccess;
import jadex.commons.MethodInfo;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.ExceptionDelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.IResultListener;

// todo: use IPlan (and plan executor abstract to be able to execute plans as subcomponents)
// todo: allow using multi-step plans

/**
 *  Action for executing a plan step. 
 */
public class ExecutePlanStepAction implements IConditionalComponentStep
{
	/** The plan. */
	protected RPlan rplan;
	
//	/** The resume command. */
//	protected ICommand rescom;
	
	/**
	 *  Create a new action.
	 */
	public ExecutePlanStepAction(RPlan rplan)
	{
//		this(rplan, null);
		this.rplan = rplan;
	}
	
//	/**
//	 *  Create a new action.
//	 */
//	public ExecutePlanStepAction(RPlan rplan, ICommand rescom)
//	{
////		System.err.println("epsa: "+rplan);
////		Thread.dumpStack();
////		this.element = element;
//		this.rplan = rplan;
//		this.rescom = rescom;
//	}
	
	/**
	 *  Test if the action is valid.
	 *  @return True, if action is valid.
	 */
	public boolean isValid()
	{
		// todo: abort execution
		boolean ret = RPlan.PlanLifecycleState.NEW.equals(rplan.getLifecycleState())
			|| RPlan.PlanLifecycleState.BODY.equals(rplan.getLifecycleState());
		
//		if(ret)
//		{
//			Object element = rplan.getReason();
//			if(element instanceof RGoal)
//			{
//				RGoal rgoal = (RGoal)element;
//				ret = RGoal.GOALLIFECYCLESTATE_ACTIVE.equals(rgoal.getLifecycleState())
//					&& RGoal.GOALPROCESSINGSTATE_INPROCESS.equals(rgoal.getProcessingState());
//				// todo: hack, how to avoid side effect
//				if(!ret)
//					rplan.abort();
//			}
//		}
			
//		if(!ret)
//			System.out.println("not valid: "+rplan);
		
		return ret;
	}
	
	/**
	 *  Execute the command.
	 *  @param args The argument(s) for the call.
	 *  @return The result of the command.
	 */
	public IFuture execute(final IInternalAccess ia)
	{
		final Future ret = new Future();
		
//		if(!isReasonValid())
//			System.out.println("executing invalid candidate: "+rplan);
		
//		if(rplan.toString().indexOf("go_home")!=-1)
//			System.out.println("plan exe: "+rplan);
		
		// problem plan context for steps needed that allows to know
		// when a plan has completed 
		
		final Object element = rplan.getReason();
		if(element instanceof RGoal)
		{
			RGoal rgoal = (RGoal)element;
			
//			System.out.println("executing candidate: "+rplan+" "+rgoal.getLifecycleState()+" "+rgoal.getProcessingState());
			
			if(!(RGoal.GoalLifecycleState.ACTIVE.equals(rgoal.getLifecycleState())
				&& RGoal.GoalProcessingState.INPROCESS.equals(rgoal.getProcessingState())))
			{
				// todo: hack, how to avoid side effect
//				rplan.abort();
				return IFuture.DONE;
			}
		}
		
		// Initial context condition evaluation
		// Checks the context condition also directly before a plan is executed
		// Otherwise the rule might trigger only after the next state change (event)
		checkContextCondition().addResultListener(new ExceptionDelegationResultListener(ret)
		{
			public void customResultAvailable(Boolean context) throws Exception
			{
				if(!context)
				{
					rplan.abort();
					if(rplan.getReason() instanceof RProcessableElement)
					{
						((RProcessableElement)rplan.getReason()).planFinished(rplan.getAgent(), null);
					}
				}
				else
				{
					// Rescom now directly executed 
			//		if(RPlan.PlanProcessingState.WAITING.equals(rplan.getProcessingState()))
			//		{
			//			rescom.execute(null);
			////			rplan.continueAfterWait(rescom);
			//		}else if
					// A new plan body must only be executed if it hasn't been aborted 
					if(!rplan.isFinishing() && RPlan.PlanLifecycleState.NEW.equals(rplan.getLifecycleState()))
					{
						// Set plan as child of goal
						if(element instanceof RGoal)
						{
							RGoal rgoal = (RGoal)element;
							rgoal.setChildPlan(rplan);
						}
						
//						System.out.println("execute plan: "+rplan);
						
			//			final BDIAgentInterpreter ip = (BDIAgentInterpreter)((BDIAgent)ia).getInterpreter();
						ia.getComponentFeature(IInternalBDIAgentFeature.class).getCapability().addPlan(rplan);
						
						IPlanBody body = rplan.getBody();
						body.executePlan().addResultListener(new IResultListener()
						{
							public void resultAvailable(Void result)
							{
								ia.getComponentFeature(IInternalBDIAgentFeature.class).getCapability().removePlan(rplan);
								Object reason = rplan.getReason();
								if(reason instanceof RProcessableElement)
								{
									((RProcessableElement)reason).planFinished(ia, rplan);
								}
							}
							
							public void exceptionOccurred(Exception exception)
							{
								resultAvailable(null);
							}
						});
					}
					// Only needs to to something for waiting and new plans
					// Should processing state be set back to ready in case the plan is not within a step?
			//		else
			//		{
			//			System.out.println("Plan proc state invalid: "+rplan.getProcessingState()+" "+rplan);
			//		}
					
					ret.setResult(null);
				}
			}
		});
		
		return ret;
	}
	
	/**
	 *  Get the rplan.
	 */
	public RPlan	getRPlan()
	{
		return rplan;
	}
	
	/**
	 *  Check the context condition.
	 *  @return True if context is ok.
	 */
	protected IFuture checkContextCondition()
	{
		Future ret = new Future();
		
		// Check context condition initially, allows for fast abort before first step
		MPlan mplan = (MPlan)rplan.getModelElement();
		final MethodInfo mi = mplan.getBody().getContextConditionMethod(rplan.getAgent().getClassLoader());
		boolean context = true;
		if(mi!=null)
		{
			IFuture fut = BDILifecycleAgentFeature.invokeBooleanMethod(rplan.getBody().getBody(), mi.getMethod(rplan.getAgent().getClassLoader()), 
				mplan, null, rplan, rplan.getAgent());
			// todo: case in which context condition is futureized
			fut.addResultListener(new DelegationResultListener(ret));
		}
		else if(mplan.getContextCondition()!=null)
		{
			context = BDILifecycleAgentFeature.evaluateCondition(rplan.getAgent(), mplan.getContextCondition(), rplan.getModelElement(), 
				Collections.singletonMap(rplan.getFetcherName(), (Object)rplan));
			ret.setResult(context);
		}
		else
		{
			ret.setResult(context);
		}
		
//		System.out.println("context cond: "+context+" "+mplan.getName());
		
		return ret;
	}
	
//	/**
//	 * 
//	 */
//	protected boolean isReasonValid()
//	{
//		boolean ret = true;
//		Object element = rplan.getReason();
//		if(element instanceof RGoal)
//		{
//			RGoal rgoal = (RGoal)element;
//			ret = IGoal.GoalLifecycleState.ACTIVE.equals(rgoal.getLifecycleState())
//				&& IGoal.GoalProcessingState.INPROCESS.equals(rgoal.getProcessingState());
//		}
//		return ret;
//	}
	
	/**
	 *  Return a string.
	 */
	public String	toString()
	{
		return "ExecutePlanStepAction("+rplan+")";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy