/***************************************************************** 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.proto.states; //#CUSTOM_EXCLUDE_FILE import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.*; /** * This behaviour is a simple implementation of a message receiver. * It puts into the given key of the given datastore the received message * according to the given message template and timeout. All these * data must be passed in the constructor. * If the timeout expires before any message arrives, the behaviour * terminates and put null into the datastore. * @author Tiziana Trucco - TILab * @version $Date: 2005-09-16 15:54:46 +0200 (ven, 16 set 2005) $ $Revision: 5780 $ **/ public class MsgReceiver extends SimpleBehaviour { /** A numeric constant to mean that a timeout expired. */ public static final int TIMEOUT_EXPIRED = -1001; /** A numeric constant to mean that the receive operation was interrupted. */ public static final int INTERRUPTED = -1002; /** A numeric constant to mean that the deadline for the receive operation will never expire. */ public static final int INFINITE = -1; protected MessageTemplate template; protected long deadline; protected Object receivedMsgKey; private boolean received; private boolean expired; private boolean interrupted; private int ret; /** * Constructor. * @param a a reference to the Agent * @param mt the MessageTemplate of the message to be received, if null * the first received message is returned by this behaviour * @param deadline a timeout for waiting until a message arrives. It must * be expressed as an absolute time, as it would be returned by * <code>System.currentTimeMillisec()</code> * @param s the dataStore for this bheaviour * @param msgKey the key where the beahviour must put the received * message into the DataStore. **/ public MsgReceiver(Agent a, MessageTemplate mt, long deadline, DataStore s, Object msgKey) { super(a); setDataStore(s); template = mt; this.deadline = deadline; receivedMsgKey = msgKey; received = false; expired = false; interrupted = false; } //#APIDOC_EXCLUDE_BEGIN // For persistence service protected MsgReceiver() { } public void action() { if (interrupted) { if (receivedMsgKey != null) { getDataStore().put(receivedMsgKey, null); } ret = INTERRUPTED; return; } ACLMessage msg = myAgent.receive(template); if (msg != null) { if (receivedMsgKey != null) { getDataStore().put(receivedMsgKey, msg); } received = true; ret = msg.getPerformative(); handleMessage(msg); } else { if (deadline >= 0) { // If a timeout was set, then check if it is expired long blockTime = deadline - System.currentTimeMillis(); if(blockTime <=0){ //timeout expired if (receivedMsgKey != null) { getDataStore().put(receivedMsgKey, null); } expired = true; ret = TIMEOUT_EXPIRED; handleMessage(null); }else{ block(blockTime); } } else { block(); } } } public boolean done() { return received || expired || interrupted; } /** * @return the performative if a message arrived, * <code>TIMEOUT_EXPIRED</code> if the timeout expired or * <code>INTERRUPTED</code> if this <code>MsgReceiver</code> * was interrupted calling the <code>interrupt()</code> method. **/ public int onEnd() { received =false; expired =false; interrupted =false; return ret; } //#APIDOC_EXCLUDE_END /** This is invoked when a message matching the specified template is received or the timeout has expired (the <code>msg</code> parameter is null in this case). Users may redefine this method to react to this event. The default implementation of does nothing. */ protected void handleMessage(ACLMessage msg) { } /** Reset this behaviour, possibly replacing the receive templatt and other data. @param mt The template to match ACL messages against during the receive operation. @param deadline The relative timeout of the receive operation. If the <code>INFINITE</code> constant is used, then no deadline is set and the operation will wait until a matching ACL message arrives. @param s The datastore where the received ACL message is to be put. @param msgKey The key to use to put the received message into the selected datastore. */ public void reset(MessageTemplate mt, long deadline, DataStore s, Object msgKey) { super.reset(); received = false; expired = false; interrupted =false; setTemplate(mt); setDeadline(deadline); setDataStore(s); setReceivedKey(msgKey); } /** * This method allows modifying the deadline **/ public void setDeadline(long deadline) { this.deadline = deadline; } /** * This method allows modifying the template **/ public void setTemplate(MessageTemplate mt) { template=mt; } /** * This method allows modifying the key in the DS where to put the * received message **/ public void setReceivedKey(Object key) { receivedMsgKey = key; } /** Signal an interruption to this receiver, and cause the ongoing receive operation to abort. */ public void interrupt() { interrupted = true; restart(); } }