source: trunk/quest-ui-core/src/main/java/de/ugoe/cs/quest/plugin/jfc/JFCReplayIDCalculator.java @ 560

Last change on this file since 560 was 539, checked in by fglaser, 12 years ago
  • getFuzzyTitle method of JFCReplayIDCalculator updated. Now it mimics GUITARs

behavior.

File size: 5.8 KB
Line 
1package de.ugoe.cs.quest.plugin.jfc;
2
3import java.util.Arrays;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.List;
7import java.util.Map;
8import java.util.regex.Matcher;
9import java.util.regex.Pattern;
10
11import de.ugoe.cs.quest.plugin.jfc.eventcore.JFCEvent;
12
13/**
14 * <p>
15 * This class provides the functionality to calculate the unique GUITAR replayIDs
16 * for {@link JFCEvent}s. This code is mainly based on guitar source code: edu.umd.cs.guitar.
17 * model.JFCDefaultIDGeneratorSimple
18 *   
19 * </p>
20 * @author fabian.glaser
21 *
22 */
23
24public class JFCReplayIDCalculator {
25       
26        final int prime = 31;
27       
28        /**
29         * Properties that are used to identify widgets
30         */
31        private static List<String> ID_PROPERTIES = Arrays.asList(
32                        "Class","Title","Icon");
33       
34        private static Map<String, Integer> ID_PROPERTIES_MAP;
35        static{
36                Map<String, Integer> idmap = new HashMap<String, Integer>(4);
37                idmap.put("Class", 1);
38                idmap.put("Title", 0);
39                idmap.put("Icon", 2);
40                idmap.put("Index", 3);
41                ID_PROPERTIES_MAP = Collections.unmodifiableMap(idmap);
42        }
43               
44       
45   /**
46    * Those classes are invisible widgets but cause false-positive when
47    * calculating ID (compare guitar source code: edu.umd.cs.guitar.
48    * model.JFCDefaultIDGeneratorSimple)
49    */
50   private static List<String> IGNORED_CLASSES = Arrays.asList("javax.swing.JPanel",
51         "javax.swing.JTabbedPane", "javax.swing.JScrollPane",
52         "javax.swing.JSplitPane", "javax.swing.Box",
53         "javax.swing.JViewport", "javax.swing.JScrollBar",
54         "javax.swing.JLayeredPane",
55         "javax.swing.JList$AccessibleJList$AccessibleJListChild",
56         "javax.swing.JList$AccessibleJList", "javax.swing.JList",
57         "javax.swing.JScrollPane$ScrollBar",
58         "javax.swing.plaf.metal.MetalScrollButton");
59       
60       
61        /**
62         * Calculates the replayID needed for compatibility with Guitar suite of a JFCEvent
63         * @param event for which the ID should be calculated
64         * @return replayID
65         */
66        public String calculateReplayID(JFCEvent event){
67                String replayID = "";
68                long hashCode = 1;
69               
70                // extract target string information
71                String target = event.getTarget();
72                String[] targetParts = target.split("\\]\\.\\[");
73               
74                // we assume that first component corresponds to the notion of a
75                // window in GUITAR suite
76               
77                // calculate window hashcode
78                String[] windowInfo = targetParts[0].split("','");
79                String title = windowInfo[0];
80                String fuzzyTitle = getFuzzyTitle(title);
81                long windowHashCode = fuzzyTitle.hashCode();
82                windowHashCode = (windowHashCode * 2) & 0xffffffffL;
83               
84                long propagatedHashCode = windowHashCode;
85               
86                for (int i = 1; i < targetParts.length; i++){
87                        long localHashCode = getLocalHashCode(targetParts[i]);
88                        hashCode = propagatedHashCode * prime + localHashCode;
89                hashCode = (hashCode * 2) & 0xffffffffL;
90                       
91                if (i < targetParts.length - 1){
92                        Integer index = getIndex(targetParts[i+1]);
93                                propagatedHashCode = prime * propagatedHashCode
94                                + index.hashCode();
95                }
96                }
97               
98                replayID = "e" + hashCode;
99               
100                return replayID;
101        }
102       
103        /**
104         * Calculates the hashcode part of one component.
105         * @param targetPart A string that represents a compontent
106         * @return the local hashcode
107         */
108       
109        private long getLocalHashCode(String targetPart){
110                long hashcode = 1;
111                String[] widgetInfo = targetPart.split("','");
112                widgetInfo[0] = widgetInfo[0].substring(1);
113                int length = widgetInfo.length - 1;
114                widgetInfo[length] = widgetInfo[length].substring(0,widgetInfo[length].length()-1);
115                String wClass = widgetInfo[ID_PROPERTIES_MAP.get("Class")];
116                if (IGNORED_CLASSES.contains(wClass)) {
117                    hashcode = (prime * hashcode + (wClass.equals("null") ? 0 : (wClass
118                               .hashCode())));
119                    return hashcode;
120                }
121                else{
122                        for (String property: ID_PROPERTIES){
123                                String value = widgetInfo[ID_PROPERTIES_MAP.get(property)];
124                                if (!value.equals("null")){
125                                        hashcode = prime * hashcode + property.hashCode();
126                                        hashcode = prime * hashcode + value.hashCode();
127                                }
128                        }
129                }
130               
131                hashcode = (hashcode * 2) & 0xffffffffL;
132               
133                return hashcode;
134        }
135       
136        /**
137         * Guitar has a special way to deal with window titles when
138         * calculating unique widget IDs. This method mimics Guitar's
139         * behavior (compare guitar source code: edu.umd.cs.guitar.
140         * model.JFCDefaultIDGeneratorSimple).
141         * @param title
142         * @return
143         */
144
145        private String getFuzzyTitle(String title){
146                final List<String> PATTERNS =
147                                Arrays.asList("Rachota .*",
148                                                "OmegaT-.*",
149                                                "Buddi.*",
150                                                "Open:.*",
151                                                "JabRef.*",
152                                                "GanttProject.*",
153                                                ".*Pauker.*",
154                                                ".*FreeMind.*",
155                                                ".* - ArgoUML.*",
156                                                "Save Project .*");
157
158
159                for (String sPattern : PATTERNS) {
160                        if (matchRegex(title, sPattern)) {
161                                return sPattern;
162                        }
163                }
164
165                return title;
166        }
167
168        /**
169         * Determine if the input string matches the input regex pattern.
170         * This method mimics Guitars behavior.
171         * Attempt to match the pattern 'sPattern' with the string 'sInputString'.
172
173         * @param sInputString    Input string to match with pattern
174         * @param sPattern        Regex pattern to match with string
175         * @return                True if match, false otherwise
176         */
177        private static boolean
178        matchRegex(String sInputString,
179                        String sPattern)
180        {
181                Pattern pattern;
182                Matcher matcher;
183
184                pattern = Pattern.compile(sPattern);
185                matcher = pattern.matcher(sInputString);
186                if (matcher.matches()) {
187                        return true;
188                }
189
190                return false;
191        }
192       
193        /**
194         * Extracts the index from a component string
195         * @param targetPart String that represents the component
196         * @return Index of the component
197         */
198       
199        private Integer getIndex(String targetPart){
200                String[] widgetInfo = targetPart.split("','");
201                String index = widgetInfo[ID_PROPERTIES_MAP.get("Index")];
202                if (index.equals("-1"))
203                                throw new AssertionError("Index should only be -1 for components" +
204                                                "that have no parent.");
205               
206                return Integer.parseInt(index);
207        }
208};
Note: See TracBrowser for help on using the repository browser.