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   * @(#)AbilityDb.java 1.00
26   */
27  
28  package zeus.actors;
29  
30  import java.util.*;
31  import zeus.util.*;
32  import zeus.concepts.*;
33  import zeus.actors.event.*;
34  
35  /***
36   * This class implements the Ability Database component, which stores the
37   * acquaintances of the owning agent. Each acquaintance consists of an agent
38   * identity and the abilities that agent is believed to possess (these are
39   * stored as {@link AbilityDbItem} objects). <p>
40   *
41   * Every Zeus agent has an AbilityDb instance, a reference to which is stored
42   * in its {@link AgentContext} object. <p>
43   * Change log
44   * ----------
45   * 12-06-01 Added agentName and genSym to facilitate intialisation from extended types. 
46   * also altered init functions. 
47   */
48  
49  public class AbilityDb extends Hashtable {
50     private HSet[]  eventMonitor = new HSet[4];
51  
52     private static final int ADD    = 0;
53     private static final int MODIFY = 1;
54     private static final int DELETE = 2;
55     private static final int ACCESS = 3;
56  
57     protected Vector knownAgents = new Vector(100);
58     protected AgentContext context = null;
59      
60     protected GenSym gensym = null; 
61     protected String agentName = null; 
62  
63    //meaningless init to permit rearchitecting
64     public AbilityDb() {
65      for(int i = 0; i < eventMonitor.length; i++ )
66           eventMonitor[i] = new HSet();
67     }
68  
69  
70     public AbilityDb(AgentContext context) {
71        Assert.notNull(context);
72        this.context = context;
73        gensym = context.getGenSym(); 
74        agentName = context.whoami(); 
75        for(int i = 0; i < eventMonitor.length; i++ )
76           eventMonitor[i] = new HSet();
77     }
78  
79     public AgentContext getAgentContext() {
80         return context;
81     }
82  
83     protected boolean addItem(String name, Vector List ) {
84        if ( !List.contains(name) ) {
85           List.addElement(name);
86           return true;
87        }
88        return false;
89     }
90  
91     private boolean member(AbilityDbItem item, Vector List) {
92        AbilityDbItem elem;
93        for( int i = 0; i < List.size(); i++ ) {
94           elem = (AbilityDbItem)List.elementAt(i);
95           notifyMonitors(elem,ACCESS);
96           if ( item.equals(elem) ) return true;
97        }
98        return false;
99     }
100 
101    public void add(String type, AbilityDbItem ability_item) {
102       AbilityDbItem item = ability_item.duplicate(Fact.VAR,gensym);
103       Vector obj;
104 
105       addItem(item.getAgent(),knownAgents);
106       if ( (obj = (Vector)this.get(type)) == null ) {
107          obj = new Vector(10);
108          this.put(type,obj);
109       }
110       if ( !member(item,obj) ) {
111          obj.addElement(item);
112          notifyMonitors(item,ADD);
113       }
114    }
115 
116    public void add(String agent, AbilitySpec ability) {
117       String type = ability.getType();
118       AbilityDbItem item = new AbilityDbItem(agent,ability);
119       add(type,item);
120    }
121 
122    public void add(String item, Vector List) {
123       if ( List.isEmpty() ) return;
124       Object object = List.elementAt(0);
125 
126       if ( object instanceof AbilityDbItem ) {
127          for( int i = 0; i < List.size(); i++ )
128             this.add(item, (AbilityDbItem)List.elementAt(i) );
129       }
130       else if ( object instanceof AbilitySpec ) {
131          for( int i = 0; i < List.size(); i++ )
132             this.add(item, (AbilitySpec)List.elementAt(i) );
133       }
134    }
135 
136    public void add(Vector List) {
137       for( int i = 0; i < List.size(); i++ ) {
138          AbilityDbItem item = (AbilityDbItem)List.elementAt(i);
139          String type = item.getAbility().getType();
140          this.add(type,item);
141       }
142    }
143 
144    public void add(AbilityDbItem item) {
145       String type = item.getAbility().getType();
146       this.add(type,item);
147    }
148 
149    public void modify(AbilityDbItem previousItem, AbilityDbItem newItem) {
150        del(previousItem.getAbility().getType(),previousItem);
151        add(newItem);
152    }
153 
154    public void del(String type, AbilityDbItem item) {
155       Vector obj;
156       AbilityDbItem a;
157 
158       if ( (obj = (Vector)this.get(type)) == null ) return;
159 
160       for( int i = 0; i < obj.size(); i++ ) {
161          a = (AbilityDbItem)obj.elementAt(i);
162          if ( a.equals(item) ) {
163             obj.removeElementAt(i--);
164             notifyMonitors(a,DELETE);
165          }
166       }
167       if ( obj.isEmpty() ) this.remove(type);
168    }
169 
170    public void del(String agent, AbilitySpec ability) {
171       String type = ability.getType();
172       AbilityDbItem item = new AbilityDbItem(agent,ability);
173       del(type,item);
174    }
175 
176    public void del(String item, Vector List) {
177       if ( List.isEmpty() ) return;
178       Object object = List.elementAt(0);
179 
180       if ( object instanceof AbilityDbItem ) {
181          for( int i = 0; i < List.size(); i++ )
182             this.del(item, (AbilityDbItem) List.elementAt(i) );
183       }
184       else if ( object instanceof AbilitySpec ) {
185          for( int i = 0; i < List.size(); i++ )
186             this.del(item, (AbilitySpec) List.elementAt(i) );
187       }
188    }
189 
190 
191    public AbilityDbItem findOne(AbilitySpec ability) {
192       Vector obj;
193       Vector reduced;
194       AbilityDbItem item = null;
195 
196       if ( (obj = (Vector)this.get(ability.getType())) == null )
197          return null;
198 
199       if ( (reduced = this.reduce(obj,ability)) == null )
200          return null;
201 
202       if ( reduced.size() > 0 ) {
203          int pos = (int) (Math.random()*reduced.size());
204          item = (AbilityDbItem)reduced.elementAt(pos);
205          notifyMonitors(item,ACCESS);
206       }
207       reduced = null;
208       return item;
209    }
210 
211    public Vector findAll(AbilitySpec ability) {
212       Vector obj;
213       Vector reduced;
214       
215       if ( (obj = (Vector)this.get(ability.getType())) == null )
216          return new Vector(100);
217       
218       Core.DEBUG(3,"AbilityDb findAll: " + ability + "\n" + obj);
219       reduced = this.reduce(obj,ability);
220       return reduced;
221    }
222 
223    public Vector abilitiesOf(String person) {
224       Vector List = new Vector(100);
225       Vector items = null;
226       AbilityDbItem item;
227       Enumeration enum = this.keys();
228       String type;
229 
230       while ( enum.hasMoreElements() ) {
231          type = (String) enum.nextElement();
232          items = (Vector) this.get(type);
233          for( int i = 0; i < items.size(); i++ ) {
234             item = (AbilityDbItem) items.elementAt(i);
235             notifyMonitors(item,ACCESS);
236             if ( item.getAgent().equals(person) )
237                List.addElement( new AbilitySpec(item.getAbility()) );
238          }
239       }
240       return List;
241    }
242 
243    protected Vector reduce(Vector List, AbilitySpec ability) {
244       Vector ReducedList = new Vector(100);
245       AbilityDbItem item;
246       AbilitySpec   ab;
247       Bindings b = new Bindings(agentName);
248       Fact f2, f1 = ability.getFact();
249       int  t2, t1 = ability.getTime();
250       double c2, c1 = ability.getCost();
251 
252       for( int i = 0; i < List.size(); i++, b.clear() ) {
253          item = (AbilityDbItem) List.elementAt(i);
254          notifyMonitors(item,ACCESS);
255          ab = item.getAbility();
256          f2 = ab.getFact();
257          t2 = ab.getTime();
258          c2 = ab.getCost();
259          if ( (t1 == 0 || t2 <= t1) && (c1 == 0 || c2 <= c1) &&
260               f2.unifiesWith(f1,b) )
261             ReducedList.addElement(item);
262          else {
263             Core.DEBUG(3,"Cannot unify abilities:\n" + ability + "\n" + item );
264          }
265       }
266       return ReducedList;
267    }
268 
269    public void addAbilityMonitor(AbilityMonitor monitor, long event_type,
270                                  boolean notify_previous) {
271 
272       addAbilityMonitor(monitor,event_type);
273       if ( !notify_previous ) return;
274 
275       Enumeration enum = elements();
276       Vector List;
277       AbilityDbItem item;
278       AbilityEvent event;
279 
280       while( enum.hasMoreElements() ) {
281          List = (Vector)enum.nextElement();
282          for(int i = 0; i < List.size(); i++ ) {
283             item = (AbilityDbItem) List.elementAt(i);
284             event = new AbilityEvent(this,item,AbilityEvent.ACCESS_MASK);
285             monitor.abilityAccessedEvent(event);
286             event = new AbilityEvent(this,item,AbilityEvent.ADD_MASK);
287             monitor.abilityAddedEvent(event);
288          }
289       }
290    }
291 
292    public void addAbilityMonitor(AbilityMonitor monitor, long type) {
293       Assert.notNull(monitor);
294       if ( (type & AbilityEvent.ADD_MASK) != 0 )
295          eventMonitor[ADD].add(monitor);
296       if ( (type & AbilityEvent.MODIFY_MASK) != 0 )
297          eventMonitor[MODIFY].add(monitor);
298       if ( (type & AbilityEvent.DELETE_MASK) != 0 )
299          eventMonitor[DELETE].add(monitor);
300       if ( (type & AbilityEvent.ACCESS_MASK) != 0 )
301          eventMonitor[ACCESS].add(monitor);
302    }
303    public void removeAbilityMonitor(AbilityMonitor monitor, long type) {
304       Assert.notNull(monitor);
305       if ( (type & AbilityEvent.ADD_MASK) != 0 )
306          eventMonitor[ADD].remove(monitor);
307       if ( (type & AbilityEvent.MODIFY_MASK) != 0 )
308          eventMonitor[MODIFY].remove(monitor);
309       if ( (type & AbilityEvent.DELETE_MASK) != 0 )
310          eventMonitor[DELETE].remove(monitor);
311       if ( (type & AbilityEvent.ACCESS_MASK) != 0 )
312          eventMonitor[ACCESS].remove(monitor);
313    }
314    private void notifyMonitors(AbilityDbItem ability, int type) {
315       if ( eventMonitor[type].isEmpty() ) return;
316 
317       Enumeration enum = eventMonitor[type].elements();
318       AbilityMonitor monitor;
319       AbilityEvent event;
320       switch(type) {
321          case ADD:
322               event = new AbilityEvent(this,ability,AbilityEvent.ADD_MASK);
323               while( enum.hasMoreElements() ) {
324                  monitor = (AbilityMonitor)enum.nextElement();
325                  monitor.abilityAddedEvent(event);
326               }
327               break;
328          case MODIFY:
329               event = new AbilityEvent(this,ability,AbilityEvent.MODIFY_MASK);
330               while( enum.hasMoreElements() ) {
331                  monitor = (AbilityMonitor)enum.nextElement();
332                  monitor.abilityModifiedEvent(event);
333               }
334               break;
335          case DELETE:
336               event = new AbilityEvent(this,ability,AbilityEvent.DELETE_MASK);
337               while( enum.hasMoreElements() ) {
338                  monitor = (AbilityMonitor)enum.nextElement();
339                  monitor.abilityDeletedEvent(event);
340               }
341               break;
342          case ACCESS:
343               event = new AbilityEvent(this,ability,AbilityEvent.ACCESS_MASK);
344               while( enum.hasMoreElements() ) {
345                  monitor = (AbilityMonitor)enum.nextElement();
346                  monitor.abilityAccessedEvent(event);
347               }
348               break;
349       }
350    }
351 }