source: trunk/autoquest-plugin-android/src/main/java/de/ugoe/cs/autoquest/plugin/android/guimodel/ANDROIDGUIElementSpec.java @ 2215

Last change on this file since 2215 was 2215, checked in by pharms, 7 years ago
  • java doc issues removal
  • Property svn:mime-type set to text/plain
File size: 10.3 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.android.guimodel;
16
17import java.util.List;
18
19import de.ugoe.cs.autoquest.eventcore.IEventTargetSpec;
20import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec;
21
22/**
23 * <p>
24 * Implements the {@link IGUIElementSpec} for {@link ANDROIDGUIElement}s.
25 * </p>
26 *
27 * @version 1.0
28 * @author Florian Unger
29 */
30public class ANDROIDGUIElementSpec implements IGUIElementSpec {
31
32    /**
33     * <p>
34     * Default serial version UID
35     * </p>
36     */
37    private static final long serialVersionUID = 1L;
38
39    /*
40     * (non-Javadoc)
41     *
42     * @see de.ugoe.cs.autoquest.androidmonitor.AndroidmonitorLogFile#logComponent()
43     */
44    /**
45     * <p>
46     * Hash code of the GUI element. Used as unique identifier during parsing a log file. Note that
47     * it is possible that the hash code of an element changes over several log files even if they
48     * come from the same target.
49     * </p>
50     */
51    private int elementHash;
52
53    /**
54     * <p>
55     * Path to an element in an activity. e.g. a path of a button could look like
56     * MainActivity/DecorView/ActionBarOverlayLayout/FrameLayout/RelativeLayout/Button
57     * </p>
58     */
59    private String path;
60
61    /*
62     * (non-Javadoc)
63     *
64     * @see http://developer.android.com/reference/android/view/View.html#getId()
65     */
66    /**
67     * <p>
68     * Id of the object as it is returned by view.getId().
69     * </p>
70     */
71    private int index;
72
73    /**
74     * <p>
75     * Current name of the GUI element
76     * </p>
77     */
78    private String name;
79
80    /**
81     * <p>
82     * The type of GUI element, i.e., the class of the android GUI element.
83     * </p>
84     */
85    private String type;
86
87    /**
88     * <p>
89     * The position of the element in the original GUI.
90     * </p>
91     */
92    private int elementPosition;
93
94    /**
95     * <p>
96     * Type hierarchy of the class itself.
97     * </p>
98     */
99    private List<String> typeHierarchy = null;
100
101    /*
102     * (non-Javadoc)
103     *
104     * @see
105     * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getSecificationSimilarity(IGUIElementSpec
106     * )
107     */
108    @Override
109    public boolean getSimilarity(IEventTargetSpec other) {
110        if (this == other) {
111            return true;
112        }
113
114        if (!(other instanceof ANDROIDGUIElementSpec)) {
115            return false;
116        }
117
118        ANDROIDGUIElementSpec otherSpec = (ANDROIDGUIElementSpec) other;
119
120        if (type == null ? otherSpec.type != null : !type.equals(otherSpec.type)) {
121            return false;
122        }
123
124        /*
125         * Up to now, we compared, if the basics match. Due to testing with different virtual
126         * devices it seems to be the case that the id of a view (named index here) keeps the same
127         * even on different devices even if the hashCode changes. Some of the GUI elements does not
128         * have an id (id is -1).
129         */
130
131        if (otherSpec.getIndex() > 1 && getIndex() == otherSpec.getIndex()) {
132            return true;
133        }
134
135        /*
136         * Path and label of the elements fits together. In this case it is most likely that this
137         * elements fits together. This only makes since in the case a label exists.
138         */
139        if (otherSpec.getName() != "NOT_SET" && getName() != "NOT_SET" &&
140            !otherSpec.getName().contains("image:") && getName().contains("image:") &&
141            otherSpec.getName() == getName() && otherSpec.getPath() == getPath())
142        {
143            return true;
144        }
145
146        /*
147         * Path and position fits together. In this case it is most likely that this elements fits
148         * together.
149         */
150        if (otherSpec.getPath() == getPath() &&
151            otherSpec.getElementPosition() == getElementPosition())
152        {
153            return true;
154        }
155
156        /*
157         * Two elements could also be similar if the path of the elements is equal and the name is
158         * set, equal and not equal to "image:" even if index <= 1. This comparison is not
159         * implemented up to know due to the reason that all recorded elements up to 2015/01 either
160         * have an index > 1 or no name to be compared.
161         *
162         * In all other cases up to know it is not clear if two elements are similar.
163         *
164         * Not working:
165         *
166         * - Position of the elements: Due to the reason that there are a lot of different displays
167         * on the android market and the in the most cases the layout depends on the display size
168         * (different resolutions) similar elements have different positions.
169         */
170
171        return false;
172    }
173
174    /*
175     * (non-Javadoc)
176     *
177     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getType()
178     */
179    @Override
180    public String getType() {
181        return type;
182    }
183
184    /*
185     * (non-Javadoc)
186     *
187     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getTypeHierarchy ()
188     */
189    @Override
190    public String[] getTypeHierarchy() {
191        if (typeHierarchy == null) {
192            return new String[]
193                { (getType()) };
194        }
195        else
196            return typeHierarchy.toArray(new String[typeHierarchy.size()]);
197    }
198
199    /**
200     * <p>
201     * Returns the object hash of the specified GUI element.
202     * </p>
203     *
204     * @return the elementHash
205     */
206    public int getElementHash() {
207        return elementHash;
208    }
209
210    /**
211     * <p>
212     * Returns the path associated with the specified GUI element.
213     * </p>
214     *
215     * @return the path to an element
216     */
217    public String getPath() {
218        return path;
219    }
220
221    /**
222     * <p>
223     * Returns the GUI element identifier.
224     * </p>
225     *
226     * @return identifier of the GUI element
227     */
228    public int getIndex() {
229        return index;
230    }
231
232    /**
233     * <p>
234     * Returns the name of the specified GUI element. Displayed text in the application or image
235     * name.
236     * </p>
237     *
238     * @return text or image of the GUI element.
239     */
240    public String getName() {
241        if (name == null || name.trim().length() == 0) {
242            return "NOT_SET";
243        }
244        return name;
245    }
246
247    /**
248     *
249     * <p>
250     * Return the position of the element in the original GUI.
251     * </p>
252     *
253     * @return position of the element in the original GUI.
254     */
255    public int getElementPosition() {
256        return elementPosition;
257    }
258
259    /**
260     *
261     * <p>
262     * Set the position of the element in the original GUI.
263     * </p>
264     */
265    public void setElementPosition(int elementPosition) {
266        this.elementPosition = elementPosition;
267    }
268
269    /**
270     * <p>
271     * Sets the GUI element identifier.
272     * </p>
273     *
274     * @param indentifier
275     */
276    public void setIndex(int index) {
277        this.index = index;
278    }
279
280    /**
281     * Set the hash code associated with the GUI element.
282     *
283     * @param hash
284     *            the hash of an element object
285     */
286    public void setElementHash(int hash) {
287        this.elementHash = hash;
288    }
289
290    /**
291     * Set the path associated with the specified GUI element.
292     *
293     * @param path
294     *            the path to an element
295     */
296    public void setPath(String path) {
297        this.path = path;
298    }
299
300    /**
301     * <p>
302     * Sets the type of the specified GUI element.
303     * </p>
304     *
305     * @param type
306     *            the type
307     */
308    public void setType(String type) {
309        this.type = type;
310    }
311
312    /**
313     * <p>
314     * Sets the name of the specified GUI element. Displayed text in the application or image name.
315     * </p>
316     *
317     * @param name
318     *            the name
319     */
320    public void setName(String name) {
321        this.name = name;
322    }
323
324    /**
325     * <p>
326     * Sets the type hierarchy of the specified GUI element.
327     * </p>
328     */
329    public void setTypeHierarchy(List<String> typeHierarchy) {
330        this.typeHierarchy = typeHierarchy;
331    }
332
333    /*
334     * (non-Javadoc)
335     *
336     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#equals(IGUIElementSpec)
337     */
338    @Override
339    public boolean equals(Object other) {
340        if (this == other) {
341            return true;
342        }
343
344        if (!(other instanceof ANDROIDGUIElementSpec)) {
345            return false;
346        }
347
348        ANDROIDGUIElementSpec otherSpec = (ANDROIDGUIElementSpec) other;
349
350        return (elementHash == otherSpec.elementHash) &&
351            (path == null ? otherSpec.path == null : path.equals(otherSpec.path)) &&
352            (index == otherSpec.index) &&
353            (elementPosition == otherSpec.elementPosition) &&
354            (name == null ? otherSpec.name == null : name.equals(otherSpec.name)) &&
355            (type == null ? otherSpec.type == null : type.equals(otherSpec.type));
356    }
357
358    /*
359     * (non-Javadoc)
360     *
361     * @see java.lang.Object#hashCode()
362     */
363    @Override
364    public int hashCode() {
365        // 17 due to the reason that this is a prime number.
366        int result = 17;
367        /*
368         * 31 due to the reason that a lot of VM's could optimize this multiplication by a shift.
369         * Source: Effective Java, Joshua Bloch, 2008, p.48
370         */
371        result = 31 * result + elementHash;
372        result = 31 * result + path.hashCode();
373        result = 31 * result + index;
374        result = 31 * result + getName().hashCode();
375        result = 31 * result + type.hashCode();
376        result = 31 * result + elementPosition;
377        return result;
378    }
379
380}
Note: See TracBrowser for help on using the repository browser.