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  /*
25   * @(#)TaskDb.java 1.00
26   * Change log
27   * ----------
28   * 12-06-01 Added agentName and genSym to facilitate intialisation from extended types. 
29   */
30  
31  package zeus.actors;
32  
33  import java.util.*;
34  import zeus.util.*;
35  import zeus.concepts.*;
36  import zeus.concepts.fn.*;
37  import zeus.actors.event.*;
38  
39  /***
40   * The Task Database is a simple storage component that holds the {@link Task}
41   * descriptions known by the owning agent.  This information is used by
42   * the agent's {@link Planner} component. <p>
43   *
44   * The methods of this component are only likely to be of interest to
45   * developers who write code to monitor or change the abilities of agents.
46   * Change log
47   * ----------
48   * 12-06-01 Added agentName and orgDb to facilitate intialisation from extended types. 
49   * 
50   */
51  
52  public class TaskDb extends Hashtable {
53    protected HSet[] eventMonitor = new HSet[4];
54  
55    public static final int MODIFY = 0;
56    public static final int ADD    = 1;
57    public static final int DELETE = 2;
58    public static final int ACCESS = 3;
59    public static final int NONE   = 4;
60  
61    protected static Random rand = new Random(System.currentTimeMillis());
62    protected static int CMIN = 10;
63    protected static int CMAX = 50;
64    protected boolean demo_version = false;
65    
66    
67    protected String agentName = null; 
68    protected OrganisationDb orgDb = null; 
69  
70    protected AgentContext context = null;
71    
72    protected GenSym gensym = null; 
73  
74  
75  
76    public TaskDb () {
77      for(int i = 0; i < eventMonitor.length; i++ )
78          eventMonitor[i] = new HSet();
79      String version = SystemProps.getProperty("demo.version");
80      demo_version = (Boolean.valueOf(version)).booleanValue();
81          }
82    
83  
84    public TaskDb(AgentContext context) {
85       Assert.notNull(context);
86       this.context = context;
87       this.agentName = context.whoami(); 
88       this.orgDb = context.getOrganisationDb(); 
89       this.gensym = context.getGenSym(); 
90       context.set(this);
91       for(int i = 0; i < eventMonitor.length; i++ )
92          eventMonitor[i] = new HSet();
93       String version = SystemProps.getProperty("demo.version");
94       demo_version = (Boolean.valueOf(version)).booleanValue();
95    }
96  
97      /*** 
98          returns a reference to the agent context pointer
99          */
100   public AgentContext getAgentContext() {
101      return context;
102   }
103 
104   
105   /*** 
106     The primary method for adding new task abilities to the Task Database */
107   public void add(Task task) {
108     Assert.notNull(task);
109     debug ("LOADED TASK NAME " + task.getName()); 
110     
111     Fact[] produced = task.getPostconditions();
112     Fact[] consumed = task.getPreconditions(); // 1.2.1 Simon 
113     resolvePreconditions (task, consumed, produced); // 1.2.1 Simon 
114     resolveCostAndTime (task,consumed,produced);// 1.2.1 Simon
115     int operation = addItem(produced,task);
116     if ( operation != NONE )
117        notifyMonitors(task,operation);
118   }
119   
120   
121   /*** 
122     resolveCostAndTime is used to check that the cost and timing of the task in terms of 
123     the preconditions and postconditions of the task is properly resolved
124     . Works like this: get the cost out, check to see if it matches any of the consumed 
125     (postconditions), then check to see if it matches any of the produced (preconditions)
126     If it does, copy the values for evaluation. 
127     * ISSUES
128     *--------
129     *My main concern is that I have really foobared, and this used to be done somewhere else, but I have 
130     *broken it : suggestions to me please!
131     *@author Simon Thompson
132     *@since 1.2.1 
133   */
134   public void resolveCostAndTime (Task task, Fact[] consumed, Fact[] produced) { 
135     ValueFunction time = task.getTimeFn(); 
136     ValueFunction cost = task.getCostFn(); 
137     
138     debug("time = " + time.getClass().toString());
139     debug ("cost = " + cost.getClass().toString()); 
140      
141     if (time instanceof ArithmeticFn){
142         resolveall((ArithmeticFn)time,task,consumed);
143         resolveall((ArithmeticFn)time,task,produced); 
144     }
145     if (cost instanceof ArithmeticFn) { 
146         resolveall((ArithmeticFn)cost,task,consumed); 
147         resolveall((ArithmeticFn)cost,task,produced); 
148     }
149     
150   }
151   
152   
153   public void resolveall (ArithmeticFn target, Task task, Fact [] resolvers) { 
154     debug("in resolveall"); 
155     for (int i = 0; i<resolvers.length; i++) { 
156       Fact currentFact = resolvers[i];
157       debug ("doing " + currentFact.toString()); 
158       AttributeList attrs = currentFact.getAttributeList(); 
159       String [] attrNames = attrs.getNames(); 
160       for (int attrCount = 0; attrCount < attrNames.length; attrCount++) { 
161        target.resolve(currentFact.ID()+"." + attrNames[attrCount],currentFact.getFn(attrNames[attrCount])); 
162        debug (target.toString()); 
163       }
164         
165         
166     }
167   }
168   
169   
170   /*** 
171     resolvePreconditions is used to check through all the precondition attributes in the task as
172     they are loaded to see if there are any references to postcondition attributes, and then 
173     resolve those references so that when task chaining and execution occur the 
174     correct values will be used
175     *@since 1.2.1 
176     *@author Simon Thompson
177     */
178     public void resolvePreconditions(Task task, Fact[] consumed, Fact[] produced) { 
179         for (int count = 0; count<consumed.length; count++) {
180             Fact currentFact = consumed[count];
181             AttributeList attrs = currentFact.getAttributeList(); 
182             String [] attrName = attrs.getNames(); 
183             for (int attrCount = 0; attrCount < attrName.length; attrCount++) {
184              debug("before checknmap" + attrs.toString()); 
185              checkAndMapValue(attrName[attrCount],attrs,produced);
186              debug ("after checknmap " + attrs.toString()); 
187             }
188             
189         }
190         if (task instanceof zeus.concepts.PrimitiveTask) { 
191             ((PrimitiveTask) task).setPreconditions(consumed); 
192             ((PrimitiveTask) task).setPostconditions(produced); }
193        
194     }
195   
196   
197   /*** 
198     checkAndMapValue takes a value from an attribute and checks to see if it 
199     is a reference to a post condition. If it is, then it will map the value of the 
200     post condition reference to the precondition: if we have a precondition x.name = ?y.name 
201     where the post condition is ?y and ?y.name is ?var123 then we should map the precondition 
202     to : 
203         x.name = ?var123
204     if this is made so, all will be well, and good, good, will have triumphed. 
205     
206     @since 1.2.1
207     @author Simon Thompson
208         */
209   public void checkAndMapValue (String attrName, AttributeList attrs, Fact [] produced) { 
210     String value = attrs.getValue(attrName); 
211     if (value.startsWith ("?var")) return; 
212     for (int count = 0; count< produced.length; count ++) { 
213      Fact currentPost = produced[count];
214      String currentPostName = currentPost.getId(); 
215      debug (currentPostName + " - " + value);
216      for (int i = 0; i < value.length() - currentPostName.length();i++) { 
217         if (value.regionMatches (i, currentPostName, 0, currentPostName.length())) {
218             debug ("match"); 
219             String postAttr = value.substring(i+currentPostName.length()+1, value.length());
220             postAttr = postAttr.replace(')',' '); // get rid of trailing brackets
221             postAttr = postAttr.trim(); 
222             String attrExp = value.substring (0, i); 
223             String postVal = currentPost.getValue(postAttr); 
224             ValueFunction postFn = currentPost.getFn(postAttr); 
225             debug ("postVal = " + postVal); 
226             if (postVal != null) {
227                 ValueFunction currentVf = attrs.getFn(attrName); 
228                 if (currentVf instanceof VarFn) { 
229                     ((VarFn) currentVf).arg = postVal;
230                     attrs.remove (attrName); 
231                     attrs.setValue(attrName,currentVf); 
232                     }
233                 else if (currentVf instanceof ConstraintFn) { 
234                     ConstraintFn consVf= (ConstraintFn) currentVf; 
235                     consVf.arg = postFn;
236                     int operator = consVf.getOperator(); 
237                     String operand = ConstraintFn.operators[operator]; 
238                     ConstraintFn newFn = new ConstraintFn(operand,consVf.arg); 
239                     debug (newFn.toString()); 
240                     attrs.remove (attrName); 
241                     attrs.setValue(attrName,newFn); 
242                 }// end elseif
243                 else if (currentVf instanceof ArithmeticFn) { 
244                     ArithmeticFn arithVf = (ArithmeticFn) currentVf; 
245                     arithVf.resolve(postVal,postFn); 
246                     ValueFunction lhs = arithVf.getLHS(); 
247                     debug ("LHS = " + lhs.toString() + " class " + lhs.getClass()); 
248                     ValueFunction rhs = arithVf.getRHS(); 
249                      debug ("RHS = " + rhs.toString() + " class " + rhs.getClass()); 
250                     int operator = arithVf.getOperator(); 
251                     String operand = ArithmeticFn.operators[operator]; 
252                     ArithmeticFn newFn = new ArithmeticFn(lhs,rhs,operand);
253                     attrs.remove(attrName);
254                     attrs.setValue(attrName,newFn); 
255                     
256                     
257                 }
258                 else { 
259                     debug ("NOT recognised >>>" + currentVf.getClass().toString()); 
260                 }
261                 
262                 debug ("attrs in checknmap " + attrs.toString()); 
263                 } // end if
264         }//end if
265      }// end for
266      }// end for
267   }
268      
269   
270   public void add(Vector List) {
271     for(int i = 0; List != null && i < List.size(); i++ )
272       add((Task)List.elementAt(i));
273   }
274   
275   
276   public void add(Task[] List) {
277     for(int i = 0; List != null && i < List.length; i++ )
278       add(List[i]);
279   }
280 
281   protected int addItem(Vector List, Task task) {
282     int op = NONE;
283     for(int i = 0; i < List.size(); i++ )
284       op = Math.min(op, addItem((Fact)List.elementAt(i),task));
285     return op;
286   }
287   protected int addItem(Fact[] List, Task task) {
288     int op = NONE;
289     for(int i = 0; i < List.length; i++ )
290       op = Math.min(op, addItem(List[i],task));
291     return op;
292   }
293 
294   
295   protected int addItem(Fact fact, Task task) {
296     int op = NONE;
297     if ( fact.isLocal() ) return op;
298 
299     String type = fact.getType();
300     Hashtable obj;
301 
302     if ( (obj = (Hashtable)this.get(type)) == null ) {
303        obj = new Hashtable();
304        this.put(type,obj);
305     }
306     op =  obj.put(task.getName(),task) != null ? MODIFY : ADD;
307 
308     if ( orgDb != null ) {
309        AbilitySpec a = new AbilitySpec(task.getName(),fact,0,0);
310        OrganisationDb org = orgDb;
311        org.add(agentName,a);
312     }
313     return op;
314   }
315 
316   /*** The primary method for deleting task abilities from the Task Database */
317   public void del(Task task) {
318     Assert.notNull(task);
319     Fact[] produced = task.getPostconditions();
320     int operation = deleteItem(produced,task);
321     if ( operation != NONE )
322        notifyMonitors(task,operation);
323   }
324   
325   public void del(Vector List) {
326     for(int i = 0; List != null && i < List.size(); i++ )
327       del((Task)List.elementAt(i));
328   }
329   
330   
331   public void del(Task[] List) {
332     for(int i = 0; List != null && i < List.length; i++ )
333       del(List[i]);
334   }
335 
336   protected int deleteItem(Vector List, Task task) {
337     int op = NONE;
338     for(int i = 0; i < List.size(); i++ )
339       op = Math.min(op, deleteItem((Fact)List.elementAt(i),task));
340     return op;
341   }
342   
343   
344   protected int deleteItem(Fact[] List, Task task) {
345     int op = NONE;
346     for( int i = 0; i < List.length; i++ )
347       op = Math.min(op, deleteItem(List[i],task));
348     return op;
349   }
350   
351   
352   protected int deleteItem(Fact fact, Task task) {
353     int op = NONE;
354 
355     String type = fact.getType();
356     Hashtable List;
357     Task t;
358 
359     if ( (List = (Hashtable)this.get(type)) == null ) return op;
360 
361     op = List.remove(task.getName()) != null ? DELETE : NONE;
362 
363     if ( List.isEmpty() ) this.remove(type);
364 
365     if ( orgDb != null ) {
366         // might need to add the name param here..
367       AbilitySpec a = new AbilitySpec(task.getName(),fact,0,0);
368       OrganisationDb org = orgDb;
369       org.del(agentName,a);
370     }
371     return op;
372   }
373 
374   /*** Returns a duplicate of the task object with the given name */
375   public Task getTask(String name) {
376     Task task;
377     Hashtable data;
378     Enumeration enum = this.elements();
379     while( enum.hasMoreElements() ) {
380        data = (Hashtable) enum.nextElement();
381        task = (Task)data.get(name);
382        notifyMonitors(task,ACCESS);
383        if ( task != null ) {
384          Task retTask = (Task) task.duplicate (Fact.VAR, gensym); 
385          debug("Duplicate = " + retTask.toString()); 
386          debug("Original = " + task.toString());
387         // return (Task) task.duplicate(Fact.VAR,gensym);}
388          return (task);}
389     }
390     return null;
391   }
392 
393   /*** Deletes the task object with the given name */
394   public void deleteTask(String name) {
395     Task task;
396     Hashtable data;
397     Enumeration enum = this.elements();
398     while( enum.hasMoreElements() ) {
399        data = (Hashtable) enum.nextElement();
400        task = (Task)data.remove(name);
401        if ( task != null )
402           notifyMonitors(task,DELETE);
403     }
404   }
405 
406   /*** Randomly chooses a task able to produces a fact matching the parameter */
407   public Task findOne(Fact fact) {
408     Task task = null;
409     Vector reduced = findAll(fact);
410     if ( !reduced.isEmpty() ) {
411        int pos = (int) (Math.random()*reduced.size());
412        task = (Task)reduced.elementAt(pos);
413        notifyMonitors(task,ACCESS);
414     }
415     reduced = null; // gc
416     return task;
417   }
418 
419   /*** Retrieves the tasks that produce a fact matching the parameter */
420   public Vector findAll(Fact fact) {
421     Hashtable obj;
422 
423     if ( (obj = (Hashtable)this.get(fact.getType())) == null )
424        return new Vector();
425 
426     return this.reduce(obj,fact);
427   }
428 
429   public Vector findAll(Fact fact, Vector path) {
430      Core.DEBUG(3,"TaskDb findAll(2)");
431      Core.DEBUG(3,"tFact = " + fact);
432      Core.DEBUG(3,"tPath = " + path);
433 
434      Vector prior = findAll(fact);
435      return checkPath(prior,path);
436   }
437 
438   /*** Retrieves the tasks that produce and consume the same facts as the parameters */
439   public Vector findAll(Fact[] consumed, Fact[] produced, Vector path) {
440      Core.DEBUG(3,"TaskDb findAll(3)");
441 
442      Assert.notFalse(produced.length > 0);
443 
444      Core.DEBUG(3,consumed);
445      Core.DEBUG(3,produced);
446      Core.DEBUG(3,path);
447 
448      int index = -1;
449      for(int i = 0; index == -1 && i < produced.length; i++ )
450         if ( !produced[i].isSideEffect() ) index = i;
451 
452      Assert.notFalse(index != -1);
453      Vector prior = findAll(produced[index]);
454      Vector List = new Vector();
455      Fact[] preconds, effects;
456      Task task;
457      for(int i = 0; i < prior.size(); i++ ) {
458         task = (Task)prior.elementAt(i);
459         preconds = task.getPreconditions();
460         effects = task.getPostconditions();
461         if ( hasCondition(consumed,preconds) && hasCondition(produced,effects) )
462            List.addElement(task);
463      }
464      return checkPath(List,path);
465   }
466 
467   protected boolean hasCondition(Fact[] test, Fact[] data) {
468      boolean state = true;
469      for(int i = 0; state && i < test.length; i++ )
470         state &= hasCondition(test[i],data);
471      return state;
472   }
473 
474   protected boolean hasCondition(Fact test, Fact[] data) {
475      Bindings b = new Bindings(agentName);
476      for(int i = 0; i < data.length; i++, b.clear() )
477         if ( data[i].unifiesWith(test,b) ) return true;
478      return false;
479   }
480 
481   protected Vector checkPath(Vector prior, Vector path) {
482      Core.DEBUG(3,"Checking path...");
483      Core.DEBUG(3,"tprior = " + prior);
484 
485      if ( prior.isEmpty() ) return prior;
486 
487      Vector posterior = new Vector();
488      Bindings b = new Bindings(agentName);
489      Task task;
490      boolean ok;
491      Fact f1;
492      Fact[] consumed;
493      for(int i = 0; i < prior.size(); i++ ) {
494         task = (Task)prior.elementAt(i);
495         notifyMonitors(task,ACCESS);
496         ok = true;
497         consumed = task.getPreconditions();
498         for(int j = 0; ok && j < consumed.length; j++ ) {
499            for(int k = 0; ok && k < path.size(); k++, b.clear()) {
500               f1 = (Fact)path.elementAt(k);
501               ok = ok && !consumed[j].unifiesWith(f1,b);
502            }
503         }
504         if ( ok ) posterior.addElement(task);
505      }
506      prior = null; // gc
507 
508      Core.DEBUG(3,"posterior = " + posterior);
509 
510      return posterior;
511   }
512 
513   protected Vector reduce(Hashtable List, Fact fact) {
514     Vector ReducedList = new Vector();
515     Task task, t;
516     Bindings b = new Bindings(agentName);
517 
518     Enumeration enum = List.elements();
519     while( enum.hasMoreElements() ) {
520        task = (Task)enum.nextElement();
521        notifyMonitors(task,ACCESS);
522        t = (Task) task.duplicate(Fact.VAR,gensym);
523        Fact[] produced = t.getPostconditions();
524        Core.DEBUG(3,"TASK_IS\n" + t.pprint());
525        for(int j = 0; j < produced.length; j++, b.clear() ) {
526 
527           Core.DEBUG(3,"TaskDb reduce(): unifying\n\trequired =\n" +
528              fact.pprint() + "\n\tproduced =\n" + produced[j].pprint());
529 
530           if ( produced[j].unifiesWith(fact,b) && t.applyConstraints(b) ) {
531              Core.DEBUG(3,"After apply Constraints:\n" + t);
532              Core.DEBUG(3,"Bindings is\n" + b);
533 
534              if ( t.isPrimitive() )
535                 ((PrimitiveTask)t).setActiveEffect(j);
536              ReducedList.addElement(t);
537 
538              // begin: demonstration version only
539              if ( demo_version && t.isPrimitive() )
540                 t.setCostFn(Integer.toString(CMIN + Math.abs(rand.nextInt()%(CMAX-CMIN))));
541              // end: demonstration version only
542 
543              break;
544           }
545        }
546     }
547     sort(ReducedList);
548     return ReducedList;
549   }
550 
551   /*** Sorts a vector of tasks according to their time and cost functions */
552   protected void sort(Vector List) {
553      Vector primitive = new Vector();
554      Task t;
555      for(int i = 0; i < List.size(); i++ ) {
556         t = (Task)List.elementAt(i);
557         notifyMonitors(t,ACCESS);
558         if ( t.isPrimitive() ) {
559            primitive.addElement(t);
560            List.removeElementAt(i--);
561         }
562      }
563      sort_basic(List);
564      sort_basic(primitive);
565      for(int i = 0; i < primitive.size(); i++ )
566         List.addElement(primitive.elementAt(i));
567      primitive = null; // GC
568   }
569 
570   protected void sort_basic(Vector List) {
571      boolean changed = true;
572      Task t1, t2;
573 
574      while( changed ) {
575         changed = false;
576         for( int i = 0; i < List.size()-1; i++ ) {
577            t1 = (Task)List.elementAt(i);
578            notifyMonitors(t1,ACCESS);
579            t2 = (Task)List.elementAt(i+1);
580            notifyMonitors(t2,ACCESS);
581            if ( (t1.getCost() > t2.getCost()) ||
582                 (t1.getCost() == t2.getCost() && t1.getTime() > t2.getTime()) ) {
583               List.setElementAt(t2,i);
584               List.setElementAt(t1,i+1);
585               changed = true;
586            }
587         }
588      }
589   }
590 
591 
592   /***
593     * Use this if your code needs to react to changes in the Task Database
594     */
595   public void addTaskMonitor(TaskMonitor monitor, long event_type,
596                               boolean notify_previous) {
597       addTaskMonitor(monitor,event_type);
598       if ( !notify_previous ) return;
599 
600       Enumeration enum1 = elements();
601       Task task;
602       Hashtable data;
603       TaskEvent event;
604 
605       while( enum1.hasMoreElements() ) {
606          data = (Hashtable) enum1.nextElement();
607          Enumeration enum2 = data.elements();
608          while( enum2.hasMoreElements() ) {
609             task = (Task)enum2.nextElement();
610             event = new TaskEvent(this,task,TaskEvent.ACCESS_MASK);
611             monitor.taskAccessedEvent(event);
612             event = new TaskEvent(this,task,TaskEvent.ADD_MASK);
613             monitor.taskAddedEvent(event);
614          }
615       }
616    }
617 
618    public void addTaskMonitor(TaskMonitor monitor, long event_type) {
619       if ( (event_type & TaskEvent.ADD_MASK) != 0 )
620          eventMonitor[ADD].add(monitor);
621       if ( (event_type & TaskEvent.MODIFY_MASK) != 0 )
622          eventMonitor[MODIFY].add(monitor);
623       if ( (event_type & TaskEvent.DELETE_MASK) != 0 )
624          eventMonitor[DELETE].add(monitor);
625       if ( (event_type & TaskEvent.ACCESS_MASK) != 0 )
626          eventMonitor[ACCESS].add(monitor);
627    }
628 
629    public void removeTaskMonitor(TaskMonitor monitor, long event_type) {
630       if ( (event_type & TaskEvent.ADD_MASK) != 0 )
631          eventMonitor[ADD].remove(monitor);
632       if ( (event_type & TaskEvent.MODIFY_MASK) != 0 )
633          eventMonitor[MODIFY].remove(monitor);
634       if ( (event_type & TaskEvent.DELETE_MASK) != 0 )
635          eventMonitor[DELETE].remove(monitor);
636       if ( (event_type & TaskEvent.ACCESS_MASK) != 0 )
637          eventMonitor[ACCESS].remove(monitor);
638    }
639 
640    protected void notifyMonitors(Task task, int type) {
641       if ( eventMonitor[type].isEmpty() ) return;
642 
643       Enumeration enum = eventMonitor[type].elements();
644       TaskMonitor monitor;
645       TaskEvent event;
646       switch(type) {
647          case ADD:
648               event = new TaskEvent(this,task,TaskEvent.ADD_MASK);
649               while( enum.hasMoreElements() ) {
650                  monitor = (TaskMonitor)enum.nextElement();
651                  monitor.taskAddedEvent(event);
652               }
653               break;
654          case MODIFY:
655               event = new TaskEvent(this,task,TaskEvent.MODIFY_MASK);
656               while( enum.hasMoreElements() ) {
657                  monitor = (TaskMonitor)enum.nextElement();
658                  monitor.taskModifiedEvent(event);
659               }
660               break;
661          case DELETE:
662               event = new TaskEvent(this,task,TaskEvent.DELETE_MASK);
663               while( enum.hasMoreElements() ) {
664                  monitor = (TaskMonitor)enum.nextElement();
665                  monitor.taskDeletedEvent(event);
666               }
667               break;
668          case ACCESS:
669               event = new TaskEvent(this,task,TaskEvent.ACCESS_MASK);
670               while( enum.hasMoreElements() ) {
671                  monitor = (TaskMonitor)enum.nextElement();
672                  monitor.taskAccessedEvent(event);
673               }
674               break;
675       }
676    }
677    
678    private void debug (String out) { 
679     //  System.out.println("taskDb>> " + out); 
680    }
681    
682 }