1 package cz.cuni.amis.pogamut.base.communication.worldview;
2
3 import java.util.Map;
4
5 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEvent;
6 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
7 import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.AnnotationListenerRegistrator;
8 import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.EventListener;
9 import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectClassEventListener;
10 import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectClassListener;
11 import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectEventListener;
12 import cz.cuni.amis.pogamut.base.communication.worldview.listener.annotation.ObjectListener;
13 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
14 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
15 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
16 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectListener;
17 import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
18 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectDestroyedEvent;
19 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
20 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
21 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
22 import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectAppearedEvent;
23 import cz.cuni.amis.pogamut.base3d.worldview.object.event.WorldObjectDisappearedEvent;
24
25 /**
26 * Interface for the world view.
27 * <p><p>
28 * It assumes that each world description consists of two entites:
29 * <ol>
30 * <li>actual events described by ({@link IWorldEvent})</li>
31 * <li>existing objects described by ({@link IWorldObject})</li>
32 * </ol>
33 * The world view is designed to accept {@link IWorldEvent} and {@link IWorldObjectEvent} which describes
34 * the changes in the world. User of the world view is allowed to set up listeners for various events as well as objects.
35 * <p>
36 * Therefore there are two types of listeners:
37 * <ol>
38 * <li>{@link IWorldEventListener} - we will refer to them as 'event' listeners</li>
39 * <li>{@link IWorldObjectEventListener} - we will refer to them as 'object' listeners<br/>
40 * note that there are also a descendant {@link IWorldObjectListener} that is easier to use.</li>
41 * </ol>
42 * Generally, the world view provides 5 methods user may use to hook up the listener of a various level of specificity.
43 * <p><p>
44 * <ul>
45 * <li>
46 * <b>Level A listeners ({@link IWorldView#addEventListener(Class, IWorldEventListener)}):</b> Primarily - these listeners can be hooked up according to the event class, for instance there is {@link WorldObjectAppearedEvent} that
47 * implements IWorldObjectEvent. Therefore, if you want to be notified about every object that appears in the
48 * field of view of the agent, you should register an implementor of {@link IWorldObjectEventListener} to the class {@link WorldObjectAppearedEvent}.class.
49 * <p><p>
50 * The motivation here is, that the class of event is unique identifier of the event and therefore it may serve
51 * as identification for listener registration.
52 * <p><p>
53 * Also notice that {@link IWorldObjectEvent} is extending {@link IWorldEvent} (of course!), therefore by registering a listener to {@link IWorldEvent}.class
54 * will allow you to sniff every events that will happen in the world (or generated by the world view).
55 * </li>
56 * </ul>
57 * <p><p>
58 * Furthermore - there are {@link IWorldObjectEventListener}s that can be registered to receive only events that are happening on some
59 * {@link IWorldObject}. These are:
60 * <ul>
61 * <li><b>Level B listeners ({@link IWorldView#addObjectListener(Class, IWorldObjectListener)}):</b> listen to all events on a specific class of objects by specifying the class (this is different from the class of the event because
62 * this time we're querying class of the object not the class of the event)</li>
63 * <li><b>Level C listeners ({@link IWorldView#addObjectListener(Class, Class, IWorldObjectListener)}):</b> listen to specific event on specific class of objects</li>
64 * <li><b>Level D listeners ({@link IWorldView#addObjectListener(WorldObjectId, IWorldObjectListener)}):</b> listen to all events on specific object via specifying its object id</li>
65 * <li><b>Level E listeners ({@link IWorldView#addObjectListener(WorldObjectId, Class, IWorldObjectListener)}):</b> listen to a specific event on the specific object (via object id)</li>
66 * </ul>
67 * <p>
68 * The listener notifying scheme follows the rule from "general" listeners
69 * to "specific" listeners. The listeners are invoked in this order:
70 * <ol>
71 * <li>Level A listeners ({@link EventListener})</li>
72 * <li>Level B listeners ({@link ObjectClassListener})</li>
73 * <li>Level C listeners ({@link ObjectClassEventListener})</li>
74 * <li>Level D listeners ({@link ObjectListener})</li>
75 * <li>Level E listeners ({@link ObjectEventListener})</li>
76 * </ol>
77 * <p><p>
78 * When you need to listen on various events, use method annotations (see the links in the list) and {@link AnnotationListenerRegistrator}
79 * to automatically hook up listeners for you - note that the {@link AnnotationListenerRegistrator} are currently not supporting inheritance.
80 *
81 * @author Jimmy
82 */
83 public interface IWorldView extends IWorldChangeEventInput {
84
85 // =========
86 // COMPONENT
87 // =========
88
89 public IComponentBus getEventBus();
90
91 // ======
92 // EVENTS
93 // ======
94
95 /**
96 * Adds listener to a specific event (Level A listeners). Note that the event listener must be able
97 * to handle events of the class 'event'.
98 * <p><p>
99 * It is the most general type of listener-registration allowing you to sniff any type of events.
100 * <p><p>
101 * Events passed to the listener are filtered only according to the 'event' class.
102 * <p><p>
103 * <b>WARNING:</b> even though the method does not require templated class and listener, you must be sure
104 * that 'listener' can accept 'eventClass'.
105 *
106 * @param eventClass which event types you want to receive
107 * @param listener where you want to handle these events
108 */
109 public void addEventListener(Class<?> eventClass, IWorldEventListener<?> listener);
110
111 /**
112 * Adds listener to all events that happens on any object of the 'objectClass' (Level B listeners).
113 * <p><p>
114 * Events passed to the listener are filtered according to the 'objectClass'.
115 * <p><p>
116 * <b>WARNING:</b> even though the method does not require templated classes and listener, you must be sure
117 * that 'listener' accepts all events (IWorldObjectEvent) for objects of 'objectClass'.
118 *
119 * @param objectClass which object class you want to listen at
120 * @param eventClass which event class you want to receive
121 * @param listener where you want to handle these events
122 */
123 public void addObjectListener(Class<?> objectClass, IWorldObjectEventListener<?, ?> listener);
124
125 /**
126 * Adds listener to a specified 'event' that occurs on the specific 'objectClass' (Level C listeners).
127 * <p><p>
128 * Events passed to the listener are filtered according to the 'event' and 'objectClass' of the object the event happened upon.
129 * <p><p>
130 * <b>WARNING:</b> even though the method does not require templated classes and listener, you must be sure
131 * that 'listener' accepts 'eventClass' for objects of 'objectClass'.
132 *
133 * <p>
134 * eventClass can be any implementor of {@link IWorldObjectEvent}. E.g.
135 * {@link WorldObjectAppearedEvent}, {@link WorldObjectDestroyedEvent}, {@link WorldObjectDisappearedEvent},
136 * {@link WorldObjectFirstEncounteredEvent} or {@link WorldObjectUpdatedEvent}.
137 * </p>
138 *
139 * @param objectClass which object class you want to listen at
140 * @param eventClass which event class you want to receive
141 * @param listener where you want to handle these events
142 */
143 public void addObjectListener(Class<?> objectClass, Class<?> eventClass, IWorldObjectEventListener<?,?> listener);
144
145 /**
146 * Adds listener to all events that happens on object with specific 'objectId' (Level D listeners).
147 * <p><p>
148 * Events passed to the listener are filtered according to the 'objectId' of the object.
149 * <p><p>
150 * <b>WARNING:</b> you must ensure that 'listener' can accept the event raised on object of specified 'objectId'.
151 *
152 * @param objectId which object you want to listen at
153 * @param listener where you want to handle events
154 */
155 public void addObjectListener(WorldObjectId objectId, IWorldObjectEventListener<?, ?> listener);
156
157 /**
158 * Adds listener to a specified 'event' that occurs on the specific object with 'objectId' (Level E listeners).
159 * <p><p>
160 * Events passed to the listener are filtered according to the 'event' and 'objectId' of the object.
161 * <p><p>
162 * <b>WARNING:</b> even though the method does not require templated classes and listener, you must be sure
163 * that 'listener' accepts 'eventClass' for objects of specified 'objectId'.
164 *
165 * @param objectId which object you want to listen at
166 * @param eventClass which event classes you want to receive
167 * @param listener where you want to handle these events
168 */
169 public void addObjectListener(WorldObjectId objectId, Class<?> eventClass, IWorldObjectEventListener<?, ?> listener);
170
171 /**
172 * Removes listener from a specific event (Level A listeners).
173 *
174 * @param eventClass which events class you want to remove the listener from
175 * @param listener you want to remove
176 */
177 public void removeEventListener(Class<?> eventClass, IWorldEventListener<?> listener);
178
179 /**
180 * Removes listener from specific 'objectClass' listening for specified 'event' (Level B listeners).
181 *
182 * @param objectClass class of objects you want the listener to remove from
183 * @param eventClass which events class you want to remove the listener from
184 * @param listener you want to remove
185 */
186 public void removeObjectListener(Class<?> objectClass, IWorldObjectEventListener<?,?> listener);
187
188 /**
189 * Removes listener from specific 'objectClass' listening for specified 'event' (Level C listeners).
190 *
191 * @param objectClass class of objects you want the listener to remove from
192 * @param eventClass which events class you want to remove the listener from
193 * @param listener you want to remove
194 */
195 public void removeObjectListener(Class<?> objectClass, Class<?> eventClass, IWorldObjectEventListener<?,?> listener);
196
197
198 /**
199 * Removes listener from objects with specified 'objectId' (Level D Listeners).
200 *
201 * @param objectId id of object you want the listener to remove from
202 * @param listener you want to remove
203 */
204 public void removeObjectListener(WorldObjectId objectId, IWorldObjectEventListener<?, ?> listener);
205
206 /**
207 * Removes listener to a specified 'event' that occurs on the specific object with 'objectId' (Level E listeners).
208 *
209 * @param objectId id of object you want the listener to remove from
210 * @param eventClass event class you want to stop receiving in the listener
211 * @param listener you want to remove
212 */
213 public void removeObjectListener(WorldObjectId objectId, Class<?> eventClass, IWorldObjectEventListener<?, ?> listener);
214
215 /**
216 * Removes listener from every listeners category (from every listener level).
217 * <p><p>
218 * <b>WARNING:</b> Can be time consuming! (Iterating through all levels of listeners.)
219 *
220 * @param listener you want to remove from all listener levels
221 */
222 public void removeListener(IWorldEventListener<?> listener);
223
224 /**
225 * Tests whether the 'listener' is listening to a specific event (Level A listeners).
226 *
227 * @param eventClass which events you want to receive
228 * @param listener that is tested
229 * @return whether the listener is listening
230 */
231 public boolean isListening(Class<?> eventClass, IWorldEventListener<?> listener);
232
233 /**
234 * Tests whether the 'listener' is listening at specified 'objectClass' (Level B listeners).
235 *
236 * @param objectClass where the listener is tested
237 * @param listener that is tested
238 * @return whether the listener is listening
239 */
240 public boolean isListening(Class<?> objectClass, IWorldObjectEventListener<?,?> listener);
241
242 /**
243 * Tests whether the 'listener' is listening at specified 'objectClass' for specified 'event' (Level C listeners).
244 *
245 * @param objectClass where the listener is tested
246 * @param eventClass where the listener is tested
247 * @param listener that is tested
248 * @return whether the listener is listening
249 */
250 public boolean isListening(Class<?> objectClass, Class<?> eventClass, IWorldObjectEventListener<?,?> listener);
251
252
253 /**
254 * Tests whether the 'listener' is listening at specified 'objectId' (Level D Listeners).
255 *
256 * @param objectId where the listener is tested
257 * @param listener that is tested
258 * @return whether the listener is listening
259 */
260 public boolean isListening(WorldObjectId objectId, IWorldObjectEventListener<?, ?> listener);
261
262 /**
263 * Tests whether the 'listener' is listening to a specified 'event' that occurs on the specific object with 'objectId' (Level E listeners).
264 *
265 * @param objectId where the listener is tested
266 * @param eventClass what class is tested
267 * @param listener that is tested
268 * @return whether the listener is listening
269 */
270 public boolean isListening(WorldObjectId objectId, Class<?> eventClass, IWorldObjectEventListener<?, ?> listener);
271
272 /**
273 * Checks whether this listener is hooked to the world view (at any listener level).
274 * <p><p>
275 * <b>WARNING:</b> Can be time consuming! (Iterating through all levels of listeners.)
276 *
277 * @param listener
278 * @return
279 */
280 public boolean isListening(IWorldEventListener<?> listener);
281
282 // =======
283 // OBJECTS
284 // =======
285
286 /**
287 * Returns map of all objects that are present in the world view.
288 * <p><p>
289 * <b>WARNING:</b> If you will do iteration over the map, you must synchronize on it.
290 */
291 @SuppressWarnings("unchecked")
292 public Map<Class, Map<WorldObjectId, IWorldObject>> getAll();
293
294 /**
295 * Returns map of all objects of a specific type that are present in the world view.
296 * <p><p>
297 * <b>WARNING:</b> If you will do iteration over the map, you must synchronize on it.
298 *
299 * @param type
300 * @return
301 */
302 public <T extends IWorldObject> Map<WorldObjectId, T> getAll(Class<T> type);
303
304 /**
305 * Returns the only instance of required object if present, if there are
306 * more instances of this object then {@link IllegalArgumentException} will be thrown.
307 * <p><p>
308 * Should be used to obtain "utility" world objects such us "informations about the agent" (that
309 * is unique for the agent and as the world view should be used by only one agent...) or some
310 * "world statistics object".
311 *
312 * @param <T>
313 * @param cls Class of object to be retrieved
314 * @return the only object of given class
315 */
316 public <T extends IWorldObject> T getSingle(Class<T> cls);
317
318 /**
319 * Returns map with objects inserted according to their id.
320 * <p><p>
321 * <b>WARNING:</b> If you will do iteration over the map, you must synchronize on it.
322 * <p><p>
323 * Note that this map contains various objects, therefore you will somehow guess the correct class of the object
324 * from its id.
325 *
326 * @return
327 */
328 public Map<WorldObjectId,IWorldObject> get();
329
330 /**
331 * Returns a world object of the specific id (if exists inside the world view). Otherwise, null is returned.
332 * <p><p>
333 * Note that there is no way to tell the correct type of returned object - you have to cast it to a correct class
334 * yourself.
335 *
336 * @param id objects's id
337 * @return
338 */
339 public IWorldObject get(WorldObjectId id);
340
341 /**
342 * Returns a world object of the specific id and class (if exists inside the world view). Otherwise, null is returned.
343 * <p><p>
344 *
345 * @param id objects's id
346 * @param clazz the class of the object to be returned
347 * @return the object or null if not found
348 * @throws ClassCastException if the object with specified id exists, but is not of specified type
349 */
350 public <T extends IWorldObject> T get(WorldObjectId id, Class<T> clazz);
351
352 }