View Javadoc

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 }