it.cnr.istc.pst.platinum.ai.executive.Executive   F
last analyzed

Complexity

Total Complexity 77

Size/Duplication

Total Lines 857
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 296
dl 0
loc 857
rs 2.24
c 0
b 0
f 0
wmc 77

38 Methods

Rating   Name   Duplication   Size   Complexity  
A canStart(ExecutionNode) 0 2 1
A getProperty(String) 0 3 1
A canEnd(ExecutionNode) 0 2 1
A unsubscribe(PlanExecutionObserver) 0 3 1
A unlink() 0 9 2
A getHorizon() 0 2 1
A Executive() 0 25 2
A getStatus() 0 2 1
A subscribe(PlanExecutionObserver) 0 3 1
A link(PlatformProxy) 0 13 2
A isFailure() 0 2 1
A getTick() 0 5 1
A getNodes() 0 17 3
A initialize(PlanProtocolDescriptor) 0 23 2
A scheduleTokenStart(ExecutionNode,long) 0 27 4
A checkSchedule(ExecutionNode) 0 2 1
A getNodes(ExecutionNodeStatus) 0 2 1
A scheduleTokenDuration(ExecutionNode,long) 0 11 2
A execute(long,Goal) 0 69 4
A canStop(ExecutionNode) 0 2 1
A updateNode(ExecutionNode,ExecutionNodeStatus) 0 2 1
A scheduleUncontrollableTokenStart(ExecutionNode,long) 0 7 1
A execute() 0 5 1
A getTau() 0 7 1
A convertClockTickToSeconds(long) 0 2 1
A convertTickToTau(long) 0 8 1
A getFailureCause() 0 2 1
B sendStartCommandSignalToPlatform(ExecutionNode) 0 30 6
C onTick(long) 0 123 10
A doPrepareExecution(Goal) 0 5 1
A displayWindow(long) 0 9 2
A doPrepareExecution() 0 5 1
A sendStopCommandSignalToPlatform(ExecutionNode) 0 6 3
B success(PlatformCommand) 0 47 5
A observation(PlatformObservation) 0 7 1
A task(AgentTaskDescription) 0 2 1
A feedback(PlatformFeedback) 0 28 5
A failure(PlatformCommand) 0 25 2

How to fix   Complexity   

Complexity

Complex classes like it.cnr.istc.pst.platinum.ai.executive.Executive often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package it.cnr.istc.pst.platinum.ai.executive;
2
3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.concurrent.ConcurrentHashMap;
8
import java.util.concurrent.atomic.AtomicBoolean;
9
10
import it.cnr.istc.pst.platinum.ai.executive.dispatcher.ConditionCheckingDispatcher;
11
import it.cnr.istc.pst.platinum.ai.executive.dispatcher.Dispatcher;
12
import it.cnr.istc.pst.platinum.ai.executive.lang.ExecutionFeedback;
13
import it.cnr.istc.pst.platinum.ai.executive.lang.ExecutionFeedbackType;
14
import it.cnr.istc.pst.platinum.ai.executive.lang.ex.ExecutionException;
15
import it.cnr.istc.pst.platinum.ai.executive.lang.ex.ExecutionPreparationException;
16
import it.cnr.istc.pst.platinum.ai.executive.lang.failure.ExecutionFailureCause;
17
import it.cnr.istc.pst.platinum.ai.executive.monitor.ConditionCheckingMonitor;
18
import it.cnr.istc.pst.platinum.ai.executive.monitor.Monitor;
19
import it.cnr.istc.pst.platinum.ai.executive.pdb.ControllabilityType;
20
import it.cnr.istc.pst.platinum.ai.executive.pdb.ExecutionNode;
21
import it.cnr.istc.pst.platinum.ai.executive.pdb.ExecutionNodeStatus;
22
import it.cnr.istc.pst.platinum.ai.executive.pdb.ExecutivePlanDataBase;
23
import it.cnr.istc.pst.platinum.ai.framework.microkernel.FrameworkObject;
24
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.FrameworkLoggerConfiguration;
25
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.executive.DispatcherConfiguration;
26
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.executive.MonitorConfiguration;
27
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.executive.DispatcherPlaceholder;
28
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.executive.ExecutivePlanDataBasePlaceholder;
29
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.executive.MonitorPlaceholder;
30
import it.cnr.istc.pst.platinum.ai.framework.protocol.lang.PlanProtocolDescriptor;
31
import it.cnr.istc.pst.platinum.ai.framework.time.ex.TemporalConstraintPropagationException;
32
import it.cnr.istc.pst.platinum.ai.framework.utils.log.FrameworkLoggingLevel;
33
import it.cnr.istc.pst.platinum.ai.framework.utils.properties.FilePropertyReader;
34
import it.cnr.istc.pst.platinum.ai.framework.utils.view.executive.ExecutiveWindow;
35
import it.cnr.istc.pst.platinum.control.lang.AgentTaskDescription;
36
import it.cnr.istc.pst.platinum.control.lang.Goal;
37
import it.cnr.istc.pst.platinum.control.lang.PlatformCommand;
38
import it.cnr.istc.pst.platinum.control.lang.PlatformFeedback;
39
import it.cnr.istc.pst.platinum.control.lang.PlatformObservation;
40
import it.cnr.istc.pst.platinum.control.lang.ex.PlatformException;
41
import it.cnr.istc.pst.platinum.control.platform.PlatformObserver;
42
import it.cnr.istc.pst.platinum.control.platform.PlatformProxy;
43
44
/**
45
 * 
46
 * @author alessandro
47
 *
48
 */
49
@FrameworkLoggerConfiguration(
50
		level = FrameworkLoggingLevel.INFO
51
)
52
@MonitorConfiguration(
53
		monitor = ConditionCheckingMonitor.class
54
)
55
@DispatcherConfiguration(
56
		dispatcher = ConditionCheckingDispatcher.class
57
)
58
public class Executive extends FrameworkObject implements ExecutionManager, PlatformObserver {
59
	
60
	@ExecutivePlanDataBasePlaceholder
61
	protected ExecutivePlanDataBase pdb;										// the (executive) plan to execute
62
	
63
	@MonitorPlaceholder
64
	protected Monitor<?> monitor;												// plan monitor
65
	
66
	@DispatcherPlaceholder
67
	protected Dispatcher<?> dispatcher;											// dispatching process
68
	
69
	
70
	private static final String TIME_UNIT_PROPERTY = "time_unit_to_second";		// property specifying the amount of seconds a time unit corresponds to
71
	private static final String DISPLAY_PLAN_PROPERTY = "display_plan";			// property specifying the display plan flag
72
	private FilePropertyReader properties;										// configuration property file
73
	
74
	private ExecutionStatus status;												// executive's operating status
75
	private final Object lock;													// executive's status lock
76
	private ClockManager clock;													// execution clock controller
77
	private long currentTick;													// current tick
78
	
79
	private ExecutiveWindow window;												// executive window
80
	private Map<PlatformCommand, ExecutionNode> dispatchedIndex;				// keep track of dispatched nodes
81
	private AtomicBoolean failure;												// execution failure flag
82
	private ExecutionFailureCause cause;										// execution failure cause
83
	
84
	private PlatformProxy platformProxy;										// platform PROXY to send commands to
85
	
86
	private final List<PlanExecutionObserver> execObservers;					// plan execution observers
87
	
88
89
	/**
90
	 * 
91
	 */
92
	protected Executive() {
93
		super();
94
		
95
		// get executive file properties
96
		this.properties = new FilePropertyReader(
97
			FRAMEWORK_HOME + FilePropertyReader.DEFAULT_EXECUTIVE_PROPERTY);
98
		// set clock and initial status
99
		this.lock = new Object();
100
		
101
		// set status
102
		this.status = ExecutionStatus.INACTIVE;
103
		// set clock manager
104
		this.clock = new AtomicClockManager(this);
105
		// set the PROXY and the observer
106
		this.platformProxy = null;
107
		// set failure flag
108
		this.failure = new AtomicBoolean(false);
109
		
110
		// check plan display property
111
		if (this.getProperty(DISPLAY_PLAN_PROPERTY).equals("1")) {
112
			// create executive window
113
			this.window = new ExecutiveWindow("Executive Window");
114
		}
115
		
116
		this.execObservers = new ArrayList<>();
117
	}
118
	
119
	/**
120
	 * 
121
	 * @param o
122
	 */
123
	public void subscribe(PlanExecutionObserver o) {
124
		synchronized (this.execObservers) {
125
			this.execObservers.add(o);
126
		}
127
	}
128
	
129
	/**
130
	 * 
131
	 * @param o
132
	 */
133
	public void unsubscribe(PlanExecutionObserver o) {
134
		synchronized (this.execObservers) {
135
			this.execObservers.remove(o);
136
		}
137
	}
138
	
139
	/**
140
	 * 
141
	 */
142
	@Override
143
	public String getProperty(String property) {
144
		return this.properties.getProperty(property);
145
	}
146
147
	/**
148
	 * 
149
	 * @param proxy
150
	 */
151
	public synchronized void link(PlatformProxy proxy) {
152
		
153
		// check if already set
154
		if (this.platformProxy == null) {
155
			
156
			// bind the executive
157
			this.platformProxy = proxy;
158
			// register to the PROXY
159
			this.platformProxy.register(this);
160
			
161
		} else {
162
			
163
			warning("Platform proxy already set. Do unlink before setting another platform proxy");
164
		}
165
	}
166
	
167
	/**
168
	 * 
169
	 */
170
	public synchronized void unlink() {
171
		
172
		// unlink form simulator
173
		if (this.platformProxy != null) {
174
			
175
			// unregister
176
			this.platformProxy.unregister(this);
177
			// clear data
178
			this.platformProxy = null;
179
		}
180
	}
181
	
182
	/**
183
	 * 
184
	 * @return
185
	 */
186
	public long getHorizon() {
187
		return this.pdb.getHorizon();
188
	}
189
	
190
	/**
191
	 * 
192
	 * @return
193
	 */
194
	public ExecutionStatus getStatus() {
195
		return this.status;
196
	}
197
	
198
	/**
199
	 * 
200
	 * @param node
201
	 * @return
202
	 */
203
	public boolean canEnd(ExecutionNode node) {
204
		return this.pdb.checkEndExecutionDependencies(node);
205
	}
206
	
207
	/**
208
	 * 
209
	 * @param node
210
	 * @return
211
	 */
212
	public boolean canStart(ExecutionNode node) {
213
		return this.pdb.checkStartExecutionDependencies(node);
214
	}
215
	
216
	/**
217
	 * 
218
	 * @param node
219
	 * @return
220
	 */
221
	public boolean canStop(ExecutionNode node) {
222
		return this.pdb.checkStopExecutionDependencies(node);
223
	}
224
	
225
	/**
226
	 * Convert clock's tick to time units from execution start
227
	 * 
228
	 * @param tick
229
	 * @return
230
	 */
231
	public long convertTickToTau(long tick) {
232
		
233
		// covert tick to seconds from the execution start
234
		double seconds = this.clock.convertClockTickToSeconds(tick);
235
		// get property to convert seconds to time units
236
		double converter = Double.parseDouble(this.properties.getProperty(TIME_UNIT_PROPERTY));
237
		// convert seconds to time units
238
		return Math.round(seconds / converter);
239
	}
240
	
241
	/**
242
	 * 
243
	 * @param tick
244
	 * @return
245
	 */
246
	public double convertClockTickToSeconds(long tick) {
247
		return this.clock.convertClockTickToSeconds(tick);
248
	}
249
	
250
	/**
251
	 * 
252
	 * @return
253
	 * @throws InterruptedException
254
	 */
255
	public long getTau() 
256
			throws InterruptedException {
257
		
258
		// current tick
259
		long tick = this.clock.getCurrentTick();
260
		// cover to tau
261
		return this.convertTickToTau(tick);
262
	}
263
	
264
	/**
265
	 * 
266
	 * @return
267
	 * @throws InterruptedException
268
	 */
269
	public long getTick() 
270
			throws InterruptedException {
271
		
272
		// return current tick
273
		return this.clock.getCurrentTick();
274
	}
275
	
276
	/**
277
	 * 
278
	 * @param status
279
	 * @return
280
	 */
281
	public List<ExecutionNode> getNodes(ExecutionNodeStatus status) {
282
		return this.pdb.getNodesByStatus(status);
283
	}
284
	
285
	/**
286
	 * 
287
	 * @return
288
	 */
289
	public List<ExecutionNode> getNodes() {
290
		
291
		// list of nodes
292
		List<ExecutionNode> list = new ArrayList<>();
293
		for (ExecutionNodeStatus status : ExecutionNodeStatus.values()) {
0 ignored issues
show
Comprehensibility introduced by
The variable statusshadows a field with the same name declared in line 74. Consider renaming it.
Loading history...
294
			
295
			// skip failed nodes
296
			if (!status.equals(ExecutionNodeStatus.FAILURE)) {
297
				// add all nodes with current status
298
				list.addAll(this.getNodes(status));
299
			}
300
		}
301
		
302
		// sort node list
303
		Collections.sort(list);
304
		// get sorted list
305
		return list;
306
	}
307
	
308
	/**
309
	 * 
310
	 * @param node
311
	 * @param s
312
	 */
313
	public void updateNode(ExecutionNode node, ExecutionNodeStatus s) {
314
		this.pdb.updateNodeStatus(node, s);
315
	}
316
	
317
	/**
318
	 * 
319
	 * @param node
320
	 */
321
	public void checkSchedule(ExecutionNode node) {
322
		this.pdb.checkSchedule(node);
323
	}
324
	
325
	/***
326
	 * 
327
	 * @param node
328
	 * @param start
329
	 * @throws TemporalConstraintPropagationException
330
	 * @throws PlatformException
331
	 */
332
	public void scheduleTokenStart(ExecutionNode node, long start) 
0 ignored issues
show
Unused Code introduced by
Remove this unused method parameter "start".
Loading history...
333
			throws TemporalConstraintPropagationException, PlatformException {
334
		
335
		// check controllability type
336
		ControllabilityType type = node.getControllabilityType();
337
		switch (type) {
338
		
339
			// schedule uncontrollable token
340
			case UNCONTROLLABLE : {
341
				
342
				// simply set the proper state - no propagation is needed in this case
343
				this.updateNode(node, ExecutionNodeStatus.STARTING);
344
			}
345
			break;
346
		
347
			case PARTIALLY_CONTROLLABLE : 
348
			case CONTROLLABLE : {
349
				
350
				// update node status
351
				this.updateNode(node, ExecutionNodeStatus.IN_EXECUTION);
352
			}
353
			break;
354
		}
355
		
356
		
357
		// dispatch the command through the executive if needed
358
		this.sendStartCommandSignalToPlatform(node);
359
	}
360
	
361
	/**
362
	 * 
363
	 * @param node
364
	 * @param start
365
	 * @throws ExecutionException
366
	 */
367
	public void scheduleUncontrollableTokenStart(ExecutionNode node, long start) 
0 ignored issues
show
Unused Code introduced by
Remove this unused method parameter "start".
Loading history...
368
			throws TemporalConstraintPropagationException {
369
		
370
		// schedule the observed start time of the token
371
//		this.pdb.scheduleStartTime(node, start);s
372
		// update node status
373
		this.updateNode(node, ExecutionNodeStatus.IN_EXECUTION);
374
	}
375
	
376
	/**
377
	 * 
378
	 * @param node
379
	 * @param duration
380
	 * @throws TemporalConstraintPropagationException
381
	 * @throws PlatformException
382
	 */
383
	public void scheduleTokenDuration(ExecutionNode node, long duration) 
384
			throws TemporalConstraintPropagationException, PlatformException {
385
		
386
		// propagate scheduled duration time
387
		this.pdb.scheduleDuration(node, duration);
388
		// the node can be considered as executed
389
		this.updateNode(node, ExecutionNodeStatus.EXECUTED);
390
		// if controllable send a stop command
391
		if (node.getControllabilityType().equals(ControllabilityType.CONTROLLABLE)) {
392
			// send stop signal to the platform
393
			this.sendStopCommandSignalToPlatform(node);
394
		}
395
	}
396
	
397
	/**
398
	 * This method sets an executive system on a generated plan.
399
	 * 
400
	 * It builds the plan data-based related to the generated plan and sets
401
	 * the clock, the dispatcher and the monitor processes.
402
	 * 
403
	 * @param plan
404
	 */
405
	public final void initialize(PlanProtocolDescriptor plan) 
406
			throws InterruptedException {
407
		
408
		// check status
409
		synchronized (this.lock) {
410
			while (!this.status.equals(ExecutionStatus.INACTIVE)) {
411
				this.lock.wait();
412
			}
413
			
414
			// change status and send a signal
415
			this.status = ExecutionStatus.INITIALIZING;
416
			this.lock.notifyAll();
417
		}
418
		
419
		
420
		// set plan data-base
421
		this.pdb.setup(plan);
422
		
423
		// set complete
424
		synchronized (this.lock) {
425
			// update status and send a signal
426
			this.status = ExecutionStatus.READY;
427
			this.lock.notifyAll();
428
		}
429
	}
430
	
431
	/**
432
	 * 
433
	 * @return
434
	 * @throws Exception
435
	 */
436
	public final boolean execute() 
437
			throws Exception {
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
438
		
439
		// call executive starting at tick 0
440
		return this.execute(0, null);
441
	}
442
	
443
	/**
444
	 * Blocking method which start the execution of the plan and waits for completion.
445
	 * 
446
	 * @param startTick
447
	 * @param goal
448
	 * @return
449
	 * @throws ExecutionException
450
	 * @throws ExecutionPreparationException
451
	 * @throws InterruptedException
452
	 */
453
	public final boolean execute(long startTick, Goal goal) 
454
			throws ExecutionException, ExecutionPreparationException, InterruptedException {
455
		
456
		// check status
457
		synchronized (this.lock) {
458
			
459
			// check lock condition
460
			while (!this.status.equals(ExecutionStatus.READY)) {
461
				this.status.wait();
462
			}
463
			
464
			// change status and send signal
465
			this.status = ExecutionStatus.EXECUTING;
466
			this.lock.notifyAll();
467
		}
468
469
		
470
		// check goal 
471
		if (goal == null) {
472
			// prepare execution
473
			this.doPrepareExecution();
474
			
475
		} else {
476
			
477
			// prepare execution
478
			this.doPrepareExecution(goal);
479
		}
480
		
481
		// set dispatching index
482
		this.dispatchedIndex = new ConcurrentHashMap<>();
483
		// start clock
484
		this.clock.start(startTick);
485
		// wait execution completes
486
		this.clock.join();
487
		
488
		// check execution failure or not 
489
		if (this.failure.get()) {
490
			
491
			// execution failure
492
			error("Execution failure:\n\t- tick: " + this.cause.getInterruptionTick() +"\n"
493
					+ "\t- cause: " + this.cause.getType() + "\n");
494
			
495
			// update executive status
496
			synchronized (this.lock) {
497
				// set error state
498
				this.status = ExecutionStatus.ERROR;
499
				// send signal 
500
				this.lock.notifyAll();
501
			}
502
			
503
		} else {
504
			
505
			// successful execution 
506
			info("Execution successfully complete:\n\t- tick: " + this.currentTick + "\n");
507
			
508
			// update executive status
509
			synchronized (this.lock) {
510
				// set inactive status
511
				this.status = ExecutionStatus.INACTIVE;
512
				// send signal 
513
				this.lock.notifyAll();
514
			}
515
		}
516
			
517
		// clear monitor and dispatcher
518
		this.monitor.clear();
519
		this.dispatcher.clear();
520
		// return execution result
521
		return !this.failure.get();
522
	}
523
	
524
	/**
525
	 * 
526
	 * @return
527
	 */
528
	public ExecutionFailureCause getFailureCause() {
529
		return this.cause;
530
	}
531
	
532
	/**
533
	 * 
534
	 * @return
535
	 */
536
	public boolean isFailure() {
537
		return this.failure.get();
538
	}
539
	
540
	/**
541
	 * 
542
	 * @param tick
543
	 * @return
544
	 */
545
	@Override
546
	public boolean onTick(long tick) {
547
		
548
		// execution completion flag
549
		boolean complete = false;
550
		try  {
551
			
552
			// check failure flag
553
			if (!this.failure.get()) {
554
				
555
				// handle current tick
556
				this.currentTick = tick;
557
				debug("{Executive} -> Handle tick: " + tick + "\n");
558
				// synch step
559
				debug("{Executive} {tick: " + tick + "} -> Synchronization step\n");
560
				this.monitor.handleTick(tick);
561
				// check if execution is complete
562
				complete = this.pdb.getNodesByStatus(ExecutionNodeStatus.WAITING).isEmpty() &&
563
						this.pdb.getNodesByStatus(ExecutionNodeStatus.STARTING).isEmpty() && 
564
						this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION).isEmpty();
565
				
566
				
567
				// check complete flag 
568
				if (!complete) {
569
				
570
					// dispatching step
571
					debug("{Executive} {tick: " + tick + "} -> Dispatching step\n");
572
					this.dispatcher.handleTick(tick);
573
				}
574
			
575
			} else {
576
				
577
				// handle current tick
578
				this.currentTick = tick;
579
				// handle observations
580
				this.monitor.handleExecutionFailure(tick, this.cause);
581
				
582
				// hypothesis
583
				complete = true;
584
				
585
				// get nodes in starting state
586
				for (ExecutionNode node : this.pdb.getNodesByStatus(ExecutionNodeStatus.STARTING)) {
587
					
588
					// the executive cannot complete 
589
					complete = false;
590
					// waiting for a feedback of the node 
591
					warning("{Executive} {tick: " + tick + "} {FAILURE} -> Waiting for feedback about dispatched starting command request :\n"
592
							+ "\t- node: " + node + "\n");
593
				}
594
				
595
				// get nodes in execution 
596
				for (ExecutionNode node : this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION)) {
597
598
					
599
					// the executive cannot complete 
600
					complete = false;
601
					// waiting for a feedback of the node 
602
					warning("{Executive} {tick: " + tick + "} {FAILURE} -> Waiting for feedback about dispatched command :\n"
603
							+ "\t- node: " + node + "\n");
604
				}
605
			}
606
			
607
			// get tau
608
			long tau = this.convertTickToTau(tick);
609
			// display executive window
610
			this.displayWindow(tau);
611
			
612
			// notify plan execution observers
613
			synchronized (this.execObservers) {
614
				
615
				// check observers
616
				if (!this.execObservers.isEmpty()) {
617
					
618
					// get the list of nodes to be notified
619
					List<ExecutionNode> nodes = new ArrayList<>(this.pdb.getNodesByStatus(ExecutionNodeStatus.EXECUTED));
620
					// add nodes currently being executed
621
					nodes.addAll(this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION));
622
 				
623
					// forward notification to observers
624
					for (PlanExecutionObserver o : this.execObservers) {
625
						// notify the list of executed nodes
626
						o.onTick(tick, this.failure.get(), nodes);
627
						
628
					}
629
				}
630
			}
631
			
632
			
633
		} catch (ExecutionException ex)  {
634
			
635
			// set execution failure flag
636
			this.failure.set(true);
637
			// do not complete execution to wait for pending signals
638
			complete = false;
639
			// set execution failure cause
640
			this.cause = ex.getFailureCause();
641
			// error message
642
			error("{Executive} {tick: " + tick + "} -> Error while executing plan:\n"
643
					+ "\t- message: " + ex.getMessage() + "\n\n"
644
					+ "Wait for execution feedbacks of pending controllable and partially-controllable tokens if any... \n\n");
645
			
646
		} catch (PlatformException ex) {
647
			
648
			// set failure
649
			this.failure.set(true);
650
			// complete execution in this case
651
			complete = true;
652
			// error message
653
			error("{Executive} {tick: " + tick + "} -> Platform error:\n"
654
					+ "\t- message: " + ex.getMessage() + "\n");
655
			
656
		} catch (InterruptedException ex) {
0 ignored issues
show
introduced by
Either re-interrupt this method or rethrow the "InterruptedException".
Loading history...
657
			
658
			// execution error
659
			error(ex.getMessage());
660
			// set execution failure 
661
			this.failure.set(true);
662
			// complete execution in this case
663
			complete = true;
664
		}
665
666
		// get boolean flag
667
		return complete;
668
	} 
669
	
670
	/**
671
	 * 
672
	 * @param tau
673
	 * @throws InterruptedException
674
	 */
675
	private void displayWindow(long tau) 
676
			throws InterruptedException {
677
		
678
		// check property
679
		if (this.getProperty(DISPLAY_PLAN_PROPERTY).equals("1")) {
680
			// set the data-set to show
681
			this.window.setDataSet(this.pdb.getHorizon(), this.getNodes());
682
			// display current execution state
683
			this.window.display(tau);
684
		}
685
	}
686
687
	/**
688
	 * Perform some setting operation just before starting execution
689
	 * 
690
	 * @throws ExecutionPreparationException
691
	 */
692
	protected void doPrepareExecution() 
693
			throws ExecutionPreparationException {
694
		
695
		// prepare execution
696
		info("[Executive] Preparing execution...");
697
	}
698
	
699
	/**
700
	 * Perform some setting operation just before starting execution
701
	 * 
702
	 * @param goal
703
	 * @throws ExecutionPreparationException
704
	 */
705
	protected void doPrepareExecution(Goal goal) 
706
			throws ExecutionPreparationException {
707
		
708
		// prepare execution
709
		info("[Executive] Preparing execution of:\n- goal= " + goal + "\n");
710
	}
711
	
712
	/**
713
	 * 
714
	 * @param node
715
	 * @throws PlatformException
716
	 */
717
	public void sendStopCommandSignalToPlatform(ExecutionNode node) 
718
			throws PlatformException {
719
		
720
		if (this.platformProxy != null && this.platformProxy.isPlatformCommand(node)) {
721
			// also send stop command execution request
722
			this.platformProxy.stopNode(node);
723
		}
724
	}
725
	
726
	/**
727
	 * 
728
	 * @param node
729
	 * @throws PlatformException
730
	 */
731
	public void sendStartCommandSignalToPlatform(ExecutionNode node) 
732
			throws PlatformException {
733
		
734
		// check if a platform PROXY exists
735
		if (this.platformProxy != null) {
736
			
737
			// check controllability type 
738
			if (node.getControllabilityType().equals(ControllabilityType.PARTIALLY_CONTROLLABLE) || 
739
					node.getControllabilityType().equals(ControllabilityType.UNCONTROLLABLE)) {
740
				
741
				// check if command to execute on platform
742
				if (this.platformProxy.isPlatformCommand(node)) {
743
	 				// send command and take operation ID
744
					PlatformCommand cmd = this.platformProxy.executeNode(node);
745
					// add entry to the index
746
					this.dispatchedIndex.put(cmd, node);
747
				}
748
				
749
			} else {
750
				
751
				// check if command to execute on platform
752
				if (this.platformProxy.isPlatformCommand(node)) {
753
					// require execution start
754
					PlatformCommand cmd = this.platformProxy.startNode(node);
755
					// add entry to the index
756
					this.dispatchedIndex.put(cmd, node);
757
				}
758
			}
759
			
760
		} else {
761
			
762
			// nothing to do, no platform PROXY available
763
		}
764
	}
765
	
766
	/**
767
	 * Action execution feedback callback
768
	 */
769
	@Override
770
	public void feedback(PlatformFeedback feedback) {
771
		
772
		// check feedback type
773
		switch (feedback.getType()) {
774
		
775
			// successful action execution
776
			case SUCCESS : { 
777
				// handle command positive feedback
778
				this.success(feedback.getCmd());
779
			}
780
			break;
781
			
782
			// action execution failure
783
			case FAILURE : {
784
				// handle failure
785
				this.failure(feedback.getCmd());
786
			}
787
			break;
788
			
789
			case INTERRUPTED: {
0 ignored issues
show
Comprehensibility introduced by
End this switch case with an unconditional break, return or throw statement.
Loading history...
790
				// handle failure
791
				this.failure(feedback.getCmd());
792
			}
793
			
794
			case UNKNOWN : {
795
				// runtime exception
796
				throw new RuntimeException("Received UNKNOWN feedback type:\n- cmd: " + feedback.getCmd());
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
797
			}
798
			
799
		}
800
	}
801
	
802
	/**
803
	 * 
804
	 */
805
	@Override
806
	public void task(AgentTaskDescription task) {
807
		// nothing to do
808
	}
809
	
810
	/**
811
	 * Handle general observations from the environment
812
	 */
813
	@Override
814
	public void observation(PlatformObservation<? extends Object> obs) {
815
		
816
		/**
817
		 * TODO 
818
		 */
819
		throw new RuntimeException("[Executive] Implement observation() method...");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
820
	}
821
	
822
	/**
823
	 * 
824
	 * @param cmd
825
	 */
826
	private void success(PlatformCommand cmd) {
827
		
828
		// check command  
829
		if (this.dispatchedIndex.containsKey(cmd)) {
830
			
831
			// get execution node
832
			ExecutionNode node = this.dispatchedIndex.get(cmd);
833
			// check node current status
834
			if (node.getStatus().equals(ExecutionNodeStatus.STARTING)) {
835
				
836
				// create execution feedback
837
				ExecutionFeedback feedback = new ExecutionFeedback(
838
						this.currentTick,
839
						node, 
840
						ExecutionFeedbackType.UNCONTROLLABLE_TOKEN_START);
841
				// forward the feedback to the monitor
842
				this.monitor.addExecutionFeedback(feedback);
843
				// got start execution feedback from a completely uncontrollable token
844
				info("{Executive} {tick: " + this.currentTick + "} -> Got \"positive\" feedback about the start of the execution of an uncontrollable token:\n"
845
						+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
846
				
847
			} else if (node.getStatus().equals(ExecutionNodeStatus.IN_EXECUTION)) {
848
				
849
				// create execution feedback
850
				ExecutionFeedback feedback = new ExecutionFeedback(
851
						this.currentTick,
852
						node, 
853
						node.getControllabilityType().equals(ControllabilityType.UNCONTROLLABLE) ? 
854
								ExecutionFeedbackType.UNCONTROLLABLE_TOKEN_COMPLETE : 
855
								ExecutionFeedbackType.PARTIALLY_CONTROLLABLE_TOKEN_COMPLETE);
856
				// forward feedback to the monitor
857
				this.monitor.addExecutionFeedback(feedback);
858
				// remove operation ID from index
859
				this.dispatchedIndex.remove(cmd);
860
				// got end execution feedback from either a partially-controllable or uncontrollable token
861
				info("{Executive} {tick: " + this.currentTick + "} -> Got \"positive\" feedback about the end of the execution of either a partially-controllable or uncontrollable token:\n"
862
						+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
863
				
864
			} else {
865
				
866
				// nothing to do
867
			}
868
			
869
		} else {
870
			
871
			// no operation ID found 
872
			warning("{Executive} {tick: " + this.currentTick + "} -> Receiving feedback about an unknown operation:\n\t- cmd: " + cmd + "\n\t-data: " + cmd.getData() + "\n");
873
		}
874
	}
875
	
876
877
	/**
878
	 * 
879
	 * @param cmd
880
	 */
881
	private void failure(PlatformCommand cmd) {
882
		
883
		// check command  
884
		if (this.dispatchedIndex.containsKey(cmd)) {
885
			
886
			// get execution node
887
			ExecutionNode node = this.dispatchedIndex.get(cmd);
888
			// create execution feedback
889
			ExecutionFeedback feedback = new ExecutionFeedback(
890
					this.currentTick,
891
					node, 
892
					ExecutionFeedbackType.TOKEN_EXECUTION_FAILURE);
893
			
894
			// forward feedback to the monitor
895
			this.monitor.addExecutionFeedback(feedback);
896
			// remove operation ID from index
897
			this.dispatchedIndex.remove(cmd);
898
			// got end execution feedback from either a partially-controllable or uncontrollable token
899
			info("{Executive} {tick: " + this.currentTick + "} -> Got \"failure\" feedback about the execution of token:\n"
900
					+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
901
			
902
		} else {
903
			
904
			// no operation ID found 
905
			warning("{Executive} {tick: " + this.currentTick + "} -> Receiving feedback about an unknown operation:\n\t- cmd: " + cmd + "\n\t-data: " + cmd.getData() + "\n");
906
		}
907
	}
908
}
909