1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package zeus.actors;
29
30 import java.util.*;
31 import zeus.util.*;
32 import zeus.concepts.*;
33 import zeus.actors.rtn.util.DelegationStruct;
34 import zeus.actors.rtn.Engine;
35 import zeus.actors.event.*;
36 import zeus.agents.*;
37 import gnu.regexp.*;
38 import java.lang.reflect.*;
39
40 /***
41 * The Message Handler component implements each Zeus agent's internal "mail
42 * sorting office", continually checking the incoming-message-queue of the
43 * {@link MailBox} for new messages, and forwarding them to the relevant
44 * components within the agent. <p>
45 *
46 * The Message Handler's behaviour is controlled by two factors: first,
47 * whether a new message represents the start of a new dialogue or it is part
48 * of an existing dialogue; and second, on the message processing rules
49 * registered with it by other components of the agent.<p>
50 * Change Log <br>
51 * ----------<p>
52 * 22/08/00 Altered spelling of organization to correct version for about 6 lines - Simon
53 *
54 */
55
56 public class MsgHandler extends Thread {
57 protected HSet[] eventMonitor = new HSet[4];
58
59 protected static final int ADD = 0;
60 protected static final int FIRE = 1;
61 protected static final int DELETE = 2;
62 protected static final int FAIL = 3;
63
64 protected Hashtable addressQueryTable = new Hashtable();
65 protected Hashtable abilityQueryTable = new Hashtable();
66 protected Hashtable reportQueryTable = new Hashtable();
67
68 protected ReportLogger reportLogger = null;
69 protected AbilityLogger abilityLogger = null;
70
71 protected boolean processing;
72 protected AgentContext context = null;
73 protected RootNode MessageRootNode = null;
74 Vector attributeNodes = new Vector();
75 static int cleanupInterval = 100;
76
77 protected Queue handleQ = null;
78
79
80 public MsgHandler() {
81 ;
82 }
83
84
85 public MsgHandler(AgentContext context) {
86 super();
87 handleQ = new Queue("msg handler processing Q");
88 Assert.notNull(context);
89 this.context = context;
90 context.set(this);
91
92 for(int i = 0; i < eventMonitor.length; i++ )
93 eventMonitor[i] = new HSet();
94
95 MessageRootNode = new RootNode(this);
96
97
98 String[][] msg_pattern = {
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 };
144
145 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[0], this, "register"));
146 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[1], this, "deregister"));
147 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[2], this, "log_message"));
148 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[3], this, "log_report"));
149 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[4], this, "log_address"));
150 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[5], this, "cancel_message"));
151 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[6], this, "cancel_report"));
152 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[7], this, "cancel_address"));
153 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[8], this, "your_abilities"));
154 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[9], this, "address_of"));
155 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[10],this, "your_relations"));
156 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[11],this, "has_ability"));
157 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[12],this, "isa_facilitator"));
158 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[13],this, "kill_yourself"));
159
160 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[14],this, "log_specified_ability"));
161 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[15],this, "cancel_specified_ability"));
162 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[16],this, "add_agents_abilities"));
163 addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern[17],this, "add_information"));
164 this.setName("MsgHandler");
165 this.start();
166 }
167
168 public AgentContext getAgentContext() {
169 return context;
170 }
171
172 public void lowerStatus() {
173
174
175 }
176
177 public void stopProcessing() {
178 processing = false;
179 }
180
181
182
183 /***
184 * refactored to help readability - this method loops until it gets
185 * a valid MailBox from the agent, so that the system can initialise in
186 * the right order
187 */
188 private MailBox waitForSetUp() {
189 MailBox mbox = context.MailBox();
190 while ( mbox == null ) {
191 try {
192 sleep(300);
193 mbox = context.MailBox();
194 }
195 catch(InterruptedException e) {
196 e.printStackTrace();
197 }
198 }
199 return mbox;
200 }
201
202
203 /***
204 * thread main method - try and read incomming messages until
205 * the universe ends
206 */
207 public void run() {
208 try {
209
210 Performative msg;
211 processing = true;
212 MailBox mbox = waitForSetUp();
213
214 int count = 0;
215 while(processing) {
216
217 synchronized (handleQ) {
218
219 msg = (Performative) handleQ.dequeue();
220
221 debug("processing:" + msg.toString());
222 Core.DEBUG(1,"MsgHandler processing msg from ...\n" + msg.getSender());
223 try {
224
225 MessageRootNode.evaluate(null, msg);
226 } catch (Exception e) {
227 e.printStackTrace();
228
229 }
230 }
231 yield();
232 count++;
233 if (count > 100) {
234 System.gc();
235 count = 0;
236 }
237 }
238 }
239 catch (Exception e) {
240 e.printStackTrace();
241 }
242 }
243
244
245 /***
246 * in old versions of Zeus the msgHandler was responsible for ensuring that incomming
247 * messages were processed. However this approach meant that reengineering of the msgHandler would
248 * be necessary whenever a mailbox was built that had more than one server - basically
249 * this was a problem in terms of both coupling the mailbox,server and msgHandler
250 * objects and reducing the coheasion of the msgHandler. <p>
251 * solution: processMessage is a method that can be called by any
252 * object to see if message rules have been set that apply to this message. The
253 * servers (inboxes) are responsible for calling this method which will process the message
254 * for them - or not as they like. <p>
255 * This method puts the message on a queue, which is internal to the msgHandler. The thread
256 * run by msgHandler will then process it. //synch
257 */
258 public void processMessage(Performative msg) {
259 handleQ.enqueue(msg);
260 }
261
262
263
264 public Queue getMessageQueue() {
265 return (handleQ);
266 }
267
268
269
270
271 public void addRule(MessageRule r) {
272 MsgNode node = null;
273 MsgNode term;
274 boolean found;
275 Core.DEBUG(1,"Compiling msg processing rule ...\n\t" + r);
276 MessagePattern token = r.getPattern();
277
278
279 term = MessageRootNode;
280 Core.DEBUG(3,"=r");
281 Core.DEBUG(4,"=r[" + term + "]");
282 term.use_count++;
283 node = term;
284
285
286
287 RE[] value = token.listValues();
288 String[] attribute = token.listAttributes();
289
290 for(int k = 0; k < value.length; k++ ) {
291 if ( value[k] != null ) {
292 term = new AttributeNode(this,attribute[k],value[k]);
293 found = false;
294 for(int j = 0; !found && j < attributeNodes.size(); j++ ) {
295 found = term.equals(attributeNodes.elementAt(j));
296 if (found)
297 term = (MsgNode)attributeNodes.elementAt(j);
298 }
299 if ( !found ) {
300 attributeNodes.addElement(term);
301 Core.DEBUG(3,"+m");
302 Core.DEBUG(4,"+m[" + term + "]");
303 }
304 else {
305 Core.DEBUG(3,"=m");
306 Core.DEBUG(4,"=m[" + term + "]");
307 }
308 term.use_count++;
309 node.addSuccessor(r.getName(),term);
310 node = term;
311 }
312 }
313
314
315
316 ActionNode action = new ActionNode(this,r.getName(),r.getAction());
317 action.use_count++;
318 term.addSuccessor(r.getName(),action);
319 Core.DEBUG(3,"+a");
320 Core.DEBUG(4,"+a[" + action + "]");
321 notifyMonitors(ADD,new MessageHandlerEvent(this,r,MessageHandlerEvent.ADD_MASK));
322 }
323
324
325 public void removeRule(String name) {
326 MessageRootNode.remove(name);
327 notifyMonitors(DELETE,new MessageHandlerEvent(this,name,MessageHandlerEvent.DELETE_MASK));
328 }
329
330
331 public synchronized Object execRule(String rule, Object object, String method, Performative input) {
332 Class c = object.getClass();
333 try {
334 Class[] parameter_types = new Class[1];
335 parameter_types[0] = input.getClass();
336 Object[] arglist = new Object[1];
337 arglist[0] = input;
338
339 Core.DEBUG(2,"Invoking method " + method + " of class " +
340 c.getName() + " with parameter " + input);
341
342 Method m = c.getMethod(method,parameter_types);
343 notifyMonitors(FIRE,new MessageHandlerEvent(this,rule,object,method,input,MessageHandlerEvent.FIRE_MASK));
344 return m.invoke(object,arglist);
345 }
346 catch(Throwable err) {
347 Core.USER_ERROR("MsgHandler - Error invoking target: [" + rule +
348 "::" + object.getClass().getName() + "." + method +
349 "()]\nwith args...\n" + input + "\n" + err);
350 notifyMonitors(FAIL,new MessageHandlerEvent(this,rule,object,method,input,MessageHandlerEvent.FAIL_MASK));
351 }
352 return null;
353 }
354
355 protected void adviseAll(Address addr) {
356 Enumeration enum = addressQueryTable.keys();
357 String name, reply_with;
358 Performative reply;
359 MailBox mbox = context.MailBox();
360
361 while ( enum.hasMoreElements() ) {
362 name = (String) enum.nextElement();
363 reply_with = (String) addressQueryTable.get(name);
364
365 reply = new Performative("inform");
366 reply.setReceiver(name);
367 reply.setContent(addr.toString());
368 reply.setInReplyTo(reply_with);
369 mbox.sendMsg(reply);
370 }
371 }
372
373 public void register(Performative msg) {
374 try {
375 if (context.whoami().equalsIgnoreCase("ANServer")) {
376 Performative forwarder = new Performative(msg);
377 forwarder.setReceiver("ams");
378 forwarder.send(context);
379 }
380 String reply_with, content;
381 if ( (reply_with = msg.getReplyWith()) == null ) {
382 refuse(msg,"no reply-with tag");
383 return;
384 }
385
386 if ( (content = context.Clock().initData()) != null ) {
387 Performative reply = new Performative("inform");
388 reply.setReceiver(msg.getSender());
389 reply.setInReplyTo(reply_with);
390 reply.setContent(content + " " + System.currentTimeMillis());
391 context.MailBox().sendMsg(reply);
392 }
393 adviseAll(msg.getAddress());
394 }
395 catch(Exception e) {
396 e.printStackTrace();
397 }
398 }
399
400 public void deregister(Performative msg) {
401 Address address;
402
403 String name = msg.getSender();
404 if ( (address = msg.getAddress()) != null )
405 context.MailBox().del(address);
406
407 if ( addressQueryTable.containsKey(name) )
408 addressQueryTable.remove(name);
409
410 String reply_with = msg.getReplyWith();
411 if ( reply_with != null ) {
412 Performative reply = new Performative("inform");
413 reply.setReceiver(msg.getSender());
414 reply.setInReplyTo(reply_with);
415 reply.setContent("done deregister");
416 context.MailBox().sendMsg(reply);
417 }
418 debug("Deregister message : " + msg.toString());
419 }
420
421 public void kill_yourself(Performative msg) {
422
423 context.Agent().notifyMonitors(BasicAgent.DEATH);
424 System.exit(0);
425 }
426
427 public void add_task(Performative msg) {
428 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
429 if ( context.TaskDb() != null ) {
430 Vector List = ZeusParser.taskList(context.OntologyDb(),hd.data());
431 context.TaskDb().add(List);
432 inform(msg,"done add_task");
433 }
434 else
435 refuse(msg,"no task database");
436 }
437
438 public void modify_task(Performative msg) {
439 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
440 if ( context.TaskDb() != null ) {
441 Vector List = ZeusParser.taskList(context.OntologyDb(),hd.data());
442 context.TaskDb().add(List);
443 inform(msg,"done modify_task");
444 }
445 else
446 refuse(msg,"no task database");
447 }
448
449
450 public void delete_task(Performative msg) {
451 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
452 if ( context.TaskDb() != null ) {
453 context.TaskDb().deleteTask(hd.data());
454 inform(msg,"done delete_task");
455 }
456 else
457 refuse(msg,"no task database");
458 }
459
460
461 public void cancel_message(Performative msg) {
462 context.MailBox().stopLoggingMessages(msg.getSender());
463 }
464
465
466 public void cancel_report(Performative msg) {
467 reportQueryTable.remove(msg.getSender());
468 if ( reportQueryTable.isEmpty() ) {
469 reportLogger.stopLogging();
470 reportLogger = null;
471 }
472 }
473
474 public void cancel_specified_ability(Performative msg) {
475 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
476 if ( hd.data() == null ) {
477 refuse(msg,"no key specified");
478 return;
479 }
480 abilityQueryTable.remove(hd.data());
481 if ( abilityQueryTable.isEmpty() ) {
482 abilityLogger.stopLogging();
483 abilityLogger = null;
484 }
485 }
486
487 public void cancel_address(Performative msg) {
488 addressQueryTable.remove(msg.getSender());
489 }
490
491 public void log_message(Performative msg) {
492 String reply_with = msg.getReplyWith();
493 if ( reply_with == null ) {
494 refuse(msg,"no reply-with key");
495 return;
496 }
497 context.MailBox().logMessages(msg.getSender(),reply_with);
498 }
499
500 public void log_report(Performative msg) {
501 String reply_with = msg.getReplyWith();
502 if ( reply_with == null ) {
503 refuse(msg,"no reply-with key");
504 return;
505 }
506 else if ( context.Planner() == null ) {
507 refuse(msg,"no planner");
508 return;
509 }
510 reportQueryTable.put(msg.getSender(),reply_with);
511 if ( reportLogger == null ) reportLogger = new ReportLogger();
512 }
513
514 protected class ReportLogger extends PlanStepAdapter {
515 public ReportLogger() {
516 context.Planner().addPlanStepMonitor(this,PlanStepEvent.STATE_CHANGE_MASK);
517 }
518 public void stopLogging() {
519 context.Planner().addPlanStepMonitor(this,PlanStepEvent.STATE_CHANGE_MASK);
520 }
521 public void planStepStateChangedEvent(PlanStepEvent event) {
522 if ( reportQueryTable.isEmpty() ) return;
523
524 PlanRecord rec = event.getPlanRecord();
525 switch( rec.getState() ) {
526 case PlanRecord.FREE:
527 case PlanRecord.TEMP:
528 case PlanRecord.TENTATIVE:
529 break;
530
531 case PlanRecord.FIRM:
532 case PlanRecord.RUNNING:
533 case PlanRecord.FAILED:
534 case PlanRecord.COMPLETED:
535 case PlanRecord.JEOPARDY:
536 case PlanRecord.AGREEMENT:
537 ReportRec report = rec.report();
538 Enumeration enum = reportQueryTable.keys();
539 String agent, reply_with;
540 Performative reply;
541 while( enum.hasMoreElements() ) {
542 agent = (String)enum.nextElement();
543 reply_with = (String)reportQueryTable.get(agent);
544
545 reply = new Performative("inform");
546 reply.setContent(report.toString());
547 reply.setReceiver(agent);
548 reply.setInReplyTo(reply_with);
549 context.MailBox().sendMsg(reply);
550 }
551 break;
552 }
553 }
554 }
555
556 public void log_address(Performative msg) {
557 String reply_with = msg.getReplyWith();
558 if ( reply_with == null ) {
559 refuse(msg,"no reply-with key");
560 return;
561 }
562 addressQueryTable.put(msg.getSender(),reply_with);
563 Vector List = context.MailBox().listAddresses();
564 if ( !List.isEmpty() ) {
565 Performative reply = new Performative("inform");
566 reply.setReceiver(msg.getSender());
567 reply.setInReplyTo(reply_with);
568 reply.setContent(Misc.concat(List));
569 context.MailBox().sendMsg(reply);
570 }
571 }
572
573 public void log_specified_ability(Performative msg) {
574 String reply_with = msg.getReplyWith();
575 if ( reply_with == null ) {
576 refuse(msg,"no reply-with key");
577 return;
578 }
579 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
580 if ( hd.data() == null ) {
581 refuse(msg,"no ability specified");
582 return;
583 }
584 else if ( context.OrganisationDb() == null ) {
585
586 refuse(msg,"no organization database");
587 return;
588 }
589 AbilitySpec a = ZeusParser.abilitySpec(context.OntologyDb(),hd.data());
590 if ( a == null ) {
591 refuse(msg,"no ability specified");
592 return;
593 }
594 Vector List = context.OrganisationDb().findAll(a);
595 if ( !List.isEmpty() ) {
596 Performative reply = new Performative("inform");
597 reply.setContent(Misc.concat(List));
598 reply.setReceiver(msg.getSender());
599 reply.setInReplyTo(reply_with);
600 context.MailBox().sendMsg(reply);
601 }
602
603 Object[] data = new Object[2];
604 data[0] = msg.getSender();
605 data[1] = a;
606
607 abilityQueryTable.put(reply_with,data);
608 if ( abilityLogger == null ) abilityLogger = new AbilityLogger();
609 }
610
611 class AbilityLogger extends AbilityAdapter {
612 public AbilityLogger() {
613 context.OrganisationDb().addAbilityMonitor(this,AbilityEvent.ADD_MASK);
614 }
615 public void stopLogging() {
616 context.OrganisationDb().removeAbilityMonitor(this,AbilityEvent.ADD_MASK);
617 }
618 public void abilityAddedEvent(AbilityEvent event) {
619 if ( abilityQueryTable.isEmpty() ) return;
620
621 Enumeration enum = abilityQueryTable.keys();
622 String reply_with;
623 Performative reply;
624 Object[] data;
625 AbilitySpec b, a = event.getAbility();
626
627 Fact f2, f1 = a.getFact();
628 int t2, t1 = a.getTime();
629 double c2, c1 = a.getCost();
630
631 Bindings bindings = new Bindings(context.whoami());
632
633 while( enum.hasMoreElements() ) {
634 bindings.clear();
635 reply_with = (String)enum.nextElement();
636 data = (Object[])abilityQueryTable.get(reply_with);
637
638 b = (AbilitySpec)data[1];
639 f2 = b.getFact();
640 t2 = b.getTime();
641 c2 = b.getCost();
642 if ( (t1 == 0 || t2 <= t1) && (c1 == 0 || c2 <= c1) &&
643 f2.unifiesWith(f1,bindings) ) {
644 reply = new Performative("inform");
645 reply.setContent(event.getAbilityDbItem().toString());
646 reply.setReceiver((String)data[0]);
647 reply.setInReplyTo(reply_with);
648 context.MailBox().sendMsg(reply);
649 }
650 }
651 }
652 }
653
654 public void address_of(Performative msg) {
655 String content = msg.getContent();
656 String reply_with = msg.getReplyWith();
657 if ( reply_with == null ) {
658 refuse(msg,"no reply-with key");
659 return;
660 }
661 else if ( content == null ) {
662 failure(msg,"no content");
663 return;
664 }
665 MsgContentHandler hd = new MsgContentHandler(content);
666 Address addr;
667 if ( hd.data() != null &&
668 (addr = context.MailBox().lookup(hd.data())) != null ) {
669 Performative reply = new Performative("inform");
670 reply.setReceiver(msg.getSender());
671 reply.setInReplyTo(reply_with);
672 reply.setContent(addr.toString());
673 context.MailBox().sendMsg(reply);
674 }
675 else
676 failure(msg,"address not known");
677 }
678
679 public void your_abilities(Performative msg) {
680 try {
681 String content = msg.getContent();
682 String reply_with = msg.getReplyWith();
683 if ( reply_with == null ) {
684 refuse(msg,"no reply-with key");
685 return;
686 }
687 else if ( context.OrganisationDb() == null ) {
688
689 refuse(msg,"no organization database");
690 return;
691 }
692 Vector List = context.OrganisationDb().abilitiesOf(context.whoami());
693 if ( List.isEmpty() ) {
694 failure(msg,"no abilities");
695 return;
696 }
697 Performative reply = new Performative("inform");
698 reply.setContent(Misc.concat(List));
699 reply.setReceiver(msg.getSender());
700 reply.setInReplyTo(reply_with);
701 context.MailBox().sendMsg(reply);
702 sendServiceDescriptions(msg.getSender(), msg.getReplyWith());
703 }
704 catch (Throwable t) {
705 t.printStackTrace();
706 }
707 }
708
709
710 protected void sendServiceDescriptions(String target, String replyWith) {
711
712 try {
713 TaskDb tasks = context.getTaskDb();
714 Enumeration keys = tasks.keys();
715 while (keys.hasMoreElements()) {
716 Hashtable ofType = (Hashtable) tasks.get(keys.nextElement());
717 Enumeration allElements = ofType.elements();
718 while (allElements.hasMoreElements()) {
719
720 Task task = (Task) allElements.nextElement();
721
722 sendProfile(task, context, target, replyWith);
723 sendInstance(task, context, target, replyWith);
724 sendInstanceRange(task, context, target, replyWith);
725 sendProcess(task, context, target, replyWith);
726
727 }
728 }
729 }
730 catch (Exception e) {
731 e.printStackTrace();
732 }
733 }
734
735 private void sendProfile(Task task, AgentContext context, String target,
736 String replyWith) {
737
738 String description = task.getServiceDesc(context);
739 if(description != null && description.length() > 0) {
740 Performative sendMsg = new Performative("inform");
741 sendMsg.setReceiver(target);
742 sendMsg.setInReplyTo(replyWith);
743 sendMsg.setContent("( :serviceProfile (\"" + description + "\"))");
744 sendMsg.send(context);
745 }
746 }
747
748 private void sendInstance(Task task, AgentContext context, String target,
749 String replyWith) {
750
751 String instanceDetails = task.getInstanceDetails(context);
752 if(instanceDetails != null && instanceDetails.length() > 0) {
753 Performative instanceDesc = new Performative("inform");
754 instanceDesc.setReceiver(target);
755 instanceDesc.setInReplyTo(replyWith);
756 instanceDesc.setContent("( :serviceInstance (\"" +
757 instanceDetails + "\"))");
758 instanceDesc.send(context);
759 }
760 }
761
762 private void sendInstanceRange(Task task, AgentContext context,
763 String target, String replyWith) {
764
765 String instanceRange = task.getInstanceRange(context);
766 if(instanceRange != null && instanceRange.length() > 0) {
767 Performative instanceDesc = new Performative("inform");
768 instanceDesc.setReceiver(target);
769 instanceDesc.setInReplyTo(replyWith);
770 instanceDesc.setContent("( :serviceRange (:task " + task.getName() +
771 " :content \"" + instanceRange + "\"))");
772 instanceDesc.send(context);
773 }
774 }
775
776 private void sendProcess(Task task, AgentContext context, String target,
777 String replyWith) {
778
779 String processModel = task.getProcessModel(context);
780 if(processModel != null && processModel.length() > 0) {
781 Performative process = new Performative("inform");
782 process.setReceiver(target);
783 process.setInReplyTo(replyWith);
784 process.setContent("( :processModel (\"" + processModel + "\"))");
785 process.send(context);
786 }
787 }
788
789 public void your_relations(Performative msg) {
790 String content = msg.getContent();
791 String reply_with = msg.getReplyWith();
792 if ( reply_with == null ) {
793 refuse(msg,"no reply-with key");
794 return;
795 }
796 else if ( context.OrganisationDb() == null ) {
797
798 refuse(msg,"no organization database");
799 return;
800 }
801 Vector List = context.OrganisationDb().allRelations();
802 if ( List.isEmpty() ) {
803 failure(msg,"no relations");
804 return;
805 }
806 Performative reply = new Performative("inform");
807 reply.setContent(Misc.concat(List));
808 reply.setReceiver(msg.getSender());
809 reply.setInReplyTo(reply_with);
810 context.MailBox().sendMsg(reply);
811 }
812
813 public void has_ability(Performative msg) {
814 String content = msg.getContent();
815 String reply_with = msg.getReplyWith();
816 if ( reply_with == null ) {
817 refuse(msg,"no reply-with key");
818 return;
819 }
820 MsgContentHandler hd = new MsgContentHandler(content);
821 if ( hd.data() == null ) {
822 refuse(msg,"no ability specified");
823 return;
824 }
825 else if ( context.OrganisationDb() == null ) {
826
827 refuse(msg,"no organization database");
828 return;
829 }
830 AbilitySpec a = ZeusParser.abilitySpec(context.OntologyDb(),hd.data());
831 if ( a == null ) {
832 refuse(msg,"no ability specified");
833 return;
834 }
835 Vector List = context.OrganisationDb().findAll(a);
836 if ( List.isEmpty() ) {
837 failure(msg,"no abilities known");
838 return;
839 }
840 Performative reply = new Performative("inform");
841 reply.setContent(Misc.concat(List));
842 reply.setReceiver(msg.getSender());
843 reply.setInReplyTo(reply_with);
844 context.MailBox().sendMsg(reply);
845 }
846
847 public void isa_facilitator(Performative msg) {
848 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
849 context.addFacilitator(hd.data());
850 }
851
852 public void add_agents_abilities(Performative msg) {
853 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
854 Vector List = ZeusParser.abilitySpecList(context.OntologyDb(),hd.data());
855 String agent = msg.getSender();
856 context.OrganisationDb().add(agent,List);
857 }
858
859 public void add_information(Performative msg) {
860 try {
861 MsgContentHandler hd = new MsgContentHandler(msg.getContent());
862 Vector List = ZeusParser.factList(context.OntologyDb(),hd.data());
863
864
865 context.ResourceDb().add(dereference(List));
866 }
867 catch(Exception e) {
868
869 }
870 }
871
872 protected void refuse(Performative msg, String content) {
873 Performative reply = new Performative("refuse");
874 reply.setReceiver(msg.getSender());
875 reply.setContent(content);
876 String reply_with = msg.getReplyWith();
877 if ( reply_with != null )
878 reply.setInReplyTo(reply_with);
879 context.MailBox().sendMsg(reply);
880 }
881
882 protected void failure(Performative msg, String content) {
883 Performative reply = new Performative("failure");
884 reply.setReceiver(msg.getSender());
885 reply.setContent(content);
886 String reply_with = msg.getReplyWith();
887 if ( reply_with != null )
888 reply.setInReplyTo(reply_with);
889 context.MailBox().sendMsg(reply);
890 }
891
892 protected void not_understood(Performative msg, String content) {
893 Performative reply = new Performative("failure");
894 reply.setReceiver(msg.getSender());
895 reply.setContent(content);
896 String reply_with = msg.getReplyWith();
897 if ( reply_with != null )
898 reply.setInReplyTo(reply_with);
899 context.MailBox().sendMsg(reply);
900 }
901
902 protected void inform(Performative msg, String content) {
903 Performative reply = new Performative("inform");
904 reply.setReceiver(msg.getSender());
905 reply.setContent(content);
906 String reply_with = msg.getReplyWith();
907 if ( reply_with != null )
908 reply.setInReplyTo(reply_with);
909 context.MailBox().sendMsg(reply);
910 }
911
912
913 /***
914 * If your code needs to react to changes in the MessageHandler use this
915 * to add a MessageHandlerMonitor. This provides a programatic alternative to
916 * writing reaction rules
917 */
918 public void addMessageHandlerMonitor(MessageHandlerMonitor monitor,
919 long event_type) {
920 if ( (event_type & MessageHandlerEvent.ADD_MASK) != 0 )
921 eventMonitor[ADD].add(monitor);
922 if ( (event_type & MessageHandlerEvent.FIRE_MASK) != 0 )
923 eventMonitor[FIRE].add(monitor);
924 if ( (event_type & MessageHandlerEvent.DELETE_MASK) != 0 )
925 eventMonitor[DELETE].add(monitor);
926 if ( (event_type & MessageHandlerEvent.FAIL_MASK) != 0 )
927 eventMonitor[FAIL].add(monitor);
928 }
929
930 public void removeMessageHandlerMonitor(MessageHandlerMonitor monitor,
931 long event_type) {
932 if ( (event_type & MessageHandlerEvent.ADD_MASK) != 0 )
933 eventMonitor[ADD].remove(monitor);
934 if ( (event_type & MessageHandlerEvent.FIRE_MASK) != 0 )
935 eventMonitor[FIRE].remove(monitor);
936 if ( (event_type & MessageHandlerEvent.DELETE_MASK) != 0 )
937 eventMonitor[DELETE].remove(monitor);
938 if ( (event_type & MessageHandlerEvent.FAIL_MASK) != 0 )
939 eventMonitor[FAIL].remove(monitor);
940 }
941
942 protected void notifyMonitors(int type, MessageHandlerEvent event) {
943 if ( eventMonitor[type].isEmpty() ) return;
944
945 MessageHandlerMonitor monitor;
946 Enumeration enum = eventMonitor[type].elements();
947
948 switch(type) {
949 case ADD:
950 while( enum.hasMoreElements() ) {
951 monitor = (MessageHandlerMonitor)enum.nextElement();
952 monitor.messageRuleAddedEvent(event);
953 }
954 break;
955 case FIRE:
956 while( enum.hasMoreElements() ) {
957 monitor = (MessageHandlerMonitor)enum.nextElement();
958 monitor.messageRuleFiredEvent(event);
959 }
960 break;
961 case DELETE:
962 while( enum.hasMoreElements() ) {
963 monitor = (MessageHandlerMonitor)enum.nextElement();
964 monitor.messageRuleDeletedEvent(event);
965 }
966 break;
967 case FAIL:
968 while( enum.hasMoreElements() ) {
969 monitor = (MessageHandlerMonitor)enum.nextElement();
970 monitor.messageRuleFailedEvent(event);
971 }
972 break;
973 }
974 }
975
976 /***
977 * Replication to handle the problem of variable clashes when
978 * agents communicate with one another with variables in the
979 * content data;
980 */
981 protected final Vector dereference(Vector input) {
982 Fact f;
983 Goal g;
984 Vector result = new Vector();
985 try {
986 Object x = input.elementAt(0);
987 if ( x instanceof zeus.concepts.Fact ) {
988 for(int i = 0; i < input.size(); i++ ) {
989 f = (Fact)input.elementAt(i);
990 f = f.duplicate(Fact.VAR,context.GenSym());
991 result.addElement(f);
992 }
993 }
994 else {
995 for(int i = 0; i < input.size(); i++ ) {
996 g = (Goal)input.elementAt(i);
997 g = g.duplicate(Fact.VAR,context.GenSym());
998 result.addElement(g);
999 }
1000 }
1001 }catch (Exception e) {
1002
1003 }
1004
1005 return result;
1006 }
1007
1008 private void debug(String str) {
1009
1010
1011 }
1012
1013 }