/*
			  CARNEGIE MELLON UNIVERSITY
			    NON-EXCLUSIVE END-USER
			  SOFTWARE LICENSE AGREEMENT

    
				  RETSINA(tm)
    Reusable Environment for Task Structured Intelligent Network Agents(tm)

IMPORTANT: PLEASE READ THIS  SOFTWARE LICENSE AGREEMENT ("AGREEMENT") CAREFULLY.

          LICENSE

The CMU Software, together with  any fonts accompanying this Agreement, whether
on  disk,  in read  only  memory  or  any other  media  or  in any  other  form
(collectively,  the  "CMU Software")  is  never  sold.   It is  non-exclusively
licensed  by Carnegie  Mellon University  ("CMU") to  you solely  for  your own
internal, non-commercial research purposes on the terms of this Agreement.  CMU
retains the ownership of the CMU  Software and any subsequent copies of the CMU
Software. The CMU Software and any copies made under this Agreement are subject
to this Agreement.

          YOU MAY:

          1. LOAD and USE the CMU Software as long as the  CMU Software is only
          used on one (1) computer by one (1) user at a time. This license does
          not allow the CMU Software to exist on more than one (1)  computer at
          a time or on a computer  network,  including  without  limitation  an
          intranet network or a local area network.

          2. USE the CMU Software solely for your own internal,  non-commercial
          research purposes. 

          3. COPY the CMU Software for back-up purposes only. You may make  one
          (1) copy of the CMU Software in  machine-readable  form  for  back-up
	  purposes.  The  back-up  copy  must  contain  all  copyright  notices
	  contained in the original CMU Software.

          4. TERMINATE this Agreement by destroying the original and all copies
          of the CMU Software in whatever form.

          YOU MAY NOT:

          1. Assign, delegate or  otherwise  transfer  the  CMU  Software,  the
	  license (including this Agreement),  or  any  rights  or  obligations
	  hereunder or thereunder, to another person or entity.  Any  purported
	  assignment, delegation or transfer in  violation  of  this  provision
	  shall be void.

          2. Loan, distribute,  rent,  lease,  give,  sublicense  or  otherwise
          transfer the CMU Software (or any copy of the CMU Software), in whole
          or in part, to any other person or entity.

          3. Copy, alter, translate, decompile, disassemble,  reverse  engineer
          or create derivative works from the CMU Software, including  but  not
          limited to, modifying the CMU Software to make  it  operate  on  non-
	  compatible hardware.

          4. Remove, alter or cause not to be displayed, any copyright  notices
          or startup messages contained in the CMU Software.

          5. Export the CMU Software or the product components in violation  of
	  any United States export laws.

Title to the CMU Software,  including the ownership of all copyrights, patents,
trademarks  and  all  other  intellectual  property rights  subsisting  in  the
foregoing, and all  adaptations to and modifications of  the foregoing shall at
all times remain with CMU. CMU  retains all rights not expressly licensed under
this Agreement. The CMU  Software, including any images, graphics, photographs,
animation, video, audio, music and text incorporated therein is owned by CMU or
its  suppliers   and  is  protected   by  United  States  copyright   laws  and
international  treaty provisions.   Except as  otherwise expressly  provided in
this  Agreement,  the copying,  reproduction,  distribution  or preparation  of
derivative works  of the CMU Software  is strictly prohibited by  such laws and
treaty provisions.   Nothing in  this Agreement constitutes  a waiver  of CMU's
rights under United States copyright law.

This Agreement and your rights are  governed by the laws of the Commonwealth of
Pennsylvania.  If  for any reason a  court of competent  jurisdiction finds any
provision  of this  Agreement, or  portion  thereof, to  be unenforceable,  the
remainder of this Agreement shall continue in full force and effect.

THIS LICENSE SHALL TERMINATE AUTOMATICALLY if you fail to comply with the terms
of this Agreement.

          DISCLAIMER OF WARRANTY ON CMU SOFTWARE

You expressly  acknowledge and agree  that your use  of the CMU Software  is at
your sole risk.

THE CMU SOFTWARE IS PROVIDED "AS IS"  AND WITHOUT WARRANTY OF ANY KIND, AND CMU
EXPRESSLY  DISCLAIMS ALL  WARRANTIES, EXPRESS  OR IMPLIED,  INCLUDING,  BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY  RIGHTS.  THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE  OF THE CMU SOFTWARE IS BORNE  BY YOU.  THIS DISCLAIMER
OF WARRANTIES, REMEDIES AND LIABILITY  ARE FUNDAMENTAL ELEMENTS OF THE BASIS OF
THE AGREEMENT BETWEEN  CMU AND YOU.  CMU  WOULD NOT BE ABLE TO  PROVIDE THE CMU
SOFTWARE WITHOUT SUCH LIMITATIONS.

          LIMITATION OF LIABILITY

THE  CMU  SOFTWARE  IS  BEING  PROVIDED  TO  YOU  FREE  OF  CHARGE.   UNDER  NO
CIRCUMSTANCES, INCLUDING  NEGLIGENCE, SHALL CMU  BE LIABLE UNDER ANY  THEORY OR
FOR  ANY  DAMAGES INCLUDING,  WITHOUT  LIMITATION,  DIRECT, INDIRECT,  GENERAL,
SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY  OR OTHER DAMAGES) ARISING OUT OF
THE USE OF OR  INABILITY TO USE THE CMU SOFTWARE OR  OTHERWISE RELATING TO THIS
AGREEMENT (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS  INTERRUPTION, LOSS  OF BUSINESS  INFORMATION OR  ANY  OTHER PECUNIARY
LOSS), EVEN  IF CMU HAS BEEN ADVISED  OF THE POSSIBILITY OF  SUCH DAMAGES. SOME
JURISDICTIONS  DO  NOT ALLOW  THE  EXCLUSION  OR  LIMITATION OF  INCIDENTAL  OR
CONSEQUENTIAL DAMAGES SO THIS LIMITATION MAY NOT APPLY TO YOU.

          ADDITIONAL PROVISIONS YOU SHOULD BE AWARE OF

This Agreement constitutes  the entire agreement between you  and CMU regarding
the CMU  Software and supersedes any prior  representations, understandings and
agreements, either  oral or  written. No amendment  to or modification  of this
Agreement will be binding unless in writing and signed by CMU.

          U.S. GOVERNMENT RESTRICTED RIGHTS

If the CMU Software or any accompanying documentation is used or acquired by or
on behalf of any unit, division or agency of the United States Government, this
provision  applies.  The  CMU Software  and any  accompanying  documentation is
provided with RESTRICTED RIGHTS.  The use, modification, reproduction, release,
display,  duplication  or disclosure  thereof  by or  on  behalf  of any  unit,
division or agency  of the Government is subject to  the restrictions set forth
in  subdivision (c)(1)  of the  Commercial Computer  Software-Restricted Rights
clause at  48 CFR  52.227-19 and the  restrictions set  forth in the  Rights in
Technical   Data-Non-Commercial   Items   clause    set   forth   in   48   CFR
252.227-7013. The contractor/manufacturer of  the CMU Software and accompanying
documentation is  Carnegie Mellon  University, 5000 Forbes  Avenue, Pittsburgh,
Pennsylvania 15213, U.S.A.
*/
/* Copyright (c) 1998, Dirk Kalp, Katia Sycara, RETSINA Project,
                       Carnegie Mellon University
   All rights reserved
*/

/*----------------------------------------------------------------------------
  HISTORY:
    Spring/Summer 1998 Dirk Kalp (kalp@cs.cmu.edu)
    Created the module.

    Dec 03 1998 Dirk Kalp (kalp@cs.cmu.edu)
    Added this HISTORY log. 
----------------------------------------------------------------------------*/

package EDU.cmu.softagents.retsina.Communicator;

import  java.util.*;


/** AgentMsg defines an interface which is a conceptual view of
    the necessary components in any communication between agents.
    An AgentMsg consists of a performative and some arbitrary
    number of fields designated by a  pair.
    The performative is just a distinguished field, i.e., one
    whose fieldname is "performative". All msgs are string-based,
    i.e., the fieldnames and values are Strings.
    NOTE: Do we even want to give "performative" a distiguished
          status, just leave it arbitrary?
*/
public interface AgentMsg extends Cloneable {

  //------------------------------------------------------------
  // Define some constants we can use to refer to fields we
  // expect in any agent msg.
  //------------------------------------------------------------

  // Perfomative places a msg in some particular category.
  public static final String PERFORMATIVE = "performative";

  // Sender and receiver are standard fields for any communication.
  public static final String SENDER = "sender";
  public static final String RECEIVER = "receiver";

  // Content is the specific content being transmitted from sender
  // to receiver. All other fields in the msg can be viewed as just
  // housekeeping details in service of delivering the content from
  // sender to receiver.
  public static final String CONTENT = "content";

  // Should these really just be AgentMsg fields? Yes I think so
  // since we want these to travel between agents to connect msgs
  // belonging to a particular conversation. They weave a thread
  // through the content of each of the msgs they connect to provide
  // a context for the conversation between the sender and receiver
  // agents. So I'm moving them from InternalMsg to AgentMsg.
  public static final String REPLY_WITH = "reply-with";  
  public static final String IN_REPLY_TO = "in-reply-to";

  // Do these next 2 belong or are they entirely KQML specific?
  public static final String ONTOLOGY = "ontology";
  public static final String LANGUAGE = "language";



  //------------------------------------------------------------
  // Define some standard groupings of fields. Classes
  // implementing this interface may want to use these
  // predefined groupings to set up their particular lists of
  // fields in these categories.
  //------------------------------------------------------------

  // These are the essential required fields from a conceptual
  // point of view. Are there any others?
  public static final String[] basicRequiredFields = {PERFORMATIVE,
						      SENDER,
						      RECEIVER,
						      CONTENT,
						      REPLY_WITH,
						      IN_REPLY_TO};

  // Should we really even specify any optional fields at the
  // conceptual level of agent communication? As mentioned above
  // these might really belong at the KQML specific level or even
  // just one level of abstraction removed at the InternalMsg and
  // ExternalMsg levels. I'm not sure yet.
  public static final String[] basicOptionalFields = {LANGUAGE,
						      ONTOLOGY};

  //------------------------------------------------------------
  // Define some accessor methods that classes implementing this
  // interface should provide to get the list of each of the
  // different classes of fields as well as to add to the 
  // respective lists. Required fields must be present in a msg,
  // optional ones do not. Internal fields are ones added by and
  // used inside the agent. They should almost always be filtered
  // from a msg sent out although, in some instances (debugging
  // for example), we may want to leave them in.
  // NOTE: Classes implementing the interface may also provide
  //       some constructor args for setting the groupings. Well
  //       maybe that is a stupid idea. Probably we need static
  //       variables inside the class that the accessor methods
  //       operate on. We want to establish the groupings over
  //       the class as a whole not every instantiation of it.
  //------------------------------------------------------------

  public String[] getRequiredFields();
  public void     addRequiredFields(String[] requiredFields);
  public void     removeRequiredFields(String[] requiredField);
  public void     clearRequiredFields();
  public String[] getOptionalFields();
  public void     addOptionalFields(String[] optionalFields);
  public void     removeOptionalFields(String[] optionalField);
  public void     clearOptionalFields();
  public String[] getInternalFields();
  public void     addInternalFields(String[] internalFields);
  public void     removeInternalFields(String[] internalField);
  public void     clearInternalFields();
  public String[] getFilteredFields();
  public void     addFilteredFields(String[] filteredFields);
  public void     removeFilteredFields(String[] filteredField);
  public void     clearFilteredFields();




  //------------------------------------------------------------
  // Any class that implements an AgentMsg should provide an
  // implementation for these abstract methods that follow which
  // are primarily used to manipulate fields and their values.
  //
  // QUESTION: Should these all be synchronized. Yes, I think
  //           most if not all.
  //------------------------------------------------------------


  /** Return the value of the performative, null if there is none.
  */
  public 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 String setPerformative(String performative);


  /** Return the value of the given field, null if the field does
      not exist.
      NOTE: This is similar to getValue() in KQMLmessage class.
  */
  public 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 String setField(String fieldName, String value);


  /** Return true if a field exists, even if its value is null.
  */
  public boolean existsField(String fieldName);

  /** Return true if a field exists and its value is not null.
  */
  public 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 boolean existsNonEmptyField(String fieldName);


  /** Remove the given field if it exists. Return the value before
      the field was removed, null if it did not exist.
  */
  public String removeField(String fieldName);


  /** Produce an enumeration of all the fieldnames. This provides
      the means to retrieve the value for every field in the msg
      using "getField()" over the enumerated fieldnames. 
  */
  public Enumeration getFieldNames();




  /** Determine if the  pairs represented in the
      msg constitute a valid msg in the context of an instantiation
      of the particular msg class implementing the AgentMsg interface.

      For an InternalMsg, it tests if the msg 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.)

      For an ExternalMsg, it tests if the msg meets the minimal requirements
      for an ExternalMsg. This means that it should have the set of required
      fields (those specified for an AgentMsg plus any others added for
      this protocol). Validity means that those fields are present in the
      msg and that the 2 required fields, SENDER and RECEIVER, have actual
      values, i.e., the values are more than just whitespace strings. The
      actual test for a valid ExternalMsg is probably most often done inside
      the Communicator at the point just after the msg is received. The
      received msg arrives on a socket as a string formatted according to the
      given inter-agent msg protocol. That string is used to create the
      ExternalMsg. The validity of it is tested before converting it to the
      InternalMsg that eventually gets handed up to the application. While 
      the SENDER and RECEIVER fields must have actual values in order for
      the Communicator to process 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 boolean isValidMsg();


  /** Produce a String representation of the msg suitable for:
         - printing
         - sending to another agent (i.e., conversion of an
	   ExternalMsg to its well-defined string representation
	   that can be transmitted from the socket of one agent
	   to another)
	 - 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 String toString();


  /** Clear the msg of all its  pairs.
  */
  public void clearMsg();
}