Passed
Push — master ( 567b11...674e01 )
by Alessandro
26:11
created

repair(Goal)   F

Complexity

Conditions 28

Size

Total Lines 264
Code Lines 135

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 28
eloc 135
dl 0
loc 264
rs 0
c 1
b 0
f 0

How to fix   Long Method    Complexity   

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:

Complexity

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

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

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