1 package cz.cuni.amis.pogamut.multi.communication.worldview.impl;
2
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.Set;
7 import java.util.WeakHashMap;
8
9 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldChangeEvent;
10 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult;
11 import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
12 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
13 import cz.cuni.amis.pogamut.base.component.lifecyclebus.ILifecycleBus;
14 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
15 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
16 import cz.cuni.amis.pogamut.base3d.worldview.object.IViewable;
17 import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectDisappearedEvent;
18 import cz.cuni.amis.pogamut.multi.agent.ITeamedAgentId;
19 import cz.cuni.amis.pogamut.multi.communication.translator.event.ICompositeWorldObjectUpdatedEvent;
20 import cz.cuni.amis.pogamut.multi.communication.translator.event.ILocalWorldObjectUpdatedEvent;
21 import cz.cuni.amis.pogamut.multi.communication.worldview.ISharedWorldView;
22 import cz.cuni.amis.pogamut.multi.communication.worldview.IVisionLocalWorldView;
23 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ILocalViewable;
24 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ILocalWorldObject;
25 import cz.cuni.amis.pogamut.multi.utils.timekey.TimeKey;
26 import cz.cuni.amis.utils.ClassUtils;
27 import cz.cuni.amis.utils.exception.PogamutException;
28 import cz.cuni.amis.utils.maps.WeakHashMapMap;
29
30
31
32
33
34
35
36
37 @AgentScoped
38 public abstract class VisionLocalWorldView extends EventDrivenLocalWorldView implements IVisionLocalWorldView {
39
40 public VisionLocalWorldView(
41 ComponentDependencies dependencies,
42 ILifecycleBus bus, IAgentLogger logger,
43 ISharedWorldView parentWorldView, ITeamedAgentId agentId
44 ) {
45 super(dependencies, bus, logger, parentWorldView, agentId);
46 }
47
48 @Override
49 public void notify(IWorldChangeEvent event)
50 {
51 if ( event instanceof ILocalWorldObjectUpdatedEvent)
52 {
53 objectUpdatedEvent( (ILocalWorldObjectUpdatedEvent)event );
54 }
55 else if ( event instanceof ICompositeWorldObjectUpdatedEvent)
56 {
57 objectUpdatedEvent( ((ICompositeWorldObjectUpdatedEvent)event).getLocalEvent() );
58 }
59 else
60 {
61 super.notify(event);
62 }
63 }
64
65
66
67
68 protected Map<TimeKey, Map<WorldObjectId, IViewable>> visibleMap =
69 new WeakHashMap<TimeKey, Map<WorldObjectId, IViewable>>();
70
71
72
73
74 protected Map< TimeKey, Map<WorldObjectId, IViewable>> syncVisibleMap =
75 Collections.synchronizedMap(visibleMap);
76
77
78
79
80 @SuppressWarnings("rawtypes")
81 protected Map<TimeKey, Map<Class, Map<WorldObjectId, IViewable>>> visibleClassMap =
82 new WeakHashMapMap<TimeKey, Class, Map<WorldObjectId, IViewable>>();
83
84
85
86
87 @SuppressWarnings("rawtypes")
88 protected Map<TimeKey, Map< Class, Map<WorldObjectId,IViewable>>> syncVisibleClassMap =
89 Collections.synchronizedMap(visibleClassMap);
90
91 @Override
92 protected void objectUpdatedEvent(ILocalWorldObjectUpdatedEvent updateEvent)
93 {
94
95
96 ILocalWorldObject obj = getMostRecentLocalWorldObject( updateEvent.getId() );
97
98 boolean oldVisible = false;
99 boolean isViewable = false;
100
101 ILocalWorldObject copy = null;
102
103 if ( obj != null)
104 {
105 if ( obj instanceof ILocalViewable)
106 {
107 oldVisible = ((ILocalViewable)obj).isVisible();
108 isViewable = true;
109 }
110 copy = obj.clone();
111 }
112 else
113 {
114 copy = null;
115 }
116
117 IWorldObjectUpdateResult<ILocalWorldObject> updateResult = updateEvent.update(copy);
118
119 switch (updateResult.getResult()) {
120 case CREATED:
121 objectCreated(updateResult.getObject(), updateEvent.getSimTime());
122 return;
123 case UPDATED:
124 if (updateResult.getObject() != copy) {
125 throw new PogamutException("Update event " + updateEvent + " does not returned the same instance of the object (result UPDATED).", this);
126 }
127
128 super.addOldLocalWorldObject(obj, updateEvent.getSimTime());
129
130 boolean appearedDisappeared = false;
131
132 if (isViewable)
133 {
134 boolean visible = ((ILocalViewable)copy).isVisible();
135 if ( visible != oldVisible)
136 {
137 appearedDisappeared = true;
138 if ( visible )
139 {
140 objectAppeared((ILocalViewable)copy, updateEvent.getSimTime());
141 }
142 else
143 {
144 objectDisappeared((ILocalViewable)copy, updateEvent.getSimTime());
145 }
146 }
147 else
148 {
149
150
151 if ( visible )
152 {
153 addVisible((ILocalViewable)obj, updateEvent.getSimTime());
154 }
155 }
156 }
157
158 if ( !appearedDisappeared )
159 objectUpdated(copy, updateEvent.getSimTime());
160
161 actLocalWorldObjects.put(copy.getId(), copy);
162
163 return;
164 case SAME:
165 if (isViewable && oldVisible)
166 {
167 addVisible((ILocalViewable)obj, updateEvent.getSimTime());
168 }
169 return;
170 case DESTROYED:
171
172 super.addOldLocalWorldObject(obj, updateEvent.getSimTime());
173 objectDestroyed(copy, updateEvent.getSimTime());
174
175 return;
176 default:
177 throw new PogamutException("Unhandled object update result " + updateResult.getResult() + " for the object " + obj + ".", this);
178 }
179 }
180
181
182 protected void objectCreated( ILocalWorldObject obj , long time )
183 {
184 if ( obj instanceof ILocalViewable)
185 {
186 if ( ((ILocalViewable)obj).isVisible() )
187 {
188 objectAppeared( (ILocalViewable)obj, time );
189 }
190 }
191
192 super.objectCreated(obj, time);
193 }
194
195
196 protected void objectDestroyed( ILocalWorldObject obj , long time)
197 {
198
199
200
201
202 super.objectDestroyed(obj, time);
203 }
204
205
206
207
208
209 protected void objectAppeared( ILocalViewable obj, long time )
210 {
211
212 addVisible(obj, time);
213 }
214
215
216
217
218
219 protected void objectDisappeared( ILocalViewable obj, long time )
220 {
221
222 }
223
224
225
226
227
228
229
230
231 protected synchronized void addVisible( ILocalViewable obj , long time )
232 {
233
234 synchronized(visibleMap)
235 {
236 Map map = visibleMap.get(TimeKey.get(time));
237 if ( map == null )
238 {
239 map = new LazyCompositeObjectMap<IViewable>( time );
240 visibleMap.put(TimeKey.get(time), map );
241 }
242 ((LazyCompositeObjectMap<IViewable>)visibleMap.get(TimeKey.get(time))).addKey(obj.getId());
243 }
244 synchronized( visibleClassMap )
245 {
246 Map clsMap = visibleClassMap.get(time);
247 if ( clsMap == null )
248 {
249 clsMap = new HashMap<Class,Map>();
250 visibleClassMap.put(TimeKey.get(time),clsMap);
251 }
252 for ( Class cls : ClassUtils.getSubclasses(obj.getCompositeClass()) )
253 {
254 LazyCompositeObjectMap<IViewable> map = ((LazyCompositeObjectMap<IViewable>)visibleClassMap.get(TimeKey.get(time)).get(cls));
255 if ( map == null )
256 {
257 map = new LazyCompositeObjectMap<IViewable>( getCurrentTimeKey().getTime() );
258 visibleClassMap.get(TimeKey.get(time)).put(cls, map);
259 }
260 map.addKey(obj.getId());
261 }
262 }
263 }
264
265
266
267
268
269
270 protected synchronized void removeVisible( ILocalViewable obj, long time )
271 {
272 synchronized(visibleMap)
273 {
274 ((LazyCompositeObjectMap<IViewable>)visibleMap.get(TimeKey.get(time))).remove(obj.getId());
275 }
276 synchronized( visibleClassMap )
277 {
278 for ( Class cls : ClassUtils.getSubclasses(obj.getCompositeClass()) )
279 {
280 LazyCompositeObjectMap<IViewable> map = ((LazyCompositeObjectMap<IViewable>)visibleClassMap.get(TimeKey.get(time)).get(cls));
281 if ( map == null )
282 {
283 map = new LazyCompositeObjectMap<IViewable>( getCurrentTimeKey().getTime() );
284 visibleClassMap.get(TimeKey.get(time)).put(cls, map);
285 }
286 map.remove(obj.getId());
287 }
288 }
289 }
290
291 @Override
292 public Map<Class, Map<WorldObjectId, IViewable>> getAllVisible() {
293
294 return syncVisibleClassMap.get(currentTimeKey);
295 }
296
297 @Override
298 public <T extends IViewable> Map<WorldObjectId, T> getAllVisible(
299 Class<T> type)
300 {
301
302 Map<WorldObjectId,T> map = (Map<WorldObjectId, T>) syncVisibleClassMap.get(currentTimeKey).get(type);
303 if ( map == null )
304 {
305 map = new LazyCompositeObjectMap<T>( currentTimeKey.getTime() );
306 }
307 return map;
308 }
309
310 @Override
311 public Map<WorldObjectId, IViewable> getVisible() {
312 return syncVisibleMap.get(currentTimeKey);
313 }
314
315 @Override
316 public IViewable getVisible(WorldObjectId id) {
317 return syncVisibleMap.get(currentTimeKey).get(id);
318 }
319
320 }