package jade.wrapper.gateway; //#J2ME_EXCLUDE_FILE import jade.util.leap.Iterator; import jade.util.leap.HashMap; import jade.core.behaviours.CyclicBehaviour; import jade.util.Event; import jade.util.Logger; /** * This is a cyclic behaviour that processes the commands received via JadeGateway. * <code>JadeGateway</code> enables two alternative ways to implement a gateway * that allows non-JADE code to communicate with JADE agents. * <br> The first one is to extend the <code>GatewayAgent</code> (see its javadoc for reference). * <br> The second one is to extend this <code>GatewayBehaviour</code> and add an instance * of this Behaviour to your own agent that will have to function as a gateway. * @author Fabio Bellifemine, Telecom Italia Lab * @version $Date: $ $Revision: $ */ public abstract class GatewayBehaviour extends CyclicBehaviour { /** * Queue of all pending commands that have not yet been released (see method releaseCommand) * In this Hash, the key is the Object while the value is the Event */ private final HashMap commandQueue = new HashMap(2); private final Logger myLogger = Logger.getMyLogger(this.getClass().getName()); public void action() { Event e = (Event) myAgent.getO2AObject(); if (e == null) { block(); return; } // put the event into the command Queue commandQueue.put(e.getSource(), e); if (myLogger.isLoggable(Logger.INFO)) { myLogger.log(Logger.INFO, myAgent.getLocalName() + " started execution of command " + e.getSource()); } // call the processCommand method such as the command is executed processCommand(e.getSource()); } /** subclasses must implement this method. * The method is called each time a request to process a command * is received from the JSP Gateway. * <p> The recommended pattern is the following implementation: <code> if (c instanceof Command1) execCommand1(c); else if (c instanceof Command2) execCommand2(c); </code> * </p> * <b> REMIND THAT WHEN THE COMMAND HAS BEEN PROCESSED, * YOU MUST CALL THE METHOD <code>releaseCommand</code>. * Sometimes, you might prefer launching a new Behaviour that asynchronously processes * this command and release the command just when the Behaviour terminates, * i.e. in its <code>onEnd()</code> method. **/ abstract protected void processCommand(Object command); /** * notify that the command has been processed and remove the command from the queue * @param command is the same object that was passed in the processCommand method **/ final public void releaseCommand(Object command) { // remove the command from the queue Event e = (Event) commandQueue.remove(command); // notify that the command has been processed such as the JADEGateway is waken-up if (e != null) { if (myLogger.isLoggable(Logger.INFO)) { myLogger.log(Logger.INFO, myAgent.getLocalName() + " terminated execution of command " + command); } e.notifyProcessed(null); } } public int onEnd() { if (myLogger.isLoggable(Logger.INFO)) myLogger.log(Logger.INFO, myAgent.getLocalName() + " terminated GatewayBehaviour"); for (Iterator i = commandQueue.values().iterator(); i.hasNext();) ((Event) (i.next())).notifyProcessed(null); return super.onEnd(); } }