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 package zeus.actors;
28
29 import java.util.*;
30 import zeus.util.*;
31 import zeus.concepts.*;
32 import zeus.concepts.fn.*;
33 import zeus.actors.event.*;
34
35
36 /***
37 * This class implements the Resource Database component, whose role is to
38 * store the resources owned by the agent, (which are {@link Fact} objects).
39 * The Resource Database is simply an extended {@link Hashtable} with the fact
40 * objects held indexed by their types. <p>
41 *
42 * Developers will probably interact the Resource Database on a regular basis,
43 * as it both contains the agent's knowledge and provides a means of altering it.
44 * A reference to the Resource Database can be obtained from the agent's
45 * {@link AgentContext} object, allowing access to the methods described below;
46 * (The methods without descriptions are primarily used by other agent components
47 * and so are unlikely to be useful to developers).
48
49 <p> <i> Change log </i> <p>
50 19/08/00 - added some code to the any(Fact) method at about line 580 - 590
51 this is to stop an unnecessary exception being thrown, the new
52 behavior is that if the method is called and there are no facts of that type
53 in the resourcedb then a new fact of that type will be returned instead.
54 <P>
55 Change log
56 ----------
57 13/06/01 added a number of fields (name,planner,ontologyDb, gensym,externaldb) which are
58 used to store references that would be obtained from the AgentContext object, but
59 cannot be if the context is not available at initialisation.
60 I hope that this will enable better extensibility, but it might cause problems if the agent
61 architecture is altered at run time.
62 Added isSet method to allow programmers to check to see if
63 Added setPlanner to permit this reference to be updated easily
64 Added setName
65 Added setOntologyDb
66 Added setGenSym
67 */
68
69 public class ResourceDb extends Hashtable
70 {
71 private HSet[] eventMonitor = new HSet[4];
72
73 private static final int ADD = 0;
74 private static final int MODIFY = 1;
75 private static final int DELETE = 2;
76 private static final int ACCESS = 3;
77
78 protected AgentContext context = null;
79 protected String name = null;
80 protected Planner planner = null;
81 protected OntologyDb ontologyDb = null;
82 protected GenSym gensym = null;
83
84
85 public ResourceDb () {
86 super();
87 for(int i = 0; i < eventMonitor.length; i++ )
88 eventMonitor[i] = new HSet();
89 }
90
91 public ResourceDb(AgentContext context) {
92 super();
93 this.context = context;
94 this.name = context.whoami();
95 this.gensym = context.GenSym();
96 this.planner = context.getPlanner();
97 this.ontologyDb = context.getOntologyDb();
98 context.set(this);
99
100 for(int i = 0; i < eventMonitor.length; i++ )
101 eventMonitor[i] = new HSet();
102 }
103
104
105 /***
106 * this allows you to set the planner reference
107 */
108 public void setPlanner(Planner planner) {
109 this.planner = planner;
110 }
111
112
113 /***
114 this allows you to set the name reference
115 */
116 public void setName (String name) {
117 this.name = name;
118 }
119
120
121 /***
122 this allows you to set the gensym referencce
123 */
124 public void setGenSym(GenSym gensym) {
125 this.gensym = gensym;
126 }
127
128
129 /***
130 this allows you to set the ontolgyDb reference
131 */
132 public void setOntologyDb(OntologyDb ontologyDb) {
133 this.ontologyDb = ontologyDb;
134 }
135
136 /***
137 check that the name refernce is set
138 */
139 public boolean isNameSet() {
140 if (name == null)
141 return false;
142 else
143 return true;
144 }
145
146 /***
147 check that the gensym refernece is set
148 */
149 public boolean isGenSymSet() {
150 if (gensym == null)
151 return false;
152 else
153 return true;
154 }
155
156
157 /***
158 check that the planner reference is set
159 */
160 public boolean isPlannerSet() {
161 if (planner == null)
162 return false;
163 else
164 return true;
165 }
166
167
168 /***
169 check that the ontologyDb reference is set
170 */
171 public boolean isOntologyDbSet (){
172 if (ontologyDb == null)
173 return false;
174 else
175 return true;
176 }
177
178
179 /***
180 check that the AgentContext context field is set.
181 Note: this is not necessary for the rdb to function, but
182 is included so that
183 */
184 public boolean isContextSet() {
185 if (context == null)
186 return false;
187 else
188 return true;
189 }
190
191
192 /***
193 check to see if all necessary fields are set
194 */
195 public boolean isSet () {
196 if (isContextSet ()) return true;
197 else {
198 if (!isGenSymSet () ) {
199 System.out.println("gensym not set");
200 return false;
201 }
202 if (!isPlannerSet () ) {
203 System.out.println("planner not set");
204 return false;
205 }
206 if (!isOntologyDbSet () ) {
207 System.out.println("ontologydb not set");
208 return false;
209 }
210 if (!isNameSet () ) {
211 System.out.println("name not set");
212 return false;
213 }
214
215 }
216 return true;
217 }
218
219
220
221
222
223 /*** Use this to obtain handles to the other internal components of agent */
224 public AgentContext getAgentContext() { return context; }
225
226
227 /***
228 was synchronized
229 */
230 public synchronized ResourceItem add(Vector List) {
231 for(int i = 0; i < List.size(); i++ )
232 add( (Fact)List.elementAt(i) );
233 return null;
234 }
235
236
237 /***
238 was synchronized
239 */
240 public synchronized ResourceItem add(Fact[] List) {
241 for(int i = 0; i < List.length; i++ )
242 add( List[i] );
243 return null;
244 }
245
246 /*** The primary method for adding new facts to the Resource Database
247 was synchronized
248 */
249 public synchronized ResourceItem add(Fact fact) {
250 String type = fact.getType();
251 ResourceItem item;
252 Vector List;
253 PrimitiveNumericFn numericFn;
254
255 if ( (List = (Vector)this.get(type)) == null ) {
256 List = new Vector();
257 this.put(type,List);
258 }
259
260 if ( type.equals(OntologyDb.MONEY) && !List.isEmpty() ) {
261 for(int i = 0; i < List.size(); i++ ) {
262 item = (ResourceItem) List.elementAt(i);
263 notifyMonitors(item,ACCESS);
264 if ( !item.isReserved() ) {
265 Fact f1 = item.getFact();
266 f1.resolve(new Bindings(name));
267 numericFn = (PrimitiveNumericFn)f1.getFn(OntologyDb.AMOUNT);
268 double db_amount = numericFn.doubleValue();
269
270 fact.resolve(new Bindings(name));
271 numericFn = (PrimitiveNumericFn)fact.getFn(OntologyDb.AMOUNT);
272 double input = numericFn.doubleValue();
273
274 double total = db_amount + input;
275 if ( total == 0 ) {
276
277 List.removeElementAt(i--);
278 item.deleted();
279 notifyMonitors(item,DELETE);
280 if ( List.isEmpty() ) this.remove(type);
281 return null;
282 }
283 else {
284 List.removeElementAt(i--);
285 item.deleted();
286 notifyMonitors(item,DELETE);
287 f1.setValue(OntologyDb.AMOUNT,total);
288 f1.resolve(new Bindings(name));
289 List.addElement(item);
290 notifyMonitors(item,ADD);
291 return item;
292 }
293 }
294 }
295 }
296 item = new ResourceItem(fact);
297 List.addElement(item);
298 notifyMonitors(item,ADD);
299 return item;
300 }
301
302 /***
303 was synchronized
304 */
305 synchronized void replaceOrAdd(Fact fact) {
306 ExternalDb externalDb = context.ExternalDb();
307 if ( externalDb != null && externalDb.put(fact) ) {
308
309
310 }
311 else
312 add(fact);
313 }
314
315 public synchronized void del(Vector List) {
316 for(int i = 0; i < List.size(); i++ )
317 del((Fact)List.elementAt(i));
318 }
319
320 public synchronized void del(Fact[] List) {
321 for(int i = 0; i < List.length; i++ )
322 del(List[i]);
323 }
324
325
326 /*** The primary method for permanently removing facts from the Resource Database */
327 public synchronized void del(Fact fact) {
328 String type = fact.getType();
329 Vector List;
330
331 if ( (List = (Vector)this.get(type)) == null )
332 return;
333
334 ResourceItem item;
335 Fact f1;
336 for(int i = 0; i < List.size(); i++ ) {
337 item = (ResourceItem)List.elementAt(i);
338 f1 = item.getFact();
339 notifyMonitors(item,ACCESS);
340 if ( f1.equals(fact) ) {
341 List.removeElementAt(i--);
342 item.deleted();
343 notifyMonitors(item,DELETE);
344 }
345 }
346 if ( List.isEmpty() ) this.remove(type);
347 }
348
349 /*** Use this if facts have changed and you need to update the Resource Database */
350 public synchronized void modify(Fact f1, Fact f2) {
351 del(f1);
352 add(f2);
353 }
354
355
356 public void free(DataRec rec) {
357 if ( rec == null ) return;
358 Vector List = rec.available();
359 ResourceItem item;
360 ExternalDb externalDb = context.ExternalDb();
361
362 Fact f1;
363 for(int i = 0; i < List.size(); i++ ) {
364 item = (ResourceItem)List.elementAt(i);
365 item.cancelReservation(rec);
366 f1 = item.getFact();
367 if ( externalDb != null && !item.isReserved() &&
368 externalDb.put(f1) ) {
369 List.removeElementAt(i--);
370 item.deleted();
371 notifyMonitors(item,DELETE);
372 }
373 }
374 rec.free();
375 }
376
377 public void consume(DataRec rec) {
378 if ( rec == null ) return;
379 Vector List = rec.available();
380 Vector data;
381 Fact f1;
382 for(int i = 0; i < List.size(); i++ ) {
383 ResourceItem item = (ResourceItem) List.elementAt(i);
384 f1 = item.getFact();
385 notifyMonitors(item,ACCESS);
386 notifyMonitors(item,DELETE);
387 data = (Vector)this.get(f1.getType());
388 switch( item.consumed(rec) ) {
389 case ResourceItem.UNCHANGED:
390 notifyMonitors(item,ADD);
391 break;
392 case ResourceItem.MODIFY:
393 notifyMonitors(item,ADD);
394 break;
395 case ResourceItem.DELETE:
396 data.removeElement(item);
397 if ( data.isEmpty() )
398 this.remove(item.getFact().getType());
399 break;
400 }
401 }
402 }
403
404 public int findAll(PlanRecord rec, int precond_position,
405 int required) {
406 Core.ERROR(required > 0,1001,this);
407 DataRec datarec = rec.getDatarec(precond_position);
408 int start = rec.getStartTime();
409 return reserve(datarec,rec,start,required);
410 }
411
412 /*** Enables a resource to be secured at a certain time period, (this is
413 provided primarily for internal use) */
414 public int reserve(DataRec datarec, PlanRecord rec,
415 int start, int required) {
416 Vector List;
417 ResourceItem item;
418 Fact f1, f2, f3;
419 ExternalDb externalDb = context.ExternalDb();
420
421 Fact fact = datarec.getFact();
422 boolean consumed = !fact.isReadOnly();
423
424 if ( (List = (Vector)this.get(fact.getType())) == null )
425 List = new Vector();
426
427 int amt;
428 Bindings b = new Bindings(name);
429 for(int i = 0; required > 0 && i < List.size(); i++ ) {
430 item = (ResourceItem)List.elementAt(i);
431 f1 = item.getFact();
432 notifyMonitors(item,ACCESS);
433 int available;
434 Core.DEBUG(2,"Fact before test \n" + f1);
435 b.clear();
436 if ( (available = item.unreservedAmount(start,consumed)) > 0 &&
437 f1.unifiesWith(fact,b) && rec.applyConstraints(b) ) {
438 amt = Math.min(available,required);
439 Core.ERROR(datarec.add(item,start,amt),1002,this);
440 if ( consumed )
441 rec.updateCost(amt*f1.getUnitCost());
442 required -= amt;
443
444 Core.DEBUG(2,"Required to find Fact:\n" + fact);
445 Core.DEBUG(2,"Fact:\n" + f1 + "\nassigned to datarec " +
446 datarec.getId());
447 }
448 }
449
450 if ( required > 0 && externalDb != null ) {
451 Enumeration enum = externalDb.all(fact);
452 while( enum != null && enum.hasMoreElements() && required > 0 ) {
453 f1 = (Fact)enum.nextElement();
454 b.clear();
455 if ( f1.unifiesWith(fact,b) && rec.applyConstraints(b) ) {
456 int available = f1.getNumber();
457 f3 = externalDb.remove(f1);
458 if ( f3 != null ) {
459 item = add(f3);
460 amt = Math.min(available,required);
461 Core.ERROR(datarec.add(item,start,amt),1003,this);
462 if ( consumed )
463 rec.updateCost(amt*f3.getUnitCost());
464 required -= amt;
465
466 Core.DEBUG(2,"Required to find Fact:\n" + fact);
467 Core.DEBUG(2,"Fact:\n" + f3 + "\nassigned to datarec " +
468 datarec.getId());
469 }
470 else {
471 Core.USER_ERROR("Improperly defined externalDb: fact \"" +
472 f1 + "\" should be in externaldb, but not found");
473 }
474 }
475 }
476 }
477 return required;
478 }
479
480 public synchronized int reserve(DataRec datarec, int start, int required) {
481 Vector List;
482 ResourceItem item;
483 Fact f1, f2;
484 ExternalDb externalDb = context.ExternalDb();
485
486 Fact fact = datarec.getFact();
487 boolean consumed = !fact.isReadOnly();
488
489 if ( (List = (Vector)this.get(fact.getType())) == null )
490 List = new Vector();
491
492 int amt;
493 for(int i = 0; required > 0 && i < List.size(); i++ ) {
494 item = (ResourceItem)List.elementAt(i);
495 f1 = item.getFact();
496 notifyMonitors(item,ACCESS);
497 Bindings b = new Bindings(name);
498 int available;
499 if ( (available = item.unreservedAmount(start,consumed)) > 0 &&
500 f1.unifiesWith(fact,b) ) {
501 amt = Math.min(available,required);
502 Core.ERROR(datarec.add(item,start,amt),1005,this);
503 required -= amt;
504
505 Core.DEBUG(2,"Required to find Fact:\n" + fact);
506 Core.DEBUG(2,"Fact:\n" + f1 + "\nassigned to datarec " +
507 datarec.getId());
508 }
509 }
510
511 if ( required > 0 && externalDb != null ) {
512 Enumeration enum = externalDb.all(fact);
513 while( enum.hasMoreElements() && required > 0 ) {
514 f1 = (Fact)enum.nextElement();
515 Bindings b = new Bindings(name);
516 if ( f1.unifiesWith(fact,b) ) {
517 int available = f1.getNumber();
518 f1 = externalDb.remove(f1);
519 item = add(f1);
520 amt = Math.min(available,required);
521 Core.ERROR(datarec.add(item,start,amt),1006,this);
522 required -= amt;
523
524 Core.DEBUG(2,"Required to find Fact:\n" + fact);
525 Core.DEBUG(2,"Fact:\n" + f1 + "\nassigned to datarec " +
526 datarec.getId());
527 }
528 }
529 }
530 return required;
531 }
532
533
534 public Vector allocateResources(PlanRecord rec) {
535
536
537 Vector subgoals = new Vector();
538 Goal g;
539 int position, required;
540
541 PrimitiveTask task = rec.getTask();
542 Fact[][] consumed = task.orderPreconditions();
543
544 for(int i = 0; i < consumed.length; i++) {
545 for(int j = 0; j < consumed[i].length; j++) {
546 if ( !consumed[i][j].isNegative() ) {
547 position = task.getConsumedPos(consumed[i][j]);
548 required = rec.noRequiredItems(position);
549 if ( required > 0) {
550 g = allocateResource(rec,position,required);
551 if ( g != null ) subgoals.addElement(g);
552 }
553 }
554 }
555 if ( !subgoals.isEmpty() ) break;
556 }
557 return subgoals;
558
559 }
560
561
562
563 public Goal allocateResource(PlanRecord rec, int position,
564 int required) {
565 int s;
566 required = findAll(rec,position,required);
567
568 if ( required > 0 ) {
569
570 if (!isPlannerSet())
571 if (!isContextSet()) {
572 try {
573 throw new Exception ("Planner and AgentContext not set in ResourceDb.\n Agent is improperly initialised, sorry");
574 }
575 catch (Exception e) {
576 e.printStackTrace();
577 } }
578 else {
579 this.planner = context.getPlanner(); }
580
581 Planner planner = this.planner;
582 debug("planner = " + planner);
583
584 DataRec datarec = rec.getDatarec(position);
585 Fact desc = datarec.getFact();
586 if ( (s = planner.anySideEffect(desc,rec,position,required)) != 0 ) {
587 Fact g = new Fact(desc);
588 g.setNumber(s);
589 return rec.createSubgoal(g,position);
590 }
591 }
592 return null;
593 }
594
595 /*** Special purpose method to decrease the value of the amount attribute of MONEY facts */
596 public synchronized Fact debit(double amount) {
597 Vector List;
598 ResourceItem item;
599 Fact f1, f2, debit;
600 PrimitiveNumericFn numericFn;
601
602 Core.DEBUG(3,"About to debit: " + amount);
603 Core.ERROR(amount>=0,1006,this);
604
605 OntologyDb ontology = ontologyDb;
606 debit = ontology.getFact(Fact.FACT,OntologyDb.MONEY);
607 debit.setValue(OntologyDb.AMOUNT,amount);
608
609 List = (Vector)this.get(OntologyDb.MONEY);
610 for(int i = 0; List != null && amount > 0 && i < List.size(); i++ ) {
611 item = (ResourceItem)List.elementAt(i);
612 notifyMonitors(item,ACCESS);
613 if ( !item.isReserved() ) {
614 f1 = item.getFact();
615 f1.resolve(new Bindings(name));
616 numericFn = (PrimitiveNumericFn)f1.getFn(OntologyDb.AMOUNT);
617 double available = numericFn.doubleValue();
618 if ( available > amount ) {
619 f2 = f1.duplicate(Fact.VAR,gensym);
620 f2.setValue(OntologyDb.AMOUNT,available-amount);
621 f2.resolve(new Bindings(name));
622
623
624 List.removeElementAt(i--);
625 item.deleted();
626 notifyMonitors(item,DELETE);
627 f1.setValue(OntologyDb.AMOUNT,amount);
628
629 ResourceItem new_item = new ResourceItem(f2);
630 List.addElement(new_item);
631 notifyMonitors(new_item,ADD);
632 Core.DEBUG(3,"Debit completed: " + debit);
633 return debit;
634 }
635 else if ( available >= 0 ) {
636
637 List.removeElementAt(i--);
638 item.deleted();
639 notifyMonitors(item,DELETE);
640 amount = amount - available;
641 }
642 }
643 }
644
645
646 if ( amount > 0 ) {
647 boolean done = false;
648 for(int i = 0; List != null && !done && i < List.size(); i++ ) {
649 item = (ResourceItem)List.elementAt(i);
650 notifyMonitors(item,ACCESS);
651 if ( !item.isReserved() ) {
652 f1 = item.getFact();
653 f1.resolve(new Bindings(name));
654 numericFn = (PrimitiveNumericFn)f1.getFn(OntologyDb.AMOUNT);
655 double available = numericFn.doubleValue();
656
657
658 List.removeElementAt(i--);
659 item.deleted();
660 notifyMonitors(item,DELETE);
661 f1.setValue(OntologyDb.AMOUNT,available-amount);
662 f1.resolve(new Bindings(name));
663 List.addElement(item);
664 notifyMonitors(item,ADD);
665 done = true;
666 }
667 }
668
669 if ( !done ) {
670 f1 = ontology.getFact(Fact.FACT,OntologyDb.MONEY);
671 f1.setValue(OntologyDb.AMOUNT,0 - amount);
672 f1.resolve(new Bindings(name));
673 add(f1);
674 }
675 }
676 Core.DEBUG(3,"Debit completed: " + debit);
677 return debit;
678 }
679
680 public synchronized Fact evalLocal(Fact fact) {
681 Fact[] answer = all(fact);
682 if ( answer.length == 0 ) return null;
683 OntologyDb ontology = ontologyDb;
684 Fact result = new Fact(answer[0]);
685 for( int i = 1; i < answer.length; i++ )
686 Core.ERROR(result.disjoin(answer[i]),1008,this);
687 return result;
688 }
689
690 public synchronized boolean evalNegative(Fact fact) {
691 Fact[] answer = all(fact);
692 return ( answer.length == 0 );
693 }
694
695 public synchronized Fact[] all(String type) {
696 OntologyDb ontology = ontologyDb;
697 Fact f = ontology.getFact(Fact.VARIABLE,type);
698 return all(f);
699 }
700
701 /*** Use this to retrieve all the facts in the database that match the parameter */
702 public synchronized Fact[] all(Fact fact) {
703 Vector List;
704 ResourceItem item;
705 Fact f1;
706 ExternalDb externalDb = context.ExternalDb();
707
708 if ( (List = (Vector)this.get(fact.getType())) == null )
709 List = new Vector();
710
711 Vector answer = new Vector();
712 Bindings b = new Bindings(name);
713 for(int i = 0; i < List.size(); i++, b.clear() ) {
714 item = (ResourceItem)List.elementAt(i);
715 f1 = item.getFact();
716 notifyMonitors(item,ACCESS);
717 if ( f1.unifiesWith(fact,b) )
718 answer.addElement(f1);
719 }
720 if ( externalDb != null ) {
721 Enumeration enum = externalDb.all(fact);
722 while( enum.hasMoreElements() )
723 answer.addElement((Fact)enum.nextElement());
724 }
725
726 Fact[] results = new Fact[answer.size()];
727 for(int i = 0; i < answer.size(); i++ )
728 results[i] = (Fact) answer.elementAt(i);
729 return results;
730 }
731
732 /*** Deletes all facts matching the parameter type, should obviously
733 be used with caution */
734 public synchronized void deleteAll(String type) {
735 Vector List;
736 ResourceItem item;
737 Fact f1;
738
739 if ( (List = (Vector)this.get(type)) == null )
740 return;
741
742
743 for(int i = 0; i < List.size(); i++ ) {
744 item = (ResourceItem)List.elementAt(i);
745 f1 = item.getFact();
746 notifyMonitors(item,ACCESS);
747 if ( !item.isReserved() ) {
748 List.removeElementAt(i--);
749 item.deleted();
750 notifyMonitors(item,DELETE);
751 }
752 }
753 for(int i = 0; i < List.size(); i++ ) {
754 item = (ResourceItem)List.elementAt(i);
755 f1 = item.getFact();
756 notifyMonitors(item,ACCESS);
757 List.removeElementAt(i--);
758 item.deleted();
759 notifyMonitors(item,DELETE);
760 }
761 }
762
763 /*** Randomly retrieves a fact with the same type as the parameter */
764 public synchronized Fact any(String type) {
765 OntologyDb ontology = ontologyDb;
766 Fact f = ontology.getFact(Fact.VARIABLE,type);
767 return any(f);
768 }
769
770 /*** Use this to randomly retrieve a fact that matches the parameter */
771 public synchronized Fact any(Fact fact) {
772 Fact[] answer = all(fact);
773 if ( answer == null ) return null;
774 int pos = (int) (Math.random()*answer.length);
775
776
777 if (pos>answer.length-1) {
778
779 return fact; }
780
781 else
782 return answer[pos];
783 }
784
785 /*** Use this to test whether a particular fact exists in the database */
786 public synchronized boolean contains(Fact fact, int start) {
787 Vector List;
788 ResourceItem item;
789 Fact f1;
790 ExternalDb externalDb = context.ExternalDb();
791
792 if ( (List = (Vector)this.get(fact.getType())) == null )
793 List = new Vector();
794
795 Bindings b = new Bindings(name);
796 int required = fact.getNumber();
797 boolean consumed = !fact.isReadOnly();
798 int available;
799 for(int i = 0; required > 0 && i < List.size(); i++, b.clear()) {
800 item = (ResourceItem)List.elementAt(i);
801 f1 = item.getFact();
802 notifyMonitors(item,ACCESS);
803 if ( (available = item.unreservedAmount(start,consumed)) > 0 &&
804 f1.unifiesWith(fact,b) ) {
805 required = required - Math.min(available,required);
806 }
807 }
808
809 if ( required > 0 && externalDb != null ) {
810 Enumeration enum = externalDb.all(fact);
811 while( enum.hasMoreElements() && required > 0 ) {
812 f1 = (Fact)enum.nextElement();
813 available = f1.getNumber();
814 required = required - Math.min(available,required);
815 }
816 }
817
818 return required <= 0;
819 }
820
821
822 /***
823 * Use this if your code needs to react to changes in the Resource Database.
824 * This provides a programatic alternative to writing reaction rules
825 */
826
827 public void addFactMonitor(FactMonitor monitor, long event_type,
828 boolean notify_previous) {
829 addFactMonitor(monitor,event_type);
830 if ( !notify_previous ) return;
831
832 Enumeration enum = elements();
833 Vector List;
834 ResourceItem item;
835 FactEvent event;
836
837 while( enum.hasMoreElements() ) {
838 List = (Vector)enum.nextElement();
839 for(int i = 0; i < List.size(); i++ ) {
840 item = (ResourceItem) List.elementAt(i);
841 event = new FactEvent(this,item,FactEvent.ACCESS_MASK);
842 monitor.factAccessedEvent(event);
843 event = new FactEvent(this,item,FactEvent.ADD_MASK);
844 monitor.factAddedEvent(event);
845 }
846 }
847 }
848
849 public void addFactMonitor(FactMonitor monitor, long event_type) {
850 if ( (event_type & FactEvent.ADD_MASK) != 0 )
851 eventMonitor[ADD].add(monitor);
852 if ( (event_type & FactEvent.MODIFY_MASK) != 0 )
853 eventMonitor[MODIFY].add(monitor);
854 if ( (event_type & FactEvent.DELETE_MASK) != 0 )
855 eventMonitor[DELETE].add(monitor);
856 if ( (event_type & FactEvent.ACCESS_MASK) != 0 )
857 eventMonitor[ACCESS].add(monitor);
858 }
859
860 public void removeFactMonitor(FactMonitor monitor, long event_type) {
861 if ( (event_type & FactEvent.ADD_MASK) != 0 )
862 eventMonitor[ADD].remove(monitor);
863 if ( (event_type & FactEvent.MODIFY_MASK) != 0 )
864 eventMonitor[MODIFY].remove(monitor);
865 if ( (event_type & FactEvent.DELETE_MASK) != 0 )
866 eventMonitor[DELETE].remove(monitor);
867 if ( (event_type & FactEvent.ACCESS_MASK) != 0 )
868 eventMonitor[ACCESS].remove(monitor);
869 }
870
871 private void notifyMonitors(ResourceItem item, int type) {
872 if ( eventMonitor[type].isEmpty() ) return;
873
874 FactMonitor monitor;
875 FactEvent event;
876 Enumeration enum = eventMonitor[type].elements();
877
878 switch(type) {
879 case ADD:
880 event = new FactEvent(this,item,FactEvent.ADD_MASK);
881 while( enum.hasMoreElements() ) {
882 monitor = (FactMonitor)enum.nextElement();
883 monitor.factAddedEvent(event);
884 }
885 break;
886 case MODIFY:
887 event = new FactEvent(this,item,FactEvent.MODIFY_MASK);
888 while( enum.hasMoreElements() ) {
889 monitor = (FactMonitor)enum.nextElement();
890 monitor.factModifiedEvent(event);
891 }
892 break;
893 case DELETE:
894 event = new FactEvent(this,item,FactEvent.DELETE_MASK);
895 while( enum.hasMoreElements() ) {
896 monitor = (FactMonitor)enum.nextElement();
897 monitor.factDeletedEvent(event);
898 }
899 break;
900 case ACCESS:
901 event = new FactEvent(this,item,FactEvent.ACCESS_MASK);
902 while( enum.hasMoreElements() ) {
903 monitor = (FactMonitor)enum.nextElement();
904 monitor.factAccessedEvent(event);
905 }
906 break;
907 }
908 }
909
910 private void debug(String str) {
911
912 }
913
914 }