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

task(AgentTaskDescription)   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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