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

Last change on this file since 1490 was 1436, checked in by pharms, 10 years ago
  • corrected a bug in creating hashcodes for GUI elements (they changed after storing a GUI model to a file and then reloading it)
  • Property svn:executable set to *
File size: 9.2 KB
RevLine 
[927]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.
[831]14
[922]15package de.ugoe.cs.autoquest.eventcore.guimodel;
[545]16
[609]17import java.util.LinkedList;
18import java.util.List;
19
[545]20/**
[831]21 * <p>
22 * Skeletal implementation for GUI elements.
23 * </p>
[545]24 *
[831]25 * @version 1.0
26 * @author Patrick Harms
[545]27 */
28public abstract class AbstractDefaultGUIElement implements IGUIElement {
[831]29
30    /**
31     * <p>
32     * Id for object serialization.
33     * </p>
34     */
[545]35    public static final long serialVersionUID = 1L;
36
[831]37    /**
38     * <p>
39     * Specification of the GUI element
40     * </p>
41     */
42    private final IGUIElementSpec specification;
[545]43
[831]44    /**
45     * <p>
46     * Reference to the parent element
47     * </p>
48     */
[1259]49    private IGUIElement parent;
[1010]50   
51    /**
52     * <p>
[1121]53     * List of other GUI elements being equal to this
54     * </p>
55     */
56    private List<AbstractDefaultGUIElement> equalGUIElements = null;
57   
58    /**
59     * <p>
[1010]60     * Boolean that indicates if a GUIElement was used during a session.
61     * </p>
62     */
[1385]63    private boolean usageObserved;
[603]64
[576]65    /**
66     * <p>
[1433]67     * the reference to the GUI model to which this GUI element belongs.
68     * </p>
69     */
70    private GUIModel guiModel;
[1436]71   
72    /**
73     * <p>
74     * the hash code of this object
75     * </p>
76     */
77    private int hashCode;
[1433]78
79    /**
80     * <p>
[831]81     * Constructor. Creates a new AbstractDefaultGUIElement.
[576]82     * </p>
[831]83     *
[576]84     * @param specification
[831]85     *            specification of the created GUI element
86     * @param parent
87     *            parent of the created GUI element; null means the element is a top-level window
[565]88     */
[603]89    public AbstractDefaultGUIElement(IGUIElementSpec specification, IGUIElement parent) {
[576]90        this.specification = specification;
[1010]91        this.usageObserved = false;
[1259]92        setParent(parent);
[1436]93       
94        if (specification != null) {
95            this.hashCode = specification.hashCode();
96        }
97        else {
98            this.hashCode = 0;
99        }
[565]100    }
101
[545]102    /*
103     * (non-Javadoc)
104     *
[576]105     * @see de.ugoe.cs.tasktree.guimodel.GUIElement#getSpecification()
[545]106     */
107    @Override
[576]108    public IGUIElementSpec getSpecification() {
109        return specification;
[545]110    }
111
[831]112    /*
113     * (non-Javadoc)
114     *
[922]115     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getParent()
[603]116     */
117    @Override
118    public IGUIElement getParent() {
119        return parent;
120    }
121
[1433]122    /* (non-Javadoc)
123     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getGUIModel()
124     */
125    @Override
126    public GUIModel getGUIModel() {
127       return guiModel;
128    }
129
[831]130    /*
131     * (non-Javadoc)
132     *
[922]133     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#addEqualGUIElement(IGUIElement)
[609]134     */
135    @Override
[831]136    public void addEqualGUIElement(IGUIElement equalElement) {
[1121]137        if (!(equalElement instanceof AbstractDefaultGUIElement)) {
138            throw new IllegalArgumentException
139                ("this implementation can only handle other AbstractDefaultGUIElements");
140        }
141       
142        AbstractDefaultGUIElement other = (AbstractDefaultGUIElement) equalElement;
143       
144        synchronized (AbstractDefaultGUIElement.class) {
145            if (this.equalGUIElements == null) {
146                if (other.equalGUIElements == null) {
147                    this.equalGUIElements = new LinkedList<AbstractDefaultGUIElement>();
148                    this.equalGUIElements.add(this);
149                    this.equalGUIElements.add(other);
150                    other.equalGUIElements = this.equalGUIElements;
[1436]151                    other.hashCode = this.hashCode;
[1121]152                }
153                else {
154                    addIfNotContained(other.equalGUIElements, this);
155                    this.equalGUIElements = other.equalGUIElements;
[1436]156                    this.hashCode = other.hashCode;
[1121]157                }
158            }
159            else {
160                if (other.equalGUIElements == null) {
161                    addIfNotContained(this.equalGUIElements, other);
162                    other.equalGUIElements = this.equalGUIElements;
[1436]163                    other.hashCode = this.hashCode;
[1121]164                }
165                else if (this.equalGUIElements != other.equalGUIElements) {
166                    this.equalGUIElements.addAll(other.equalGUIElements);
167
168                    // we also have to set this new list for all other elements for which so
169                    // far list2 was registered
170                    for (AbstractDefaultGUIElement candidate : other.equalGUIElements) {
171                        candidate.equalGUIElements = this.equalGUIElements;
[1436]172                        candidate.hashCode = this.hashCode;
[1121]173                    }
174
175                    other.equalGUIElements = this.equalGUIElements;
[1436]176                    other.hashCode = this.hashCode;
[1121]177                }
178                // else
179                // in this case, both GUI elements should already be registered with the same
180                // lists.
181            }
182        }
[609]183    }
184
[545]185    /*
186     * (non-Javadoc)
187     *
[1051]188     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#isUsed()
189     */
190    @Override
191    public boolean isUsed() {
192        return usageObserved;
193    }
194
195    /*
196     * (non-Javadoc)
197     *
198     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#markUsed()
199     */
200    @Override
201    public void markUsed() {
202        this.usageObserved = true;
203    }
204
205    /*
206     * (non-Javadoc)
207     *
[576]208     * @see GUIElement#equals(GUIElement)
[545]209     */
[603]210    public final boolean equals(Object other) {
[609]211        // implement final, as GUI elements are all singletons and they equal only if they are the
212        // same object or if they are in the list of equal GUI elements
[1121]213        if (super.equals(other)) {
214            return true;
215        }
216        else if (other instanceof AbstractDefaultGUIElement) {
217            synchronized (AbstractDefaultGUIElement.class) {
218                if (equalGUIElements != null) {
219                    for (IGUIElement candidate : equalGUIElements) {
220                        if (candidate == other) {
221                            return true;
222                        }
223                    }
224                }
225            }
226        }
227
228        return false;
[545]229    }
230
[831]231    /*
232     * (non-Javadoc)
233     *
[603]234     * @see java.lang.Object#hashCode()
235     */
236    @Override
237    public final int hashCode() {
[609]238        // implement final, as GUI elements are all singletons and they equal only if they are the
239        // same object. If there are several GUI element objects that represent the same GUI element
[1436]240        // then they are stored in the list of equal elements. But at least their type is expected
241        // to be equal, so return the hash code of the type.
242        return hashCode;
[603]243    }
[1010]244   
[609]245    /**
246     * <p>
[1259]247     * updates the parent node of this node if required due to model restructuring
248     * </p>
249     */
250    void setParent(IGUIElement newParent) {
[1385]251        synchronized (AbstractDefaultGUIElement.class) {
252            // all equal GUI elements must have the same parent. Otherwise, they are not equal
253            // anymore and we would have discrepancies on the return value of getParent() on
254            // equal GUI elements.
255            this.parent = newParent;
256            if (equalGUIElements != null) {
257                for (AbstractDefaultGUIElement candidate : equalGUIElements) {
258                    candidate.parent = newParent;
259                }
260            }
261        }
[1433]262    }
[1385]263
[1433]264    /**
265     * <p>
266     * used to set the GUI model to which this GUI element belongs. Will be set automatically, if
267     * used in combination with {@link GUIModel};
268     * </p>
269     *
270     * @param guiModel
271     */
272    void setGUIModel(GUIModel guiModel) {
273        this.guiModel = guiModel;
[1259]274    }
275
276    /**
277     * <p>
[1121]278     * Adds an {@link AbstractDefaultGUIElement} as equal to a list of
279     * {@link AbstractDefaultGUIElement}s if and only if it is not already contained.
[609]280     * </p>
281     *
[1121]282     * @param equalElementsList
283     *            list of {@link AbstractDefaultGUIElement} to which the GUI element is added
284     * @param guiElement
285     *            GUI element to be added
[609]286     */
[1121]287    private void addIfNotContained(List<AbstractDefaultGUIElement> equalElementsList,
288                                   AbstractDefaultGUIElement       guiElement)
289    {
290        for (IGUIElement candidate : equalElementsList) {
291            if (candidate == guiElement) {
292                return;
[609]293            }
294        }
295
[1121]296        equalElementsList.add(guiElement);
[609]297    }
298
[545]299}
Note: See TracBrowser for help on using the repository browser.