1 package cz.cuni.amis.pogamut.sposh.elements;
2
3 import cz.cuni.amis.pogamut.sposh.elements.LapPath.Link;
4 import cz.cuni.amis.pogamut.sposh.engine.VariableContext;
5 import java.beans.PropertyChangeEvent;
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.LinkedList;
9 import java.util.List;
10 import java.util.Set;
11
12 interface IChainLink {
13
14 LapType getType();
15
16 Arguments getArgs();
17
18 FormalParameters getParams();
19
20 PoshElement getReference();
21
22 PoshElement getReferencedNode();
23
24 void register(LapChain chain);
25
26 void unregister(LapChain chain);
27 }
28
29
30
31
32 class ReferenceChainLink<REFERENCE_ELEMENT extends PoshElement & IReferenceElement> extends ChainLink {
33
34 private final REFERENCE_ELEMENT reference;
35 private final FormalParameters EMPTY_PARAMETERS = new FormalParameters();
36
37 public ReferenceChainLink(REFERENCE_ELEMENT reference) {
38 this.reference = reference;
39 }
40
41 @Override
42 public void register(LapChain chain) {
43 reference.addElementListener(chain);
44 }
45
46 @Override
47 public void unregister(LapChain chain) {
48 reference.removeElementListener(chain);
49 }
50
51 @Override
52 public LapType getType() {
53 return reference.getType();
54 }
55
56 @Override
57 public FormalParameters getParams() {
58 return EMPTY_PARAMETERS;
59 }
60
61 @Override
62 public Arguments getArgs() {
63 return reference.getArguments();
64 }
65
66 @Override
67 public REFERENCE_ELEMENT getReference() {
68 return reference;
69 }
70
71 @Override
72 public PoshElement getReferencedNode() {
73 return null;
74 }
75
76 @Override
77 public boolean equals(Object obj) {
78 if (obj == null) {
79 return false;
80 }
81 if (getClass() != obj.getClass()) {
82 return false;
83 }
84 final ReferenceChainLink<REFERENCE_ELEMENT> other = (ReferenceChainLink<REFERENCE_ELEMENT>) obj;
85 if (this.reference != other.reference) {
86 return false;
87 }
88 return true;
89 }
90
91 @Override
92 public int hashCode() {
93 int hash = 7;
94 return hash;
95 }
96 }
97
98
99
100
101 class ReferenceNodeChainLink<REFERENCED_NODE extends PoshElement & IParametrizedElement> extends ChainLink {
102
103 private final TriggeredAction action;
104 private final REFERENCED_NODE referencedNode;
105
106 public ReferenceNodeChainLink(REFERENCED_NODE referencedNode, TriggeredAction action) {
107 this.referencedNode = referencedNode;
108 this.action = action;
109 }
110
111 @Override
112 public LapType getType() {
113 return referencedNode.getType();
114 }
115
116 @Override
117 public final Arguments getArgs() {
118 return action.getArguments();
119 }
120
121 @Override
122 public final FormalParameters getParams() {
123 return referencedNode.getParameters();
124 }
125
126 @Override
127 public final TriggeredAction getReference() {
128 return action;
129 }
130
131 @Override
132 public REFERENCED_NODE getReferencedNode() {
133 return referencedNode;
134 }
135
136 @Override
137 public void register(LapChain chain) {
138 referencedNode.addElementListener(chain);
139 action.addElementListener(chain);
140 }
141
142 @Override
143 public void unregister(LapChain chain) {
144 action.removeElementListener(chain);
145 referencedNode.removeElementListener(chain);
146 }
147
148 @Override
149 public boolean equals(Object obj) {
150 if (obj == null) {
151 return false;
152 }
153 if (getClass() != obj.getClass()) {
154 return false;
155 }
156 final ReferenceNodeChainLink<REFERENCED_NODE> other = (ReferenceNodeChainLink<REFERENCED_NODE>) obj;
157 if (this.action != other.action) {
158 return false;
159 }
160 if (this.referencedNode != other.referencedNode) {
161 return false;
162 }
163 return true;
164 }
165
166 @Override
167 public int hashCode() {
168 int hash = 7;
169 return hash;
170 }
171 }
172
173
174
175
176
177
178 abstract class ChainLink implements IChainLink {
179
180 @Override
181 public String toString() {
182 return "{" + "params=" + getParams() + ", args=" + getArgs() + '}';
183 }
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public final class LapChain implements PoshElementListener {
203
204
205
206
207 private List<IChainLink> links;
208
209
210
211 private final Set<ILapChainListener> listeners = new HashSet<ILapChainListener>();
212
213
214
215
216 public LapChain() {
217 links = new LinkedList<IChainLink>();
218 }
219
220
221
222
223
224
225
226 public static LapChain fromPath(PoshPlan plan, LapPath path) {
227 LapChain chain = new LapChain();
228 Iterator<Link> iterator = path.iterator();
229 while (iterator.hasNext()) {
230 Link nodeLink = iterator.next();
231 int index = path.getLinkIndex(nodeLink) + 1;
232 LapPath nodePath = path.subpath(0, index);
233 PoshElement node = nodePath.traversePath(plan);
234 if (node instanceof TriggeredAction) {
235 TriggeredAction reference = (TriggeredAction) node;
236 chain = processReference(plan, path, chain, iterator, reference);
237 } else if (node instanceof Sense) {
238 chain = chain.derive((Sense) node);
239 } else {
240
241 }
242 }
243 return chain;
244 }
245
246 private static LapChain processReference(PoshPlan plan, LapPath path, LapChain chain, Iterator<Link> iterator, TriggeredAction reference) {
247 if (iterator.hasNext()) {
248 Link referencedNodeLink = iterator.next();
249 LapPath processedPath = path.subpath(0, path.getLinkIndex(referencedNodeLink) + 1);
250 PoshElement referencedNode = processedPath.traversePath(plan);
251 if (referencedNode instanceof Competence) {
252 chain = chain.derive(reference, (Competence) referencedNode);
253 } else if (referencedNode instanceof ActionPattern) {
254 chain = chain.derive(reference, (ActionPattern) referencedNode);
255 } else if (referencedNode instanceof Adopt) {
256 chain = chain.derive(reference, (Adopt) referencedNode);
257 } else {
258 throw new IllegalStateException("Node " + referencedNodeLink + " is not a referenced node.");
259 }
260 } else {
261 chain = chain.derive(reference);
262 }
263 return chain;
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279 public LapPath toPath() {
280 if (links.isEmpty()) {
281 return LapPath.DRIVE_COLLECTION_PATH;
282 }
283 LapPath path = LapPath.PLAN_PATH;
284 Iterator<IChainLink> it = links.iterator();
285 IChainLink link;
286 do {
287 link = it.next();
288 LapPath linkPath = LapPath.getLinkPath(link.getReference());
289 path = path.concat(linkPath);
290 } while (it.hasNext());
291
292 PoshElement referencedNode = link.getReferencedNode();
293 if (referencedNode != null) {
294 path = path.concat(referencedNode.getType(), referencedNode.getId());
295 }
296 return path;
297 }
298
299
300
301
302
303
304
305
306 private LapChain(LapChain chain, IChainLink link) {
307 this.links = new LinkedList<IChainLink>(chain.links);
308 this.links.add(link);
309 }
310
311
312
313
314
315 public void register() {
316 for (IChainLink link : links) {
317 link.register(this);
318 }
319 }
320
321
322
323
324 public void unregister() {
325 for (IChainLink link : links) {
326 link.unregister(this);
327 }
328 }
329
330
331
332
333
334
335
336
337
338 public <REFERENCED_NODE extends PoshElement & IParametrizedElement> LapChain derive(TriggeredAction action, REFERENCED_NODE referencedNode) {
339 assert action.getName().equals(referencedNode.getName());
340
341 return new LapChain(this, new ReferenceNodeChainLink(referencedNode, action));
342 }
343
344
345
346
347
348
349
350
351
352 public <REFERENCE extends PoshElement & IReferenceElement> LapChain derive(REFERENCE reference) {
353 return new LapChain(this, new ReferenceChainLink(reference));
354 }
355
356
357
358
359
360
361
362 public LapChain subchain(int beginIndex, int endIndex) {
363 LapChain subchain = new LapChain();
364 for (IChainLink link : links.subList(beginIndex, endIndex)) {
365 subchain = new LapChain(subchain, link);
366 }
367 return subchain;
368 }
369
370
371
372
373 public int size() {
374 return links.size();
375 }
376
377 @Override
378 public String toString() {
379 StringBuilder sb = new StringBuilder("Chain{");
380 boolean first = true;
381 for (IChainLink link : links) {
382 if (!first) {
383 sb.append(',');
384 }
385 sb.append(link.toString());
386 }
387 sb.append('}');
388
389 return sb.toString();
390 }
391
392
393
394
395 public VariableContext createContext() {
396 VariableContext ctx = new VariableContext();
397
398 for (IChainLink link : links) {
399 ctx = new VariableContext(ctx, link.getArgs(), link.getParams());
400 }
401 return ctx;
402 }
403
404 @Override
405 public void childElementAdded(PoshElement parent, PoshElement child) {
406 }
407
408 @Override
409 public void childElementMoved(PoshElement parent, PoshElement child, int oldIndex, int newIndex) {
410 }
411
412 @Override
413 public void childElementRemoved(PoshElement parent, PoshElement child, int removedChildPosition) {
414 }
415
416 @Override
417 public void propertyChange(PropertyChangeEvent evt) {
418 emitLinkChanged();
419 }
420
421 public boolean addChainListener(ILapChainListener listener) {
422 return listeners.add(listener);
423 }
424
425 public boolean removeChainListener(ILapChainListener listener) {
426 return listeners.remove(listener);
427 }
428
429 private void emitLinkChanged() {
430 ILapChainListener[] listenersArray = listeners.toArray(new ILapChainListener[listeners.size()]);
431
432 for (ILapChainListener listener : listenersArray) {
433 listener.notifyLinkChanged();
434 }
435 }
436
437 @Override
438 public boolean equals(Object obj) {
439 if (obj == null) {
440 return false;
441 }
442 if (getClass() != obj.getClass()) {
443 return false;
444 }
445 final LapChain other = (LapChain) obj;
446 if (this.links != other.links && (this.links == null || !this.links.equals(other.links))) {
447 return false;
448 }
449 return true;
450 }
451
452 @Override
453 public int hashCode() {
454 int hash = 3;
455 hash = 31 * hash + (this.links != null ? this.links.hashCode() : 0);
456 return hash;
457 }
458 }