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);
state = ALL_RESULT_NOTIFICATION_RECEIVED_STATE;
handleFailure(firstReply);
break;
}
case ACLMessage.INFORM:{
Vector allResNot= (Vector) ds.get(ALL_RESULT_NOTIFICATIONS_KEY);
allResNot.addElement(firstReply);
state = ALL_RESULT_NOTIFICATION_RECEIVED_STATE;
handleInform(firstReply);
break;
}
default:{
state = RECEIVE_REPLY_STATE;
handleOutOfSequence(firstReply);
break;
}
}
break;
}else{
if(timeout > 0){
long blockTime = endingTime - System.currentTimeMillis();
if(blockTime <=0 )
//timeout Expired
state = ALL_REPLIES_RECEIVED_STATE;
else //timeout not yet expired.
block(blockTime);
}else //request without timeout.
block();
break;
}
}
case RECEIVE_2ND_REPLY_STATE:{
//after received an AGREE message. Wait for the second message.
ACLMessage secondReply = myAgent.receive(mt);
if(secondReply != null){
DataStore ds = getDataStore();
switch (secondReply.getPerformative()){
case ACLMessage.INFORM:{
//call the method handleAllResponses since if an agree was arrived it was not called.
state = ALL_RESULT_NOTIFICATION_RECEIVED_STATE;
Vector allResNot = (Vector) ds.get(ALL_RESULT_NOTIFICATIONS_KEY);
allResNot.addElement(secondReply);
handleInform(secondReply);
break;
}
case ACLMessage.FAILURE:{
state = ALL_RESULT_NOTIFICATION_RECEIVED_STATE;
Vector allResNot = (Vector) ds.get(ALL_RESULT_NOTIFICATIONS_KEY);
allResNot.addElement(secondReply);
handleFailure(secondReply);
break;
}
default:{