📄 simpleachievereinitiator.java
字号:
/*****************************************************************
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;
//#CUSTOM_EXCLUDE_FILE
import java.util.Vector;
import java.util.Date;
import jade.core.behaviours.SimpleBehaviour;
import jade.core.behaviours.DataStore;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.util.leap.Iterator;
import jade.core.Agent;
import jade.core.AID;
import jade.util.Logger;
/**
* This is simple implementation of the AchieveREInitiator.
* This implementation in particular is 1:1 and does not allow
* the possibility to add Handler.
*
* This is a single homogeneous and effective implementation of
* all the FIPA-Request-like interaction protocols defined by FIPA,
* that is all those protocols where the initiator sends a single message
* (i.e. it performs a single communicative act) within the scope
* of an interaction protocol in order to verify if the RE (Rational
* Effect) of the communicative act has been achieved or not.
* <p>
* FIPA has already specified a number of these interaction protocols, like
* FIPA-Request, FIPA-query, FIPA-Request-When, FIPA-recruiting,
* FIPA-brokering, FIPA-subscribe, that allows the initiator to verify if the
* expected rational effect of a single communicative act has been achieved.
* <p>
* The structure of these protocols is equal.
* The initiator sends a message (in general it performs a communicative act).
* <p>
* The responder can then reply by sending a <code>not-understood</code>, or a
* <code>refuse</code> to
* achieve the rational effect of the communicative act, or also
* an <code>agree</code> message to communicate the agreement to perform
* (possibly in the future) the communicative act. This first category
* of reply messages has been here identified as a response.
* <p> The responder performs the action and, finally, must respond with an
* <code>inform</code> of the result of the action (eventually just that the
* action has been done) or with a <code>failure</code> if anything went wrong.
* This second category of reply messages has been here identified as a
* result notification.
* <p> Notice that we have extended the protocol to make optional the
* transmission of the agree message. Infact, in most cases performing the
* action takes so short time that sending the agree message is just an
* useless and uneffective overhead; in such cases, the agree to perform the
* communicative act is subsumed by the reception of the following message in
* the protocol.
* <p>
* Read carefully the section of the
* <a href="..\..\..\programmersguide.pdf"> JADE programmer's guide </a>
* that describes
* the usage of this class.
* <p> <b>Known bugs:</b>
* <i> The handler <code>handleAllResponses</code> is not called if the <code>
* agree</code> message is skipped and the <code>inform</code> message
* is received instead.
*
* @see SimpleAchieveREResponder
* @see AchieveREInitiator
* @see AchieveREResponder
* @author Tiziana Trucco - TILab
* @version $Date: 2005-09-16 15:54:46 +0200 (ven, 16 set 2005) $ $Revision: 5780 $
**/
public class SimpleAchieveREInitiator extends SimpleBehaviour{
private final static int PREPARE_MSG_STATE =0;
private final static int SEND_MSG_STATE = 1;
private final static int RECEIVE_REPLY_STATE = 2;
private final static int RECEIVE_2ND_REPLY_STATE = 3;
private final static int ALL_REPLIES_RECEIVED_STATE = 4;
private final static int ALL_RESULT_NOTIFICATION_RECEIVED_STATE = 5;
/**
* key to retrive from the datastore the ACLMessage passed in the constructor
**/
public final String REQUEST_KEY = "_request" + hashCode() ;
/**
* key to retrive from the datastore the ACLMessage that has been sent.
**/
public final String REQUEST_SENT_KEY = "_request_sent" + hashCode();
/**
* key to retrive the second reply received.
**/
public final String SECOND_REPLY_KEY = "_2nd_reply" + hashCode();
/**
* key to retrive all the responses received.
**/
public final String ALL_RESPONSES_KEY = "_all-responses" + hashCode();
/**
* key to retrive the result notification received.
**/
public final String ALL_RESULT_NOTIFICATIONS_KEY = "_all-result-notification" + hashCode();
//private ACLMessage request = null;
private MessageTemplate mt = null;
private int state = PREPARE_MSG_STATE;
private boolean finished;
private long timeout = -1;
private long endingTime = 0;
private Logger logger= Logger.getMyLogger(this.getClass().getName());
/**
* Construct for the class by creating a new empty DataStore
* @see #SimpleAchieveREInitiator(Agent, ACLMessage, DataStore)
**/
public SimpleAchieveREInitiator(Agent a,ACLMessage msg){
this(a,msg,new DataStore());
}
/**
* Constructs a <code>SimpleAchieveREInitiator</code> behaviour
* @param a The agent performing the protocol
* @param msg The message that must be used to initiate the protocol.
* Notice that in this simple implementation, the
* <code>prepareMessage</code>
* method returns a single message.
* @param s The <code>DataStore</code> that will be used by this
* <code>SimpleAchieveREInitiator</code>
*/
public SimpleAchieveREInitiator(Agent a,ACLMessage msg,DataStore store){
super(a);
setDataStore(store);
// request = msg;
getDataStore().put(REQUEST_KEY,msg);
finished = false;
}
public final void action(){
switch(state){
case PREPARE_MSG_STATE:{
//retrive the message to send
ACLMessage msg = prepareRequest((ACLMessage)getDataStore().get(REQUEST_KEY));
getDataStore().put(REQUEST_SENT_KEY,msg);
state = SEND_MSG_STATE;
break;
}
case SEND_MSG_STATE:{
//send the message. If there is more than one receiver only the first will be taken into account.
DataStore ds = getDataStore();
String conversationID = null;
ACLMessage request = (ACLMessage)ds.get(REQUEST_SENT_KEY);
if (request == null){
//no message to send --> protocol finished;
//state = FINAL_STATE;
finished = true;
break;
}else{
if(request.getConversationId()== null){
conversationID = "C" +hashCode()+"_" + System.currentTimeMillis();
request.setConversationId(conversationID);
}
else
conversationID = request.getConversationId();
mt = MessageTemplate.MatchConversationId(conversationID);
//send the message only to the first receiver.
Iterator receivers = request.getAllReceiver();
AID r = (AID)receivers.next();
request.clearAllReceiver();
request.addReceiver(r);
if(receivers.hasNext())
if(logger.isLoggable(Logger.WARNING))
logger.log(Logger.WARNING,"The message you are sending has more than one receivers. The message will be sent only to the first one !!");
if(r.equals(myAgent.getAID())){
//if myAgent is the receiver then modify the messageTemplate
//to avoid intercepting the request as it was a reply.
mt = MessageTemplate.and(mt,MessageTemplate.not(MessageTemplate.MatchCustom(request,true)));
}
//set the timeout
//FIXME: if the Timeout is already expired before the message will be sent, it will be considered a infinite timeout
Date d = request.getReplyByDate();
if(d!=null)
timeout = d.getTime() - (new Date()).getTime();
else
timeout = -1;
endingTime = System.currentTimeMillis()+ timeout;
myAgent.send(request);
state = RECEIVE_REPLY_STATE;
}
break;
}
case RECEIVE_REPLY_STATE:{
ACLMessage firstReply = myAgent.receive(mt);
if(firstReply != null){
DataStore ds = getDataStore();
switch(firstReply.getPerformative()){
case ACLMessage.AGREE:{
state = RECEIVE_2ND_REPLY_STATE;
Vector allResp = (Vector)ds.get(ALL_RESPONSES_KEY);
allResp.addElement(firstReply);
handleAgree(firstReply);
//all the responses have been collected.
handleAllResponses((Vector)getDataStore().get(ALL_RESPONSES_KEY));
break;
}
case ACLMessage.REFUSE:{
Vector allResp = (Vector) ds.get(ALL_RESPONSES_KEY);
allResp.addElement(firstReply);
state = ALL_REPLIES_RECEIVED_STATE;
handleRefuse(firstReply);
break;
}
case ACLMessage.NOT_UNDERSTOOD:{
Vector allResp = (Vector) ds.get(ALL_RESPONSES_KEY);
allResp.addElement(firstReply);
state = ALL_REPLIES_RECEIVED_STATE;
handleNotUnderstood(firstReply);
break;
}
case ACLMessage.FAILURE:{
Vector allResNot = (Vector) ds.get(ALL_RESULT_NOTIFICATIONS_KEY);
allResNot.addElement(firstReply);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -