In order to implement artifacts that provides I/O functionalities for interacting with the external world (e.g. network communication, user I/O, GUI, etc.), a further kind of await primitive is provided, accepting an object of type IBlockingCommand representing a command to be executed. The primitive suspends the execution of the operation until the specified command - which typically contains some kind of I/O and a blocking behaviour - has been executed. In the following example, two agents communicate by means of two artifacts that function as network port, providing I/O network communication based on UDP sockets.

MAS example07_extcommand {

  environment: c4jason.CartagoEnvironment

  agents:
  sender agentArchClass c4jason.CAgentArch #1;
  receiver agentArchClass c4jason.CAgentArch #1;

  classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}

The agent sender creates and uses its port to send two messages:

!send_info.

+!send_info : true
  <- makeArtifact("senderPort","c4jexamples.Port",[23000]);
     sendMsg("hello1","localhost:25000");
     sendMsg("hello2","localhost:25000").

The agent receiver creates and uses its own port to get the messages, using two different receiving styles:

!receive_msgs.

+!receive_msgs : true
  <- makeArtifact("receiverPort","c4jexamples.Port",[25000],Id);
     receiveMsg(Msg,Sender);
     println("received ",Msg," from ",Sender);
     focus(Id);
     startReceiving.

+new_msg(Msg,Sender)
  <- println("received ",Msg," from ",Sender).

The first message is received by means of a receiveMsg action, while the second as a signal new_msg generated by the artifact.The Port artifact exploits the await with a blocking command to implement its functionalities:

public class Port extends Artifact {

  DatagramSocket socket;
  ReadCmd cmd;
  boolean receiving;

  @OPERATION
  void init(int port) throws Exception {
    socket = new DatagramSocket(port);
    cmd = new ReadCmd();
    receiving = false;
  }

  @OPERATION
  void sendMsg(String msg, String fullAddress) {
    try {
      int index = fullAddress.indexOf(':');
      InetAddress address = InetAddress.getByName(fullAddress.substring(
          0, index));
      int port = Integer.parseInt(fullAddress.substring(index + 1));
      socket.send(new DatagramPacket(msg.getBytes(),
          msg.getBytes().length, address, port));
    } catch (Exception ex) {
      this.failed(ex.toString());
    }
  }

  @OPERATION
  void receiveMsg(OpFeedbackParam msg, OpFeedbackParam sender) {
    await(cmd);
    msg.set(cmd.getMsg());
    sender.set(cmd.getSender());
  }

  @OPERATION
  void startReceiving() {
    receiving = true;
    execInternalOp("receiving");
  }

  @INTERNAL_OPERATION
  void receiving() {
    while (true) {
      await(cmd);
      signal("new_msg", cmd.getMsg(), cmd.getSender());
    }
  }

  @OPERATION
  void stopReceiving() {
    receiving = false;
  }

  class ReadCmd implements IBlockingCmd {

    private String msg;
    private String sender;
    private DatagramPacket packet;

    public ReadCmd() {
      packet = new DatagramPacket(new byte[1024], 1024);
    }

    public void exec() {
      try {
        socket.receive(packet);
        byte[] info = packet.getData();
        msg = new String(info);
        sender = packet.getAddress().toString();
      } catch (Exception ex) {
      }
    }

    public String getMsg() {
      return msg;
    }

    public String getSender() {
      return sender;
    }
  }
}

The ReadCmd implements a blocking command - implementing the IBlockingCmd interface - containing in the exec method the command code, in this case receiving an UDP packet from a socket.

Highlights: