1 package cz.cuni.amis.pogamut.sposh.elements;
2
3 import cz.cuni.amis.pogamut.sposh.exceptions.CycleException;
4 import cz.cuni.amis.pogamut.sposh.exceptions.DuplicateNameException;
5 import cz.cuni.amis.pogamut.sposh.exceptions.FubarException;
6 import cz.cuni.amis.pogamut.sposh.exceptions.InvalidNameException;
7 import cz.cuni.amis.pogamut.sposh.exceptions.MissingParameterException;
8 import java.awt.datatransfer.DataFlavor;
9 import java.text.MessageFormat;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.logging.Level;
15 import java.util.logging.Logger;
16
17
18
19
20
21
22
23
24
25
26
27 public final class ActionPattern extends PoshDummyElement<ActionPattern, PoshPlan> implements IParametrizedElement {
28
29
30
31
32 private String name;
33
34
35
36
37
38 @Deprecated
39 private String comment;
40
41
42
43 private final List<TriggeredAction> actions = new ArrayList<TriggeredAction>();
44
45
46
47 private final List<TriggeredAction> actionsUm = Collections.unmodifiableList(actions);
48
49
50
51 protected FormalParameters params;
52
53
54
55 public static final String apName = "apName";
56
57
58
59 public static final String apComment = "apComment";
60
61
62
63 public static final String apParams = "apParams";
64
65
66
67 public static final DataFlavor dataFlavor = new DataFlavor(ActionPattern.class, "action-pattern-node");
68
69
70
71
72
73
74
75
76
77 ActionPattern(String name, FormalParameters params, List<TriggeredAction> ap, String comment) {
78 assert name != null;
79 assert params != null;
80 assert comment != null;
81
82 this.name = name;
83 this.params = params;
84 this.comment = comment;
85
86 for (TriggeredAction action : ap) {
87 assert action.getParent() == null;
88 action.setParent(this);
89 actions.add(action);
90 }
91 }
92
93
94
95
96
97
98 public void addAction(TriggeredAction action) throws CycleException {
99 int beyondLastActionIndex = actionsUm.size();
100 addAction(beyondLastActionIndex, action);
101 }
102
103
104
105
106
107
108
109
110 public void addAction(int index, TriggeredAction action) throws CycleException {
111 assert !action.isChildOfParent();
112
113 action.setParent(this);
114 actions.add(index, action);
115
116 PoshPlan root = getRootNode();
117 if (root != null && root.isCycled()) {
118 actions.remove(action);
119 throw CycleException.createFromName(action.getName());
120 }
121 emitChildNode(action);
122 }
123
124 @Override
125 public String toString() {
126 StringBuilder sb = new StringBuilder("\t(AP ");
127 sb.append(name);
128
129
130 if (!params.isEmpty()) {
131 sb.append(" vars(");
132 sb.append(params.toString());
133 sb.append(")");
134 }
135
136 sb.append(" (");
137 boolean firstAction = true;
138 for (TriggeredAction action : actionsUm) {
139 if (!firstAction) {
140 sb.append(' ');
141 } else {
142 firstAction = false;
143 }
144 sb.append(action.toString());
145 }
146 sb.append(')');
147 if (!comment.isEmpty()) {
148 sb.append(" \"");
149 sb.append(comment);
150 sb.append('"');
151 }
152 sb.append(")\n");
153 return sb.toString();
154 }
155
156 @Override
157 public List<TriggeredAction> getChildDataNodes() {
158 return actionsUm;
159 }
160
161
162
163
164
165
166
167 public void setName(String name) throws InvalidNameException, DuplicateNameException, CycleException {
168 name = name.trim();
169
170 if (!name.matches(IDENT_PATTERN)) {
171 throw InvalidNameException.create(name);
172 }
173 if (!getName().equals(name)) {
174 if (getRootNode() != null && !getRootNode().isUniqueNodeName(name)) {
175 throw DuplicateNameException.create(name);
176 }
177 }
178
179 String oldName = this.name;
180 this.name = name;
181
182 if (getRootNode() != null && getRootNode().isCycled()) {
183 this.name = oldName;
184 throw CycleException.createFromName(name);
185 }
186
187 firePropertyChange(apName, oldName, name);
188 }
189
190
191
192
193
194
195 @Override
196 public String getName() {
197 return name;
198 }
199
200
201
202
203
204 public String getHtmlDescription() {
205 return "<html>Action pattern: " + getName() + "<br/><pre>" + toString() + "</pre></html>";
206 }
207
208 @Override
209 public boolean moveChild(int newIndex, PoshElement child) {
210 assert child instanceof TriggeredAction;
211 return moveChildInList(actions, (TriggeredAction) child, newIndex);
212 }
213
214 @Override
215 public DataFlavor getDataFlavor() {
216 return dataFlavor;
217 }
218
219 @Override
220 public LapType getType() {
221 return LapType.ACTION_PATTERN;
222 }
223
224
225
226
227
228
229 public void removeAction(TriggeredAction action) {
230 assert actions.contains(action);
231
232 if (actions.size() == 1) {
233 try {
234 addAction(LapElementsFactory.createAction());
235 } catch (CycleException ex) {
236 String msg = MessageFormat.format("Adding an action with default name {0} causes a cycle.", LapElementsFactory.DEFAULT_ACTION);
237 Logger.getLogger(ActionPattern.class.getName()).log(Level.SEVERE, msg, ex);
238 throw new FubarException(msg, ex);
239 }
240 }
241
242 int removedActionPosition = actionsUm.indexOf(action);
243
244 actions.remove(action);
245 action.setParent(null);
246
247 emitChildDeleted(action, removedActionPosition);
248 }
249
250
251
252
253
254
255 public List<TriggeredAction> getActions() {
256 return actionsUm;
257 }
258
259
260
261
262
263
264
265 @Override
266 public FormalParameters getParameters() {
267 return params;
268 }
269
270
271
272
273
274
275 @Deprecated
276 String getComment() {
277 return comment;
278 }
279
280
281
282
283
284
285 @Deprecated
286 void setComment(String newComment) {
287 assert newComment != null;
288 String oldComment = this.comment;
289 this.comment = newComment;
290
291 firePropertyChange(apComment, oldComment, newComment);
292 }
293
294
295
296
297
298
299 @Override
300 public void setParameters(FormalParameters newParams) {
301 FormalParameters oldParams = params;
302 this.params = newParams;
303
304 firePropertyChange(apParams, oldParams, newParams);
305 }
306
307
308
309
310
311
312
313
314
315
316 @Override
317 public void rename(String newAPName) throws InvalidNameException, DuplicateNameException, CycleException {
318 PoshPlan plan = getRootNode();
319 if (plan == null) {
320 throw new IllegalStateException("AP " + getName() + " is not part of a plan.");
321 }
322
323 List<TriggeredAction> planReferences = plan.getAllReferences();
324 List<TriggeredAction> referencingActions = new LinkedList<TriggeredAction>();
325
326 for (TriggeredAction planAction : planReferences) {
327 boolean actionReferencesAP = planAction.getName().equals(getName());
328 if (actionReferencesAP) {
329 referencingActions.add(planAction);
330 }
331 }
332
333
334 for (TriggeredAction referencingAction : referencingActions) {
335 referencingAction.setActionName(newAPName);
336 }
337
338 this.setName(newAPName);
339 }
340
341
342
343
344
345
346
347
348 public TriggeredAction getAction(int actionId) {
349 return actionsUm.get(actionId);
350 }
351 }