/*****************************************************************
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.domain;
//#MIDP_EXCLUDE_FILE
import jade.core.behaviours.CyclicBehaviour;
import jade.content.Concept;
import jade.content.Predicate;
import jade.content.onto.basic.Action;
import jade.content.onto.basic.Done;
import jade.content.onto.basic.Result;
import jade.content.onto.OntologyException;
import jade.content.lang.Codec.CodecException;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.ConversationList;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.KBManagement.KBIterator;
import jade.proto.SSIteratedAchieveREResponder;
import jade.util.leap.List;
import jade.util.leap.ArrayList;
import jade.util.Logger;
/**
This behaviour serves search requests according to the iterated-fipa-request
protocol.
@author Giovanni Caire - TILAB
*/
class DFIteratedSearchManagementBehaviour extends CyclicBehaviour {
private df theDF;
private MessageTemplate template;
private ConversationList conversations;
private Logger logger;
public DFIteratedSearchManagementBehaviour(df theDF, MessageTemplate mt) {
super(theDF);
this.theDF = theDF;
conversations = new ConversationList(theDF);
template = MessageTemplate.and(mt, conversations.getMessageTemplate());
logger = Logger.getMyLogger(theDF.getLocalName());
}
public void action() {
ACLMessage msg = theDF.receive(template);
if (msg != null) {
if (logger.isLoggable(Logger.FINE)) {
logger.log(Logger.FINE, "DF "+myAgent.getName()+": Iterated-search request received from "+msg.getSender().getName()+". Conv-ID = "+msg.getConversationId());
}
theDF.addBehaviour(new SSIteratedAchieveREResponder(theDF, msg) {
private KBIterator iterator = null;
private String myConversationId = null;
private int cnt = 0; // Only for debugging purposes
protected ACLMessage handleRequest(ACLMessage request) throws RefuseException, FailureException, NotUnderstoodException {
ACLMessage reply = null;
if (logger.isLoggable(Logger.FINE)) {
logger.log(Logger.FINE, "DF "+myAgent.getName()+": Iterated-search "+request.getConversationId()+". Serving request # "+cnt);
}
cnt++;
try {
// Parse the request content
Action aExpr = (Action) theDF.getContentManager().extractContent(request);
Search search = (Search) aExpr.getAction();
SearchConstraints constraints = search.getConstraints();
int maxResult = theDF.getActualMaxResults(constraints);
// If this is the first REQUEST, create the Iterator
if (iterator == null) {
if (logger.isLoggable(Logger.FINER)) {
logger.log(Logger.FINER, "DF "+myAgent.getName()+": Iterated-search "+request.getConversationId()+". Initializing KBIterator");
}
iterator = theDF.iteratedSearchAction(search, request.getSender());
if (logger.isLoggable(Logger.FINEST)) {
logger.log(Logger.FINEST, "DF "+myAgent.getName()+": Iterated-search "+request.getConversationId()+". KBIterator correctly initialized");
}
}
// Get the requested number of results
List ll = new ArrayList();
for (int i = 0; i < maxResult; ++i) {
if (iterator.hasNext()) {
ll.add(iterator.next());
}
else {
if (logger.isLoggable(Logger.FINER)) {
logger.log(Logger.FINER, "DF "+myAgent.getName()+": Iterated-search "+request.getConversationId()+". Closing KBIterator");
}
iterator.close();
// FIXME: properly handle recursive search
closeSessionOnNextReply();
break;
}
}
if (logger.isLoggable(Logger.FINE)) {
logger.log(Logger.FINE, "DF "+myAgent.getName()+": Iterated-search "+request.getConversationId()+". Sending back "+ll.size()+" results");
}
// Fill the reply
reply = request.createReply();
try {
Result result = new Result(aExpr, ll);
theDF.getContentManager().fillContent(reply, result);
reply.setPerformative(ACLMessage.INFORM);
}
catch (Exception e) {
// Unexpected error encoding the reply
e.printStackTrace();
throw new FailureException(ExceptionVocabulary.INTERNALERROR+" \""+e.getMessage()+"\"");
}
}
catch (OntologyException oe) {
throw new NotUnderstoodException(ExceptionVocabulary.UNRECOGNISEDVALUE+" content");
}
catch (CodecException ce) {
throw new NotUnderstoodException(ExceptionVocabulary.UNRECOGNISEDVALUE+" content");
}
catch (FailureException fe) {
throw fe;
}
catch (Throwable t) {
// Unexpected error
t.printStackTrace();
throw new FailureException(ExceptionVocabulary.INTERNALERROR+" \""+t.getMessage()+"\"");
}
return reply;
}
protected void handleCancel(ACLMessage cancel) {
if (logger.isLoggable(Logger.FINE)) {
logger.log(Logger.FINE, "DF "+myAgent.getName()+": Iterated-search "+cancel.getConversationId()+". Serving cancel");
}
if (iterator != null) {
if (logger.isLoggable(Logger.FINER)) {
logger.log(Logger.FINER, "DF "+myAgent.getName()+": Iterated-search "+cancel.getConversationId()+". Closing KBIterator");
}
iterator.close();
}
}
/**
Avoid conflicts between the main MessageTemplate and that used
internally by this IteratedFipaRequestResponder.
*/
protected void afterReply(ACLMessage reply) {
if (reply != null) {
myConversationId = reply.getConversationId();
conversations.registerConversation(myConversationId);
}
}
/**
When the protocol terminates, deregister the conversation
*/
public int onEnd() {
conversations.deregisterConversation(myConversationId);
return super.onEnd();
}
} );
}
else {
block();
}
}
}