1 package cz.cuni.amis.pogamut.ut2004multi.communication.module;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.Map;
6 import java.util.Set;
7
8 import cz.cuni.amis.pogamut.base.agent.IAgentId;
9 import cz.cuni.amis.pogamut.base.agent.utils.runner.impl.MultipleAgentRunner;
10 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
11 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
12 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
13 import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
14 import cz.cuni.amis.pogamut.base3d.worldview.IVisionWorldView;
15 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ICompositeWorldObject;
16 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ILocalWorldObject;
17 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ISharedProperty;
18 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ISharedWorldObject;
19 import cz.cuni.amis.pogamut.multi.communication.worldview.object.IStaticWorldObject;
20 import cz.cuni.amis.pogamut.multi.communication.worldview.property.PropertyId;
21 import cz.cuni.amis.pogamut.multi.utils.timekey.TimeKey;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.UT2004CompositeObjectCreator;
23 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.UT2004SharedObjectCreator;
24 import cz.cuni.amis.utils.exception.PogamutException;
25 import cz.cuni.amis.utils.maps.HashMapMap;
26 import cz.cuni.amis.utils.maps.WeakHashTriMap;
27
28
29
30
31
32
33
34
35
36
37
38
39 public class SharedKnowledgeDatabase {
40
41 int team;
42
43 static protected Map<Integer, SharedKnowledgeDatabase> instances = new HashMap<Integer, SharedKnowledgeDatabase>();
44
45 protected Set<IAgentId> registeredAgents = new HashSet<IAgentId>();
46
47
48
49
50
51 protected Map<IAgentId, IVisionWorldView> agentWorldViews = new HashMap<IAgentId, IVisionWorldView>();
52
53
54
55
56 protected Map<IAgentId, Set<IWorldObjectEventListener>> listeners = new HashMap<IAgentId, Set<IWorldObjectEventListener>>();
57
58
59
60
61 protected WeakHashTriMap<TimeKey, WorldObjectId, PropertyId, ISharedProperty> sharedProperties = new WeakHashTriMap<TimeKey, WorldObjectId, PropertyId, ISharedProperty>();
62
63
64
65
66 protected HashMapMap< WorldObjectId, PropertyId, ISharedProperty> currSharedProperties = new HashMapMap< WorldObjectId, PropertyId, ISharedProperty>();
67
68
69
70
71 protected Map<WorldObjectId, Long> lastUpdateTime = new HashMap<WorldObjectId, Long>();
72
73
74
75
76 protected HashMap<TimeKey,Set<IAgentId>> heldKeys = new HashMap<TimeKey,Set<IAgentId>>();
77
78
79
80
81 protected Map<IAgentId, TimeKey> currentTimeKeys = new HashMap<IAgentId, TimeKey>();
82
83
84
85
86 protected Set<Class> registeredClasses = new HashSet<Class>();
87
88 protected SharedKnowledgeDatabase( int team )
89 {
90 this.team = team;
91 }
92
93
94
95
96
97
98
99
100 protected void addTimeLock( TimeKey timeKey, IAgentId id)
101 {
102 synchronized (heldKeys)
103 {
104 Set<IAgentId> agentLocks = heldKeys.get(timeKey);
105 if ( agentLocks == null )
106 {
107 agentLocks = new HashSet<IAgentId>();
108 heldKeys.put(timeKey, agentLocks);
109 }
110
111 for ( TimeKey t : heldKeys.keySet() )
112 {
113 if ( t.getTime() >= timeKey.getTime())
114 {
115 heldKeys.get(t).add(id);
116 }
117 }
118 }
119 }
120
121
122
123
124
125
126 protected void removeTimeLock( TimeKey timeKey, IAgentId id)
127 {
128 synchronized (heldKeys)
129 {
130 Set<IAgentId> agentLocks = heldKeys.get(timeKey);
131 agentLocks.remove(id);
132 if ( agentLocks.isEmpty() )
133 {
134 heldKeys.remove(timeKey);
135 }
136 }
137 }
138
139
140
141
142
143
144
145
146
147
148 public static SharedKnowledgeDatabase get( int team )
149 {
150 SharedKnowledgeDatabase instance = instances.get(team);
151 if ( instance == null )
152 {
153 instance = new SharedKnowledgeDatabase(team);
154 instances.put(team, instance);
155 };
156 return instance;
157 }
158
159
160
161
162
163
164
165
166
167
168
169 public void addAgent( IAgentId id, IVisionWorldView agentWorldView, int team)
170 {
171 if (team != this.team)
172 {
173 throw new PogamutException("Trying to add an agent of different team than the one registered with this sharedKnowledgeDatabase.", this);
174 }
175 synchronized (registeredAgents)
176 {
177 if ( registeredAgents.contains(id) )
178 {
179 return;
180 };
181 registeredAgents.add(id);
182 agentWorldViews.put(id, agentWorldView);
183 for ( Class c : registeredClasses )
184 {
185 addClassListener(agentWorldView, c, id);
186 }
187 }
188 }
189
190
191
192
193
194
195
196 public void addObjectClass(Class c)
197 {
198 synchronized (registeredClasses)
199 {
200 registeredClasses.add(c);
201 for ( IAgentId id : registeredAgents)
202 {
203 addClassListener(agentWorldViews.get(id),c, id);
204 }
205 }
206 }
207
208
209
210
211
212
213 public boolean removeObjectClass(Class c)
214 {
215 synchronized (registeredClasses)
216 {
217 return registeredClasses.remove(c);
218 }
219 }
220
221
222
223
224
225
226
227
228 public boolean removeAgent( IAgentId id)
229 {
230 synchronized (registeredAgents)
231 {
232 if ( !registeredAgents.contains(id) )
233 {
234 return false;
235 }
236 IVisionWorldView wv = agentWorldViews.get(id);
237 Set<IWorldObjectEventListener> listenerSet = listeners.get(id);
238 if ( listenerSet != null)
239 {
240 for (IWorldObjectEventListener listener : listenerSet )
241 {
242 wv.removeListener(listener);
243 }
244 }
245 agentWorldViews.remove(id);
246 registeredAgents.remove(id);
247 listeners.remove(id);
248 return true;
249 }
250 }
251
252
253
254
255
256
257
258 public IWorldObject getObject(WorldObjectId id, IAgentId agentId)
259 {
260 synchronized (sharedProperties)
261 {
262 ICompositeWorldObject agentObject = (ICompositeWorldObject)agentWorldViews.get(agentId).get(id);
263 if (agentObject == null)
264 {
265 return null;
266 }
267 ILocalWorldObject localPart = agentObject.getLocal();
268 IStaticWorldObject staticPart = agentObject.getStatic();
269 Map<PropertyId, ISharedProperty> properties = agentObject.getShared().getProperties();
270 TimeKey timeKey = TimeKey.get(localPart.getSimTime());
271 for ( PropertyId pId : currSharedProperties.get(id).keySet() )
272 {
273 ISharedProperty p = sharedProperties.get(timeKey, id, pId);
274 if ( p == null )
275 {
276 p = currSharedProperties.get(id, pId);
277 }
278 properties.put(p.getPropertyId(), p);
279 }
280 Class msgClass = localPart.getCompositeClass();
281
282 ISharedWorldObject sharedPart = UT2004SharedObjectCreator.create( msgClass , id , properties.values());
283 return UT2004CompositeObjectCreator.createObject(localPart, sharedPart, staticPart);
284 }
285 }
286
287
288
289
290
291
292
293
294
295
296
297 protected void addClassListener(IVisionWorldView wv, Class c, IAgentId agentId)
298 {
299 synchronized (listeners)
300 {
301 IWorldObjectEventListener listener =
302 new AgentSpecificObjectEventListener<IWorldObject, IWorldObjectEvent<IWorldObject>>(agentId) {
303
304 @Override
305 public void notify(IWorldObjectEvent<IWorldObject> event)
306 {
307 SharedKnowledgeDatabase.this.processObjEvent(event, this.agentId);
308 };
309 };
310
311 wv.addObjectListener(c, listener);
312
313 Set<IWorldObjectEventListener> listenerSet = listeners.get(agentId);
314 if ( listenerSet == null )
315 {
316 listenerSet = new HashSet<IWorldObjectEventListener>();
317 listeners.put(agentId, listenerSet);
318 };
319 listenerSet.add(listener);
320 }
321 }
322
323
324
325
326
327
328 protected void processObjEvent(IWorldObjectEvent<IWorldObject> event, IAgentId agentId)
329 {
330 synchronized (sharedProperties)
331 {
332
333 TimeKey currentTime = currentTimeKeys.get(agentId);
334 if ( currentTime != null )
335 {
336 if ( currentTimeKeys.get(agentId).getTime() < event.getSimTime())
337 {
338 TimeKey newTimeKey = TimeKey.get(event.getSimTime());
339
340 this.removeTimeLock(currentTimeKeys.get(agentId), agentId);
341 currentTimeKeys.put(agentId, newTimeKey);
342 this.addTimeLock(newTimeKey, agentId);
343 }
344 }
345 else
346 {
347 TimeKey newTimeKey = TimeKey.get(event.getSimTime());
348 currentTimeKeys.put(agentId, newTimeKey);
349 this.addTimeLock(newTimeKey, agentId);
350 }
351
352 WorldObjectId id = event.getId();
353
354 ISharedWorldObject sharedObj = ((ICompositeWorldObject)event.getObject()).getShared();
355
356 long lastUpdateTime = -1;
357 if ( this.lastUpdateTime.containsKey(id) )
358 {
359 lastUpdateTime = this.lastUpdateTime.get(id);
360 }
361
362
363 if ( sharedObj.getSimTime() >= lastUpdateTime )
364 {
365 for ( ISharedProperty p : sharedObj.getProperties().values())
366 {
367 if ( p.getValue() != null )
368 {
369 PropertyId propertyId = p.getPropertyId();
370 ISharedProperty old = currSharedProperties.get(id, propertyId);
371 for ( TimeKey key : heldKeys.keySet() )
372 {
373 if ( sharedProperties.get(key, id, propertyId) == null )
374 {
375 sharedProperties.put(key,id, propertyId, p);
376 }
377 }
378 }
379 }
380 }
381 }
382 }
383 }