Test Setup Failed
Push — master ( bb3bf3...1e7564 )
by Alessandro
17:55
created

execute(Goal)   B

Complexity

Conditions 6

Size

Total Lines 75
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 31
dl 0
loc 75
rs 8.2026
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.control.acting;
2
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.LinkedList;
6
import java.util.List;
7
import java.util.Map;
8
9
import it.cnr.istc.pst.platinum.ai.deliberative.Planner;
10
import it.cnr.istc.pst.platinum.ai.executive.Executive;
11
import it.cnr.istc.pst.platinum.ai.executive.lang.ex.ExecutionPreparationException;
12
import it.cnr.istc.pst.platinum.ai.executive.lang.failure.ExecutionFailureCause;
13
import it.cnr.istc.pst.platinum.ai.executive.pdb.ExecutionNode;
14
import it.cnr.istc.pst.platinum.ai.executive.pdb.ExecutionNodeStatus;
15
import it.cnr.istc.pst.platinum.ai.framework.domain.PlanDataBaseBuilder;
16
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ComponentValue;
17
import it.cnr.istc.pst.platinum.ai.framework.domain.component.Decision;
18
import it.cnr.istc.pst.platinum.ai.framework.domain.component.DomainComponent;
19
import it.cnr.istc.pst.platinum.ai.framework.domain.component.PlanDataBase;
20
import it.cnr.istc.pst.platinum.ai.framework.domain.component.ex.DecisionPropagationException;
21
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.NoSolutionFoundException;
22
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.SynchronizationCycleException;
23
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.plan.SolutionPlan;
24
import it.cnr.istc.pst.platinum.ai.framework.utils.properties.FilePropertyReader;
25
import it.cnr.istc.pst.platinum.control.lang.AgentTaskDescription;
26
import it.cnr.istc.pst.platinum.control.lang.Goal;
27
import it.cnr.istc.pst.platinum.control.lang.GoalStatus;
28
import it.cnr.istc.pst.platinum.control.lang.PlatformFeedback;
29
import it.cnr.istc.pst.platinum.control.lang.PlatformObservation;
30
import it.cnr.istc.pst.platinum.control.lang.TokenDescription;
31
import it.cnr.istc.pst.platinum.control.lang.ex.PlatformException;
32
import it.cnr.istc.pst.platinum.control.platform.PlatformObserver;
33
import it.cnr.istc.pst.platinum.control.platform.PlatformProxy;
34
import it.cnr.istc.pst.platinum.control.platform.PlatformProxyBuilder;
35
import it.cnr.istc.pst.platinum.control.platform.RunnablePlatformProxy;
36
37
/**
38
 * 
39
 * @author alessandro
40
 *
41
 */
42
public class GoalOrientedActingAgent implements PlatformObserver {
43
	
44
	private final Object lock;								// lock state;
45
	private ActingAgentStatus status;						// agent status
46
47
	private final Map<GoalStatus, List<Goal>> queue;		// goal queue
48
	
49
	private String ddl;										// path to the domain specification file
50
	private PlanDataBase pdb;								// internal plan database representation
51
	
52
	private List<Thread> processes;							// goal oriented processes
53
	private DeliberativeProcess deliberative;				// internal deliberative process
54
	private Class<? extends Planner> pClass;				// planner class
55
	private boolean displayPlan;							// display plan flag
56
	
57
	private ExecutiveProcess executive;						// internal executive process
58
	private ContingencyHandlerProcess contingencyHandler;	// internal contingency handler process
59
	private Class<? extends Executive> eClass;				// executive class
60
	
61
	protected PlatformProxy proxy;
62
	private FilePropertyReader properties;
63
	
64
	/**
65
	 * 
66
	 * @param agentPropertyFile
67
	 */
68
	@SuppressWarnings("unchecked")
69
	public GoalOrientedActingAgent(String agentPropertyFile) {
70
		
71
		try {
72
			
73
			// set lock and status
74
			this.lock = new Object();
75
			// set status
76
			this.status = ActingAgentStatus.OFFLINE;
77
			// set goal buffer
78
			this.queue = new HashMap<>();
0 ignored issues
show
Performance introduced by
When using a map whose keys are EnumValues, consider using an EnumMap instead, which is more performant in this case.

The Java documentation explain EnumMap.

Loading history...
79
			// set goal queue
80
			for (GoalStatus s : GoalStatus.values()) {
81
				this.queue.put(s, new LinkedList<>());
82
			}
83
			
84
			// set internal plan database representation
85
			this.pdb = null;
86
			// set platform
87
			this.processes = null;
88
			
89
			
90
			// get agent property file
91
			this.properties = new FilePropertyReader(agentPropertyFile);
92
			
93
			// get DDL file 
94
			String ddlFile = this.properties.getProperty("model");
95
			// check if null
96
			if (ddlFile == null || ddlFile.equals("")) {
97
				throw new RuntimeException("You need to specify an acting model of the agent in \"etc/agent.properties\"!");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
98
			}
99
			
100
			// set the model
101
			this.ddl = ddlFile;
102
			
103
			// read the class name of the planner
104
			String plannerClassName = this.properties.getProperty("planner");
105
			// set planner class
106
			this.pClass = (Class<? extends Planner>) Class.forName(plannerClassName);
107
			// set display plan flag
108
			this.displayPlan = this.properties.getProperty("display_plan").equals("1") ? true : false;
109
110
			// read the class name of the executive
111
			String executiveClassName = this.properties.getProperty("executive");
112
			// set executive class
113
			this.eClass = (Class<? extends Executive>) Class.forName(executiveClassName);
114
			
115
			
116
			
117
			// read the class of the platform 
118
			String platformClassName = this.properties.getProperty("platform");
119
			// check if a platform is necessary
120
			if (platformClassName != null && !platformClassName.equals("")) {
121
				
122
				// get platform configuration file 
123
				String configFile = this.properties.getProperty("platform_config_file");
124
				// check platform configuration file 
125
				if (configFile == null || configFile.equals("")) {
126
					throw new RuntimeException("Specify a configuration file for the platform in \"" + agentPropertyFile + "\"!");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
127
				}
128
				
129
				// print agent configuration
130
				System.out.println("Configuration of the Goal-Oriented Acting Agent:\n"
131
						+ "\tDDL file: " +  ddlFile + "\n"
132
						+ "\tDeliberative Clas: " + plannerClassName + "\n"
133
						+ "\tExecutive Class: " + executiveClassName + "\n"
134
						+ "\tPlatform Class: " + platformClassName + "\n"
135
						+ "\tPlatform Config file: " + configFile + "\n");
136
				
137
				
138
				// create platform PROXY
139
				Class<? extends PlatformProxy> clazz = (Class<? extends PlatformProxy>) Class.forName(platformClassName); 
140
				// create PROXY
141
				this.proxy = PlatformProxyBuilder.build(clazz, configFile);
142
				
143
			} else {
144
				
145
				// print agent configuration
146
				System.out.println("Configuration of the Goal-Oriented Acting Agent:\n"
147
						+ "\tDDL file: " +  ddlFile + "\n"
148
						+ "\tDeliberative Clas: " + plannerClassName + "\n"
149
						+ "\tExecutive Class: " + executiveClassName + "\n");
150
			}
151
			
152
			
153
			// setup deliberative and executive processes
154
			this.setupProcesses();
155
			
156
		} catch (Exception ex) {
157
			throw new RuntimeException(ex.getMessage());
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
158
		}
159
		
160
		
161
	}
162
	
163
	
164
	/**
165
	 * 
166
	 */
167
	private void setupProcesses() {
168
		
169
		// set the list of processes
170
		this.processes = new ArrayList<>();
171
		// set goal listener thread
172
		this.processes.add(new Thread(new Runnable() {
173
174
			/**
175
			 * 
176
			 */
177
			@Override
178
			public void run() {
179
				
180
				boolean running = true;
181
				while(running) {
182
					
183
					try {
184
						
185
						// check buffered goals
186
						Goal goal = waitGoal(GoalStatus.BUFFERED);
187
						System.out.println("Selecting goal.. \n" + goal + "\n");
188
						// simply select the extracted goal
189
						select(goal);
190
						
191
					} catch (InterruptedException ex) {
0 ignored issues
show
introduced by
Either re-interrupt this method or rethrow the "InterruptedException".
Loading history...
192
						running = false;
193
					}
194
				}
195
			}
196
		}));
197
		
198
		
199
		// set goal deliberative
200
		this.deliberative = new DeliberativeProcess(this.pClass, this.displayPlan, this);
201
		this.processes.add(new Thread(this.deliberative));
202
	
203
		// set goal executive
204
		this.executive = new ExecutiveProcess(this.eClass, this);
205
		this.processes.add(new Thread(this.executive));
206
	
207
		// set goal failure handler
208
		this.contingencyHandler = new ContingencyHandlerProcess(this);
209
		this.processes.add(new Thread(this.contingencyHandler));
210
		
211
		// finally register to platform events
212
		if (this.proxy != null) {
213
			this.proxy.register(this);
214
		}
215
	}
216
	
217
	
218
	/**
219
	 * 
220
	 * @return
221
	 */
222
	public synchronized ActingAgentStatus getStatus() {
223
		return status;
224
	}
225
	
226
	/**
227
	 * 
228
	 */
229
	@Override
230
	public void task(AgentTaskDescription task) {
231
		// buffer task planning request
232
		this.buffer(task);
233
	}
234
	
235
	/**
236
	 * 
237
	 */
238
	@Override
239
	public void feedback(PlatformFeedback feedback) {
240
		// nothing to do
241
	}
242
	
243
	/**
244
	 * 
245
	 */
246
	@Override
247
	public void observation(PlatformObservation<? extends Object> obs) {
248
		// nothing to do
249
	}
250
	
251
	
252
	/**
253
	 * Trigger acting process by buffering a description of a goal to plan and execute for
254
	 * 
255
	 * @param description
256
	 */
257
	public void buffer(AgentTaskDescription description) {
258
		
259
		// protect access to the queue
260
		synchronized (this.queue) {
261
			System.out.println("[Agent] Receiving task ...\n" + description + "\n");
262
			// create goal 
263
			Goal goal = new Goal(description);
264
			// set goal status
265
			goal.setStatus(GoalStatus.BUFFERED);
266
			// add a goal to the queue
267
			this.queue.get(goal.getStatus()).add(goal);
268
			// send signal
269
			this.queue.notifyAll();
270
		}
271
	}
272
	
273
	/**
274
	 * Blocking call returning a list of finished or aborted goals.
275
	 * 
276
	 * @return
277
	 * @throws InterruptedException
278
	 */
279
	public List<Goal> getResults() 
280
			throws InterruptedException {
281
		
282
		// wait some finished or aborted goal
283
		List<Goal> goals = new ArrayList<>();
284
		synchronized (this.queue) {
285
			
286
			while (this.queue.get(GoalStatus.ABORTED).isEmpty() && 
287
					this.queue.get(GoalStatus.FINISHED).isEmpty()) {
288
				// wait
289
				this.queue.wait();
290
			}
291
			
292
			// take aborted goals
293
			goals.addAll(this.queue.get(GoalStatus.ABORTED));
294
			// clear queue
295
			this.queue.get(GoalStatus.ABORTED).clear();
296
			// take finished goals
297
			goals.addAll(this.queue.get(GoalStatus.FINISHED));
298
			// clear queue
299
			this.queue.get(GoalStatus.FINISHED).clear();
300
			
301
			// send signal
302
			this.queue.notifyAll();
303
		}
304
		
305
		// get finished and aborted goals
306
		return goals;
307
	}
308
	
309
	/**
310
	 * 
311
	 */
312
	protected void select(Goal goal) {
313
		
314
		// protect access to the queue
315
		synchronized (this.queue) {
316
			
317
			// remove goal form the current queue
318
			this.queue.get(goal.getStatus()).remove(goal);
319
			// set goal status
320
			goal.setStatus(GoalStatus.SELECTED);
321
			// add goal to the queue
322
			this.queue.get(goal.getStatus()).add(goal);
323
			// send signal
324
			this.queue.notifyAll();
325
		}
326
	}
327
	
328
	/**
329
	 * 
330
	 */
331
	protected void commit(Goal goal) {
332
		
333
		// protect access to the queue
334
		synchronized (this.queue) {
335
			
336
			// remove goal form the current queue
337
			this.queue.get(goal.getStatus()).remove(goal);
338
			// set goal status
339
			goal.setStatus(GoalStatus.COMMITTED);
340
			// add goal to the queue
341
			this.queue.get(goal.getStatus()).add(goal);
342
			// send signal
343
			this.queue.notifyAll();
344
		}
345
	}
346
	
347
	/**
348
	 * 
349
	 */
350
	protected void suspend(Goal goal) {
351
		
352
		// protect access to the queue
353
		synchronized (this.queue) {
354
			
355
			// remove goal form the current queue
356
			this.queue.get(goal.getStatus()).remove(goal);
357
			// set goal status
358
			goal.setStatus(GoalStatus.SUSPENDED);
359
			// add goal to the queue
360
			this.queue.get(goal.getStatus()).add(goal);
361
			// send signal
362
			this.queue.notifyAll();
363
		}
364
	}
365
366
	/**
367
	 * 
368
	 */
369
	protected void finish(Goal goal) {
370
		
371
		// protect access to the queue
372
		synchronized (this.queue) {
373
			
374
			// remove goal form the current queue
375
			this.queue.get(goal.getStatus()).remove(goal);
376
			// set goal status
377
			goal.setStatus(GoalStatus.FINISHED);
378
			// add goal to the queue
379
			this.queue.get(goal.getStatus()).add(goal);
380
			// send signal
381
			this.queue.notifyAll();
382
		}
383
	}
384
	
385
	/**
386
	 * 
387
	 */
388
	protected void abort(Goal goal) {
389
		
390
		// protect access to the queue
391
		synchronized (this.queue) {
392
			
393
			// remove goal form the current queue
394
			this.queue.get(goal.getStatus()).remove(goal);
395
			// set goal status
396
			goal.setStatus(GoalStatus.ABORTED);
397
			// add goal to the queue
398
			this.queue.get(goal.getStatus()).add(goal);
399
			// send signal
400
			this.queue.notifyAll();
401
		}		
402
	}
403
	
404
	/**
405
	 * 
406
	 * @throws InterruptedException
407
	 * @throws PlatformException
408
	 */
409
	public void start() 
410
			throws InterruptedException, PlatformException {
411
		
412
		synchronized (this.lock) {
413
			while (!this.status.equals(ActingAgentStatus.OFFLINE)) {
414
				// wait 
415
				this.lock.wait();
416
			}
417
			
418
			// change status
419
			this.status = ActingAgentStatus.STARTING;
420
			// send signal
421
			this.lock.notifyAll();
422
		}
423
		
424
		// start PROXY if necessary
425
		if (this.proxy instanceof RunnablePlatformProxy) {
426
			// start runnable PROXY
427
			((RunnablePlatformProxy) this.proxy).start();
428
		}
429
		
430
		
431
		// start all internal processes
432
		for (Thread p : this.processes) {
433
			p.start();
434
		}
435
436
		synchronized (this.lock) {
437
			// change status
438
			this.status = ActingAgentStatus.RUNNING;
439
			// notify all
440
			this.lock.notifyAll();
441
		}
442
	}
443
	
444
	/**
445
	 * 
446
	 * @throws InterruptedException
447
	 */
448
	public void stop() 
449
			throws InterruptedException, PlatformException
450
	{
451
		synchronized (this.lock) {
452
			while (!this.status.equals(ActingAgentStatus.READY) && 
453
					!this.status.equals(ActingAgentStatus.RUNNING)) {
454
				// wait 
455
				this.lock.wait();
456
			}
457
			
458
			// change status
459
			this.status = ActingAgentStatus.STOPPING;
460
			// send signal
461
			this.lock.notifyAll();
462
		}
463
		
464
		
465
		// interrupt internal processes and wait termination
466
		for (Thread p : this.processes) {
467
			p.interrupt();
468
			p.join();
469
		}
470
		
471
		// stop platform PROXY
472
		if (this.proxy instanceof RunnablePlatformProxy) {
473
			// stop platform PROXY
474
			((RunnablePlatformProxy) this.proxy).stop();
475
		}
476
		
477
		synchronized (this.lock) {
478
			// change status
479
			this.status = ActingAgentStatus.OFFLINE;
480
			// notify all
481
			this.lock.notifyAll();
482
		}
483
	}
484
	
485
	/**
486
	 * 
487
	 * @throws InterruptedException
488
	 * @throws SynchronizationCycleException
489
	 * @throws PlatformException
490
	 */
491
	public void initialize() 
492
			throws InterruptedException, SynchronizationCycleException, PlatformException {
493
		
494
		synchronized (this.lock) {
495
			while(!this.status.equals(ActingAgentStatus.RUNNING)) {
496
				// wait a signal
497
				this.lock.wait();
498
			}
499
			
500
			// change status
501
			this.status = ActingAgentStatus.INITIALIZING;
502
			// send signal 
503
			this.lock.notifyAll();
504
		}
505
		
506
		// set plan database on the given planning domain
507
		this.pdb = PlanDataBaseBuilder.createAndSet(this.ddl);
508
		
509
		synchronized (this.lock) {
510
			// change status
511
			this.status = ActingAgentStatus.READY;
512
			// send signal
513
			this.lock.notifyAll();
514
		}
515
	}
516
	
517
	/**
518
	 * 
519
	 * @throws InterruptedException
520
	 */
521
	public void clear() 
522
			throws InterruptedException {
523
		
524
		synchronized (this.lock) {
525
			while (!this.status.equals(ActingAgentStatus.FAILURE) && 
526
					!this.status.equals(ActingAgentStatus.READY)) {
527
				// wait
528
				this.lock.wait();
529
			}
530
			
531
			// change status
532
			this.status = ActingAgentStatus.CLEARNING;
533
			// send signal 
534
			this.lock.notifyAll();
535
		}
536
		
537
		// clear queue
538
		this.queue.clear();
539
		// clear domain file specification
540
		this.ddl = null;
541
		// clear plan database 
542
		this.pdb = null;
543
		// clear PROXY
544
		this.proxy = null;
545
		
546
		synchronized (this.lock) {
547
			// change status
548
			this.status = ActingAgentStatus.RUNNING;
549
			// send signal
550
			this.lock.notifyAll();
551
		}
552
 	}
553
554
	/**
555
	 * 
556
	 * @return
557
	 * @throws InterruptedException
558
	 * @throws NoSolutionFoundException 
559
	 */
560
	protected boolean plan(Goal goal) 
561
			throws InterruptedException {
562
		
563
		// wait when planning can be actually performed if necessary
564
		synchronized (this.lock) {
565
			while (!this.status.equals(ActingAgentStatus.READY)) {
566
				// wait 
567
				this.lock.wait();
568
			}
569
			
570
			// change status
571
			this.status = ActingAgentStatus.DELIBERATING;
572
			// send signal
573
			this.lock.notifyAll();
574
		}
575
		
576
		// planning process result
577
		boolean success = true;
578
		
579
		// list of goal decisions
580
		List<Decision> goals = new ArrayList<>();
581
		// list of fact decisions
582
		List<Decision> facts = new ArrayList<>();
583
		try {
584
			
585
			// get task description
586
			AgentTaskDescription task = goal.getTaskDescription();
587
			// set known information concerning components
588 View Code Duplication
			for (TokenDescription f : task.getFacts()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
589
				
590
				// get domain component
591
				DomainComponent component = this.pdb.getComponentByName(f.getComponent());
592
				// get goal referred value
593
				ComponentValue value = component.getValueByName(f.getValue());
594
				// check start time bound
595
				long[] start = f.getStart();
596
				if (start == null) {
597
					start = new long[] {
598
						this.pdb.getOrigin(),
599
						this.pdb.getHorizon()
600
					};
601
				}
602
				
603
				// check end time bound
604
				long[] end = f.getEnd();
605
				if (end == null) {
606
					end = new long[] {
607
						this.pdb.getOrigin(),
608
						this.pdb.getHorizon()
609
					};
610
				}
611
				
612
				// check duration bound
613
				long[] duration = f.getDuration();
614
				if (duration == null) {
615
					duration = new long[] {
616
						value.getDurationLowerBound(),
617
						value.getDurationUpperBound()
618
					};
619
				}
620
				
621
				// check labels
622
				String[] labels = f.getLabels();
623
				if (labels == null) {
624
					labels = new String[] {};
625
				}
626
				
627
				// create fact decision
628
				Decision decision = component.create(
629
						value, 
630
						labels,
631
						start,
632
						end,
633
						duration
634
						);
635
				
636
				// also activate fact decision
637
				component.activate(decision);
638
				// add decision to fact list
639
				facts.add(decision);
640
			}
641
			
642
			// set planning goals 
643 View Code Duplication
			for (TokenDescription g : task.getGoals()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
644
				
645
				// get domain component
646
				DomainComponent component = this.pdb.getComponentByName(g.getComponent());
647
				// get goal referred value
648
				ComponentValue value = component.getValueByName(g.getValue());
649
				// check start time bound
650
				long[] start = g.getStart();
651
				if (start == null) {
652
					start = new long[] {
653
						this.pdb.getOrigin(),
654
						this.pdb.getHorizon()
655
					};
656
				}
657
				
658
				// check end time bound
659
				long[] end = g.getEnd();
660
				if (end == null) {
661
					end = new long[] {
662
						this.pdb.getOrigin(),
663
						this.pdb.getHorizon()
664
					};
665
				}
666
				
667
				// check duration bound
668
				long[] duration = g.getDuration();
669
				if (duration == null) {
670
					duration = new long[] {
671
						value.getDurationLowerBound(),
672
						value.getDurationUpperBound()
673
					};
674
				}
675
				
676
				// check labels
677
				String[] labels = g.getLabels();
678
				if (labels == null) {
679
					labels = new String[] {};
680
				}
681
				
682
				// create goal decision
683
				Decision decision = component.create(
684
						value, 
685
						labels,
686
						start,
687
						end,
688
						duration
689
						);
690
				
691
				// set as mandatory expansion decision
692
				decision.setMandatoryExpansion();
693
				// add decision to goal list
694
				goals.add(decision);
695
			}
696
			
697
			
698
			// start planning time
699
			long now = System.currentTimeMillis();
700
			try {
701
				
702
				// deliberate on the current status of the plan database
703
				SolutionPlan plan = this.deliberative.doHandle(this.pdb);
704
				// set generated plan
705
				goal.setPlan(plan);
706
				
707
			} catch (NoSolutionFoundException ex) {
708
				
709
				// failure - no plan can be found
710
				success = false;
711
				// remove and deactivate facts
712
				for (Decision f : facts) {
713
					f.getComponent().deactivate(f);
714
					f.getComponent().free(f);
715
				}
716
				
717
				// remove and deactivate goals
718
				for (Decision g : goals) {
719
					g.getComponent().deactivate(g);
720
					g.getComponent().free(g);
721
				}
722
				
723
			} finally {
724
				
725
				// compute actual planning time
726
				long time = System.currentTimeMillis() - now;
727
				// add planning time attempt to the goal
728
				goal.addPlanningAttempt(time);
729
			}
730
			
731
			
732
		} catch (DecisionPropagationException ex) {
733
			// problem setup error 
734
			success = false;
735
			// remove and deactivate facts
736
			for (Decision f : facts) {
737
				f.getComponent().deactivate(f);
738
				f.getComponent().free(f);
739
			}
740
			
741
			// remove and deactivate goals
742
			for (Decision g : goals) {
743
				g.getComponent().deactivate(g);
744
				g.getComponent().free(g);
745
			}
746
			
747
			// print an error message
748
			System.err.println("Error while propagating intial facts from task description:\n"
749
					+ "\t- message: " + ex.getMessage() + "\n");
750
		}
751
		
752
		
753
		// update agent status
754
		synchronized (this.lock) {
755
			
756
			// update status according to the result of the planning process
757
			if (success) {
758
				this.status = ActingAgentStatus.READY;
759
				
760
			} else {
761
				
762
				// failure
763
				this.status = ActingAgentStatus.FAILURE;
764
			}
765
			
766
			// send signal
767
			this.lock.notifyAll();
768
		}
769
		
770
		// return planning process result
771
		return success;
772
	}
773
	
774
	/**
775
	 * 
776
	 * @param goal
777
	 * @return
778
	 * @throws InterruptedException
779
	 */
780
	protected boolean execute(Goal goal) 
781
			throws InterruptedException {
782
		
783
		synchronized (this.lock) {
784
			while (!this.status.equals(ActingAgentStatus.READY)) {
785
				// wait
786
				this.lock.wait();
787
			}
788
			
789
			// update status
790
			this.status = ActingAgentStatus.EXECUTING;
791
			// send signal
792
			this.lock.notifyAll();
793
 		}
794
		
795
		// execution result
796
		boolean complete = true;
797
		// re-planning flag
798
		boolean replanning = false;
799
		// start execution time
800
		long now = System.currentTimeMillis();
801
		try {
802
			
803
			// execute the plan
804
			this.executive.doHandle(goal);
805
			
806
		} catch (ExecutionPreparationException ex) {
807
			
808
			// execution failure
809
			complete = false;
810
			// no re-planning since the execution has not even started
811
			replanning = false;
812
			
813
			// print message
814
			System.err.println(ex.getMessage());
815
			
816
		} catch (Exception ex) {
817
			
818
			// execution failure
819
			complete = false;
820
			// re-planning is necessary
821
			replanning = true;
822
			
823
			// print message
824
			System.err.println(ex.getMessage());
825
			
826
		} finally {
827
			
828
			// compute actual execution time
829
			long time = System.currentTimeMillis() - now;
830
			// add execution attempt time
831
			goal.addExecutionAttempt(time);
832
		}
833
		
834
		// update agent status
835
		synchronized (this.lock) {
836
			// update status according to the execution results
837
			if (complete || 
838
					!replanning) {
839
				
840
				// set ready status
841
				this.status = ActingAgentStatus.READY;
842
				
843
			} else {
844
				
845
				// suspend status for contingency handling and re-planning
846
				this.status = ActingAgentStatus.SUSPENDED;
847
			}
848
			
849
			// send signal
850
			this.lock.notifyAll();
851
		}
852
		
853
		// return execution result
854
		return complete || !replanning;
855
	}
856
	
857
	/**
858
	 * 
859
	 * @param goal
860
	 * @return
861
	 * @throws InterruptedException
862
	 */
863
	protected boolean repair(Goal goal) 
864
			throws InterruptedException
865
	{
866
		synchronized (this.lock) {
867
			while (!this.status.equals(ActingAgentStatus.SUSPENDED)) {
868
				// wait
869
				this.lock.wait();
870
			}
871
			
872
			// update status
873
			this.status = ActingAgentStatus.DELIBERATING;
874
			// send signal
875
			this.lock.notifyAll();
876
 		}
877
		
878
		// repairing result
879
		boolean success = true;
880
		// start contingency handling time
881
		long now = System.currentTimeMillis();
882
		try
883
		{
884
			// repair plan data
885
			System.out.println("\n\nPLAN REPAIR\n");
886
			
887
			// list of kept decisions 
888
			List<Decision> kept = new ArrayList<>();
889
			// clear domain components
890
			for (DomainComponent comp : this.pdb.getComponents())
891
			{
892
				// clear component 
893
				System.out.println("CLEAR COMPONENT : " + comp.getName() + "\n");
894
				
895
				// remove all pending decisions
896
				System.out.println("\nREMOVE ALL PENDING DECISIONS\n");
897
				// list of pending decisions
898
				List<Decision> pendings = comp.getPendingDecisions();
899
				for (Decision pending : pendings) 
900
				{
901
					// completely remove decision and related relations
902
					System.out.println("\nCLEAR DECISION " + pending + " AND RELATED RELATIONS");
903
					comp.deactivate(pending);
904
					comp.free(pending);
905
				}
906
				
907
				// get execution trace 
908
				List<ExecutionNode> trace = goal.getExecutionTraceByComponentName(comp.getName());
909
				// remove active decisions that have not been executed
910
				System.out.println("\nREMOVE ALL ACTIVE DECISIONS THAT HAVE NOT BEEN EXECUTED\n");
911
				// list of active decisions
912
				List<Decision> actives = comp.getActiveDecisions();
913
				for (Decision active : actives)
914
				{
915
					// check if the token has been executed
916
					System.out.println("\nACTIVE DECISION " + active + "\n");
917
					boolean executed = false;
918
					for (ExecutionNode node : trace) {
919
						// check if the temporal interval has been executed
920
						if (node.getInterval().equals(active.getToken().getInterval())){
921
							executed = true;
922
							break;
923
						}
924
					}
925
					
926
					// check flag
927
					if (executed) {
928
						// keep the decision as active
929
						System.out.println("\nKEEP DECISION AS ACTIVE SINCE ALREADY EXECUTED");
930
						kept.add(active);
931
					}
932
					else {
933
						// clear and remove decision and related relations
934
						System.out.println("\nREMOVE DECISION AND RELATED RELATIONS SINCE NOT EXECUTED");
935
						comp.deactivate(active);
936
						comp.free(active);
937
					}
938
				}
939
			}
940
			
941
			
942
			// check execution failure cause
943
			ExecutionFailureCause cause = goal.getFailureCause();
944
			// check type
945
			switch (cause.getType())
946
			{
947
				case NODE_DURATION_OVERFLOW : {
948
					// keep the decision as active and consider it as executed
949
					System.out.println("\nHANDLE DURATION OVERFLOW FAILURE\n");
950
					ExecutionNode node = cause.getInterruptionNode();
951
					// find the related decision
952
					for (DomainComponent comp : this.pdb.getComponents()) {
953
						// get active decisions
954
						List<Decision> actives = comp.getActiveDecisions();
955
						for (Decision active : actives) {
956
							// check temporal intervals
957
							if (node.getInterval().equals(active.getToken().getInterval())) {
958
								// keep the decision as active 
959
								System.out.println("\nKEEP DECISION " + active + "\n");
960
								kept.add(active);
961
							}
962
						}
963
					}
964
				}
965
				break;
966
				
967
				case NODE_EXECUTION_ERROR :
968
				case NODE_START_OVERFLOW : {
969
					// remove decisions they are going to be re-planned
970
					System.out.println("\nHANDLE START OVERFLOW FAILURE / EXECUTION ERRROR FAILURE\n");
971
					ExecutionNode node = cause.getInterruptionNode();
972
					// find the related decision
973
					for (DomainComponent comp : this.pdb.getComponents()) {
974
						// get active decisions
975
						List<Decision> actives = comp.getActiveDecisions();
976
						for (Decision active : actives) {
977
							// check temporal intervals
978
							if (node.getInterval().equals(active.getToken().getInterval())) {
979
								// keep the decision as active 
980
								System.out.println("\nREMOVE DECISION " + active + "\n");
981
								comp.deactivate(active);
982
								comp.free(active);
983
							}
984
						}
985
					}
986
				}
987
				break;
988
				
989
				default:
990
					throw new RuntimeException("Unknown Execution Failure Cause : " + cause.getType());
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
991
			}
992
			
993
			
994
			
995
			// get task description
996
			AgentTaskDescription task = goal.getTaskDescription();
997
			// set planning goals 
998
			for (TokenDescription g : task.getGoals()) 
999
			{
1000
				// get domain component
1001
				DomainComponent component = this.pdb.getComponentByName(g.getComponent());
1002
				// get goal referred value
1003
				ComponentValue value = component.getValueByName(g.getValue());
1004
				// check start time bound
1005
				long[] start = g.getStart();
1006
				if (start == null) {
1007
					start = new long[] {
1008
						this.pdb.getOrigin(),
1009
						this.pdb.getHorizon()
1010
					};
1011
				}
1012
				
1013
				// check end time bound
1014
				long[] end = g.getEnd();
1015
				if (end == null) {
1016
					end = new long[] {
1017
						this.pdb.getOrigin(),
1018
						this.pdb.getHorizon()
1019
					};
1020
				}
1021
				
1022
				// check duration bound
1023
				long[] duration = g.getDuration();
1024
				if (duration == null) {
1025
					duration = new long[] {
1026
						value.getDurationLowerBound(),
1027
						value.getDurationUpperBound()
1028
					};
1029
				}
1030
				
1031
				// check labels
1032
				String[] labels = g.getLabels();
1033
				if (labels == null) {
1034
					labels = new String[] {};
1035
				}
1036
				
1037
				/*
1038
				 * TODO : check parameter relations
1039
				 */
1040
				
1041
				// create goal decision
1042
				Decision decision = component.create(
1043
						value, 
1044
						labels,
1045
						start,
1046
						end,
1047
						duration,
1048
						ExecutionNodeStatus.IN_EXECUTION);
1049
				
1050
				// add decision to goal list
1051
				System.out.println("REPAIR GOAL : [" + decision.getId() +"]:" + decision.getComponent().getName() + "." + decision.getValue().getLabel() + " "
1052
						+ "AT [" + decision.getStart()[0]  + ", " + decision.getStart()[1] + "] "
1053
						+ "[" + decision.getEnd()[0] + ", " + decision.getEnd()[1] + "] "
1054
						+ "[" + decision.getDuration()[0] + ", " + decision.getDuration()[1] + "]");
1055
			}
1056
			
1057
			
1058
			// deliberate on the current status of the plan database
1059
			SolutionPlan plan = this.contingencyHandler.doHandle(
1060
					this.pClass, 
1061
					this.pdb);
1062
			
1063
			
1064
			// set repaired plan
1065
			goal.setPlan(plan);
1066
			// set goal as repaired
1067
			goal.setRepaired(true);
1068
			// set the tick the execution will start
1069
			goal.setExecutionTick(goal.getFailureCause().getInterruptionTick());
1070
			// clear execution trace
1071
			goal.clearExecutionTrace();
1072
		}
1073
		catch (Exception ex) 
1074
		{
1075
			// error while repairing
1076
			success = false;
1077
			// error message
1078
			System.err.println("Error while trying to repair the plan\n"
1079
					+ "\t- message: " + ex.getMessage() + "\n");
1080
			
1081
			// completely clear all the plan database
1082
			for (DomainComponent comp : this.pdb.getComponents()) {
1083
				// remove all pending decisions
1084
				List<Decision> pendings = comp.getPendingDecisions();
1085
				for (Decision pending : pendings) {
1086
					comp.deactivate(pending);
1087
					comp.free(pending);
1088
					
1089
				}
1090
				
1091
				// remove all active decisions
1092
				List<Decision> actives = comp.getActiveDecisions();
1093
				for (Decision active : actives) {
1094
					comp.deactivate(active);
1095
					comp.free(active);
1096
				}
1097
				
1098
				// finally completely clear component
1099
				comp.clear();
1100
			}
1101
		}
1102
		finally 
1103
		{
1104
			// compute actual planning time
1105
			long time = System.currentTimeMillis() - now;
1106
			// add planning time attempt to the goal
1107
			goal.addContingencyHandlingAttempt(time);
1108
			goal.addPlanningAttempt(time);
1109
		}
1110
		
1111
		
1112
		synchronized (this.lock) {
1113
			// update status according to the execution results
1114
			if (success) {
1115
				this.status = ActingAgentStatus.READY;
1116
			}
1117
			else {
1118
				this.status = ActingAgentStatus.FAILURE;
1119
			}
1120
			
1121
			// send signal
1122
			this.lock.notifyAll();
1123
		}
1124
		
1125
		// return execution result
1126
		return success;
1127
	}
1128
	
1129
	
1130
	
1131
	
1132
	
1133
	/**
1134
	 * 
1135
	 * @param status
1136
	 * @throws InterruptedException
1137
	 */
1138
	protected Goal waitGoal(GoalStatus status) 
1139
			throws InterruptedException
1140
	{
1141
		// goal 
1142
		Goal goal = null;
1143
		// wait a selected goal
1144
		synchronized (this.queue) {
1145
			// check selected buffer
1146
			while (this.queue.get(status).isEmpty()) {
1147
				// wait a selected goal
1148
				this.queue.wait();
1149
			}
1150
			
1151
			// remove the first selected goal from the queue
1152
			goal = this.queue.get(status).remove(0);
1153
			// send signal
1154
			this.queue.notifyAll();
1155
		}
1156
		
1157
		// get extracted goal
1158
		return goal;
1159
	}
1160
}
1161