View Javadoc

1   
2   package cz.cuni.amis.pogamut.base.agent.navigation.impl;
3   
4   import java.util.List;
5   import java.util.logging.Level;
6   import java.util.logging.Logger;
7   
8   import cz.cuni.amis.pogamut.base.agent.navigation.IPathExecutor;
9   import cz.cuni.amis.pogamut.base.agent.navigation.IPathExecutorHelper;
10  import cz.cuni.amis.pogamut.base.agent.navigation.IPathExecutorState;
11  import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
12  import cz.cuni.amis.pogamut.base.agent.navigation.IStuckDetector;
13  import cz.cuni.amis.pogamut.base.agent.navigation.PathExecutorState;
14  import cz.cuni.amis.utils.exception.PogamutException;
15  import cz.cuni.amis.utils.future.FutureStatus;
16  import cz.cuni.amis.utils.future.FutureWithListeners;
17  import cz.cuni.amis.utils.future.IFutureListener;
18  
19  /**
20   * BasePathExecutor provides a stub implementation of abstract methods of the {@link AbstractPathExecutor} 
21   * which correctly sets the path executor states along the way and provide methods for reporting failures.
22   * <p><p>
23   * Note that it is somewhat hard to use this stub-implementation as the base for implementing 
24   * your own {@link IPathExecutor} implementation - the {@link AbstractPathExecutor} might be more suitable.
25   * That's because this implementation is defining a way how its fields are used, how methods should be synchronized,
26   * how they are called (method protocol), etc.
27   * <p><p>
28   * Implementation notes:
29   * <ul>
30   *   <li>
31   *     As the {@link IPathExecutorState} may have different implementation providing different kind of the information
32   *     about the path - {@link BasePathExecutor} defines {@link BasePathExecutor#createState(PathExecutorState)} as a hook
33   *     for custom {@link IPathExecutorState} implementation (currently it uses simple {@link BasePathExecutorState}). 
34   *   </li>
35   *   <li>
36   *     Many methods here are made final - this might seem to block your inventions, but it is actually for your own good.
37   *     If you find yourself in need to override some method that is made final, it is advised that you switch to {@link AbstractPathExecutor}
38   *     or copy-paste the {@link BasePathExecutor} code and do your changes in copied code.
39   *   </li>
40   *   <li>
41   *     There are several important final methods that drive the {@link BasePathExecutor}.
42   *     <ul>
43   *       <li>{@link BasePathExecutor#followPath(IPathFuture)} - interface public method / meant to be called from the outside - begin following the path / handles path future listener</li>
44   *       <li>{@link BasePathExecutor#pathComputed()} - protected method / it is automatically called by the {@link BasePathExecutor} whenever the path future returns the path</li>
45   *       <li>{@link BasePathExecutor#pathComputationFailed()} - protected method / it is automatically called by the {@link BasePathExecutor} whenever path future reports {@link FutureStatus#CANCELED} or {@link FutureStatus#COMPUTATION_EXCEPTION}.
46   *       <li>{@link BasePathExecutor#switchToAnotherPathElement(int)} - protected method / meant to be called from within the path executor (descendant) whenever the executor should start to navigate towards another path element</li>
47   *       <li>{@link BasePathExecutor#stuck(IStuckDetector)} - protected method / automatically called by {@link BasePathExecutor#executePath()} whenever one of the {@link AbstractPathExecutor#stuckDetectors} reports stuck</li>
48   *       <li>{@link BasePathExecutor#stop()} - interface public method / meant to be called both from the outside or from the inside of path executor / stops the path executor</li>
49   *     </ul>	
50   *   </li>
51   *   <li>
52   *   	Important final methods from the previous paragraph are usually split into three parts
53   *   	<ol>
54   *   	  <li>their actual implementation that can't be overridden, it (usually) changes the state of the path executor and recalls pre/post methods</li>
55   *   	  <li>pre-phase method that is called (from within the method's implementation) just before the state of the executor is changed</li>
56   *   	  <li>post-phase method that is called (from within the method's implementation) just after the state of the executor is changed</li> 
57   *   	</ol>
58   *   	Pre/Post-phase methods are usually abstract (if not, they contain meaningful implementation but that can be overriden if wished for) and are meant to be implemented in descendants. 
59   *      They allow you to fine control the state of the executor before and after the change of its state without the need to program boring part of the code that changes the state in a correct way. 
60   *      Think of implementing the descendant of this class as implementing reactions to the changes of executor's state.
61   *   </li>
62   *   <li>
63   *   	Additionally, there are methods that are not called from anywhere of {@link BasePathExecutor}. These are:
64   *      <ul>
65   *        <li>{@link BasePathExecutor#switchToAnotherPathElement(int)} - this method should be called either from {@link BasePathExecutor#prePathComputedImpl()} or {@link BasePathExecutor#pathComputed()} to mark
66   *            the index of the path element that is going to be pursued first (this index will likely be '0').</li>
67   *        <li>{@link BasePathExecutor#stuck(IStuckDetector)} - use this method to report that the stuck has been detected</li>
68   *        <li>{@link BasePathExecutor#checkStuckDetectors()}    
69   *      </ul>
70   *   </li>
71   *   <li>
72   *   	It is up to the descendant how the path execution will be actually implemented (either by some event-driven model, i.e.,
73   *      reacting on the events that will come from the environment, or spawning some thread that will regularly perform some operation, etc.).
74   *   </li>
75   * </ul>
76   * 
77   * @author Jimmy
78   */
79  public abstract class BasePathExecutor<PATH_ELEMENT> extends AbstractPathExecutor<PATH_ELEMENT> implements IPathExecutorHelper<PATH_ELEMENT> {
80  
81  	/**
82  	 * Mutex object synchronizing access to {@link BasePathExecutor#followPath(IPathFuture)} and
83  	 * {@link BasePathExecutor#stop()} methods.
84  	 */
85  	protected Object mutex = new Object();
86  	
87  	/**
88  	 * Current path future of the path executor. Path future is set in {@link BasePathExecutor#followPath(IPathFuture)}
89  	 * and removed (set to 'null') in {@link BasePathExecutor#stop()}.
90  	 */
91  	protected IPathFuture<PATH_ELEMENT> pathFuture = null;
92  	
93  	/**
94  	 * Marks the index of the previous path element (path element that has been previously pursued) 
95  	 * from the path element list of {@link BasePathExecutor#getPath()}.
96  	 * <p><p>
97  	 * Setting value to this field manually must be done only inside {@link BasePathExecutor#preSwitchToAnotherPathElementImpl(int)}
98  	 * and {@link BasePathExecutor#switchToAnotherPathElementImpl()}.
99  	 */
100 	protected int previousPathElementIndex = -1;
101 	
102 	/**
103 	 * Marks the index of the current path element (path element that is currently pursued) 
104 	 * from the path element list of {@link BasePathExecutor#getPath()}.
105 	 * <p><p>
106 	 * Setting value to this field manually must be done only inside {@link BasePathExecutor#preSwitchToAnotherPathElementImpl(int)}
107 	 * and {@link BasePathExecutor#switchToAnotherPathElementImpl()}.
108 	 */
109 	protected int pathElementIndex = -1;
110 	
111 	/**
112 	 * {@link BasePathExecutor#pathFuture} listener that recalls methods {@link BasePathExecutor#pathComputed()}
113 	 * or {@link BasePathExecutor#pathComputationFailed()} based upon the change of the future status. Note that
114 	 * the listener recalls these methods only if the event comes from the {@link BasePathExecutor#pathFuture} to prevent
115 	 * wrong invocations. 
116 	 * <p><p>
117 	 * If you wish to use different implementation of the {@link IFutureListener}, reinstantiate this field
118 	 * in the constructor of your own descendant.
119 	 */
120 	IFutureListener<List<PATH_ELEMENT>> pathFutureListener = new IFutureListener<List<PATH_ELEMENT>>() {
121 		
122 		@Override
123 		public void futureEvent(FutureWithListeners<List<PATH_ELEMENT>> source, FutureStatus oldStatus, FutureStatus newStatus) {
124 			synchronized(mutex) {
125 				source.removeFutureListener(this);
126 				if (pathFuture != source) {
127 					// we've been called from the future that is not being used by the executor
128 					return;
129 				}
130 				switch(newStatus) {
131 				case FUTURE_IS_READY:
132 					pathComputed();
133 					return;
134 				case COMPUTATION_EXCEPTION:
135 				case CANCELED:
136 					pathComputationFailed();
137 					return;
138 				case FUTURE_IS_BEING_COMPUTED:
139 					throw new RuntimeException("FutureWithListeners can't change its state to FUTURE_IS_BEING_COMPUTED.");
140 				}
141 			}
142 		}	
143 		
144 	};
145 	
146 	public BasePathExecutor() {
147 		this(null);
148 	}
149 	
150 	public BasePathExecutor(Logger log) {
151 		this.log = log;
152 	}
153 
154 //	@Override
155 	@Override
156 	public int getPathElementIndex() {
157 		return pathElementIndex;
158 	}
159 	
160 	@Override
161 	public IPathFuture<PATH_ELEMENT> getPathFuture() {
162 		return pathFuture;
163 	}
164 	
165 	@Override
166 	public PATH_ELEMENT getPathFrom() {
167 		return getPathFuture().getPathFrom();
168 	}
169 	
170 	@Override
171 	public PATH_ELEMENT getPathTo() {
172 		return getPathFuture().getPathTo();
173 	}
174 
175 	
176 	/**
177 	 * Utility method that is responsible for creating new state for the path executor. You may override this method
178 	 * to fine-control which implementations {@link IPathExecutorState} are instantiated.
179 	 * <p><p>
180 	 * This method allows you to provide own {@link IPathExecutorState} implementation that may carry additional
181 	 * information about the executor's state.
182 	 *  
183 	 * @param state
184 	 * @return
185 	 */
186 	protected IPathExecutorState createState(PathExecutorState state) {
187 		switch(state) {
188 		case SWITCHED_TO_ANOTHER_PATH_ELEMENT: return new BasePathExecutorState(PathExecutorState.SWITCHED_TO_ANOTHER_PATH_ELEMENT);
189 		default: return BasePathExecutorState.getState(state);
190 		}
191 	}
192 	
193 	// ---
194 	// =====
195 	// followPath()
196 	// =====
197 	// ---
198 	
199 	/**
200 	 * Tell the executor to start navigating the agent along the 'path'.
201 	 * <p><p>
202 	 * If called and the {@link BasePathExecutor#isExecuting()}, it first calls {@link BasePathExecutor#stop()}.
203 	 * <p><p>
204 	 * For more info see {@link AbstractPathExecutor#followPath(IPathFuture)}
205 	 * 
206 	 * @param path path to navigate along
207 	 */
208 	@Override
209 	public final void followPath(IPathFuture<? extends PATH_ELEMENT> path) {
210 		synchronized(mutex) {
211 			if (isExecuting()) {
212 				stop();			
213 			}
214 			if (log != null && log.isLoggable(Level.INFO)) log.info("followPath called, destination " + path.getPathTo());			
215 			pathFuture = (IPathFuture<PATH_ELEMENT>) path;
216 			preFollowPathImpl();
217 			switchState(createState(PathExecutorState.FOLLOW_PATH_CALLED));
218 			followPathImpl();
219 			if (path == null) {
220 				pathComputationFailed();
221 				return;
222 			}
223 			switch(path.getStatus()) {
224 			case COMPUTATION_EXCEPTION:
225 			case CANCELED:
226 				pathComputationFailed();
227 				return;
228 			case FUTURE_IS_READY:
229 				if (getPath() == null) {
230 					pathComputationFailed();
231 				} else {
232 					pathComputed();
233 				}
234 				return;
235 			case FUTURE_IS_BEING_COMPUTED:
236 				pathFuture.addFutureListener(pathFutureListener);
237 				break;
238 			default:
239 				throw new RuntimeException("Unhandled path future status '" + path.getStatus() + "'.");
240 			}
241 			// if we get here, we've add a future listener to 'pathFuture'
242 			// but what if the path future status has changed before we have attached the listener?
243 			// ... check it again :-)
244 			switch(path.getStatus()) {
245 			case COMPUTATION_EXCEPTION:
246 			case CANCELED:
247 				pathComputationFailed();
248 				return;
249 			case FUTURE_IS_READY:
250 				pathComputed();
251 				return;
252 			case FUTURE_IS_BEING_COMPUTED:
253 				return;
254 			default:
255 				throw new RuntimeException("Unhandled path future status '" + path.getStatus() + "'.");
256 			}
257 		}
258 	}
259 	
260 	/**
261 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#FOLLOW_PATH_CALLED} from within
262 	 * the {@link BasePathExecutor#followPath(IPathFuture)} method.
263 	 * <p><p>
264 	 * You may utilize this methods this way:
265 	 * <ul>
266 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
267 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
268 	 * </ul>
269 	 * <p>
270 	 * Current implementation ensures that the state of the path executor is cleared.
271 	 */
272 	protected void preFollowPathImpl() {	
273 		// ensure that the previous state is cleared
274 		previousPathElementIndex = -1;
275 		pathElementIndex = -1;
276 	}
277 
278 	/**
279 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#FOLLOW_PATH_CALLED} from
280 	 * within the {@link BasePathExecutor#followPath(IPathFuture)} method.
281 	 * <p><p>
282 	 * You may utilize this method this way:
283 	 * <ul>
284 	 *   <li>Examine the state of the executor / values produced by executor state listeners.</li>
285 	 * </ul> 
286 	 */
287 	protected abstract void followPathImpl();
288 	
289 	// ---
290 	// =====
291 	// pathComputed()
292 	// =====
293 	// ---
294 	
295 	/**
296 	 * Path has been computed and is available in {@link BasePathExecutor#pathFuture}. This method is automatically called
297 	 * from the {@link BasePathExecutor#followPath(IPathFuture)} or by {@link BasePathExecutor#pathFutureListener} whenever
298 	 * the path is ready. 
299 	 * <p><p>
300 	 * Effective only if the state is: {@link PathExecutorState#FOLLOW_PATH_CALLED}
301 	 */
302 	protected final void pathComputed() {
303 		synchronized(mutex) {
304 			if (notInState(PathExecutorState.FOLLOW_PATH_CALLED)) return;
305 			if (log != null && log.isLoggable(Level.FINE)) log.fine("path computed, size == " + getPath().size());
306 			pathFuture.removeFutureListener(pathFutureListener);			
307 			prePathComputedImpl();
308 			switchState(createState(PathExecutorState.PATH_COMPUTED));
309 			if (inState(PathExecutorState.PATH_COMPUTED)) {
310 				pathComputedImpl();
311 			}
312 		}
313 	}
314 	
315 	/**
316 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#PATH_COMPUTED} from within
317 	 * the {@link BasePathExecutor#pathComputed()} method. Note that since this method is called, the path can be simply 
318 	 * obtained by calling {@link BasePathExecutor#getPath()}.
319 	 * <p><p>
320 	 * You may utilize this method (for instance) to:
321 	 * <ul>
322 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
323 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
324 	 * </ul>
325 	 * <p>
326 	 * Note that you should call {@link BasePathExecutor#switchToAnotherPathElement(int)} (to mark the index of the first path element)
327 	 * in this method or in {@link BasePathExecutor#pathComputedImpl()}. The first path element index will likely be '0'.
328 	 * <p><p>
329 	 * Resets and enables all {@link AbstractPathExecutor#stuckDetectors}.
330 	 */
331 	protected void prePathComputedImpl() {
332 		for (IStuckDetector detector : stuckDetectors) {
333 			detector.reset();
334 			detector.setEnabled(true);
335 		}
336 	}
337 	
338 	/**
339 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#PATH_COMPUTED} from
340 	 * within the {@link BasePathExecutor#pathComputed()} method. Note that the path can be simply obtained
341 	 * by calling {@link BasePathExecutor#getPath()}.
342 	 * <p><p>
343 	 * You may utilize this method (for instance) to:
344 	 * <ul>
345 	 *   <li>Examine the state of the executor / values produced by executor state listeners.</li>
346 	 * </ul> 
347 	 * <p>
348 	 * Note that you should call {@link BasePathExecutor#switchToAnotherPathElement(int)} (to mark the index of the first path element)
349 	 * in this method or in {@link BasePathExecutor#prePathComputedImpl()}. The first path element index will likely be '0'.
350 	 */
351 	protected abstract void pathComputedImpl();
352 	
353 	// ---
354 	// =====
355 	// pathComputationFailed()
356 	// =====
357 	// ---
358 	
359 	/**
360 	 * Path computation has failed, path is unavailable and the executor can't start navigate the agent through the environment.
361 	 * This method is automatically called
362 	 * from the {@link BasePathExecutor#followPath(IPathFuture)} or by {@link BasePathExecutor#pathFutureListener} whenever
363 	 * it is found out that the path can never be obtained from the {@link BasePathExecutor#pathFuture}.
364 	 * <p><p>
365 	 * Effective only if the state is: {@link PathExecutorState#FOLLOW_PATH_CALLED}
366 	 */
367 	protected final void pathComputationFailed() {
368 		synchronized(mutex) {
369 			if (notInState(PathExecutorState.FOLLOW_PATH_CALLED)) return;
370 			if (log != null && log.isLoggable(Level.WARNING)) log.warning("path computation failed");
371 			if (pathFuture != null) {
372 				pathFuture.removeFutureListener(pathFutureListener);
373 			}
374 			prePathComputationFailed();
375 			switchState(createState(PathExecutorState.PATH_COMPUTATION_FAILED));
376 			if (inState(PathExecutorState.PATH_COMPUTATION_FAILED)) {
377 				pathComputationFailedImpl();
378 			}
379 		}		
380 	}
381 	
382 	/**
383 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#PATH_COMPUTATION_FAILED} from within
384 	 * the {@link BasePathExecutor#pathComputationFailed()} method.
385 	 * <p><p>
386 	 * You may utilize this methods (for instance) to:
387 	 * <ul>
388 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
389 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
390 	 *   <li>Clean up some executor's fields.</li>
391 	 * </ul>
392 	 * <p>
393 	 * Empty implementation, does not doing anything.
394 	 */
395 	protected void prePathComputationFailed() {
396 	}
397 	
398 	/**
399 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#PATH_COMPUTATION_FAILED} from
400 	 * within the {@link BasePathExecutor#pathComputationFailed()} method. Note that the path can be simply obtained
401 	 * by calling {@link BasePathExecutor#getPath()}.
402 	 * <p><p>
403 	 * You may utilize this method (for instance) to:
404 	 * <ul>
405 	 *   <li>Examine the state of the executor / values produced by executor state listeners.</li>
406 	 *   <li>Clean up some executor's fields.</li>
407 	 * </ul> 
408 	 */
409 	protected abstract void pathComputationFailedImpl();
410 	
411 	// ---
412 	// =====
413 	// switchToAnotherPathElement()
414 	// =====
415 	// ---
416 	
417 	/**
418 	 * Switches from current path element index into the new one. You have to call this method
419 	 * from your implementation whenever you want to change {@link BasePathExecutor#pathElementIndex}.
420 	 * <p><p>
421 	 * This method should be also called as a reaction to {@link BasePathExecutor#pathComputed()} method call, i.e.,
422 	 * from {@link BasePathExecutor#prePathComputedImpl()} or {@link BasePathExecutor#pathComputedImpl()} to change
423 	 * the index into '0' (or other index as you see fit).
424 	 * <p><p>
425 	 * Effective only if {@link AbstractPathExecutor#isExecuting()}.
426 	 */
427 	@Override
428 	public final void switchToAnotherPathElement(int index) {
429 		synchronized(mutex) {
430 			if (!isExecuting()) return;			
431 			List<PATH_ELEMENT> path = getPath();
432 			if (path == null) throw new PogamutException("Can't switch to element of index '" + index + "' as the current path executor's path is null.", this);
433 			if (index < 0 || index >= path.size()) throw new PogamutException("Can't switch to element of index '" + index + "' as it is out of path range (path.size() = " + path.size() + ").", this);
434 			if (log != null && log.isLoggable(Level.FINER)) log.finer("switching to path element " + (index+1) + "/" + getPath().size() + " -> " + path.get(index));
435 			preSwitchToAnotherPathElementImpl(index);		
436 			switchState(createState(PathExecutorState.SWITCHED_TO_ANOTHER_PATH_ELEMENT));
437 			if (inState(PathExecutorState.SWITCHED_TO_ANOTHER_PATH_ELEMENT)) {
438 				switchToAnotherPathElementImpl();
439 			}
440 		}
441 	}
442 	
443 	/**
444 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#SWITCHED_TO_ANOTHER_PATH_ELEMENT} from within
445 	 * the {@link BasePathExecutor#switchToAnotherPathElement(int)} method. Note that this method is called to alter
446 	 * values inside {@link BasePathExecutor#previousPathElementIndex} and {@link BasePathExecutor#pathElementIndex}
447 	 * by using 'newIndex'.
448 	 * <p><p>
449 	 * You may additionally utilize this method (for instance) to:
450 	 * <ul>
451 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
452 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
453 	 * </ul>
454 	 * <p>
455 	 * Current implementation does (and nothing else):
456 	 * <ul>
457 	 *   <li>previousPathElementIndex = pathElementIndex;</li>
458 	 *   <li>pathElementIndex = newIndex;</li>
459 	 * </ul>
460 	 * 
461 	 * @param newIndex index of the path element that should be pursued now 
462 	 */
463 	protected void preSwitchToAnotherPathElementImpl(int newIndex) {
464 		previousPathElementIndex = pathElementIndex;
465 		pathElementIndex = newIndex;
466 	}
467 	
468 	/**
469 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#SWITCHED_TO_ANOTHER_PATH_ELEMENT} from
470 	 * within the {@link BasePathExecutor#switchToAnotherPathElement(int)} method. Note that this method
471 	 * is called after the values inside {@link BasePathExecutor#previousPathElementIndex} and {@link BasePathExecutor#pathElementIndex}
472 	 * are overwritten with new ones. 
473 	 * <p><p>
474 	 * You may utilize this method (for instance) to:
475 	 * <ul>
476 	 *   <li>Examine the state of the executor / values produced by executor state listeners.</li>
477 	 * </ul> 
478 	 */
479 	protected abstract void switchToAnotherPathElementImpl();
480 	
481 	// ---
482 	// =====
483 	// stop()
484 	// =====
485 	// ---
486 	
487 	/**
488 	 * Used to stop the path executor, for more info see {@link AbstractPathExecutor#stop()}.
489 	 * <p><p>
490 	 * Effective only if the state is <b>NOT</b>: {@link PathExecutorState#STOPPED}
491 	 */
492 	@Override
493 	public final void stop() {
494 		synchronized(mutex) {			
495 			if (inState(PathExecutorState.STOPPED)) return;
496 			if (log != null && log.isLoggable(Level.INFO)) log.info("stop");
497 			stopImpl();
498 			switchState(createState(PathExecutorState.STOPPED));	
499 			if (inState(PathExecutorState.STOPPED)) {
500 				stopped();
501 			}			
502 		}
503 	}
504 	
505 	/**
506 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#STOPPED} from within the 
507 	 * {@link BasePathExecutor#stop()} method. Note that this method is called to clean up internal data structures
508 	 * before we switch itself into {@link PathExecutorState#STOPPED} state.
509 	 * <p><p>
510 	 * You may additionally utilize this method (for instance) to:
511 	 * <ul>
512 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
513 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
514 	 * </ul>
515 	 * <p>
516 	 * Current implementation does (and nothing else):
517 	 * <ul>
518 	 *   <li>sets {@link BasePathExecutor#previousPathElementIndex} and {@link BasePathExecutor#pathElementIndex} to -1</li>
519 	 *   <li>removes {@link BasePathExecutor#pathFutureListener} from the {@link BasePathExecutor#pathFuture}</li>
520 	 *   <li>sets {@link BasePathExecutor#pathFuture} to null</li>
521 	 *   <li>disables all {@link AbstractPathExecutor#stuckDetectors}</li>   	 
522 	 * </ul>
523 	 * 
524 	 * @param newIndex index of the path element that should be pursued now 
525 	 */
526 	protected void stopImpl() {
527 		previousPathElementIndex = -1;
528 		pathElementIndex = -1;			
529 		if (pathFuture != null) {
530 			pathFuture.removeFutureListener(pathFutureListener);
531 			pathFuture = null;
532 		}
533 		for (IStuckDetector stuckDetector : stuckDetectors) {
534 			stuckDetector.setEnabled(false);
535 		}
536 	}
537 	
538 	/**
539 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#STOPPED} from
540 	 * within the {@link BasePathExecutor#stop()} method.
541 	 * <p><p>
542 	 * You may utilize this method (for instance) to:
543 	 * <ul>
544 	 *   <li>Finish the internal data structures clean up.</li>
545 	 * </ul> 
546 	 */
547 	protected abstract void stopped();
548 	
549 	// ---
550 	// =====
551 	// checkStuckDetectors()
552 	// =====
553 	// ---
554 	
555 	/**
556 	 * This method checks (one-by-one) stuck detectors whether some of them is reporting that the agent has stuck.
557 	 * If the stuck is detected, particular {@link IStuckDetector} is returned. If the stuck is not detected,
558 	 * null is returned.
559 	 * 
560 	 * @return first detector to report that agent has stuck or null
561 	 */
562 	@Override
563 	public IStuckDetector checkStuckDetectors() {
564 		for (IStuckDetector detector : stuckDetectors) {
565 			if (detector.isStuck()) {
566 				return detector;
567 			}
568 		}
569 		return null;
570 	}
571 	
572 	// ---
573 	// =====
574 	// stuck()
575 	// =====
576 	// ---
577 	
578 	/**
579 	 * Method that changes the state to {@link PathExecutorState#STUCK} that should be called whenever some 
580 	 * stuck detector detects that the agent is stuck.
581 	 * <p><p>
582 	 * It is currently called only from {@link BasePathExecutor#checkStuckDetectors()} which must be called from
583 	 * the descendant.
584 	 * <p><p>
585 	 * Note that you may actually pass 'null' as 'detector' into the method.
586 	 * <p><p>
587 	 * Effective only if the state is: {@link PathExecutorState#FOLLOW_PATH_CALLED} or {@link PathExecutorState#PATH_COMPUTED} or {@link PathExecutorState#SWITCHED_TO_ANOTHER_PATH_ELEMENT}
588 	 */
589 	@Override
590 	public final void stuck() {
591 		synchronized(mutex) {
592 			if (notInState(PathExecutorState.FOLLOW_PATH_CALLED, PathExecutorState.PATH_COMPUTED, PathExecutorState.SWITCHED_TO_ANOTHER_PATH_ELEMENT)) return;
593 			preStuckImpl();
594 			switchState(createState(PathExecutorState.STUCK));
595 			if (inState(PathExecutorState.STUCK)) {
596 				stuckImpl();
597 			}
598 		}
599 	}
600 	
601 	/**
602 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#STUCKD} from within the 
603 	 * {@link BasePathExecutor#stuck(IStuckDetector)} method. Note that this method is called to clean up internal data structures
604 	 * before we switch itself into {@link PathExecutorState#STUCK} state.
605 	 * <p><p>
606 	 * BasePathExecutor's implementation disables all {@link BasePathExecutor#stuckDetectors}.
607 	 * <p><p>
608 	 * You may utilize this method (for instance) to:
609 	 * <ul>
610 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
611 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
612 	 * </ul>
613 	 * <p><p>
614 	 * Current implementation does (and nothing else):
615 	 * <ul>
616 	 *   <li>disables all {@link AbstractPathExecutor#stuckDetectors}</li>
617 	 * </ul>
618 	 */
619 	protected void preStuckImpl() {	
620 		for (IStuckDetector stuckDetector : stuckDetectors) {
621 			stuckDetector.setEnabled(false);
622 		}
623 	}
624 	
625 	/**
626 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#STUCK} from
627 	 * within the {@link BasePathExecutor#stuck(IStuckDetector)} method.
628 	 * <p><p>
629 	 * You may utilize this method (for instance) to:
630 	 * <ul>
631 	 *   <li>Finish the internal data structures clean up.</li>
632 	 * </ul>
633 	 * <p><p>
634 	 * <b>WARNING:</b> 'null' may be passed as 'detector' if the stuck has been detected by different component 
635 	 */
636 	protected abstract void stuckImpl();
637 	
638 	// ---
639 	// =====
640 	// targetReached()
641 	// =====
642 	// ---
643 	
644 	/**
645 	 * Method that should be called whenever the path executor reaches the end of the path. Currently this method
646 	 * is not called from anywhere of {@link BasePathExecutor}.
647 	 * <p><p>
648 	 * Effective only if the state is: {@link PathExecutorState#FOLLOW_PATH_CALLED} or {@link PathExecutorState#PATH_COMPUTED} or {@link PathExecutorState#SWITCHED_TO_ANOTHER_PATH_ELEMENT}
649 	 */
650 	public final void targetReached() {
651 		synchronized(mutex) {
652 			if (notInState(PathExecutorState.FOLLOW_PATH_CALLED, PathExecutorState.PATH_COMPUTED, PathExecutorState.SWITCHED_TO_ANOTHER_PATH_ELEMENT)) return;
653 			preTargetReachedImpl();
654 			switchState(createState(PathExecutorState.TARGET_REACHED));
655 			if (inState(PathExecutorState.TARGET_REACHED)) {
656 				targetReachedImpl();
657 			}
658 		}
659 	}
660 	
661 	/**
662 	 * Method that is called just before the executor's state is switched to {@link PathExecutorState#TARGET_REACHED} from within the 
663 	 * {@link BasePathExecutor#targetReached()} method.
664 	 * <p><p>
665 	 * You may utilize this method (for instance) to:
666 	 * <ul>
667 	 *   <li>Initialize inner/public fields that can be used by executor state listeners.</li>
668 	 *   <li>Store values that should be passed into {@link BasePathExecutor#createState(PathExecutorState)} to create more-informed state object.</li>
669 	 *   <li>Clean up some internal data structures as the target has been reached.</li>
670 	 * </ul> 
671 	 * <p>
672 	 * Empty implementation, does not doing anything.
673 	 */
674 	protected void preTargetReachedImpl() {		
675 	}
676 	
677 	/**
678 	 * Method that is called just after the executor's state is switched to {@link PathExecutorState#TARGET_REACHED} from
679 	 * within the {@link BasePathExecutor#targetReached()} method.
680 	 * <p><p>
681 	 * You may utilize this method (for instance) to:
682 	 * <ul>
683 	 *   <li>Examine the state of the executor / values produced by executor state listeners.</li>
684 	 *   <li>Clean up some internal data structures as the target has been reached.</li>
685 	 * </ul> 
686 	 */
687 	protected abstract void targetReachedImpl();
688 	
689 }