/** This module defines a KQML based msg communication protocol and formats to be used on the application side of the Communicator. That is, the application is the agent or entity which has incorporated the Communicator module as its mechanism for communicating with external agents. InternalKQMLmessage extends KQMLmessage by implementing the methods of the InternalMsg interface defined in the Communicator. Msgs in the application that conform to the InternalMsg interface can be handed to the Communicator for transmission. The Communicator will translate an InternalMsg to an ExternalMsg before sending it out to the external agent. The internal msgs and external msgs may use the same base protocol, such as KQML, or they may use different protocols. The only requirement is that they implement the InternalMsg and ExternalMsg interfaces respectively since the Communicator views all msgs it sends or receives from these abstract points of view. Implement the methods of the InternalMsg interface on top of the methods of KQMLmessage. NOTE: The idea here would be to allow any basic communication protocol, KQML being just one example, to be extended with an implementation of the InternalMsg interface on top of an existing class for the protocol. New protocols could be substituted by doing the same subclassing off their existing class. Use of the subclass can be localized to a few well defined places (I think/hope) such as constructor calls (should we also have a createMsg() interface method in AgentMsg whose implementation calls the actual subclass constructor to even further reduce the number of places where code need be changed when substituting a new protocol?). The actual objects passed around (as method args for example) would just be declared as type InternalMsg with only the interface methods being used as accessors into the actual msg. I need to think more about whether this provides the necessary structure for flexible plug and play of different protocols on the internal and external sides of the Communicator to accomodate a variety of agents. Is this the right view of the abstraction needed? In addition, for implementing a new protocol, which did not have a previous java class already implemented, one would simply build it by directly implementing the required abstract methods - there would be nothing to subclass from. (I just wanted to state the obvious.) */ public class InternalKQMLmessage extends KQMLmessage implements InternalMsg { /** A constructor that creates a new InternalMsg without any fields present initially. */ public InternalKQMLmessage() { /** A constructor that creates a new InternalMsg from a string representation of an InternalMsg. */ public InternalKQMLmessage(String internalMsgString) { //------------------------------------------------------------ // Next we implement methods from the AgentMsg interface. //------------------------------------------------------------ /** Return the value of the performative, null if there is none. */ public synchronized String getPerformative() { /** Set the performative to the indicated value. Create it if it did not exist. Return the previous value, null if did not exist previously. */ public synchronized String setPerformative(String performative) { /** Return the value of the given field, null if the field does not exist. */ public synchronized String getField(String fieldName) { /** Set the given field to the indicated value. Create the field if it did not exist. Return the previous value held in the field, null if did not exist previously. NOTE: This is similar to addFieldValuePair() in KQMLmessage class. */ public synchronized String setField(String fieldName, String value) { /** Return true if a field exists, even if its value is null. */ public synchronized boolean existsField(String fieldName) { /** Return true if a field exists and its value is not null. */ public synchronized boolean existsNonNullField(String fieldName) { /** Return true if a field exists and its value is not empty, i.e. it is not just a whitespace string. */ public synchronized boolean existsNonEmptyField(String fieldName) { /** Produce a String representation of the msg suitable for: - printing - passing around internally, in lieu of an InternalMsg, when simple strings seem more appropriate (perhaps as args in external query functions) This method should know how to produce a string representation of the msg in the correct format of the particular msg class implementing the AgentMsg interface. (NOTE: Do we want to have a more uniquely named method instead such as "toStringMsg()"?) */ public synchronized String toString() { /** Determine if thepairs represented in the msg constitute a valid msg in the context of an instantiation of the particular msg class implementing the AgentMsg interface. Test if the InternalMsg meets the minimal requirements for an InternalMsg. This means that it should have the set of required fields (those specified for an AgentMsg plus any others added for this protocol) and the set of internal fields specified for an InternalMsg. Validity means that all those fields are present in the msg and that the 2 required fields, SENDER and RECEIVER, plus all the internal fields have actual values, i.e., the values are more than just whitespace strings. The actual test for a valid msg is probably most often done inside the Communicator just before it sends the msg out via a Connection to an external agent. The Communicator depends on the required and internal fields when doing the actual IO. It is not uncommon for the application side to pass an invalid InternalMsg into the Communicator. In particular, the Communicator API the application side uses to send a msg to an external server agent takes an InternalMsg arg and a ConnectionDescriptor arg. The Communicator method uses the ConnectionDescriptor to fill in the internal fields of the msg with the information about the Connection. It then calls isValidMsg() to make sure the msg is complete before passing it down into the Communicator's low level IO routines. While the internal fields and the SENDER and RECEIVER fields must have actual values in order for the Communicator to send the msg, other required fields such as CONTENT, REPLY_WITH, and IN_REPLY_TO may be empty since they are not strictly essential to the Communicator. However, we do require that those non-essential fields be present in the msg even with empty values since we want to enforce a notion of uniformity in the basic format of inter-agent msgs. An empty value can be the null string (i.e., "") or any whitespace string (eg., " ", " \t\n", etc.) */ public synchronized boolean isValidMsg() { // NOTE: It would be nice to have this as a static method but I wouldn't // be able to put it in InternalMsg since interfaces can't have // static methods. But I do want it to be in every class that // implements InternalMsg. So I have to keep it as an instance method. // /** When an agent needs to send a reply msg to an external agent, he can use the external agent's msg being replied to in order to build the reply msg. The method here assumes that the msg instance here is the external agent's msg we want to reply to. So the method takes this msg and clones it, swaps sender and receiver, assigns new performative and content and reply-with, and sets in-reply-to from this msgs's reply-with. The msg built is returned as the reply msg. */ public synchronized InternalMsg buildReplyMsg(String performative, String content, String replyWith) /** This method overloads buildReplyMsg() to leave the reply-with field empty. This is intended for use with Communicator msg send methods that fill in the reply-with field to perform synchronized communication (with blocking) with the external agent or to establish a redirection of msgs from the external agent into a Provision queue. */ public synchronized InternalMsg buildReplyMsg(String performative, String content)