View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-2001. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  /*
25   * @(#)Performative.java 1.00
26   */
27  
28  package zeus.concepts;
29  
30  import java.io.*;
31  import java.util.*;
32  import zeus.util.*;
33  import zeus.actors.*;
34  import zeus.actors.factories.*; 
35  import zeus.actors.outtrays.*;
36  
37  /***
38   * The Performative class provides a standard data structure for inter-agent
39   * messaging. The message format and available message types have been derived 
40   * from the FIPA Agent Communication Language description. <p>
41   *
42   * This class contains methods that allow the attributes of performative objects
43   * to be set and modified, although typically developers will only need to
44   * invoke one of the constructors. More information on performatives and the
45   * communication mechanism is provided in the Zeus Technical Manual.
46   */
47  
48  
49  public class Performative 
50  {
51     public static final String[] MESSAGE_TYPES = {
52        "accept-proposal",
53        "agree",
54        "cancel",
55        "cfp",
56        "confirm",
57        "disconfirm",
58        "failure",
59        "inform",
60        "inform-if",
61        "inform-ref",
62        "not-understood",
63        "propose",
64        "query-if",
65        "query-ref",
66        "refuse",
67        "reject-proposal",
68        "request",
69        "request-when",
70        "request-whenever",
71        "subscribe",
72        "request-forward"
73     };
74     
75       public static final String[] MESSAGE_TYPES_UPPER = {
76        "ACCEPT-PROPOSAL",
77        "AGREE",
78        "CANCEL",
79        "CFP",
80        "CONFIRM",
81        "DISCONFIRM",
82        "FAILURE",
83        "INFORM",
84        "INFORM-IF",
85        "INFORM-REF",
86        "NOT-UNDERSTOOD",
87        "PROPOSE",
88        "QUERY-IF",
89        "QUERY-REF",
90        "REFUSE",
91        "REJECT-PROPOSAL",
92        "REQUEST",
93        "REQUEST-WHEN",
94        "REQUEST-WHENEVER",
95        "SUBSCRIBE",
96        "REQUEST-FORWARD"
97     };
98  
99     public static final String[] ATTRIBUTE_TYPES = {
100       "type",
101       "sender",
102       "receiver",
103       "content",
104       "reply-with",
105       "in-reply-to",
106       "reply-by",
107       "ontology",
108       "language",
109       "protocol",
110       "conversation-id",
111       "reply-to"
112    };
113    // note reply-to has been added to the end if this array 
114 
115    private static final int TYPE            = 0;
116    private static final int SENDER          = 1;
117    private static final int RECEIVER        = 2;
118    private static final int CONTENT         = 3;
119    private static final int REPLY_WITH      = 4;
120    private static final int IN_REPLY_TO     = 5;
121    private static final int REPLY_BY        = 6;
122    private static final int ONTOLOGY        = 7;
123    private static final int LANGUAGE        = 8;
124    private static final int PROTOCOL        = 9;
125    private static final int CONVERSATION_ID = 10;
126    private static final int REPLY_TO        = 11; 
127 
128    protected String    type;
129    protected String    sender;
130    protected HSet      receivers = new HSet();
131    protected String    content;
132    protected String    replyWith;
133    protected String    inReplyTo;
134    protected String    replyBy;
135    protected String    ontology;
136    protected String    language;
137    protected String    protocol;
138    protected String    conversationId;
139    protected Hashtable envelope = new Hashtable();
140    protected String    replyTo; 
141 
142    public Performative () { 
143     }
144 
145    public Performative(String type) {
146       setType(type);
147    }
148 
149    public Performative(Performative perf) {
150       String  token;
151       Hashtable table;
152       Enumeration data;
153 
154       if ( (token = perf.getType()) != null )		setType(token);
155       if ( (token = perf.getSender()) != null )		setSender(token);
156       if ( (data  = perf.getReceivers()) != null )	setReceivers(data);
157       if ( (token = perf.getReplyWith()) != null )	setReplyWith(token);
158       if ( (token = perf.getInReplyTo()) != null )	setInReplyTo(token);
159       if ( (token = perf.getReplyBy()) != null )	setReplyBy(token);
160       if ( (token = perf.getOntology()) != null )	setOntology(token);
161       if ( (token = perf.getLanguage()) != null )	setLanguage(token);
162       if ( (token = perf.getContent()) != null )	setContent(token);
163       if ( (token = perf.getProtocol()) != null )	setProtocol(token);
164       if ( (token = perf.getConversationId()) != null )	setConversationId(token);
165       if ( (table = perf.getEnvelope()) != null )	setEnvelope(table);
166       if ( (token = perf.getReplyTo()) != null ) setReplyTo(token); 
167    }
168 
169 
170    public void setType(String type) {
171     type = type.trim();
172       if ( Misc.member(type,MESSAGE_TYPES) ) {
173          this.type = type;
174       }
175       else if ( Misc.member(type,MESSAGE_TYPES_UPPER) ) {
176          this.type = type;
177       }
178       else {
179          Core.ERROR(null,1,"Invalid Performative type: " + type);
180       }
181    }
182 
183    public void setSender(String value){
184         sender = value; }
185    
186    
187    public void setReceiver(String value){
188         receivers.add(value); }
189    
190    
191    public void setReplyWith(String value){
192         replyWith = value; }
193    
194    
195    public void setInReplyTo(String value){
196         inReplyTo = value; }
197    
198    
199    public void setReplyBy(String value) { 
200         replyBy = value; }
201    
202    
203    public void setReplyTo (String value) { 
204         replyTo = value; 
205    }
206 
207 
208    public void setOntology(String value) {
209         ontology = value; }
210         
211         
212    public void setLanguage(String value) { 
213         language = value; }
214         
215         
216    public void setContent(String value) {
217         content = value; }
218 
219 
220    public void setProtocol(String value) {
221         protocol = value; }
222         
223         
224    public void setConversationId(String value) { 
225         conversationId = value; }
226 
227 
228 
229    public void setReceivers(Vector input) {
230       receivers.clear();
231       Enumeration enum = input.elements();
232       while( enum.hasMoreElements() )
233          receivers.add(enum.nextElement());
234    }
235    
236    
237    public void setReceivers(HSet input) {
238       receivers.clear();
239       Enumeration enum = input.elements();
240       while( enum.hasMoreElements() )
241          receivers.add(enum.nextElement());
242    }
243    
244    
245    public void setReceivers(Enumeration enum) {
246       receivers.clear();
247       while( enum.hasMoreElements() )
248          receivers.add(enum.nextElement());
249    }
250 
251    public void setAddress(Address value )  {
252       envelope.put("address",value);
253    }
254    
255    
256    public void setSendTime(Time value)	   {
257       envelope.put("sendTime",value);
258    }
259    
260    
261    public void setReceiveTime(Time value)  {
262       envelope.put("receiveTime",value);
263    }
264 
265    public void setEnvelopeItem(String name, Object item) {
266       envelope.put(name,item);
267    }
268 
269 
270    public Object getEnvelopeItem(String name) {
271       return envelope.get(name);
272    }
273 
274 
275    public void setEnvelope(Hashtable input) {
276       envelope.clear();
277       Enumeration enum = input.keys();
278       Object key;
279       Object value;
280       while( enum.hasMoreElements() ) {
281          key = enum.nextElement();
282          value = input.get(key);
283          envelope.put(key,value);
284       }
285    }
286 
287    public Hashtable getEnvelope() { 
288         return envelope; }
289 
290 
291    public String getType() { 
292         return type; }
293         
294         
295    public String getSender() {
296         return sender; }
297         
298         
299    public String getReplyWith(){
300         return replyWith; }
301         
302         
303    public String getInReplyTo()	{ 
304         return inReplyTo; }
305         
306         
307    public String getReplyBy(){ 
308         return replyBy; }
309         
310         
311    public String getReplyTo () {
312         return replyTo; 
313    }
314         
315         
316    public String getOntology() {
317         return ontology; }
318         
319         
320    public String getLanguage() {
321         return language; }
322         
323         
324    public String getContent() {
325         return content; }
326         
327         
328    public String getProtocol(){
329         return protocol; }
330         
331         
332    public String getConversationId() {
333         return conversationId; }
334 
335 
336    public String getReceiver() {
337       Enumeration enum = receivers.elements();
338       try {
339         return (String) enum.nextElement();}
340         catch (Exception e ) { 
341             return enum.nextElement().toString(); }
342    }
343    
344    
345    public Enumeration getReceivers(){
346       return receivers.elements();
347    }
348 
349 
350    public Address getAddress()	{
351       Object item = envelope.get("address");
352       if ( item instanceof String ) {
353          Address a = ZeusParser.address((String)item);
354          envelope.put("address",a);
355          return a;
356       }
357       else
358          return (Address)item;
359    }
360    
361    
362    public Time getSendTime()	{
363       Object item = envelope.get("sendTime");
364       if ( item instanceof String ) {
365          Time t = new Time((String)item);
366          envelope.put("sendTime", t);
367          return t;
368       }
369       else
370          return (Time)item;
371    }
372    
373    
374    public Time getReceiveTime()	{
375       Object item = envelope.get("receiveTime");
376       if ( item instanceof String ) {
377          Time t = new Time((String)item);
378          envelope.put("receiveTime", t);
379          return t;
380       }
381       else
382          return (Time)item;
383    }
384 
385 
386    public boolean isValid() {
387       return type != null && sender != null && !receivers.isEmpty();
388    }
389 
390 
391 
392 
393 StringBuffer sb ;
394 
395    public final String toString() {
396       sb = new StringBuffer(300); 
397       sb.append ("(");
398       sb.append (type);
399       sb.append ("\n");
400     //  String str = "(" + type + "\n";
401 
402       if ( sender != null ) {
403          sb.append (" :sender ");
404          sb.append (sender);
405          sb.append ("\n");
406          }
407       //   str += " :sender " + sender + "\n";
408       if ( receivers != null && !receivers.isEmpty() ) {
409          sb.append (" :receiver " );
410          if ( receivers.size() > 1 ){
411           sb.append ("(");
412           sb.append (Misc.concat(receivers));
413           sb.append (")");
414           }
415          else {
416            sb.append ( Misc.concat(receivers));
417           }
418           sb.append ("\n");
419          //str += " :receiver " + s + "\n";
420       }
421       if ( replyWith != null ) {
422          sb.append (" :reply-with ");
423          sb.append (replyWith);
424          sb.append ("\n");
425 //         str += " :reply-with " + replyWith + "\n";
426         }
427       if ( inReplyTo != null ) {
428           sb.append (" :in-reply-to ");
429           sb.append (inReplyTo);
430           sb.append ("\n");
431           }
432          //str += " :in-reply-to " + inReplyTo + "\n";
433       if ( replyBy != null ) {
434           sb.append (" :reply-by ");
435           sb.append (replyBy);
436           sb.append ("\n");
437           }
438          //str += " :reply-by " + replyBy + "\n";
439       if ( ontology != null ) {
440           sb.append (" :ontology ");
441           sb.append (ontology);
442           sb.append ("\n");
443         }
444   //         str += " :ontology " + ontology + "\n";
445       if ( language != null ) {
446          sb.append (" :language ");
447          sb.append (language);
448          sb.append ("\n");
449          }
450          //str += " :language " + language + "\n";
451       if ( content != null ) {
452         sb.append (" :content ");
453         sb.append ("\"");
454         String temp = Misc.escape (content); 
455         sb.append (temp);
456         temp = null; 
457         sb.append ("\"");
458         sb.append ("\n");
459         }
460          //str += " :content " + "\"" + Misc.escape(content) + "\"" + "\n";
461       if ( protocol != null ) {
462           sb.append (" :protocol ");
463           sb.append (protocol);
464           sb.append ("\n");
465       }
466        //  str += " :protocol " + protocol + "\n";
467       if ( conversationId != null ) {
468          sb.append (" :conversation-id ");
469          sb.append (conversationId);
470          sb.append ("\n");
471          }
472          //str += " :conversation-id " + conversationId + "\n";
473       if ( replyTo != null ) {
474           sb.append (" :reply-to ");
475           sb.append (replyTo);
476           sb.append ("\n");
477         }
478          //str += " :reply-to " + replyTo + "\n";
479 
480       if ( envelope != null && !envelope.isEmpty() ) {
481          sb.append(" :envelope (");
482          Enumeration enum = envelope.keys();
483          String key;
484          Object value;
485          while( enum.hasMoreElements() ) {
486             key = (String)enum.nextElement();
487             value = envelope.get(key);
488             sb.append("(");
489             sb.append(key);
490             sb.append(" \"");
491             sb.append ( Misc.escape(value.toString()));
492             sb.append ("\")");
493          }
494          sb.append(")");
495       }
496 
497       sb.append(")\n");
498       return sb.toString();
499    }
500 
501    
502    public Object getAttribute(String attribute) {
503       switch( Misc.whichPosition(attribute,ATTRIBUTE_TYPES) ) {
504          case TYPE:
505               return type;
506          case SENDER:
507               return sender;
508          case RECEIVER:
509               return getReceiver();
510          case CONTENT:
511               return content;
512          case REPLY_WITH:
513               return replyWith;
514          case IN_REPLY_TO:
515               return inReplyTo;
516          case REPLY_BY:
517               return replyBy;
518          case ONTOLOGY:
519               return ontology;
520          case LANGUAGE:
521               return language;
522          case PROTOCOL:
523               return protocol;
524          case CONVERSATION_ID:
525               return conversationId;
526          case REPLY_TO: 
527               return replyTo; 
528          default:
529               return envelope.get(attribute);
530       }
531    }
532    public void setAttribute(String attribute, Object value) {
533       switch( Misc.whichPosition(attribute,ATTRIBUTE_TYPES) ) {
534          case TYPE:
535               setType((String)value);
536               break;
537          case SENDER:
538               setSender((String)value);
539               break;
540          case RECEIVER:
541               setReceiver((String)value);
542               break;
543          case CONTENT:
544               setContent((String)value);
545               break;
546          case REPLY_WITH:
547               setReplyWith((String)value);
548               break;
549          case IN_REPLY_TO:
550               setInReplyTo((String)value);
551               break;
552          case REPLY_BY:
553               setReplyBy((String)value);
554               break;
555          case ONTOLOGY:
556               setOntology((String)value);
557               break;
558          case LANGUAGE:
559               setLanguage((String)value);
560               break;
561          case PROTOCOL:
562               setProtocol((String)value);
563               break;
564          case CONVERSATION_ID:
565               setConversationId((String)value);
566               break;
567          case REPLY_TO:
568               setReplyTo ((String) value); 
569               break;
570          
571          default:
572               envelope.put(attribute,value);
573               break;
574       }
575    }
576 
577     public void send (AgentContext context) { 
578         TransportFactory factory = context.getTransportFactory(); 
579         try {
580             OutTray out = factory.getTransport (this.getReceiver()); 
581           //  System.out.println("out =" + out.toString()); 
582             
583               context.MailBox().sendMsg(this);
584               // this way causes the mailbox to update the guis
585            // out.send((Performative)this); 
586             }
587             catch (Exception e) { 
588                 e.printStackTrace(); 
589             }
590         /*
591             catch (UnsuitableMessageException ume) { 
592                 System.out.println("wrong type of address - can't send this performative to that address"); 
593                 System.out.println("Probably you are sending a Zeus performative to a FIPA agent directly "); 
594                 System.out.println("which won't work, instead use the ACC proxy mechanism"); 
595             }
596             } // watch out, nested exception about (sorry). 
597             catch (TransportUnsupportedException tue) { 
598                 System.out.println("Address of receiver is not a known format for this agent architecture"); 
599             }*/
600     }
601 
602 
603 }