source: trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/guimodel/JFCGUIElementSpec.java @ 1876

Last change on this file since 1876 was 1722, checked in by dmay, 10 years ago

Implement new command, that generates Jacareto indices. Also, get rid of all previous index hacks.

File size: 12.0 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.plugin.jfc.guimodel;
16
17import java.util.ArrayList;
18import java.util.List;
19
20import org.apache.commons.collections15.CollectionUtils;
21
22import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
23import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec;
24
25/**
26 * <p>
27 * Implements the specification of {@link IGUIElement} for {@link JFCGUIElement}s.
28 * </p>
29 *
30 * @version 1.0
31 * @author Patrick Harms
32 */
33public class JFCGUIElementSpec implements IGUIElementSpec {
34
35    /**
36     * <p>
37     * Id for object serialization.
38     * </p>
39     */
40    private static final long serialVersionUID = 1L;
41
42    /**
43     * <p>
44     * Current name of the GUI element
45     * </p>
46     */
47    private String name;
48
49    /**
50     * <p>
51     * Previous names of the GUI element as it may have changed over time.
52     * </p>
53     */
54    private List<String> formerNames = new ArrayList<String>();
55
56    /**
57     * <p>
58     * Type of the GUI element, i.e., its Java class.
59     * </p>
60     */
61    private String type = null;
62
63    /**
64     * <p>
65     * Icon associated with the GUI element.
66     * </p>
67     */
68    private String icon = null;
69
70    /**
71     * <p>
72     * Index of the GUI element in its parent element.
73     * </p>
74     */
75    private int index = -1;
76
77    /**
78     * <p>
79     * An alternative index of the specified GUI element in its parent element. Each element type is
80     * counted separately. This index is used for replaying programs such as Jacareto.
81     * </p>
82     */
83    private int altIndex = -1;
84
85    /**
86     * <p>
87     * Hash code of the GUI element. Used as unique identifier during its existence.
88     * </p>
89     */
90    private int elementHash = -1;
91
92    /**
93     * <p>
94     * Previous hashes of the GUI element as the GUI element may have been destroyed and recreated.
95     * </p>
96     */
97    private List<Integer> formerElementHashes = new ArrayList<Integer>();
98
99    /**
100     * <p>
101     * Type hierarchy of the class itself
102     * </p>
103     */
104    private List<String> typeHierarchy = null;
105
106    /*
107     * (non-Javadoc)
108     *
109     * @see
110     * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getSecificationSimilarity(IGUIElementSpec
111     * )
112     */
113    @Override
114    public boolean getSimilarity(IGUIElementSpec other) {
115        if (this == other) {
116            return true;
117        }
118
119        if (!(other instanceof JFCGUIElementSpec)) {
120            return false;
121        }
122
123        JFCGUIElementSpec otherSpec = (JFCGUIElementSpec) other;
124
125        if (type == null ? otherSpec.type != null : !type.equals(otherSpec.type)) {
126            return false;
127        }
128
129        if (icon == null ? otherSpec.icon != null : !icon.equals(otherSpec.icon)) {
130            return false;
131        }
132
133        // up to now, we compared, if the basics match. Now lets compare the id, the name and the
134        // index. All may change. The name may be reset (e.g. the title of a frame using the
135        // asterisk in the case data was changed). The id may change if e.g. a dialog is closed
136        // and reopend, i.e. a new instance is created. The index may change, if later in a panel
137        // a new element is added or another one is removed. If the element hash or the name stay
138        // the same, then similarity is given. Therefore these are the first two comparisons
139
140        if (elementHash == otherSpec.elementHash) {
141            return true;
142        }
143
144        if ((name != null) && (name.equals(otherSpec.name))) {
145            return true;
146        }
147
148        if ((((name == null) && (otherSpec.name == null)) || (("".equals(name)) && (""
149            .equals(otherSpec.name)))) &&
150            (formerNames.size() == 0) &&
151            (otherSpec.formerNames.size() == 0))
152        {
153            return true;
154        }
155
156        // if the id and the name did not stay the same, then the name should be checked first.
157        // One of all known names of one of the specs must be equal to one of the known names of the
158        // respective other spec for similarity. Furthermore, if this is given, the index should
159        // have stayed the same.
160
161        if ((otherSpec.name != null) && formerNames.contains(otherSpec.name)) {
162            return index == otherSpec.index;
163        }
164
165        if ((name != null) && otherSpec.formerNames.contains(name)) {
166            return index == otherSpec.index;
167        }
168
169        if (CollectionUtils.containsAny(formerNames, otherSpec.formerNames)) {
170            return index == otherSpec.index;
171        }
172
173        // ok. Even the names do not match. This is usually a clear indication, that the elements
174        // are distinct. However, we check, if the former ids matched. This is very unlikely
175        // to happen. But it may occur, if a GUI element does not have a name or its name stays
176        // the empty string and if this GUI element is created, destroyed, and created again.
177        // Again we are restrictive and request the index to be equal as well.
178
179        if (formerElementHashes.contains(otherSpec.elementHash)) {
180            return index == otherSpec.index;
181        }
182
183        if (otherSpec.formerElementHashes.contains(elementHash)) {
184            return index == otherSpec.index;
185        }
186
187        if (CollectionUtils.containsAny(formerElementHashes, otherSpec.formerElementHashes)) {
188            return index == otherSpec.index;
189        }
190
191        // now we can be really sure, that the GUI elements differ
192
193        return false;
194    }
195
196    /*
197     * (non-Javadoc)
198     *
199     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#equals(IGUIElementSpec)
200     */
201    @Override
202    public boolean equals(Object other) {
203        if (this == other) {
204            return true;
205        }
206
207        if (!(other instanceof JFCGUIElementSpec)) {
208            return false;
209        }
210
211        JFCGUIElementSpec otherSpec = (JFCGUIElementSpec) other;
212
213        return (name == null ? otherSpec.name == null : name.equals(otherSpec.name)) &&
214            (type == null ? otherSpec.type == null : type.equals(otherSpec.type)) &&
215            (icon == null ? otherSpec.icon == null : icon.equals(otherSpec.icon)) &&
216            (index == otherSpec.index) && (elementHash == otherSpec.elementHash);
217    }
218
219    /*
220     * (non-Javadoc)
221     *
222     * @see java.lang.Object#hashCode()
223     */
224    @Override
225    public int hashCode() {
226        return (name + type + icon + index + elementHash).hashCode();
227    }
228
229    /**
230     * <p>
231     * Returns the name of the specified GUI element.
232     * </p>
233     *
234     * @return the name
235     */
236    public String getName() {
237        StringBuffer names = new StringBuffer();
238
239        if (name != null) {
240            names.append('"');
241            names.append(name);
242            names.append('"');
243        }
244        else {
245            names.append("NOT_SET");
246        }
247
248        if (formerNames.size() > 0) {
249
250            names.append(" (aka ");
251
252            for (int i = 0; i < formerNames.size(); i++) {
253                if (i > 0) {
254                    names.append("/");
255                }
256
257                names.append('"');
258                names.append(formerNames.get(i));
259                names.append('"');
260            }
261
262            names.append(")");
263        }
264
265        return names.toString();
266    }
267
268    /**
269     * <p>
270     * Returns the title of the specified GUI element.
271     * </p>
272     *
273     * @return the title
274     */
275    public String getType() {
276        return type;
277    }
278
279    /**
280     * <p>
281     * Returns the icon associated with the specified GUI element.
282     * </p>
283     *
284     * @return the icon
285     */
286    public String getIcon() {
287        return icon;
288    }
289
290    /**
291     * <p>
292     * Returns the index of the specified GUI element in its parent element.
293     * </p>
294     *
295     * @return the index
296     */
297    public int getIndex() {
298        return index;
299    }
300
301    /**
302     * <p>
303     * Returns an alternative index of the specified GUI element in its parent element. Each element
304     * type is counted separately.
305     * </p>
306     *
307     * @return the index
308     */
309    public int getAltIndex() {
310        return altIndex;
311    }
312
313    /**
314     * <p>
315     * Returns the object hash of the specified GUI element.
316     * </p>
317     *
318     * @return the elementHash
319     */
320    public int getElementHash() {
321        return elementHash;
322    }
323
324    /**
325     * <p>
326     * Sets the alternative index.
327     * </p>
328     *
329     * @param newAltIndex
330     *            the index
331     */
332    public void setAltIndex(int newAltIndex) {
333        altIndex = newAltIndex;
334    }
335
336    /**
337     * <p>
338     * Sets the name of the specified GUI element.
339     * </p>
340     *
341     * @param newName
342     *            the name
343     */
344    public void setName(String newName) {
345        if ((this.name != null) && (!this.name.equals(newName)) &&
346            (!this.formerNames.contains(this.name)))
347        {
348            this.formerNames.add(this.name);
349        }
350
351        this.name = newName;
352    }
353
354    /**
355     * <p>
356     * Sets the type of the specified GUI element.
357     * </p>
358     *
359     * @param type
360     *            the type
361     */
362    public void setType(String type) {
363        this.type = type;
364    }
365
366    /**
367     * <p>
368     * Sets the icon associated with the specified GUI element.
369     * </p>
370     *
371     * @param icon
372     *            the icon
373     */
374    public void setIcon(String icon) {
375        this.icon = icon;
376    }
377
378    /**
379     * <p>
380     * Sets the index in its parent element of the specified GUI element.
381     * </p>
382     *
383     * @param index
384     *            the index
385     */
386    public void setIndex(int index) {
387        this.index = index;
388    }
389
390    /**
391     * <p>
392     * Sets the object hash of the specified GUI element.
393     * </p>
394     *
395     * @param newElementHash
396     *            the element hash
397     */
398    public void setElementHash(int newElementHash) {
399        if ((this.elementHash > -1) && !this.formerElementHashes.contains(this.elementHash)) {
400            this.formerElementHashes.add(this.elementHash);
401        }
402
403        this.elementHash = newElementHash;
404    }
405
406    /**
407     * <p>
408     * Sets the type hierarchy of the specified GUI element.
409     *
410     * @param typeHierarchy
411     *            </p>
412     */
413    public void setTypeHierarchy(List<String> typeHierarchy) {
414        this.typeHierarchy = typeHierarchy;
415    }
416
417    /**
418     * <p>
419     * Updates the specification with another specification.
420     * </p>
421     *
422     * @param furtherSpec
423     *            specification used to update the current specification
424     */
425    void update(JFCGUIElementSpec other) {
426        if (other != this) {
427            for (int formerElementHash : other.formerElementHashes) {
428                setElementHash(formerElementHash);
429            }
430
431            if (elementHash != other.elementHash) {
432                elementHash = other.elementHash;
433            }
434
435            for (String formerName : other.formerNames) {
436                setName(formerName);
437            }
438
439            if ((name == null) || (!name.equals(other.name))) {
440                setName(other.name);
441            }
442        }
443    }
444
445    /*
446     * (non-Javadoc)
447     *
448     * @see java.lang.Object#toString()
449     */
450    public String toString() {
451        return "[" + getName() + ";\"" + type + "\";\"" + icon + "\";" + index + ";" + elementHash +
452            "]";
453    }
454
455    @Override
456    public String[] getTypeHierarchy() {
457        if (typeHierarchy == null) {
458            return new String[]
459                { (getType()) };
460        }
461        else
462            return typeHierarchy.toArray(new String[typeHierarchy.size()]);
463    }
464
465}
Note: See TracBrowser for help on using the repository browser.