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 IWorldObject obj = get(updateEvent.getId());
141
142 boolean wasVisible = obj != null && obj instanceof IViewable && ((IViewable)obj).isVisible();
143
144 IWorldObjectUpdateResult updateResult = updateEvent.update(obj);
145
146 if (updateResult == null) {
147 throw new PogamutException("Update result is null (updateEvent.update(obj) == null)! Cannot update object of ID " + updateEvent.getId() + "!", this);
148 }
149
150 switch (updateResult.getResult()) {
151 case CREATED:
152 objectCreated(updateResult.getObject());
153 return;
154 case UPDATED:
155 if (updateResult.getObject() != obj) {
156 throw new PogamutException("Update event " + updateEvent + " does not returned the same instance of the object (result UPDATED).", this);
157 }
158 if (obj instanceof IViewable) {
159 boolean isVisible = ((IViewable)obj).isVisible();
160 if (wasVisible) {
161 objectUpdated(obj);
162 if (!isVisible) {
163 objectDisappeared((IViewable) obj);
164 }
165 } else {
166 if (isVisible) {
167 objectAppeared((IViewable) obj);
168 }
169 objectUpdated(obj);
170 }
171 } else {
172 objectUpdated(obj);
173 }
174
175 return;
176 case SAME:
177 return;
178 case DESTROYED:
179 objectDestroyed(obj);
180 return;
181 default:
182 throw new PogamutException("Unhandled object update result " + updateResult.getResult() + " for the object " + obj + ".", this);
183 }
184 }
185
186
187
188
189 @Override
190 protected void objectCreated(IWorldObject obj) {
191 addWorldObject(obj);
192 raiseEvent(new WorldObjectFirstEncounteredEvent<IWorldObject>(obj, obj.getSimTime()));
193 if (obj instanceof IViewable) {
194 IViewable viewable = (IViewable)obj;
195 if (viewable.isVisible()) {
196 objectAppeared(viewable);
197 }
198 }
199 objectUpdated(obj);
200 }
201
202
203
204
205
206 protected void objectAppeared(IViewable obj) {
207 addVisibleObject(obj);
208 raiseEvent(new WorldObjectAppearedEvent<IViewable>(obj, obj.getSimTime()));
209 }
210
211
212
213
214
215 protected void objectDisappeared(IViewable obj) {
216 removeVisibleObject(obj);
217 raiseEvent(new WorldObjectDisappearedEvent<IViewable>(obj, obj.getSimTime()));
218 }
219
220
221
222
223
224
225
226 protected void objectDestroyed(IWorldObject obj) {
227 if (obj instanceof IViewable) {
228 IViewable viewable = (IViewable)obj;
229 if (viewable.isVisible()) {
230 objectDisappeared(viewable);
231 }
232 }
233 removeWorldObject(obj);
234 raiseEvent(new WorldObjectDestroyedEvent<IWorldObject>(obj, obj.getSimTime()));
235 }
236
237
238 }