Passed
Push — master ( 8df666...567b11 )
by Alessandro
15:49
created

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