Passed
Push — master ( cffa13...ed6750 )
by Alessandro
06:08
created

updateNode(ExecutionNode,ExecutionNodeStatus)   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
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
				// dispatching step
562
				debug("{Executive} {tick: " + tick + "} -> Dispatching step\n");
563
				this.dispatcher.handleTick(tick);
564
				
565
				// check if execution is complete
566
				complete = this.pdb.getNodesByStatus(ExecutionNodeStatus.WAITING).isEmpty() &&
567
						this.pdb.getNodesByStatus(ExecutionNodeStatus.STARTING).isEmpty() && 
568
						this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION).isEmpty();
569
			
570
			} else {
571
				
572
				// handle current tick
573
				this.currentTick = tick;
574
				// handle observations
575
				this.monitor.handleExecutionFailure(tick, this.cause);
576
				
577
				// hypothesis
578
				complete = true;
579
				
580
				// get nodes in starting state
581
				for (ExecutionNode node : this.pdb.getNodesByStatus(ExecutionNodeStatus.STARTING)) {
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 starting command request :\n"
587
							+ "\t- node: " + node + "\n");
588
				}
589
				
590
				// get nodes in execution 
591
				for (ExecutionNode node : this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION)) {
592
593
					
594
					// the executive cannot complete 
595
					complete = false;
596
					// waiting for a feedback of the node 
597
					warning("{Executive} {tick: " + tick + "} {FAILURE} -> Waiting for feedback about dispatched command :\n"
598
							+ "\t- node: " + node + "\n");
599
				}
600
			}
601
			
602
			// get tau
603
			long tau = this.convertTickToTau(tick);
604
			// display executive window
605
			this.displayWindow(tau);
606
			
607
			// notify plan execution observers
608
			synchronized (this.execObservers) {
609
				
610
				// check observers
611
				if (!this.execObservers.isEmpty()) {
612
					
613
					// get the list of nodes to be notified
614
					List<ExecutionNode> nodes = new ArrayList<>(this.pdb.getNodesByStatus(ExecutionNodeStatus.EXECUTED));
615
					// add nodes currently being executed
616
					nodes.addAll(this.pdb.getNodesByStatus(ExecutionNodeStatus.IN_EXECUTION));
617
 				
618
					// forward notification to observers
619
					for (PlanExecutionObserver o : this.execObservers) {
620
						// notify the list of executed nodes
621
						o.onTick(tick, this.failure.get(), nodes);
622
						
623
					}
624
				}
625
			}
626
			
627
			
628
		} catch (ExecutionException ex)  {
629
			
630
			// set execution failure flag
631
			this.failure.set(true);
632
			// do not complete execution to wait for pending signals
633
			complete = false;
634
			// set execution failure cause
635
			this.cause = ex.getFailureCause();
636
			// error message
637
			error("{Executive} {tick: " + tick + "} -> Error while executing plan:\n"
638
					+ "\t- message: " + ex.getMessage() + "\n\n"
639
					+ "Wait for execution feedbacks of pending controllable and partially-controllable tokens if any... \n\n");
640
			
641
		} catch (PlatformException ex) {
642
			
643
			// set failure
644
			this.failure.set(true);
645
			// complete execution in this case
646
			complete = true;
647
			// error message
648
			error("{Executive} {tick: " + tick + "} -> Platform error:\n"
649
					+ "\t- message: " + ex.getMessage() + "\n");
650
			
651
		} catch (InterruptedException ex) {
0 ignored issues
show
introduced by
Either re-interrupt this method or rethrow the "InterruptedException".
Loading history...
652
			
653
			// execution error
654
			error(ex.getMessage());
655
			// set execution failure 
656
			this.failure.set(true);
657
			// complete execution in this case
658
			complete = true;
659
		}
660
661
		// get boolean flag
662
		return complete;
663
	} 
664
	
665
	/**
666
	 * 
667
	 * @param tau
668
	 * @throws InterruptedException
669
	 */
670
	private void displayWindow(long tau) 
671
			throws InterruptedException {
672
		
673
		// check property
674
		if (this.getProperty(DISPLAY_PLAN_PROPERTY).equals("1")) {
675
			// set the data-set to show
676
			this.window.setDataSet(this.pdb.getHorizon(), this.getNodes());
677
			// display current execution state
678
			this.window.display(tau);
679
		}
680
	}
681
682
	/**
683
	 * Perform some setting operation just before starting execution
684
	 * 
685
	 * @throws ExecutionPreparationException
686
	 */
687
	protected void doPrepareExecution() 
688
			throws ExecutionPreparationException {
689
		
690
		// prepare execution
691
		info("[Executive] Preparing execution...");
692
	}
693
	
694
	/**
695
	 * Perform some setting operation just before starting execution
696
	 * 
697
	 * @param goal
698
	 * @throws ExecutionPreparationException
699
	 */
700
	protected void doPrepareExecution(Goal goal) 
701
			throws ExecutionPreparationException {
702
		
703
		// prepare execution
704
		info("[Executive] Preparing execution of:\n- goal= " + goal + "\n");
705
	}
706
	
707
	/**
708
	 * 
709
	 * @param node
710
	 * @throws PlatformException
711
	 */
712
	public void sendStopCommandSignalToPlatform(ExecutionNode node) 
713
			throws PlatformException {
714
		
715
		if (this.platformProxy != null && this.platformProxy.isPlatformCommand(node)) {
716
			// also send stop command execution request
717
			this.platformProxy.stopNode(node);
718
		}
719
	}
720
	
721
	/**
722
	 * 
723
	 * @param node
724
	 * @throws PlatformException
725
	 */
726
	public void sendStartCommandSignalToPlatform(ExecutionNode node) 
727
			throws PlatformException {
728
		
729
		// check if a platform PROXY exists
730
		if (this.platformProxy != null) {
731
			
732
			// check controllability type 
733
			if (node.getControllabilityType().equals(ControllabilityType.PARTIALLY_CONTROLLABLE) || 
734
					node.getControllabilityType().equals(ControllabilityType.UNCONTROLLABLE)) {
735
				
736
				// check if command to execute on platform
737
				if (this.platformProxy.isPlatformCommand(node)) {
738
	 				// send command and take operation ID
739
					PlatformCommand cmd = this.platformProxy.executeNode(node);
740
					// add entry to the index
741
					this.dispatchedIndex.put(cmd, node);
742
				}
743
				
744
			} else {
745
				
746
				// check if command to execute on platform
747
				if (this.platformProxy.isPlatformCommand(node)) {
748
					// require execution start
749
					PlatformCommand cmd = this.platformProxy.startNode(node);
750
					// add entry to the index
751
					this.dispatchedIndex.put(cmd, node);
752
				}
753
			}
754
			
755
		} else {
756
			
757
			// nothing to do, no platform PROXY available
758
		}
759
	}
760
	
761
	/**
762
	 * Action execution feedback callback
763
	 */
764
	@Override
765
	public void feedback(PlatformFeedback feedback) {
766
		
767
		// check feedback type
768
		switch (feedback.getType()) {
769
		
770
			// successful action execution
771
			case SUCCESS : { 
772
				// handle command positive feedback
773
				this.success(feedback.getCmd());
774
			}
775
			break;
776
			
777
			// action execution failure
778
			case FAILURE : {
779
				// handle failure
780
				this.failure(feedback.getCmd());
781
			}
782
			break;
783
			
784
			case UNKNOWN : {
785
				// runtime exception
786
				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...
787
			}
788
			
789
		}
790
	}
791
	
792
	/**
793
	 * 
794
	 */
795
	@Override
796
	public void task(AgentTaskDescription task) {
797
		// nothing to do
798
	}
799
	
800
	/**
801
	 * Handle general observations from the environment
802
	 */
803
	@Override
804
	public void observation(PlatformObservation<? extends Object> obs) {
805
		
806
		/* 
807
		 * TODO Auto-generated method stub
808
		 */
809
	}
810
	
811
	/**
812
	 * 
813
	 * @param cmd
814
	 */
815
	private void success(PlatformCommand cmd) {
816
		
817
		// check command  
818
		if (this.dispatchedIndex.containsKey(cmd)) {
819
			
820
			// get execution node
821
			ExecutionNode node = this.dispatchedIndex.get(cmd);
822
			// check node current status
823
			if (node.getStatus().equals(ExecutionNodeStatus.STARTING)) {
824
				
825
				// create execution feedback
826
				ExecutionFeedback feedback = new ExecutionFeedback(
827
						this.currentTick,
828
						node, 
829
						ExecutionFeedbackType.UNCONTROLLABLE_TOKEN_START);
830
				// forward the feedback to the monitor
831
				this.monitor.addExecutionFeedback(feedback);
832
				// got start execution feedback from a completely uncontrollable token
833
				info("{Executive} {tick: " + this.currentTick + "} -> Got \"positive\" feedback about the start of the execution of an uncontrollable token:\n"
834
						+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
835
				
836
			} else if (node.getStatus().equals(ExecutionNodeStatus.IN_EXECUTION)) {
837
				
838
				// create execution feedback
839
				ExecutionFeedback feedback = new ExecutionFeedback(
840
						this.currentTick,
841
						node, 
842
						node.getControllabilityType().equals(ControllabilityType.UNCONTROLLABLE) ? 
843
								ExecutionFeedbackType.UNCONTROLLABLE_TOKEN_COMPLETE : 
844
								ExecutionFeedbackType.PARTIALLY_CONTROLLABLE_TOKEN_COMPLETE);
845
				// forward feedback to the monitor
846
				this.monitor.addExecutionFeedback(feedback);
847
				// remove operation ID from index
848
				this.dispatchedIndex.remove(cmd);
849
				// got end execution feedback from either a partially-controllable or uncontrollable token
850
				info("{Executive} {tick: " + this.currentTick + "} -> Got \"positive\" feedback about the end of the execution of either a partially-controllable or uncontrollable token:\n"
851
						+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
852
				
853
			} else {
854
				
855
				// nothing to do
856
			}
857
			
858
		} else {
859
			
860
			// no operation ID found 
861
			warning("{Executive} {tick: " + this.currentTick + "} -> Receiving feedback about an unknown operation:\n\t- cmd: " + cmd + "\n\t-data: " + cmd.getData() + "\n");
862
		}
863
	}
864
	
865
866
	/**
867
	 * 
868
	 * @param cmd
869
	 */
870
	private void failure(PlatformCommand cmd) {
871
		
872
		// check command  
873
		if (this.dispatchedIndex.containsKey(cmd)) {
874
			
875
			// get execution node
876
			ExecutionNode node = this.dispatchedIndex.get(cmd);
877
			// create execution feedback
878
			ExecutionFeedback feedback = new ExecutionFeedback(
879
					this.currentTick,
880
					node, 
881
					ExecutionFeedbackType.TOKEN_EXECUTION_FAILURE);
882
				
883
			// forward feedback to the monitor
884
			this.monitor.addExecutionFeedback(feedback);
885
			// remove operation ID from index
886
			this.dispatchedIndex.remove(cmd);
887
			// got end execution feedback from either a partially-controllable or uncontrollable token
888
			info("{Executive} {tick: " + this.currentTick + "} -> Got \"failure\" feedback about the execution of token:\n"
889
					+ "\t- node: " + node.getGroundSignature() + " (" + node + ")\n");
890
			
891
		} else {
892
			
893
			// no operation ID found 
894
			warning("{Executive} {tick: " + this.currentTick + "} -> Receiving feedback about an unknown operation:\n\t- cmd: " + cmd + "\n\t-data: " + cmd.getData() + "\n");
895
		}
896
	}
897
}
898