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.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
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 }