Total Complexity | 94 |
Total Lines | 1156 |
Duplicated Lines | 8.82 % |
Changes | 2 | ||
Bugs | 0 | Features | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like it.cnr.istc.pst.platinum.control.acting.GoalOrientedActingAgent 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; |
||
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<>(); |
||
|
|||
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\"!"); |
||
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 + "\"!"); |
||
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()); |
||
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) { |
||
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()) |
|
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()) |
|
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()); |
||
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 | } |
||
1199 |
The Java documentation explain EnumMap.