1 package cz.cuni.amis.pogamut.base3d.worldview.impl;
2
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.Map;
6
7 import com.google.inject.name.Named;
8
9 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult;
10 import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
11 import cz.cuni.amis.pogamut.base.communication.worldview.impl.EventDrivenWorldView;
12 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
13 import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
14 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectDestroyedEvent;
15 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
16 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
17 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
18 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
19 import cz.cuni.amis.pogamut.base3d.worldview.IVisionWorldView;
20 import cz.cuni.amis.pogamut.base3d.worldview.object.IViewable;
21 import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectAppearedEvent;
22 import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectDisappearedEvent;
23 import cz.cuni.amis.utils.ClassUtils;
24 import cz.cuni.amis.utils.exception.PogamutException;
25 import cz.cuni.amis.utils.maps.HashMapMap;
26
27 public class VisionWorldView extends EventDrivenWorldView implements IVisionWorldView {
28
29 public static final String WORLDVIEW_DEPENDENCY = "VisionWorldViewDependency";
30
31
32
33
34
35
36
37
38
39
40 private HashMapMap<Class, WorldObjectId, IViewable> worldVisibleObjects =
41 new HashMapMap<Class, WorldObjectId, IViewable>();
42
43
44
45
46 private Map<Class, Map<WorldObjectId, IViewable>> syncWorldVisibleObjects =
47 Collections.synchronizedMap(worldVisibleObjects);
48
49
50
51
52 private Map<WorldObjectId, IViewable> visibleObjects =
53 Collections.synchronizedMap(new HashMap<WorldObjectId, IViewable>());
54
55 public VisionWorldView(@Named(WORLDVIEW_DEPENDENCY) ComponentDependencies dependencies, IComponentBus bus, IAgentLogger log) {
56 super(dependencies, bus, log);
57 }
58
59 @Override
60 protected void cleanUp() {
61 super.cleanUp();
62 synchronized(worldVisibleObjects) {
63 worldVisibleObjects.clear();
64 }
65 synchronized(visibleObjects) {
66 visibleObjects.clear();
67 }
68 synchronized(notifyEventsList) {
69 notifyEventsList.clear();
70 }
71 }
72
73 @Override
74 public Map<Class, Map<WorldObjectId, IViewable>> getAllVisible() {
75 return syncWorldVisibleObjects;
76 }
77
78 @SuppressWarnings("unchecked")
79 @Override
80 public <T extends IViewable> Map<WorldObjectId, T> getAllVisible(Class<T> type) {
81 return (Map<WorldObjectId, T>) syncWorldVisibleObjects.get(type);
82 }
83
84 @Override
85 public Map<WorldObjectId, IViewable> getVisible() {
86 return visibleObjects;
87 }
88
89 @Override
90 public IViewable getVisible(WorldObjectId id) {
91 return visibleObjects.get(id);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 protected synchronized void addVisibleObject(IViewable worldObject) {
108 visibleObjects.put(worldObject.getId(), worldObject);
109 for (Class cls : ClassUtils.getSubclasses(worldObject.getClass())) {
110 syncWorldVisibleObjects.get(cls).put(worldObject.getId(), worldObject);
111 }
112 }
113
114
115
116
117
118
119
120
121 protected synchronized void removeVisibleObject(IViewable worldObject) {
122 visibleObjects.remove(worldObject.getId());
123 for (Class<?> cls : ClassUtils.getSubclasses(worldObject.getClass())) {
124 syncWorldVisibleObjects.get(cls).remove(worldObject.getId());
125 }
126 }
127
128
129
130
131
132
133
134
135
136
137
138 @Override
139 protected void objectUpdatedEvent(IWorldObjectUpdatedEvent updateEvent) {
140 if (updateEvent == null) {
141 log.warning("Could not process object update, as its ID is null: " + updateEvent);
142 return;
143 }
144
145 IWorldObject obj = get(updateEvent.getId());
146
147 boolean wasVisible = obj != null && obj instanceof IViewable && ((IViewable)obj).isVisible();
148
149 IWorldObjectUpdateResult updateResult = updateEvent.update(obj);
150
151 if (updateResult == null) {
152 throw new PogamutException("Update result is null (updateEvent.update(obj) == null)! Cannot update object of ID " + updateEvent.getId() + "!", this);
153 }
154
155 switch (updateResult.getResult()) {
156 case CREATED:
157 objectCreated(updateResult.getObject());
158 return;
159 case UPDATED:
160 if (updateResult.getObject() != obj) {
161 throw new PogamutException("Update event " + updateEvent + " does not returned the same instance of the object (result UPDATED).", this);
162 }
163 if (obj instanceof IViewable) {
164 boolean isVisible = ((IViewable)obj).isVisible();
165 if (wasVisible) {
166 objectUpdated(obj);
167 if (!isVisible) {
168 objectDisappeared((IViewable) obj);
169 }
170 } else {
171 if (isVisible) {
172 objectAppeared((IViewable) obj);
173 }
174 objectUpdated(obj);
175 }
176 } else {
177 objectUpdated(obj);
178 }
179
180 return;
181 case SAME:
182 return;
183 case DESTROYED:
184 objectDestroyed(obj);
185 return;
186 default:
187 throw new PogamutException("Unhandled object update result " + updateResult.getResult() + " for the object " + obj + ".", this);
188 }
189 }
190
191
192
193
194 @Override
195 protected void objectCreated(IWorldObject obj) {
196 addWorldObject(obj);
197 raiseEvent(new WorldObjectFirstEncounteredEvent<IWorldObject>(obj, obj.getSimTime()));
198 if (obj instanceof IViewable) {
199 IViewable viewable = (IViewable)obj;
200 if (viewable.isVisible()) {
201 objectAppeared(viewable);
202 }
203 }
204 objectUpdated(obj);
205 }
206
207
208
209
210
211 protected void objectAppeared(IViewable obj) {
212 addVisibleObject(obj);
213 raiseEvent(new WorldObjectAppearedEvent<IViewable>(obj, obj.getSimTime()));
214 }
215
216
217
218
219
220 protected void objectDisappeared(IViewable obj) {
221 removeVisibleObject(obj);
222 raiseEvent(new WorldObjectDisappearedEvent<IViewable>(obj, obj.getSimTime()));
223 }
224
225
226
227
228
229
230
231 protected void objectDestroyed(IWorldObject obj) {
232 if (obj instanceof IViewable) {
233 IViewable viewable = (IViewable)obj;
234 if (viewable.isVisible()) {
235 objectDisappeared(viewable);
236 }
237 }
238 removeWorldObject(obj);
239 raiseEvent(new WorldObjectDestroyedEvent<IWorldObject>(obj, obj.getSimTime()));
240 }
241
242
243 }