All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jason.stdlib.send Maven / Gradle / Ivy

Go to download

Jason is a fully-fledged interpreter for an extended version of AgentSpeak, a BDI agent-oriented logic programming language.

The newest version!
package jason.stdlib;

import jason.JasonException;
import jason.asSemantics.Agent;
import jason.asSemantics.DefaultInternalAction;
import jason.asSemantics.Intention;
import jason.asSemantics.Message;
import jason.asSemantics.TransitionSystem;
import jason.asSemantics.Unifier;
import jason.asSyntax.Atom;
import jason.asSyntax.ListTerm;
import jason.asSyntax.ListTermImpl;
import jason.asSyntax.NumberTerm;
import jason.asSyntax.StringTerm;
import jason.asSyntax.Structure;
import jason.asSyntax.Term;
import jason.asSyntax.VarTerm;

import java.util.concurrent.TimeUnit;

/**
  

Internal action: .send.

Description: sends a message to an agent.

Parameters:

  • + receiver (atom, string, or list): the receiver of the message. It is the unique name of the agent that will receive the message (or list of names).
  • + ilf (atom): the illocutionary force of the message (tell, achieve, ...).
  • + message (literal): the content of the message.
  • + answer (any term [optional]): the answer of an ask message (for performatives askOne, askAll, and askHow).
  • + timeout (number [optional]): timeout (in milliseconds) when waiting for an ask answer.

Messages with an ask illocutionary force can optionally have arguments 3 and 4. In case they are given, .send suspends the intention until an answer is received and unified with arg[3], or the message request times out as specified by arg[4]. Otherwise, the intention is not suspended and the answer (which is a tell message) produces a belief addition event as usual.

Examples (suppose that agent jomi is sending the messages):

  • .send(rafael,tell,value(10)): sends value(10) to the agent named rafael. The literal value(10)[source(jomi)] will be added as a belief in rafael's belief base.
  • .send(rafael,achieve,go(10,30): sends go(10,30) to the agent named rafael. When rafael receives this message, an event <+!go(10,30)[source(jomi)],T> will be added in rafael's event queue.
  • .send(rafael,askOne,value(beer,X)): sends value(beer,X) to the agent named rafael. This askOne is an asynchronous ask since it does not suspend jomi's intention. If rafael has, for instance, the literal value(beer,2) in its belief base, this belief is automatically sent back to jomi. Otherwise an event like +?value(beer,X)[source(self)] is generated in rafael's side and the result of this query is then sent to jomi. In the jomi's side, the rafael's answer is added in the jomi's belief base and an event like +value(beer,10)[source(rafael)] is generated.
  • .send(rafael,askOne,value(beer,X),A): sends value(beer,X) to the agent named rafael. This askOne is a synchronous askOne, it suspends jomi's intention until rafael's answer is received. The answer (something like value(beer,10)) unifies with A.
  • .send(rafael,askOne,value(beer,X),A,2000): as in the previous example, but agent jomi waits for 2 seconds. If no message is received by then, A unifies with timeout.
@see jason.stdlib.broadcast @see jason.stdlib.my_name */ public class send extends DefaultInternalAction { @Override public boolean canBeUsedInContext() { return false; } private boolean lastSendWasSynAsk = false; @Override public int getMinArgs() { return 3; } @Override public int getMaxArgs() { return 5; } @Override protected void checkArguments(Term[] args) throws JasonException { super.checkArguments(args); // check number of arguments if (!args[0].isAtom() && !args[0].isList() && !args[0].isString()) throw JasonException.createWrongArgument(this,"TO parameter ('"+args[0]+"') must be an atom, a string or a list of receivers!"); if (! args[1].isAtom()) throw JasonException.createWrongArgument(this,"illocutionary force parameter ('"+args[1]+"') must be an atom!"); } @Override public Object execute(final TransitionSystem ts, Unifier un, Term[] args) throws Exception { checkArguments(args); final Term to = args[0]; Term ilf = args[1]; Term pcnt = args[2]; // remove source annots in the content (in case it is a pred) // -- CHANGE: use nested annots //try { // ((Pred)pcnt).delSources(); //} catch (Exception e) {} // create a message to be sent final Message m = new Message(ilf.toString(), ts.getUserAgArch().getAgName(), null, pcnt); // async ask has a fourth argument and should suspend the intention lastSendWasSynAsk = m.isAsk() && args.length > 3; if (lastSendWasSynAsk) { m.setSyncAskMsgId(); ts.getC().addPendingIntention(m.getMsgId(), ts.getC().getSelectedIntention()); } // (un)tell or unknown performative with 4 args is a reply to if ( (m.isTell() || m.isUnTell() || !m.isKnownPerformative()) && args.length > 3) { Term mid = args[3]; if (! mid.isAtom()) { throw new JasonException("The Message ID ('"+mid+"') parameter of the internal action 'send' is not an atom!"); } m.setInReplyTo(mid.toString()); } // send the message if (to.isList()) { for (Term t: (ListTerm)to) { delegateSendToArch(t, ts, m); } } else { delegateSendToArch(to, ts, m); } if (lastSendWasSynAsk && args.length == 5) { // get the timeout deadline Term tto = args[4]; if (tto.isNumeric()) { Agent.getScheduler().schedule( new Runnable() { public void run() { // if the intention is still in PI, brings it back to C.I with the timeout Intention intention = ts.getC().removePendingIntention(m.getMsgId()); if (intention != null) { // unify "timeout" with the fourth parameter of .send Structure send = (Structure)intention.peek().removeCurrentStep(); Term timeoutAns = null; if (to.isList()) { VarTerm answers = new VarTerm("AnsList___"+m.getMsgId()); Unifier un = intention.peek().getUnif(); timeoutAns = un.get(answers); if (timeoutAns == null) timeoutAns = new ListTermImpl(); } else { timeoutAns = new Atom("timeout"); } intention.peek().getUnif().unifies(send.getTerm(3), timeoutAns); // add the intention back in C.I ts.getC().resumeIntention(intention); ts.getUserAgArch().wakeUpAct(); } } }, (long)((NumberTerm)tto).solve(), TimeUnit.MILLISECONDS); } else { throw new JasonException("The 5th parameter of send must be a number (timeout) and not '"+tto+"'!"); } } return true; } private void delegateSendToArch(Term to, TransitionSystem ts, Message m) throws Exception { if (!to.isAtom() && !to.isString()) throw new JasonException("The TO parameter ('"+to+"') of the internal action 'send' is not an atom!"); String rec = null; if (to.isString()) rec = ((StringTerm)to).getString(); else rec = to.toString(); if (rec.equals("self")) rec = ts.getUserAgArch().getAgName(); m.setReceiver(rec); ts.getUserAgArch().sendMsg(m); } @Override public boolean suspendIntention() { return lastSendWasSynAsk; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy