1 package cz.cuni.amis.pogamut.sposh.engine;
2
3 import cz.cuni.amis.pogamut.sposh.elements.ActionPattern;
4 import cz.cuni.amis.pogamut.sposh.elements.LapPath;
5 import cz.cuni.amis.pogamut.sposh.elements.LapType;
6 import cz.cuni.amis.pogamut.sposh.elements.PoshPlan;
7 import cz.cuni.amis.pogamut.sposh.elements.PrimitiveCall;
8 import cz.cuni.amis.pogamut.sposh.elements.TriggeredAction;
9 import cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor;
10
11 /**
12 * Executor for AP. If successfull, return specified result, otherwise FAIL.
13 *
14 * @author Honza
15 */
16 @SuppressWarnings("unchecked")
17 class APExecutor extends AbstractExecutor implements ElementExecutor {
18
19 /**
20 * Plan this executor is using to resolve actions and so on.
21 */
22 private final PoshPlan plan;
23 /**
24 * The pattern this executor is executing.
25 */
26 private final ActionPattern actionPattern;
27 /**
28 * Index of action that will be executed in the next call of {@link #fire(cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor)
29 * }. At the start, it is 0 (because first action should be exeucted). Once
30 * it is equal to size of {@link ActionPattern#getActions()}, we have
31 * finished this {@link APExecutor}.
32 */
33 private int index = 0;
34 /**
35 * Once this {@link APExecutor} finished all its actions (i.e. all its
36 * actions have properly been fired and surfaced back here), return this.
37 *
38 * TODO: Is this even needed? SURFACE fo all should be sufficient.
39 */
40 private FireResult.Type result;
41
42 /**
43 * Create a new AP executor
44 *
45 * @param plan plan, we will use it to look up what are actions in ap
46 * @param ap ap that will be executed.
47 * @param result what to return in case of successful AP execution (SURFACE
48 * or FULFILLED)
49 * @param ctx
50 * @param log logger to record actions of this executor
51 */
52 APExecutor(PoshPlan plan, ActionPattern ap, FireResult.Type result, LapPath apPath, VariableContext ctx, EngineLog log) {
53 super(apPath, ctx, log);
54
55 assert apPath.traversePath(plan) == ap;
56
57 this.plan = plan;
58 this.actionPattern = ap;
59 this.index = 0;
60 this.result = result;
61 }
62
63 @Override
64 public FireResult fire(IWorkExecutor workExecuter) {
65 engineLog.pathReached(path);
66 if (index == actionPattern.getActions().size()) {
67 return new FireResult(result);
68 }
69 // index is not incremented here, it should be done only whenever the action finishes its execution,
70 // see createActionExecutor()
71 TriggeredAction action = actionPattern.getActions().get(index);
72 StackElement stackElement = createActionExecutor(action.getActionCall());
73 return new FireResult(FireResult.Type.FOLLOW, stackElement);
74 }
75
76 /**
77 * Create an executor for the passed action according to what it really is
78 * (C/AP/P).
79 *
80 * @param plan
81 * @param action
82 * @return
83 */
84 private StackElement createActionExecutor(PrimitiveCall actionCall) {
85 LapPath actionPath = path.concat(LapType.ACTION, index);
86 StackElement element = getElement(plan, actionCall, actionPath,
87 new Runnable() { // FINISHED CALLBACK
88
89 @Override
90 public void run() {
91 ++index;
92 }
93 },
94 null,
95 new Runnable() { // RUNNING ONCE CALLBACK
96
97 @Override
98 public void run() {
99 ++index;
100 }
101 },
102 null);
103 if (element.getExecutor() instanceof APExecutor) {
104 // APExecutor won't trigger SUCCESS-CALLBACK ... must manually move index of next-to-be-executed action
105 ++index;
106 }
107 return element;
108 }
109 }