source: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerationRule.java @ 619

Last change on this file since 619 was 619, checked in by pharms, 12 years ago
  • adapted implementation to now generate a full GUI model as well as concrete GUI interaction events
File size: 19.5 KB
Line 
1// Module    : $RCSfile: EventGenerationRule.java,v $
2// Version   : $Revision: 0.0 $  $Author: patrick $  $Date: 22.08.2012 $
3// Project   : quest-plugin-mfc
4// Creation  : 2012 by patrick
5// Copyright : Patrick Harms, 2012
6package de.ugoe.cs.quest.plugin.mfc;
7
8import java.util.ArrayList;
9import java.util.List;
10
11import org.jdom.Element;
12import org.jdom.Namespace;
13
14import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessageType;
15
16/**
17 * <p>
18 * TODO comment
19 * </p>
20 *
21 * @version $Revision: $ $Date: 22.08.2012$
22 * @author 2012, last modified by $Author: patrick$
23 */
24class EventGenerationRule {
25
26    /**
27     * <p>
28     * the namespace used for parsing the rule
29     * </p>
30     */
31    private Namespace namespace;
32
33    /**
34     * <p>
35     * the name of the rule
36     * </p>
37     */
38    private String name;
39
40    /**
41     * <p>
42     * the list of conditions for the rule to be matched
43     * </p>
44     */
45    private List<MessageCondition> messageConditions;
46
47    /**
48     * <p>
49     * the list of parameters to be provided to the generated event
50     * </p>
51     */
52    private List<Term> eventParameters;
53
54    /**
55     * <p>
56     * the list of replay message generation rules
57     * </p>
58     */
59    private List<ReplayMessageSpec> replayMessageSpecifications;
60
61    /**
62     * <p>
63     * TODO: comment
64     * </p>
65     *
66     * @param ruleElement
67     * @param rulesNamespace
68     */
69    @SuppressWarnings("unchecked")
70    EventGenerationRule(Element ruleElement, Namespace rulesNamespace) {
71        this.namespace = rulesNamespace;
72       
73        this.name = ruleElement.getAttributeValue("name");
74       
75        this.messageConditions = new ArrayList<MessageCondition>();
76        this.eventParameters = new ArrayList<Term>();
77        this.replayMessageSpecifications = new ArrayList<ReplayMessageSpec>();
78       
79        for (Element child : (List<Element>) ruleElement.getChildren()) {
80            if ("msg".equals(child.getName()) && namespace.equals(child.getNamespace())) {
81                messageConditions.add(new MessageCondition(child));
82            }
83            else if ("idinfo".equals(child.getName()) && namespace.equals(child.getNamespace())) {
84                for (Element parameterElements : (List<Element>) child.getChildren()) {
85                    eventParameters.add(new Term(parameterElements));
86                }
87            }
88            else if ("genMsg".equals(child.getName()) && namespace.equals(child.getNamespace())) {
89                replayMessageSpecifications.add(new ReplayMessageSpec(child));
90            }
91            else if ("genMsgSeq".equals(child.getName()) && namespace.equals(child.getNamespace())) {
92                replayMessageSpecifications.add(new ReplayMessageSpec(child));
93            }
94            else {
95                throw new IllegalArgumentException
96                    ("the provided rules can not be parsed: unknown element " + child.getName());
97            }
98        }
99    }
100
101    /**
102     * @return the name
103     */
104    String getName() {
105        return name;
106    }
107
108    /**
109     * <p>
110     * TODO: comment
111     * </p>
112     *
113     * @return
114     */
115    List<MessageCondition> getMessageConditions() {
116        return messageConditions;
117    }
118
119    /**
120     * <p>
121     * TODO: comment
122     * </p>
123     *
124     * @return
125     */
126    List<Term> getEventParameters() {
127        return eventParameters;
128    }
129
130    /**
131     * <p>
132     * TODO: comment
133     * </p>
134     *
135     * @return
136     */
137    List<ReplayMessageSpec> getReplayMessageSpecifications() {
138        return replayMessageSpecifications;
139    }
140
141    /**
142     * <p>
143     * TODO comment
144     * </p>
145     *
146     * @version $Revision: $ $Date: 22.08.2012$
147     * @author 2012, last modified by $Author: patrick$
148     */
149    class MessageCondition {
150
151        /**
152         * <p>
153         * true, if the condition defines to match several conditions
154         * </p>
155         */
156        private boolean matchMultiple;
157       
158        /**
159         * <p>
160         * the type of the message matched by the condition
161         * </p>
162         */
163        private WindowsMessageType messageType;
164
165        /**
166         * <p>
167         * the term conditions associate with the rule condition
168         * </p>
169         */
170        private List<AttributeCondition> attributeConditions;
171
172        /**
173         * <p>
174         * the list of messages to be stored, if the message matches, for continuing the
175         * rule application
176         * </p>
177         */
178        private ArrayList<Term> messagesToStore;
179
180        /**
181         * <p>
182         * TODO: comment
183         * </p>
184         *
185         * @param msgChild
186         */
187        @SuppressWarnings("unchecked")
188        private MessageCondition(Element msgChild) {
189            this.matchMultiple = "true".equals(msgChild.getAttributeValue("multiple"));
190            this.messageType =
191                WindowsMessageType.parseMessageType(msgChild.getAttributeValue("type"));
192           
193            this.attributeConditions = new ArrayList<AttributeCondition>();
194            for (Element childElement : (List<Element>) msgChild.getChildren("equals", namespace)) {
195                attributeConditions.add(new AttributeCondition(childElement));
196            }
197           
198            this.messagesToStore = new ArrayList<Term>();
199            for (Element childElement : (List<Element>) msgChild.getChildren("store", namespace)) {
200                messagesToStore.add(new Term(childElement));
201            }
202            for (Element childElement :
203                 (List<Element>) msgChild.getChildren("storeSeq", namespace))
204            {
205                messagesToStore.add(new Term(childElement));
206            }
207        }
208
209        /**
210         * @return the matchMultiple
211         */
212        boolean matchMultiple() {
213            return matchMultiple;
214        }
215
216        /**
217         * <p>
218         * TODO: comment
219         * </p>
220         *
221         * @return
222         */
223        WindowsMessageType getMessageType() {
224            return messageType;
225        }
226
227        /**
228         * <p>
229         * TODO: comment
230         * </p>
231         *
232         * @return
233         */
234        List<AttributeCondition> getAttributeConditions() {
235            return attributeConditions;
236        }
237
238        /**
239         * @return the valuesToStore
240         */
241        ArrayList<Term> getMessagesToStore() {
242            return messagesToStore;
243        }
244
245    }
246
247    /**
248     * <p>
249     * TODO comment
250     * </p>
251     *
252     * @version $Revision: $ $Date: 22.08.2012$
253     * @author 2012, last modified by $Author: patrick$
254     */
255    class AttributeCondition {
256
257        /**
258         * <p>
259         * the left hand side of the condition
260         * </p>
261         */
262        private Term leftHandSide;
263       
264        /**
265         * <p>
266         * the left hand side of the condition
267         * </p>
268         */
269        private Term rightHandSide;
270
271        /**
272         * <p>
273         * TODO: comment
274         * </p>
275         *
276         * @param childElement
277         */
278        private AttributeCondition(Element conditionElement) {
279            this.leftHandSide = new Term((Element) conditionElement.getChildren().get(0));
280            this.rightHandSide = new Term((Element) conditionElement.getChildren().get(1));
281        }
282       
283        /**
284         * @return the leftHandSide
285         */
286        Term getLeftHandSide() {
287            return leftHandSide;
288        }
289
290        /**
291         * @return the rightHandSide
292         */
293        Term getRightHandSide() {
294            return rightHandSide;
295        }
296
297    }
298
299    /**
300     * <p>
301     * TODO comment
302     * </p>
303     *
304     * @version $Revision: $ $Date: 22.08.2012$
305     * @author 2012, last modified by $Author: patrick$
306     */
307    class Term {
308
309        /**
310         * <p>
311         * the name of the term
312         * </p>
313         */
314        private String name;
315       
316        /**
317         * <p>
318         * the value of the term, if it is a constValue, null instead
319         * </p>
320         */
321        private String value;
322
323        /**
324         * <p>
325         * the variable name of the object, i.e. a message, of which a parameter is identified if
326         * the term is a winInfoValue or a msgInfoValue; null instead
327         * </p>
328         */
329        private String messageId;
330
331        /**
332         * <p>
333         * the name of the parameter of the object, e.g. a message, of which a parameter is
334         * identified if the term is a paramValue, null instead
335         * </p>
336         */
337        private String messageParameterName;
338
339        /**
340         * <p>
341         * the variable name of the message sequence denoted by the term in case of a seqValue;
342         * null instead
343         * </p>
344         */
345        private String sequenceId;
346
347        /**
348         * <p>
349         * the name of the parameter of the sequence of which a parameter is
350         * identified if the term is a seqValue, null instead
351         * </p>
352         */
353        private String sequenceParameterName;
354
355        /**
356         * <p>
357         * the name of the parameter of the window of the object, e.g. a message, of which a
358         * parameter is identified if the term is a winInfoValue, null instead
359         * </p>
360         */
361        private String windowParameterName;
362
363        /**
364         * <p>
365         * the name of the info of the message of which a parameter is identified if the
366         * term is a msgInfoValue, null instead
367         * </p>
368         */
369        private String messageInfoName;
370
371        /**
372         * <p>
373         * the name of the parameter of the message into which a value shall be stored if the
374         * term is a resolveHwnd, null instead
375         * </p>
376         */
377        private String storeParameterName;
378
379        /**
380         * <p>
381         * the list of handles to be resolved in case the term is a store or storeSeq, null instead
382         * </p>
383         */
384        private List<Term> resolveHandles;
385
386        /**
387         * <p>
388         * TODO: comment
389         * </p>
390         *
391         * @param object
392         */
393        @SuppressWarnings("unchecked")
394        private Term(Element termElement) {
395            this.name = termElement.getName();
396           
397            if ("constValue".equals(name)) {
398                this.value = termElement.getAttributeValue("value");
399            }
400            else if ("paramValue".equals(name)) {
401                this.messageId = termElement.getAttributeValue("obj");
402                this.messageParameterName = termElement.getAttributeValue("param");
403            }
404            else if ("winInfoValue".equals(name)) {
405                this.messageId = termElement.getAttributeValue("obj");
406                this.windowParameterName = termElement.getAttributeValue("winParam");
407            }
408            else if ("msgInfoValue".equals(name)) {
409                this.messageId = termElement.getAttributeValue("obj");
410                this.messageInfoName = termElement.getAttributeValue("msgParam");
411            }
412            else if ("seqValue".equals(name)) {
413                this.sequenceId = termElement.getAttributeValue("seqObj");
414                this.sequenceParameterName = termElement.getAttributeValue("param");
415            }
416            else if ("store".equals(name)) {
417                this.messageId = termElement.getAttributeValue("var");
418                if ((termElement.getChildren() != null) && (termElement.getChildren().size() > 0)) {
419                    this.resolveHandles = new ArrayList<Term>();
420                    for (Element child : (List<Element>) termElement.getChildren()) {
421                        this.resolveHandles.add(new Term(child));
422                    }
423                }
424            }
425            else if ("storeSeq".equals(name)) {
426                this.sequenceId = termElement.getAttributeValue("varSeq");
427                if ((termElement.getChildren() != null) && (termElement.getChildren().size() > 0)) {
428                    this.resolveHandles = new ArrayList<Term>();
429                    for (Element child : (List<Element>) termElement.getChildren()) {
430                        this.resolveHandles.add(new Term(child));
431                    }
432                }
433            }
434            else if ("resolveHwnd".equals(name)) {
435                this.messageParameterName = termElement.getAttributeValue("param");
436                this.storeParameterName = termElement.getAttributeValue("storeParam");
437            }
438        }
439
440        /**
441         * @return the name
442         */
443        String getName() {
444            return name;
445        }
446
447        /**
448         * @return the value
449         */
450        String getValue() {
451            return value;
452        }
453
454        /**
455         * @return the object
456         */
457        String getMessageId() {
458            return messageId;
459        }
460
461        /**
462         * @return the objectParameter
463         */
464        String getMessageParameterName() {
465            return messageParameterName;
466        }
467
468        /**
469         * @return the sequenceId
470         */
471        String getSequenceId() {
472            return sequenceId;
473        }
474
475        /**
476         * @return the sequenceParameter
477         */
478        String getSequenceParameterName() {
479            return sequenceParameterName;
480        }
481
482        /**
483         * @return the windowParameter
484         */
485        String getWindowParameterName() {
486            return windowParameterName;
487        }
488
489        /**
490         * @return the messageParameter
491         */
492        String getMessageInfoName() {
493            return messageInfoName;
494        }
495
496        /**
497         * @return the storeParameter
498         */
499        String getStoreParameterName() {
500            return storeParameterName;
501        }
502
503        /**
504         * @return the resolveHandles
505         */
506        List<Term> getResolveHandles() {
507            return resolveHandles;
508        }
509
510    }
511   
512    /**
513     * <p>
514     * TODO comment
515     * </p>
516     *
517     * @version $Revision: $ $Date: 22.08.2012$
518     * @author 2012, last modified by $Author: patrick$
519     */
520    class ReplayMessageSpec {
521
522        /**
523         * <p>
524         * determines, if this specification defines one, or a sequence of messages
525         * </p>
526         */
527        private boolean generateSingleMessage;
528       
529        /**
530         * <p>
531         * the id of a concrete message of message sequence to be replayed as is
532         * </p>
533         */
534        private String replayObjectId;
535
536        private Term type;
537
538        private Term target;
539
540        private Term lparamLoWord;
541
542        private Term lparamHiWord;
543
544        private Term lparam;
545
546        private Term wparamLoWord;
547
548        private Term wparamHiWord;
549
550        private Term wparam;
551
552        private int delay;
553       
554        /**
555         * <p>
556         * TODO: comment
557         * </p>
558         *
559         * @param child
560         */
561        @SuppressWarnings("unchecked")
562        private ReplayMessageSpec(Element replayMessageSpecElement) {
563            List<Element> children = replayMessageSpecElement.getChildren();
564            if ("genMsg".equals(replayMessageSpecElement.getName())) {
565                generateSingleMessage = true;
566                if (children.size() == 1) {
567                    replayObjectId = children.get(0).getAttributeValue("obj");
568                }
569            }
570            else {
571                generateSingleMessage = false;
572                if (children.size() == 1) {
573                    replayObjectId = children.get(0).getAttributeValue("seqObj");
574                }
575            }
576           
577            this.delay = Integer.parseInt(replayMessageSpecElement.getAttributeValue("delay"));
578           
579            if (children.size() > 1) {
580                for (Element child : children) {
581                    Element termElement = (Element) child.getChildren().get(0);
582                   
583                    if (child.getName().equals("type")) {
584                        this.type = new Term(termElement);
585                    }
586                    else if (child.getName().equals("target")) {
587                        this.target = new Term(termElement);
588                       
589                        if (!generateSingleMessage) {
590                            // in this case, the target is always a sequence value term, i.e.
591                            // the targets of the originally recorded sequence. So the
592                            // replay object id is set to this sequence
593                            replayObjectId = target.getSequenceId();
594                        }
595                    }
596                    else if (child.getName().equals("LPARAM")) {
597                        Element loWordElement = child.getChild("LOWORD", namespace);
598                        if (loWordElement != null) {
599                            this.lparamLoWord =
600                                new Term((Element) loWordElement.getChildren().get(0));
601                        }
602                       
603                        Element hiWordElement = child.getChild("HIWORD", namespace);
604                        if (hiWordElement != null) {
605                            this.lparamHiWord =
606                                 new Term((Element) hiWordElement.getChildren().get(0));
607                        }
608                       
609                        if ((lparamLoWord == null) && (lparamHiWord == null)) {
610                            this.lparam = new Term(termElement);
611                        }
612                    }
613                    else if (child.getName().equals("WPARAM")) {
614                        Element loWordElement = child.getChild("LOWORD", namespace);
615                        if (loWordElement != null) {
616                            this.wparamLoWord =
617                                new Term((Element) loWordElement.getChildren().get(0));
618                        }
619                       
620                        Element hiWordElement = child.getChild("HIWORD", namespace);
621                        if (hiWordElement != null) {
622                            this.wparamHiWord =
623                                 new Term((Element) hiWordElement.getChildren().get(0));
624                        }
625                       
626                        if ((wparamLoWord == null) && (wparamHiWord == null)) {
627                            this.wparam = new Term(termElement);
628                        }
629                    }
630                }
631            }
632        }
633
634        /**
635         * <p>
636         * TODO: comment
637         * </p>
638         *
639         * @return
640         */
641        boolean generateSingleMessage() {
642            return generateSingleMessage;
643        }
644
645        /**
646         * <p>
647         * TODO: comment
648         * </p>
649         *
650         * @return
651         */
652        String getReplayObjectId() {
653            return replayObjectId;
654        }
655
656        /**
657         * @return the type
658         */
659        Term getType() {
660            return type;
661        }
662
663        /**
664         * @return the target
665         */
666        Term getTarget() {
667            return target;
668        }
669
670        /**
671         * @return the lparamLoWord
672         */
673        Term getLparamLoWord() {
674            return lparamLoWord;
675        }
676
677        /**
678         * @return the lparamHiWord
679         */
680        Term getLparamHiWord() {
681            return lparamHiWord;
682        }
683
684        /**
685         * @return the lparam
686         */
687        Term getLparam() {
688            return lparam;
689        }
690
691        /**
692         * @return the wparamLoWord
693         */
694        Term getWparamLoWord() {
695            return wparamLoWord;
696        }
697
698        /**
699         * @return the wparamHiWord
700         */
701        Term getWparamHiWord() {
702            return wparamHiWord;
703        }
704
705        /**
706         * @return the wparam
707         */
708        Term getWparam() {
709            return wparam;
710        }
711
712        /**
713         * @return the delay
714         */
715        int getDelay() {
716            return delay;
717        }
718
719    }
720}
Note: See TracBrowser for help on using the repository browser.