source: trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/AbstractDefaultGUIElement.java @ 1024

Last change on this file since 1024 was 1010, checked in by fglaser, 12 years ago
  • new method getUsageObserved() in IGUIElement, implemented in AbstractDefaultGUIElement. AbstractDefaultGUIElement now also

has markAsUsed() method, that sets internal boolean usageObserved to true.

  • JFCSimplifiedLogParser and MFCLogParser were updated and now mark GUI elements that have been targeted during a session as used.
  • Property svn:executable set to *
File size: 9.6 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.eventcore.guimodel;
16
17import java.util.IdentityHashMap;
18import java.util.LinkedList;
19import java.util.List;
20
21/**
22 * <p>
23 * Skeletal implementation for GUI elements.
24 * </p>
25 *
26 * @version 1.0
27 * @author Patrick Harms
28 */
29public abstract class AbstractDefaultGUIElement implements IGUIElement {
30
31    /**
32     * <p>
33     * Id for object serialization.
34     * </p>
35     */
36    public static final long serialVersionUID = 1L;
37
38    /**
39     * <p>
40     * The reference to equal GUI element manager (needed to preserve singleton behavior, even
41     * though the objects are not singleton).
42     * </p>
43     */
44    private static final EqualGUIElementManager equalGUIElementManager =
45        new EqualGUIElementManager();
46
47    /**
48     * <p>
49     * Specification of the GUI element
50     * </p>
51     */
52    private final IGUIElementSpec specification;
53
54    /**
55     * <p>
56     * Reference to the parent element
57     * </p>
58     */
59    private final IGUIElement parent;
60   
61    /**
62     * <p>
63     * Boolean that indicates if a GUIElement was used during a session.
64     * </p>
65     */
66    boolean usageObserved;
67
68    /**
69     * <p>
70     * Constructor. Creates a new AbstractDefaultGUIElement.
71     * </p>
72     *
73     * @param specification
74     *            specification of the created GUI element
75     * @param parent
76     *            parent of the created GUI element; null means the element is a top-level window
77     */
78    public AbstractDefaultGUIElement(IGUIElementSpec specification, IGUIElement parent) {
79        this.specification = specification;
80        this.parent = parent;
81        this.usageObserved = false;
82    }
83
84    /*
85     * (non-Javadoc)
86     *
87     * @see de.ugoe.cs.tasktree.guimodel.GUIElement#getSpecification()
88     */
89    @Override
90    public IGUIElementSpec getSpecification() {
91        return specification;
92    }
93
94    /*
95     * (non-Javadoc)
96     *
97     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getParent()
98     */
99    @Override
100    public IGUIElement getParent() {
101        return parent;
102    }
103
104    /*
105     * (non-Javadoc)
106     *
107     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#addEqualGUIElement(IGUIElement)
108     */
109    @Override
110    public void addEqualGUIElement(IGUIElement equalElement) {
111        equalGUIElementManager.addEqualGUIElements(this, equalElement);
112    }
113
114    /*
115     * (non-Javadoc)
116     *
117     * @see GUIElement#equals(GUIElement)
118     */
119    public final boolean equals(Object other) {
120        // implement final, as GUI elements are all singletons and they equal only if they are the
121        // same object or if they are in the list of equal GUI elements
122        return super.equals(other) || equalGUIElementManager.equals(this, other);
123    }
124
125    /*
126     * (non-Javadoc)
127     *
128     * @see java.lang.Object#hashCode()
129     */
130    @Override
131    public final int hashCode() {
132        // implement final, as GUI elements are all singletons and they equal only if they are the
133        // same object. If there are several GUI element objects that represent the same GUI element
134        // then they are stored in the list of equal elements. In this case, the hash code of the
135        // list is unique within the system
136        return equalGUIElementManager.hashCode(this);
137    }
138   
139        @Override
140        public boolean getUsageObserved() {
141                return usageObserved;
142        }
143       
144        /**
145         * <p>
146         * Marks a GUI element as used.
147         * </p>
148         */
149        public void markAsUsed(){
150                this.usageObserved = true;
151        }
152
153    /**
154     * <p>
155     * This internal helper class manages equal GUI elements. This is necessary, as we often first
156     * identify many GUI elements as different and later use a heuristic to determine that they are
157     * the same. This class provides the means to preserve the singleton behavior of the GUI
158     * elements after we merge two GUI elements.
159     * </p>
160     *
161     * @version 1.0
162     * @author Patrick Harms
163     */
164    private static class EqualGUIElementManager {
165
166        /**
167         * <p>
168         * The internal map of GUI elements mapping each registered element to its equal variants.
169         * We use the {@link IdentityHashMap} as a normal hash map would not work because of the
170         * changing of the hash code of GUI elements at runtime.
171         * </p>
172         */
173        private IdentityHashMap<IGUIElement, List<IGUIElement>> identityHashMap =
174            new IdentityHashMap<IGUIElement, List<IGUIElement>>();
175
176        /**
177         * <p>
178         * Adds a new equals relationship between two {@link IGUIElement}s to the equality manager.
179         * </p>
180         *
181         * @param guiElement1
182         *            first equal GUI element
183         * @param guiElement2
184         *            second equal GUI element
185         */
186        private synchronized void addEqualGUIElements(IGUIElement guiElement1,
187                                                      IGUIElement guiElement2)
188        {
189            List<IGUIElement> list1 = identityHashMap.get(guiElement1);
190            List<IGUIElement> list2 = identityHashMap.get(guiElement2);
191
192            if (list1 == null) {
193                if (list2 == null) {
194                    list2 = new LinkedList<IGUIElement>();
195                    list2.add(guiElement1);
196                    list2.add(guiElement2);
197                    identityHashMap.put(guiElement1, list2);
198                    identityHashMap.put(guiElement2, list2);
199                }
200                else {
201                    addIfNotContained(list2, guiElement1);
202                    identityHashMap.put(guiElement1, list2);
203                }
204            }
205            else {
206                if (list2 == null) {
207                    addIfNotContained(list1, guiElement2);
208                    identityHashMap.put(guiElement2, list1);
209                }
210                else if (list1 != list2) {
211                    list1.addAll(list2);
212                    identityHashMap.put(guiElement2, list1);
213                }
214                // else
215                // in this case, both GUI elements should already be registered with the same
216                // lists.
217            }
218        }
219
220        /**
221         * <p>
222         * Returns the object hash of a {@link IGUIElement}.
223         * </p>
224         *
225         * @param guiElement
226         *            gui element whose object hash is determined
227         * @return the object hash
228         */
229        private synchronized int hashCode(IGUIElement guiElement) {
230            return System.identityHashCode(getEqualElementsList(guiElement));
231        }
232
233        /**
234         * <p>
235         * Determines the equality of two {@link IGUIElement}s based on the information of the
236         * identify manager. Two elements are equal, if they have been added as equal using
237         * {@link #addEqualGUIElements(IGUIElement, IGUIElement)}.
238         * </p>
239         *
240         * @param guiElement
241         *            GUI element to which the object is compared
242         * @param other
243         *            object that is compared to the GUI element
244         * @return
245         */
246        private synchronized boolean equals(IGUIElement guiElement, Object other) {
247            if (other instanceof IGUIElement) {
248                for (IGUIElement candidate : getEqualElementsList(guiElement)) {
249                    if (candidate == other) {
250                        return true;
251                    }
252                }
253            }
254
255            return false;
256        }
257
258        /**
259         * <p>
260         * Returns the equal {@link IGUIElement} of a given {@link IGUIElement}.
261         * </p>
262         *
263         * @param guiElement
264         *            GUI element of which the equal elements are returned
265         * @return the equal GUI elements
266         */
267        private List<IGUIElement> getEqualElementsList(IGUIElement guiElement) {
268            List<IGUIElement> returnValue = identityHashMap.get(guiElement);
269
270            if (returnValue == null) {
271                returnValue = new LinkedList<IGUIElement>();
272                returnValue.add(guiElement);
273                identityHashMap.put(guiElement, returnValue);
274            }
275
276            return returnValue;
277        }
278
279        /**
280         * <p>
281         * Adds {@link IGUIElement} as equal to a list of {@link IGUIElement} if and only if it is
282         * not already contained.
283         * </p>
284         *
285         * @param equalElementsList
286         *            list of {@link IGUIElement} to which the GUI element is added
287         * @param guiElement
288         *            GUI element to be added
289         */
290        private void addIfNotContained(List<IGUIElement> equalElementsList, IGUIElement guiElement)
291        {
292            for (IGUIElement candidate : equalElementsList) {
293                if (candidate == guiElement) {
294                    return;
295                }
296            }
297
298            equalElementsList.add(guiElement);
299        }
300
301    }
302
303}
Note: See TracBrowser for help on using the repository browser.