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-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  package zeus.actors.rtn;
25  
26  import java.util.*;
27  import java.awt.*;
28  import java.awt.event.*;
29  
30  import zeus.util.*;
31  import zeus.concepts.*;
32  import zeus.actors.*;
33  import zeus.actors.event.*;
34  import zeus.actors.graphs.*;
35  import zeus.actors.rtn.util.*;
36  
37  
38  public class Engine extends Thread {
39     static final int ARC_CREATE       = 0;
40     static final int ARC_DISPOSE      = 1;
41     static final int ARC_FAIL         = 2;
42     static final int ARC_SUCCEED      = 3;
43  
44     static final int NODE_CREATE       = 0;
45     static final int NODE_DISPOSE      = 1;
46     static final int NODE_STATE_CHANGE = 2;
47  
48     static final int GRAPH_CREATE       = 0;
49     static final int GRAPH_DISPOSE      = 1;
50     static final int GRAPH_STATE_CHANGE = 2;
51  
52     static final int INITATE_CONVERSATION = 0;
53     static final int CONTINUE_CONVERSATION = 1;
54  
55     public static String[] COORDINATION_MESSAGE_TYPES = {
56        "accept-proposal",
57        "reject-proposal",
58        "cfp",
59        "propose",
60        "refuse",
61        "cancel",
62        "failure",
63        "result",
64        "payment",
65        "invoice"
66     };
67  
68     protected zeus.util.Queue queue = new zeus.util.Queue();
69     protected Vector msgQueue = new Vector();
70     protected NodeWaitTable msgWaitTable;
71     protected boolean running = true;
72     protected AuditTable auditTable = null;
73     protected AgentContext context = null;
74     protected Hashtable itemsForSale = new Hashtable();
75     protected Hashtable keyTable = new Hashtable();
76  
77     protected HSet[] nodeMonitors = new HSet[3];
78     protected HSet[] arcMonitors = new HSet[4];
79     protected HSet[] graphMonitors = new HSet[3];
80     protected HSet[] conversationMonitors = new HSet[2];
81  
82     public Engine () {
83     super ();
84     }
85  
86     public Engine(AgentContext context) {
87        Assert.notNull(context);
88        this.context = context;
89        context.set(this);
90  
91        auditTable = new AuditTable(this);
92  
93        for(int i = 0; i < graphMonitors.length; i++ )
94           graphMonitors[i] = new HSet();
95        for(int i = 0; i < nodeMonitors.length; i++ )
96           nodeMonitors[i] = new HSet();
97        for(int i = 0; i < arcMonitors.length; i++ )
98           arcMonitors[i] = new HSet();
99        for(int i = 0; i < conversationMonitors.length; i++ )
100          conversationMonitors[i] = new HSet();
101 
102       msgWaitTable = new NodeWaitTable(this,queue);
103       this.setPriority(Thread.NORM_PRIORITY-1);
104 
105       // Initialize default message processing rules
106       String[] pattern = { "type", "cfp",
107                            "reply-with", "//A(//w)(.*)//Z",
108                            "in-reply-to", "" };
109       context.MsgHandler().addRule(new MessageRuleImpl(context.newId("Rule"),
110          pattern, this, "new_dialogue")
111       );
112 
113       this.start();
114       Thread waitTable = new Thread(msgWaitTable);
115       waitTable.setPriority(Thread.NORM_PRIORITY-2);
116       waitTable.start(); 
117       
118   
119    }
120    
121    //synchronized
122    /*** 
123     1.3 addition to stop planner deadlock
124     */
125    public synchronized void callCheckRecords() { 
126       Planner planner = context.getPlanner();
127       planner.checkRecords(); 
128    }
129    
130    
131    //synchronized 
132    /*** 
133     1.3 addition to stop planner deadlock
134     */
135     public synchronized void callShuffle () { 
136      Planner planner = context.getPlanner(); 
137      planner.shuffle(); 
138     }
139 
140    
141    public AgentContext getAgentContext() {
142       return context;
143    }
144    
145    public AuditTable getAuditTable() {
146       return auditTable;
147    }
148    
149    
150    public void run() {
151      this.setName("Engine"); 
152       Node node;
153       while(running) {
154          node = (Node)queue.dequeue();
155          synchronized(this) {
156             node.run(this);
157             node = null; 
158          }
159         yield();
160       }
161    }
162 
163    public void stopProcessing() {
164       running = false;
165    }
166 
167 
168  /***
169       This routine is used by this agent to begin a negotiation dialogue
170       with another (remote) agent
171    */
172    public synchronized void new_dialogue(String comms_key, String agent,
173                             String msg_type, Vector goals) {
174                                 // sync
175   
176 
177       String content = Misc.concat(goals);
178       Core.DEBUG(1,"start_dialogue:\n\tAgent: " + agent +
179          "\n\tCommsKey: " + comms_key + "\n\tMsgType: " + msg_type +
180 	 "\n\tContent: " + content);
181 
182       Performative msg = new Performative(msg_type);
183       msg.setReplyWith(comms_key);
184       msg.setReceiver(agent);
185       msg.setContent(content);
186       context.MailBox().sendMsg(msg);
187       notifyConversationMonitors(comms_key,context.whoami(),agent,msg_type,
188                                  goals,INITATE_CONVERSATION);
189    }
190 
191  /***
192       This routine is used by a remote agent to start a negotiation dialogue
193       with this agent
194    */
195    public synchronized void new_dialogue(Performative msg) {
196   
197       String key = msg.getReplyWith();
198       String agent = msg.getSender();
199       String data = msg.getContent();
200 
201       Vector goals = ZeusParser.goalList(context.OntologyDb(),data);
202       goals = dereference(goals);
203       notifyConversationMonitors(key,agent,context.whoami(),msg.getType(),
204                                  goals,INITATE_CONVERSATION);
205 
206       achieve(agent,key,goals);
207    }
208 
209 
210 /***
211       This routine is used by this agent to continue a negotiation dialogue
212       with another (remote) agent
213    */
214    //synchronized
215    public synchronized void continue_dialogue(String comms_key, String agent,
216                                  String msg_type, Vector goals) {
217       String content = Misc.concat(goals);
218       Core.DEBUG(1,"continue_dialogue:\n\tAgent: " + agent +
219          "\n\tCommsKey: " + comms_key + "\n\tMsgType: " + msg_type +
220 	 "\n\tContent: " + content);
221 
222       Performative msg = new Performative(msg_type);
223       msg.setInReplyTo(comms_key);
224       msg.setReceiver(agent);
225       msg.setContent(content);
226       context.MailBox().sendMsg(msg);
227       notifyConversationMonitors(comms_key,context.whoami(),agent,msg_type,
228                                  goals,CONTINUE_CONVERSATION);
229    }
230 
231 
232     // synchronized
233    public synchronized void continue_dialogue(String comms_key, String agent,
234                                  String msg_type, String data_type,
235 				 String data_key, Vector goals) {
236   
237       String content = Misc.concat(goals);
238       Core.DEBUG(1,"continue_dialogue:\n\tAgent: " + agent +
239          "\n\tCommsKey: " + comms_key + "\n\tMsgType: " + msg_type +
240          "\n\tDataType: " + data_type + "\n\tDataKey: " + data_key +
241 	 "\n\tContent: " + content);
242 
243       Performative msg = new Performative(msg_type);
244       Core.ERROR(msg_type.equals("inform"),2,this);
245       msg.setInReplyTo(comms_key);
246       msg.setReceiver(agent);
247       msg.setContent(data_type + " " + data_key + " " + content);
248       context.MailBox().sendMsg(msg);
249       notifyConversationMonitors(comms_key,context.whoami(),agent,msg_type,
250                                  data_type,data_key,goals,
251                                  CONTINUE_CONVERSATION);
252    
253    }
254    
255    
256 
257    public synchronized void continue_dialogue(Performative msg) {
258    /***
259       This routine is used by a remote agent to continue a negotiation dialogue
260       with this agent
261    */
262  //  synchronized (this) { 
263  try { // bug hunting!
264       String agent = msg.getSender();
265       String content = msg.getContent();
266       String msg_type = msg.getType();
267       String msg_key = msg.getInReplyTo();
268       Vector goals;
269       if ( msg_type.equals("inform") ) {
270          MsgContentHandler hd = new MsgContentHandler(content);
271          String data_type = hd.tag();
272          String data_key = hd.data(0);
273          String data = hd.rest(0);
274          goals = ZeusParser.factList(context.OntologyDb(),data);
275          goals = dereference(goals);
276          notifyConversationMonitors(msg_key,agent,context.whoami(),
277                                     msg_type,data_type,data_key,goals,
278                                     CONTINUE_CONVERSATION);
279          add(new DelegationStruct(agent,data_type,data_key,goals));
280       }
281       else {
282          goals = ZeusParser.goalList(context.OntologyDb(),content);
283          goals = dereference(goals);
284          notifyConversationMonitors(msg_key,agent,context.whoami(),msg_type,
285                                     goals,CONTINUE_CONVERSATION);
286          add(new DelegationStruct(agent,msg_type,msg_key,goals));
287       }
288  }catch (Exception e) { 
289     e.printStackTrace(); 
290  }
291 
292  // }
293    }
294 
295    protected synchronized final Vector dereference(Vector input) {
296       /***
297           Replication to handle the problem of variable clashes when
298           agents communicate with one another with variables in the
299           content data;
300       */
301 
302       Fact f;
303       Goal g;
304       Vector result = new Vector();
305 	try { 
306       Object x = input.elementAt(0);
307       if ( x instanceof zeus.concepts.Fact ) {
308          for(int i = 0; i < input.size(); i++ ) {
309             f = (Fact)input.elementAt(i);
310             f = f.duplicate(Fact.VAR,context.GenSym());
311             result.addElement(f);
312          }
313       }
314       else {
315          for(int i = 0; i < input.size(); i++ ) {
316             g = (Goal)input.elementAt(i);
317             g = g.duplicate(Fact.VAR,context.GenSym());
318             result.addElement(g);
319          }
320       }} 
321 	catch (Exception e) { 
322 	e.printStackTrace(); 
323 	}
324       return result;
325    }
326 
327     //synchronized
328    public  void achieve(String agent, String buyers_key,
329                                     Vector goals) {
330       Core.ERROR(!agent.equals(context.whoami()), 2, this);
331       // achieve received from a remote agent - first check if the item
332       // required by the agent can be sold directly; i.e. we are waiting to
333       // sell the item.
334 
335       // assume only one item in the goal list
336       Goal g = (Goal)goals.elementAt(0);
337       Fact f = g.getFact();
338       String sellers_key;
339       DelegationStruct ds = null;
340       if ( (sellers_key = waitingToSell(f)) != null ) {
341          itemsForSale.remove(sellers_key);
342          ds = new DelegationStruct(agent,"cfp",buyers_key,goals);
343          msgQueue.addElement(ds);
344          Core.DEBUG(2,"Waking seller node with key = " + sellers_key);
345          keyTable.put(sellers_key,buyers_key);
346          msgWaitTable.wakeup(sellers_key);
347          return;
348       }
349 
350       GraphStruct gs = new GraphStruct(agent,buyers_key,goals);
351       g0 graph = new g0();
352       notifyGraphMonitors(graph,GRAPH_CREATE);
353       graph.run(this,gs);
354    }
355    
356    
357    //synchronized
358    public  void achieve(Goal goal) {
359       // this is a locally called "achieve", hence we do not need to check
360       // whether we have anything for sale - no point selling something back
361       // to your self
362 
363       GraphStruct gs = new GraphStruct(context.whoami(),goal);
364       g0 g = new g0();
365       notifyGraphMonitors(g,GRAPH_CREATE);
366       g.run(this,gs);
367    }
368    
369    // synchronized 
370    public void achieve(Goal goal, String key) {
371       // this is also a locally called "achieve", hence we do not need to check
372       // whether we have anything for sale
373 
374       Assert.notFalse( goal.whichType() == Goal.DISCRETE );
375       DelegationStruct ds =
376          new DelegationStruct(goal.getDesiredBy(),"enact",key,goal);
377       auditTable.enact(ds);
378    }
379    
380    
381    //synchronized
382    public  void buy(Goal goal) {
383       buy g = new buy();
384       notifyGraphMonitors(g,GRAPH_CREATE);
385       GraphStruct gs = new GraphStruct(context.whoami(),goal);
386       g.run(this,gs);
387    }
388    
389    //synchronized
390    public  void sell(Goal goal) {
391       sell g = new sell();
392       notifyGraphMonitors(g,GRAPH_CREATE);
393       GraphStruct gs = new GraphStruct(context.whoami(),goal);
394       g.run(this,gs);
395    }
396 
397 //synchronized
398    public  void add(Node node) {
399       queue.enqueue(node);
400    }
401 
402  //synchronized
403    public void add(DelegationStruct ds) {
404       Core.DEBUG(2,"Engine: new msg received\n" + ds);
405 
406       if ( ds.msg_type.equals("result") ) {
407          auditTable.goodsReceived(ds);
408       }
409       else if ( ds.msg_type.equals("payment") ) {
410          auditTable.paymentReceived(ds);
411       }
412       else if ( ds.msg_type.equals("invoice") ) {
413          auditTable.invoiceReceived(ds);
414       }
415       else if ( ds.msg_type.equals("failure") ) {
416          int type = auditTable.exception(ds);
417 
418          GraphStruct gs = new GraphStruct();
419          gs.goal = ds.goals;
420          gs.internal = new Vector();
421          gs.external = Misc.copyVector(gs.goal);
422          gs.key = ds.key;
423          gs.agent = context.whoami();
424          gs.ignore_agents.addElement(ds.agent);
425 
426          double t = Double.MAX_VALUE;
427          Goal g;
428          for(int i = 0; i < gs.goal.size(); i++ ) {
429             g = (Goal)gs.goal.elementAt(i);
430             t = Math.min(t,g.getConfirmTime().getTime());
431          }
432 
433          /* Timeout heuristic */
434          gs.timeout = (t-context.now())/(gs.goal.size()+0.5);
435 
436          gs.any = new Integer(type);
437          g2 graph = new g2();
438          notifyGraphMonitors(graph,GRAPH_CREATE);
439          graph.run(this,gs);
440       }
441       else if ( ds.msg_type.equals("cancel") ) {
442          auditTable.cancel(ds);
443       }
444       else if ( ds.msg_type.equals("enact") ) {
445          auditTable.enact(ds);
446       }
447       else {
448          msgQueue.addElement(ds);
449          msgWaitTable.wakeup(ds.key);
450       }
451    }
452 
453 
454     //synchronized 
455    public void addItemForSale(String sellers_key, Fact fact) {
456       Core.ERROR(itemsForSale.put(sellers_key,fact) == null, 1, this);
457    }
458    
459    
460    //synchronized
461    public  void removeItemForSale(String sellers_key) {
462       itemsForSale.remove(sellers_key);
463       keyTable.remove(sellers_key);
464    }
465    
466    //synchronized 
467    public String getBuyersKey(String sellers_key) {
468       return (String)keyTable.get(sellers_key);
469    }
470 
471 
472    protected String waitingToSell(Fact fact) {
473       Enumeration keys = itemsForSale.keys();
474       String key;
475       Fact f;
476       Bindings b = new Bindings(context.whoami());
477       while( keys.hasMoreElements() ) {
478          b.clear();
479          key = (String)keys.nextElement();
480          f = (Fact)itemsForSale.get(key);
481          if ( f.unifiesWith(fact,b) )
482             return key;
483       }
484       return null;
485    }
486 
487 
488     //synchronized
489    public synchronized void wakeup(String key) {
490       msgWaitTable.wakeup(key);
491    }
492 
493 
494     //synchronized 
495    public synchronized void replan(PlannerQueryStruct struct, String key) {
496       GraphStruct gs = new GraphStruct();
497 
498       gs.goal = struct.goals;
499       gs.internal = struct.internal;
500       gs.external = struct.external;
501       gs.agent = context.whoami();
502       gs.key = key;
503 
504       Goal g;
505       double t = Double.MAX_VALUE;
506       for(int i = 0; i < gs.goal.size(); i++ ) {
507          g = (Goal)gs.goal.elementAt(i);
508          t = Math.min(t,g.getConfirmTime().getTime());
509       }
510       gs.timeout = (t-context.now())/(gs.goal.size()+0.5);
511       g1 graph = new g1();
512       notifyGraphMonitors(graph,GRAPH_CREATE);
513       graph.run(this,gs);
514    }
515    
516    //synchronized 
517    public void agentWithAbilityFound(Performative msg) {
518       String key = msg.getInReplyTo();
519       String content = msg.getContent();
520       if ( context.OrganisationDb() != null ) {
521          Vector v = ZeusParser.abilityDbItemList(context.OntologyDb(),content);
522          context.OrganisationDb().add(v);
523          msgWaitTable.wakeup(key);
524       }
525    }
526    
527    // synchronized 
528   synchronized void  waitForMsg(Node node) {
529       msgWaitTable.add(node);
530    }
531    
532    // synchronized
533    public synchronized DelegationStruct replyReceived(String key) {
534       DelegationStruct ds;
535       for( int i = 0; i < msgQueue.size(); i++ ) {
536          ds = (DelegationStruct)msgQueue.elementAt(i);
537          if ( ds.key.equals(key) ) {
538             msgQueue.removeElementAt(i--);
539             return ds;
540          }
541       }
542       return null;
543    }
544    
545    //synchronized
546    public synchronized DelegationStruct replyReceived(String key,
547                                                       String type) {
548       DelegationStruct ds;
549       for( int i = 0; i < msgQueue.size(); i++ ) {
550          ds = (DelegationStruct)msgQueue.elementAt(i);
551          if ( ds.key.equals(key) && ds.msg_type.equals(type) ) {
552             msgQueue.removeElementAt(i--);
553             return ds;
554          }
555       }
556       return null;
557    }
558 
559 
560     //synchronized 
561    public synchronized void replaceReply(Vector replies) {
562       if ( replies == null || replies.isEmpty() ) return;
563       for(int i = 0; i < replies.size(); i++ )
564          msgQueue.addElement(replies.elementAt(i));
565    }
566 
567 
568  //synchronized
569    public Vector repliesReceived(String key) {
570       Vector items = new Vector();
571       DelegationStruct ds;
572       for( int i = 0; i < msgQueue.size(); i++ ) {
573          ds = (DelegationStruct)msgQueue.elementAt(i);
574          if ( ds.key.equals(key) ) {
575             items.addElement(ds);
576             msgQueue.removeElementAt(i--);
577          }
578       }
579       return items;
580    }
581    
582    //synchronized
583    public synchronized Vector repliesReceived(String key, String type) {
584       Vector items = new Vector();
585       DelegationStruct ds;
586       for( int i = 0; i < msgQueue.size(); i++ ) {
587          ds = (DelegationStruct)msgQueue.elementAt(i);
588          if ( ds.key.equals(key) && ds.msg_type.equals(type) ) {
589             items.addElement(ds);
590             msgQueue.removeElementAt(i--);
591          }
592       }
593       return items;
594    }
595 
596    // ---- Event Monitoring ----
597    public void addConversationMonitor(ConversationMonitor monitor,
598                                       long event_mask) {
599       if ( (event_mask & ConversationEvent.INITIATE_MASK) != 0 )
600          conversationMonitors[INITATE_CONVERSATION].add(monitor);
601       if ( (event_mask & ConversationEvent.CONTINUE_MASK) != 0 )
602          conversationMonitors[CONTINUE_CONVERSATION].add(monitor);
603    }
604    public void removeConversationMonitor(ConversationMonitor monitor, 
605                                          long event_mask) {
606       if ( (event_mask & ConversationEvent.INITIATE_MASK) != 0 )
607          conversationMonitors[INITATE_CONVERSATION].remove(monitor);
608       if ( (event_mask & ConversationEvent.CONTINUE_MASK) != 0 )
609          conversationMonitors[CONTINUE_CONVERSATION].remove(monitor);
610    }
611 
612    public void addNodeMonitor(NodeMonitor monitor, long event_mask) {
613       if ( (event_mask & NodeEvent.CREATE_MASK) != 0 )
614          nodeMonitors[NODE_CREATE].add(monitor);
615       if ( (event_mask & NodeEvent.STATE_CHANGE_MASK) != 0 )
616          nodeMonitors[NODE_STATE_CHANGE].add(monitor);
617       if ( (event_mask & NodeEvent.DISPOSE_MASK) != 0 )
618          nodeMonitors[NODE_DISPOSE].add(monitor);
619    }
620    public void removeNodeMonitor(NodeMonitor monitor, long event_mask) {
621       if ( (event_mask & NodeEvent.CREATE_MASK) != 0 )
622          nodeMonitors[NODE_CREATE].remove(monitor);
623       if ( (event_mask & NodeEvent.STATE_CHANGE_MASK) != 0 )
624          nodeMonitors[NODE_STATE_CHANGE].remove(monitor);
625       if ( (event_mask & NodeEvent.DISPOSE_MASK) != 0 )
626          nodeMonitors[NODE_DISPOSE].remove(monitor);
627    }
628 
629    public void addGraphMonitor(GraphMonitor monitor, long event_mask) {
630       if ( (event_mask & GraphEvent.CREATE_MASK) != 0 )
631          graphMonitors[GRAPH_CREATE].add(monitor);
632       if ( (event_mask & GraphEvent.STATE_CHANGE_MASK) != 0 )
633          graphMonitors[GRAPH_STATE_CHANGE].add(monitor);
634       if ( (event_mask & GraphEvent.DISPOSE_MASK) != 0 )
635          graphMonitors[GRAPH_DISPOSE].add(monitor);
636    }
637    public void removeGraphMonitor(GraphMonitor monitor, long event_mask) {
638       if ( (event_mask & GraphEvent.CREATE_MASK) != 0 )
639          graphMonitors[GRAPH_CREATE].remove(monitor);
640       if ( (event_mask & GraphEvent.STATE_CHANGE_MASK) != 0 )
641          graphMonitors[GRAPH_STATE_CHANGE].remove(monitor);
642       if ( (event_mask & GraphEvent.DISPOSE_MASK) != 0 )
643          graphMonitors[GRAPH_DISPOSE].remove(monitor);
644    }
645 
646    public void addArcMonitor(ArcMonitor monitor, long event_mask) {
647       if ( (event_mask & ArcEvent.CREATE_MASK) != 0 )
648          arcMonitors[ARC_CREATE].add(monitor);
649       if ( (event_mask & ArcEvent.SUCCEED_MASK) != 0 )
650          arcMonitors[ARC_SUCCEED].add(monitor);
651       if ( (event_mask & ArcEvent.FAIL_MASK) != 0 )
652          arcMonitors[ARC_FAIL].add(monitor);
653       if ( (event_mask & ArcEvent.DISPOSE_MASK) != 0 )
654          arcMonitors[ARC_DISPOSE].add(monitor);
655    }
656    public void removeArcMonitor(ArcMonitor monitor, long event_mask) {
657       if ( (event_mask & ArcEvent.CREATE_MASK) != 0 )
658          arcMonitors[ARC_CREATE].remove(monitor);
659       if ( (event_mask & ArcEvent.SUCCEED_MASK) != 0 )
660          arcMonitors[ARC_SUCCEED].remove(monitor);
661       if ( (event_mask & ArcEvent.FAIL_MASK) != 0 )
662          arcMonitors[ARC_FAIL].remove(monitor);
663       if ( (event_mask & ArcEvent.DISPOSE_MASK) != 0 )
664          arcMonitors[ARC_DISPOSE].remove(monitor);
665    }
666 
667    void notifyConversationMonitors(String comms_key, String sender, 
668                                    String receiver, String msg_type, 
669 			           Vector data, int type) {
670       if ( conversationMonitors[type].isEmpty() ) return;
671 
672       ConversationMonitor monitor;
673       ConversationEvent event;
674       Enumeration enum = conversationMonitors[type].elements();
675 
676       switch(type) {
677          case INITATE_CONVERSATION:
678               event = new ConversationEvent(this,this,comms_key,sender, 
679                                             receiver,msg_type,data,
680                                             ConversationEvent.INITIATE_MASK);
681               while( enum.hasMoreElements() ) {
682                  monitor = (ConversationMonitor)enum.nextElement();
683                  monitor.conversationInitiatedEvent(event);
684               }
685               break;
686          case CONTINUE_CONVERSATION:
687               event = new ConversationEvent(this,this,comms_key,sender, 
688                                             receiver,msg_type,data,
689                                             ConversationEvent.CONTINUE_MASK);
690               while( enum.hasMoreElements() ) {
691                  monitor = (ConversationMonitor)enum.nextElement();
692                  monitor.conversationContinuedEvent(event);
693               }
694               break;
695       }
696    }
697 
698    void notifyConversationMonitors(String comms_key, String sender, 
699                                    String receiver, String msg_type, 
700 			           String data_type, String data_key,
701                                    Vector data, int type) {
702       if ( conversationMonitors[type].isEmpty() ) return;
703 
704       ConversationMonitor monitor;
705       ConversationEvent event;
706       Enumeration enum = conversationMonitors[type].elements();
707 
708       switch(type) {
709          case INITATE_CONVERSATION:
710               event = new ConversationEvent(this,this,comms_key,sender, 
711                                             receiver,msg_type,
712                                             data_type, data_key, data,
713                                             ConversationEvent.INITIATE_MASK);
714               while( enum.hasMoreElements() ) {
715                  monitor = (ConversationMonitor)enum.nextElement();
716                  monitor.conversationInitiatedEvent(event);
717               }
718               break;
719          case CONTINUE_CONVERSATION:
720               event = new ConversationEvent(this,this,comms_key,sender, 
721                                             receiver,msg_type,
722                                             data_type, data_key, data,
723                                             ConversationEvent.CONTINUE_MASK);
724               while( enum.hasMoreElements() ) {
725                  monitor = (ConversationMonitor)enum.nextElement();
726                  monitor.conversationContinuedEvent(event);
727               }
728               break;
729       }
730    }
731 
732    void notifyNodeMonitors(Node node, int type) {
733       if ( nodeMonitors[type].isEmpty() ) return;
734 
735       NodeMonitor monitor;
736       NodeEvent event;
737       Enumeration enum = nodeMonitors[type].elements();
738 
739       switch(type) {
740          case NODE_CREATE:
741               event = new NodeEvent(this,node,NodeEvent.CREATE_MASK);
742               while( enum.hasMoreElements() ) {
743                  monitor = (NodeMonitor)enum.nextElement();
744                  monitor.nodeCreatedEvent(event);
745               }
746               break;
747          case NODE_DISPOSE:
748               event = new NodeEvent(this,node,NodeEvent.DISPOSE_MASK);
749               while( enum.hasMoreElements() ) {
750                  monitor = (NodeMonitor)enum.nextElement();
751                  monitor.nodeDisposedEvent(event);
752               }
753               break;
754          case NODE_STATE_CHANGE:
755               event = new NodeEvent(this,node,NodeEvent.STATE_CHANGE_MASK);
756               while( enum.hasMoreElements() ) {
757                  monitor = (NodeMonitor)enum.nextElement();
758                  monitor.nodeStateChangedEvent(event);
759               }
760               break;
761       }
762    }
763 
764    void notifyGraphMonitors(Graph graph, int type) {
765       if ( graphMonitors[type].isEmpty() ) return;
766 
767       GraphMonitor monitor;
768       GraphEvent event;
769       Enumeration enum = graphMonitors[type].elements();
770 
771       switch(type) {
772          case GRAPH_CREATE:
773               event = new GraphEvent(this,graph,GraphEvent.CREATE_MASK);
774               while( enum.hasMoreElements() ) {
775                  monitor = (GraphMonitor)enum.nextElement();
776                  monitor.graphCreatedEvent(event);
777               }
778               break;
779          case GRAPH_DISPOSE:
780               event = new GraphEvent(this,graph,GraphEvent.DISPOSE_MASK);
781               while( enum.hasMoreElements() ) {
782                  monitor = (GraphMonitor)enum.nextElement();
783                  monitor.graphDisposedEvent(event);
784               }
785               break;
786          case GRAPH_STATE_CHANGE:
787               event = new GraphEvent(this,graph,GraphEvent.STATE_CHANGE_MASK);
788               while( enum.hasMoreElements() ) {
789                  monitor = (GraphMonitor)enum.nextElement();
790                  monitor.graphStateChangedEvent(event);
791               }
792               break;
793       }
794    }
795 
796    void notifyArcMonitors(Arc arc, Node node, int type) {
797       if ( arcMonitors[type].isEmpty() ) return;
798 
799       ArcMonitor monitor;
800       ArcEvent event;
801       Enumeration enum = arcMonitors[type].elements();
802 
803       switch(type) {
804          case ARC_CREATE:
805               event = new ArcEvent(this,arc,node,ArcEvent.CREATE_MASK);
806               while( enum.hasMoreElements() ) {
807                  monitor = (ArcMonitor)enum.nextElement();
808                  monitor.arcCreatedEvent(event);
809               }
810               break;
811          case ARC_DISPOSE:
812               event = new ArcEvent(this,arc,node,ArcEvent.DISPOSE_MASK);
813               while( enum.hasMoreElements() ) {
814                  monitor = (ArcMonitor)enum.nextElement();
815                  monitor.arcDisposedEvent(event);
816               }
817               break;
818          case ARC_SUCCEED:
819               event = new ArcEvent(this,arc,node,ArcEvent.SUCCEED_MASK);
820               while( enum.hasMoreElements() ) {
821                  monitor = (ArcMonitor)enum.nextElement();
822                  monitor.arcSucceededEvent(event);
823               }
824               break;
825          case ARC_FAIL:
826               event = new ArcEvent(this,arc,node,ArcEvent.FAIL_MASK);
827               while( enum.hasMoreElements() ) {
828                  monitor = (ArcMonitor)enum.nextElement();
829                  monitor.arcFailedEvent(event);
830               }
831               break;
832       }
833    }
834 }
835 
836