Passed
Push — master ( db1c1a...cc7f70 )
by Alessandro
06:22
created

onTick(long)   C

Complexity

Conditions 9

Size

Total Lines 116
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 51
dl 0
loc 116
rs 6.2703
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
	 * Convert clock's tick to time units from execution start
218
	 * 
219
	 * @param tick
220
	 * @return
221
	 */
222
	public long convertTickToTau(long tick) {
223
		
224
		// covert tick to seconds from the execution start
225
		double seconds = this.clock.convertClockTickToSeconds(tick);
226
		// get property to convert seconds to time units
227
		double converter = Double.parseDouble(this.properties.getProperty(TIME_UNIT_PROPERTY));
228
		// convert seconds to time units
229
		return Math.round(seconds / converter);
230
	}
231
	
232
	/**
233
	 * 
234
	 * @param tick
235
	 * @return
236
	 */
237
	public double convertClockTickToSeconds(long tick) {
238
		return this.clock.convertClockTickToSeconds(tick);
239
	}
240
	
241
	/**
242
	 * 
243
	 * @return
244
	 * @throws InterruptedException
245
	 */
246
	public long getTau() 
247
			throws InterruptedException {
248
		
249
		// current tick
250
		long tick = this.clock.getCurrentTick();
251
		// cover to tau
252
		return this.convertTickToTau(tick);
253
	}
254
	
255
	/**
256
	 * 
257
	 * @return
258
	 * @throws InterruptedException
259
	 */
260
	public long getTick() 
261
			throws InterruptedException {
262
		
263
		// return current tick
264
		return this.clock.getCurrentTick();
265
	}
266
	
267
	/**
268
	 * 
269
	 * @param status
270
	 * @return
271
	 */
272
	public List<ExecutionNode> getNodes(ExecutionNodeStatus status) {
273
		return this.pdb.getNodesByStatus(status);
274
	}
275
	
276
	/**
277
	 * 
278
	 * @return
279
	 */
280
	public List<ExecutionNode> getNodes() {
281
		
282
		// list of nodes
283
		List<ExecutionNode> list = new ArrayList<>();
284
		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...
285
			
286
			// skip failed nodes
287
			if (!status.equals(ExecutionNodeStatus.FAILURE)) {
288
				// add all nodes with current status
289
				list.addAll(this.getNodes(status));
290
			}
291
		}
292
		
293
		// sort node list
294
		Collections.sort(list);
295
		// get sorted list
296
		return list;
297
	}
298
	
299
	/**
300
	 * 
301
	 * @param node
302
	 * @param s
303
	 */
304
	public void updateNode(ExecutionNode node, ExecutionNodeStatus s) {
305
		this.pdb.updateNodeStatus(node, s);
306
	}
307
	
308
	/**
309
	 * 
310
	 * @param node
311
	 */
312
	public void checkSchedule(ExecutionNode node) {
313
		this.pdb.checkSchedule(node);
314
	}
315
	
316
	/***
317
	 * 
318
	 * @param node
319
	 * @param start
320
	 * @throws TemporalConstraintPropagationException
321
	 * @throws PlatformException
322
	 */
323
	public void scheduleTokenStart(ExecutionNode node, long start) 
0 ignored issues
show
Unused Code introduced by
Remove this unused method parameter "start".
Loading history...
324
			throws TemporalConstraintPropagationException, PlatformException {
325
		
326
		// check controllability type
327
		ControllabilityType type = node.getControllabilityType();
328
		switch (type) {
329
		
330
			// schedule uncontrollable token
331
			case UNCONTROLLABLE : {
332
				
333
				// simply set the proper state - no propagation is needed in this case
334
				this.updateNode(node, ExecutionNodeStatus.STARTING);
335
			}
336
			break;
337
		
338
			case PARTIALLY_CONTROLLABLE : 
339
			case CONTROLLABLE : {
340
				
341
				// update node status
342
				this.updateNode(node, ExecutionNodeStatus.IN_EXECUTION);
343
			}
344
			break;
345
		}
346
		
347
		
348
		// dispatch the command through the executive if needed
349
		this.sendStartCommandSignalToPlatform(node);
350
	}
351
	
352
	/**
353
	 * 
354
	 * @param node
355
	 * @param start
356
	 * @throws ExecutionException
357
	 */
358
	public void scheduleUncontrollableTokenStart(ExecutionNode node, long start) 
0 ignored issues
show
Unused Code introduced by
Remove this unused method parameter "start".
Loading history...
359
			throws TemporalConstraintPropagationException {
360
		
361
		// schedule the observed start time of the token
362
//		this.pdb.scheduleStartTime(node, start);s
363
		// update node status
364
		this.updateNode(node, ExecutionNodeStatus.IN_EXECUTION);
365
	}
366
	
367
	/**
368
	 * 
369
	 * @param node
370
	 * @param duration
371
	 * @throws TemporalConstraintPropagationException
372
	 * @throws PlatformException
373
	 */
374
	public void scheduleTokenDuration(ExecutionNode node, long duration) 
375
			throws TemporalConstraintPropagationException, PlatformException {
376
		
377
		// propagate scheduled duration time
378
		this.pdb.scheduleDuration(node, duration);
379
		// the node can be considered as executed
380
		this.updateNode(node, ExecutionNodeStatus.EXECUTED);
381
		// if controllable send a stop command
382
		if (node.getControllabilityType().equals(ControllabilityType.CONTROLLABLE)) {
383
			// send stop signal to the platform
384
			this.sendStopCommandSignalToPlatform(node);
385
		}
386
	}
387
	
388
	/**
389
	 * This method sets an executive system on a generated plan.
390
	 * 
391
	 * It builds the plan data-based related to the generated plan and sets
392
	 * the clock, the dispatcher and the monitor processes.
393
	 * 
394
	 * @param plan
395
	 */
396
	public final void initialize(PlanProtocolDescriptor plan) 
397
			throws InterruptedException {
398
		
399
		// check status
400
		synchronized (this.lock) {
401
			while (!this.status.equals(ExecutionStatus.INACTIVE)) {
402
				this.lock.wait();
403
			}
404
			
405
			// change status and send a signal
406
			this.status = ExecutionStatus.INITIALIZING;
407
			this.lock.notifyAll();
408
		}
409
		
410
		
411
		// set plan data-base
412
		this.pdb.setup(plan);
413
		
414
		// set complete
415
		synchronized (this.lock) {
416
			// update status and send a signal
417
			this.status = ExecutionStatus.READY;
418
			this.lock.notifyAll();
419
		}
420
	}
421
	
422
	/**
423
	 * 
424
	 * @return
425
	 * @throws Exception
426
	 */
427
	public final boolean execute() 
428
			throws Exception {
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
429
		
430
		// call executive starting at tick 0
431
		return this.execute(0, null);
432
	}
433
	
434
	/**
435
	 * Blocking method which start the execution of the plan and waits for completion.
436
	 * 
437
	 * @param startTick
438
	 * @param goal
439
	 * @return
440
	 * @throws ExecutionException
441
	 * @throws ExecutionPreparationException
442
	 * @throws InterruptedException
443
	 */
444
	public final boolean execute(long startTick, Goal goal) 
445
			throws ExecutionException, ExecutionPreparationException, InterruptedException {
446
		
447
		// check status
448
		synchronized (this.lock) {
449
			
450
			// check lock condition
451
			while (!this.status.equals(ExecutionStatus.READY)) {
452
				this.status.wait();
453
			}
454
			
455
			// change status and send signal
456
			this.status = ExecutionStatus.EXECUTING;
457
			this.lock.notifyAll();
458
		}
459
460
		
461
		// check goal 
462
		if (goal == null) {
463
			// prepare execution
464
			this.doPrepareExecution();
465
			
466
		} else {
467
			
468
			// prepare execution
469
			this.doPrepareExecution(goal);
470
		}
471
		
472
		// set dispatching index
473
		this.dispatchedIndex = new ConcurrentHashMap<>();
474
		// start clock
475
		this.clock.start(startTick);
476
		// wait execution completes
477
		this.clock.join();
478
		
479
		// check execution failure or not 
480
		if (this.failure.get()) {
481
			
482
			// execution failure
483
			error("Execution failure:\n\t- tick: " + this.cause.getInterruptionTick() +"\n"
484
					+ "\t- cause: " + this.cause.getType() + "\n");
485
			
486
			// update executive status
487
			synchronized (this.lock) {
488
				// set error state
489
				this.status = ExecutionStatus.ERROR;
490
				// send signal 
491
				this.lock.notifyAll();
492
			}
493
			
494
		} else {
495
			
496
			// successful execution 
497
			info("Execution successfully complete:\n\t- tick: " + this.currentTick + "\n");
498
			
499
			// update executive status
500
			synchronized (this.lock) {
501
				// set inactive status
502
				this.status = ExecutionStatus.INACTIVE;
503
				// send signal 
504
				this.lock.notifyAll();
505
			}
506
		}
507
			
508
		// clear monitor and dispatcher
509
		this.monitor.clear();
510
		this.dispatcher.clear();
511
		// return execution result
512
		return !this.failure.get();
513
	}
514
	
515
	/**
516
	 * 
517
	 * @return
518
	 */
519
	public ExecutionFailureCause getFailureCause() {
520
		return this.cause;
521
	}
522
	
523
	/**
524
	 * 
525
	 * @return
526
	 */
527
	public boolean isFailure() {
528
		return this.failure.get();
529
	}
530
	
531
	/**
532
	 * 
533
	 * @param tick
534
	 * @return
535
	 */
536
	@Override
537
	public boolean onTick(long tick) {
538
		
539
		// execution completion flag
540
		boolean complete = false;
541
		try  {
542
			
543
			// check failure flag
544
			if (!this.failure.get()) {
545
				
546
				// handle current tick
547
				this.currentTick = tick;
548
				debug("{Executive} -> Handle tick: " + tick + "\n");
549
				// synch step
550
				debug("{Executive} {tick: " + tick + "} -> Synchronization step\n");
551
				this.monitor.handleTick(tick);
552
				// dispatching step
553
				debug("{Executive} {tick: " + tick + "} -> Dispatching step\n");
554
				this.dispatcher.handleTick(tick);
555
				
556
				// check if execution is complete
557
				complete = this.pdb.getNodesByStatus(ExecutionNodeStatus.WAITING).isEmpty() &&
558
						this.pdb.getNodesByStatus(ExecutionNodeStatus.STARTING).isEmpty() && 
559
						this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION).isEmpty();
560
			
561
			} else {
562
				
563
				// handle current tick
564
				this.currentTick = tick;
565
				// handle observations
566
				this.monitor.handleExecutionFailure(tick, this.cause);
567
				
568
				// hypothesis
569
				complete = true;
570
				// get nodes in starting state
571
				for (ExecutionNode node : this.pdb.getNodesByStatus(ExecutionNodeStatus.STARTING)) {
572
					
573
					// the executive cannot complete 
574
					complete = false;
575
					// waiting for a feedback of the node 
576
					warning("{Executive} {tick: " + tick + "} {FAILURE} -> Waiting for feedback about dispatched starting command request :\n"
577
							+ "\t- node: " + node + "\n");
578
				}
579
				
580
				// get nodes in execution 
581
				for (ExecutionNode node : this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION)) {
582
					
583
					// the executive cannot complete 
584
					complete = false;
585
					// waiting for a feedback of the node 
586
					warning("{Executive} {tick: " + tick + "} {FAILURE} -> Waiting for feedback about dispatched command :\n"
587
							+ "\t- node: " + node + "\n");
588
				}
589
			}
590
			
591
			// get tau
592
			long tau = this.convertTickToTau(tick);
593
			// display executive window
594
			this.displayWindow(tau);
595
			
596
			// notify plan execution observers
597
			synchronized (this.execObservers) {
598
				
599
				// check observers
600
				if (!this.execObservers.isEmpty()) {
601
					
602
					// get the list of nodes to be notified
603
					List<ExecutionNode> nodes = new ArrayList<>(this.pdb.getNodesByStatus(ExecutionNodeStatus.EXECUTED));
604
					// add nodes currently being executed
605
					nodes.addAll(this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION));
606
 				
607
					// forward notification to observers
608
					for (PlanExecutionObserver o : this.execObservers) {
609
						// notify the list of executed nodes
610
						o.onTick(tick, this.failure.get(), nodes);
611
						
612
					}
613
				}
614
			}
615
			
616
			
617
		} catch (ExecutionException ex)  {
618
			
619
			// set execution failure flag
620
			this.failure.set(true);
621
			// do not complete execution to wait for pending signals
622
			complete = false;
623
			// set execution failure cause
624
			this.cause = ex.getFailureCause();
625
			// error message
626
			error("{Executive} {tick: " + tick + "} -> Error while executing plan:\n"
627
					+ "\t- message: " + ex.getMessage() + "\n\n"
628
					+ "Wait for execution feedbacks of pending controllable and partially-controllable tokens if any... \n\n");
629
			
630
		} catch (PlatformException ex) {
631
			
632
			// set failure
633
			this.failure.set(true);
634
			// complete execution in this case
635
			complete = true;
636
			// error message
637
			error("{Executive} {tick: " + tick + "} -> Platform error:\n"
638
					+ "\t- message: " + ex.getMessage() + "\n");
639
			
640
		} catch (InterruptedException ex) {
0 ignored issues
show
introduced by
Either re-interrupt this method or rethrow the "InterruptedException".
Loading history...
641
			
642
			// execution error
643
			error(ex.getMessage());
644
			// set execution failure 
645
			this.failure.set(true);
646
			// complete execution in this case
647
			complete = true;
648
		}
649
650
		// get boolean flag
651
		return complete;
652
	} 
653
	
654
	/**
655
	 * 
656
	 * @param tau
657
	 * @throws InterruptedException
658
	 */
659
	private void displayWindow(long tau) 
660
			throws InterruptedException {
661
		
662
		// check property
663
		if (this.getProperty(DISPLAY_PLAN_PROPERTY).equals("1")) {
664
			// set the data-set to show
665
			this.window.setDataSet(this.pdb.getHorizon(), this.getNodes());
666
			// display current execution state
667
			this.window.display(tau);
668
		}
669
	}
670
671
	/**
672
	 * Perform some setting operation just before starting execution
673
	 * 
674
	 * @throws ExecutionPreparationException
675
	 */
676
	protected void doPrepareExecution() 
677
			throws ExecutionPreparationException {
678
		
679
		// prepare execution
680
		info("[Executive] Preparing execution...");
681
	}
682
	
683
	/**
684
	 * Perform some setting operation just before starting execution
685
	 * 
686
	 * @param goal
687
	 * @throws ExecutionPreparationException
688
	 */
689
	protected void doPrepareExecution(Goal goal) 
690
			throws ExecutionPreparationException {
691
		
692
		// prepare execution
693
		info("[Executive] Preparing execution of:\n- goal= " + goal + "\n");
694
	}
695
	
696
	/**
697
	 * 
698
	 * @param node
699
	 * @throws PlatformException
700
	 */
701
	public void sendStopCommandSignalToPlatform(ExecutionNode node) 
702
			throws PlatformException {
703
		
704
		if (this.platformProxy != null && this.platformProxy.isPlatformCommand(node)) {
705
			// also send stop command execution request
706
			this.platformProxy.stopNode(node);
707
		}
708
	}
709
	
710
	/**
711
	 * 
712
	 * @param node
713
	 * @throws PlatformException
714
	 */
715
	public void sendStartCommandSignalToPlatform(ExecutionNode node) 
716
			throws PlatformException {
717
		
718
		// check if a platform PROXY exists
719
		if (this.platformProxy != null) {
720
			
721
			// check controllability type 
722
			if (node.getControllabilityType().equals(ControllabilityType.PARTIALLY_CONTROLLABLE) || 
723
					node.getControllabilityType().equals(ControllabilityType.UNCONTROLLABLE)) {
724
				
725
				// check if command to execute on platform
726
				if (this.platformProxy.isPlatformCommand(node)) {
727
	 				// send command and take operation ID
728
					PlatformCommand cmd = this.platformProxy.executeNode(node);
729
					// add entry to the index
730
					this.dispatchedIndex.put(cmd, node);
731
				}
732
				
733
			} else {
734
				
735
				// check if command to execute on platform
736
				if (this.platformProxy.isPlatformCommand(node)) {
737
					// require execution start
738
					PlatformCommand cmd = this.platformProxy.startNode(node);
739
					// add entry to the index
740
					this.dispatchedIndex.put(cmd, node);
741
				}
742
			}
743
			
744
		} else {
745
			
746
			// nothing to do, no platform PROXY available
747
		}
748
	}
749
	
750
	/**
751
	 * Action execution feedback callback
752
	 */
753
	@Override
754
	public void feedback(PlatformFeedback feedback) {
755
		
756
		// check feedback type
757
		switch (feedback.getType()) {
758
		
759
			// successful action execution
760
			case SUCCESS : { 
761
				// handle command positive feedback
762
				this.success(feedback.getCmd());
763
			}
764
			break;
765
			
766
			// action execution failure
767
			case FAILURE : {
768
				// handle failure
769
				this.failure(feedback.getCmd());
770
			}
771
			break;
772
			
773
			case UNKNOWN : {
774
				// runtime exception
775
				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...
776
			}
777
			
778
		}
779
	}
780
	
781
	/**
782
	 * 
783
	 */
784
	@Override
785
	public void task(AgentTaskDescription task) {
786
		// nothing to do
787
	}
788
	
789
	/**
790
	 * Handle general observations from the environment
791
	 */
792
	@Override
793
	public void observation(PlatformObservation<? extends Object> obs) {
794
		
795
		/* 
796
		 * TODO Auto-generated method stub
797
		 */
798
	}
799
	
800
	/**
801
	 * 
802
	 * @param cmd
803
	 */
804
	private void success(PlatformCommand cmd) {
805
		
806
		// check command  
807
		if (this.dispatchedIndex.containsKey(cmd)) {
808
			
809
			// get execution node
810
			ExecutionNode node = this.dispatchedIndex.get(cmd);
811
			// check node current status
812
			if (node.getStatus().equals(ExecutionNodeStatus.STARTING)) {
813
				
814
				// create execution feedback
815
				ExecutionFeedback feedback = new ExecutionFeedback(
816
						this.currentTick,
817
						node, 
818
						ExecutionFeedbackType.UNCONTROLLABLE_TOKEN_START);
819
				// forward the feedback to the monitor
820
				this.monitor.addExecutionFeedback(feedback);
821
				// got start execution feedback from a completely uncontrollable token
822
				info("{Executive} {tick: " + this.currentTick + "} -> Got \"positive\" feedback about the start of the execution of an uncontrollable token:\n"
823
						+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
824
				
825
			} else if (node.getStatus().equals(ExecutionNodeStatus.IN_EXECUTION)) {
826
				
827
				// create execution feedback
828
				ExecutionFeedback feedback = new ExecutionFeedback(
829
						this.currentTick,
830
						node, 
831
						node.getControllabilityType().equals(ControllabilityType.UNCONTROLLABLE) ? 
832
								ExecutionFeedbackType.UNCONTROLLABLE_TOKEN_COMPLETE : 
833
								ExecutionFeedbackType.PARTIALLY_CONTROLLABLE_TOKEN_COMPLETE);
834
				// forward feedback to the monitor
835
				this.monitor.addExecutionFeedback(feedback);
836
				// remove operation ID from index
837
				this.dispatchedIndex.remove(cmd);
838
				// got end execution feedback from either a partially-controllable or uncontrollable token
839
				info("{Executive} {tick: " + this.currentTick + "} -> Got \"positive\" feedback about the end of the execution of either a partially-controllable or uncontrollable token:\n"
840
						+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
841
				
842
			} else {
843
				
844
				// nothing to do
845
			}
846
			
847
		} else {
848
			
849
			// no operation ID found 
850
			warning("{Executive} {tick: " + this.currentTick + "} -> Receiving feedback about an unknown operation:\n\t- cmd: " + cmd + "\n\t-data: " + cmd.getData() + "\n");
851
		}
852
	}
853
	
854
855
	/**
856
	 * 
857
	 * @param cmd
858
	 */
859
	private void failure(PlatformCommand cmd) {
860
		
861
		// check command  
862
		if (this.dispatchedIndex.containsKey(cmd)) {
863
			
864
			// get execution node
865
			ExecutionNode node = this.dispatchedIndex.get(cmd);
866
			// create execution feedback
867
			ExecutionFeedback feedback = new ExecutionFeedback(
868
					this.currentTick,
869
					node, 
870
					ExecutionFeedbackType.TOKEN_EXECUTION_FAILURE);
871
				
872
			// forward feedback to the monitor
873
			this.monitor.addExecutionFeedback(feedback);
874
			// remove operation ID from index
875
			this.dispatchedIndex.remove(cmd);
876
			// got end execution feedback from either a partially-controllable or uncontrollable token
877
			info("{Executive} {tick: " + this.currentTick + "} -> Got \"failure\" feedback about the execution of token:\n"
878
					+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
879
			
880
		} else {
881
			
882
			// no operation ID found 
883
			warning("{Executive} {tick: " + this.currentTick + "} -> Receiving feedback about an unknown operation:\n\t- cmd: " + cmd + "\n\t-data: " + cmd.getData() + "\n");
884
		}
885
	}
886
}
887