/***************************************************************** 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(); } } }