/***************************************************************** JADE - Java Agent DEvelopment Framework is a framework to develop multi-agent systems in compliance with the FIPA specifications. Copyright (C) 2000 CSELT S.p.A. GNU Lesser General Public License This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 2.1 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *****************************************************************/ package jade.core.behaviours; import jade.core.*; import java.util.Date; /** * This abstract class implements a OneShot task that must be executed * only one just after a given timeout is elapsed. * <p> The task is simply the call to the method * <code>handleElapsedTimeout()</code> that must be implemented by * all subclasses. Notice that the best practice in JADE is when * this method just adds a behaviour to the agent class. * <p> All subclasses have available the protected variable * <code>myAgent</code> that points to the agent class. * <p> The programmer must use this abstract class in this simple way: * <ul> * <li> implements a subclass that extends WakerBehaviour. This subclass * must implement the method <code>handleElapsedTimeout</code>. * <li> add the subclass to the list of behaviour of this agent by using * <code>addBehaviour()</code> method. * <li> the method <code>handleElapsedTimeout</code> must implement the * task that will be executed after the timeout is elapsed. * </ul> * * @author Fabio Bellifemine - CSELT S.p.A. * @version $Date: 2009-04-20 11:58:28 +0200 (lun, 20 apr 2009) $ $Revision: 6114 $ */ public abstract class WakerBehaviour extends SimpleBehaviour { //private static final long MINIMUM_TIMEOUT = 10000; // 1 second /** @serial */ private long wakeupTime, blockTime, timeout; /** @serial */ private int state; /** @serial */ private boolean finished; /** * This method constructs the behaviour. * @param a is the pointer to the agent * @param wakeupDate is the date when the task must be executed */ public WakerBehaviour(Agent a, Date wakeupDate) { super(a); timeout = 0; wakeupTime = wakeupDate.getTime(); state = 0; finished = false; } /** * This method constructs the behaviour. * @param a is the pointer to the agent * @param timeout indicates the number of milliseconds after which the * task must be executed */ public WakerBehaviour(Agent a, long timeout) { super(a); wakeupTime = -1; this.timeout = timeout; state = 0; finished = false; } public final void action() { if (!finished) { switch (state) { case 0: { // Adjust wakeupTime in case the user set a relative time if (wakeupTime == -1) { wakeupTime = System.currentTimeMillis()+timeout; } // in this state the behaviour blocks itself blockTime = wakeupTime - System.currentTimeMillis(); if (blockTime > 0) // MINIMUM_TIMEOUT) //blockTime = MINIMUM_TIMEOUT; block(blockTime); state++; break; } case 1: { // in this state the behaviour can be restarted for two reasons // 1. the timeout is elapsed (then the handler method is called // and the behaviour is definitively finished) // 2. a message has arrived for this agent (then it blocks again and // the FSM remains in this state) blockTime = wakeupTime - System.currentTimeMillis(); if (blockTime <= 0) { // timeout is expired finished = true; onWake(); } else block(blockTime); break; } default : { state=0; break; } } // end of switch } } //end of action /** This method is invoked when the deadline defined in the constructor is reached (or when the timeout specified in the constructor expires). Subclasses are expected to define this method specifying the action that must be performed at that time. */ protected void onWake() { handleElapsedTimeout(); } /** * @deprecated Use onWake() instead */ protected void handleElapsedTimeout() { } /** * This method must be called to reset the behaviour and starts again * @param wakeupDate is the new time when the task must be executed again */ public void reset(Date wakeupDate) { reset(); wakeupTime = wakeupDate.getTime(); } /** * This method must be called to reset the behaviour and starts again * @param timeout indicates in how many milliseconds from now the behaviour * must be waken up again. */ public void reset(long timeout) { reset(); this.timeout = timeout; } /** * This method must be called to reset the behaviour and starts again */ public void reset() { super.reset(); wakeupTime = -1; state = 0; finished = false; } /** * Make this WakerBehaviour terminate without calling the onWake() method. * Calling stop() has the same effect as removing this WakerBehaviour, but is Thread safe */ public void stop() { finished = true; restart(); } public final boolean done() { return finished; } public final long getWakeupTime() { return wakeupTime; } }