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