1 package cz.cuni.amis.pogamut.sposh.engine;
2
3 import cz.cuni.amis.pogamut.sposh.elements.DriveElement;
4 import cz.cuni.amis.pogamut.sposh.elements.Freq;
5 import cz.cuni.amis.pogamut.sposh.elements.LapPath;
6 import cz.cuni.amis.pogamut.sposh.elements.LapType;
7 import cz.cuni.amis.pogamut.sposh.elements.PoshPlan;
8 import cz.cuni.amis.pogamut.sposh.elements.PrimitiveCall;
9 import cz.cuni.amis.pogamut.sposh.engine.timer.ITimer;
10 import cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor;
11 import java.util.ArrayList;
12 import java.util.List;
13
14
15
16
17
18 class DEExecutor extends AbstractExecutor {
19 private final PoshPlan plan;
20 private final DriveElement drive;
21 private final SenseListExecutor<DriveElement> trigger;
22 private final Freq freq;
23 private long lastFired = Integer.MAX_VALUE;
24 private ElementStackTrace stackTrace = new ElementStackTrace();
25
26 DEExecutor(PoshPlan plan, DriveElement de, LapPath drivePath, VariableContext ctx, EngineLog log) {
27 super(drivePath, ctx, log);
28
29 assert drivePath.traversePath(plan) == de;
30
31 this.plan = plan;
32 this.drive = de;
33 this.freq = de.getFreq();
34 this.trigger = new SenseListExecutor<DriveElement>(de.getTrigger(), drivePath, ctx, log);
35 }
36
37 private LapPath createDriveActionPath() {
38 return path.concat(LapType.ACTION, 0);
39 }
40
41 private StackElement createInitialStackElement(PoshPlan plan, PrimitiveCall actionCall) {
42 LapPath driveActionPath = createDriveActionPath();
43 return getElement(plan, actionCall, driveActionPath);
44 }
45
46
47
48
49
50
51
52
53 public synchronized boolean isReady(long timestamp, IWorkExecutor workExecuter) {
54 long passed = timestamp - lastFired;
55
56 if (Freq.compare(freq.tick(), passed) > 0) {
57 engineLog.fine("Max.firing frequency for drive " + drive.getName() + " exceeded, has to be at least " + freq.tick() + "ms, but was only " + passed);
58 return false;
59 }
60 TriggerResult triggerResult = trigger.fire(workExecuter, true);
61 return triggerResult.wasSuccess();
62 }
63
64
65
66
67
68
69
70 public synchronized FireResult.Type fire(IWorkExecutor workExecuter, ITimer timer) {
71 engineLog.pathReached(path);
72
73
74 List<CExecutor> competences = new ArrayList<CExecutor>();
75 for (int i = stackTrace.size()-1; i >= 0; --i) {
76 StackElement element = stackTrace.get(i);
77 if (element.getExecutor() instanceof CExecutor) {
78 competences.add((CExecutor) element.getExecutor());
79 continue;
80 }
81 if (element.getExecutor() instanceof ADExecutor) {
82
83 if (((ADExecutor)element.getExecutor()).isExit(workExecuter)) {
84
85
86 stackTrace.cutDownToIncluding(element.getExecutor());
87 competences.clear();
88 } else {
89
90
91 break;
92 }
93 continue;
94 }
95 }
96
97
98 for (int i = competences.size()-1; i >= 0; --i) {
99 CExecutor competence = competences.get(i);
100 if (competence.isGoalSatisfied(workExecuter)) {
101
102
103 stackTrace.cutDownToIncluding(competence);
104 break;
105 }
106 }
107
108
109 if (stackTrace.isEmpty()) {
110 PrimitiveCall actionCall = drive.getAction().getActionCall();
111 engineLog.finest("Stack of drive " + drive.getName() + " is empty, adding initial element: " + actionCall.toString());
112 stackTrace.add(createInitialStackElement(plan, actionCall));
113 return FireResult.Type.CONTINUE;
114 }
115
116
117 FireResult result = stackTrace.peek().getExecutor().fire(workExecuter);
118 lastFired = timer.getTime();
119
120 engineLog.fine("The fired element returned: " + result.getType());
121 switch (result.getType()) {
122 case FULFILLED:
123
124
125
126
127
128 stackTrace.removeAllElements();
129 break;
130 case FAILED:
131
132 stackTrace.removeAllElements();
133 break;
134 case FOLLOW:
135
136
137
138 stackTrace.push(result.getNextElement());
139 break;
140 case CONTINUE:
141
142
143 break;
144 case SURFACE:
145 case SURFACE_CONTINUE:
146
147
148 stackTrace.pop();
149 break;
150 default:
151 throw new IllegalStateException("State \"" + result.getType() + "\" not expected. Serious error.");
152 }
153 return result.getType();
154 }
155
156 ElementStackTrace getStackTrace() {
157 return stackTrace;
158 }
159
160
161
162
163
164 public String getName() {
165 return drive.getName();
166 }
167
168
169
170
171 public void driveInterrupted() {
172
173 while (stackTrace.size() > 0 && !(stackTrace.peek().getExecutor() instanceof ADExecutor)) {
174 stackTrace.pop();
175 }
176 }
177 }