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

Last change on this file since 609 was 609, checked in by pharms, 12 years ago
  • implemented equality of GUI elements only for identical objects or registered equal objects to allow for singleton behavior also for objects already referenced elsewhere
  • Property svn:executable set to *
File size: 7.2 KB
Line 
1// Module    : $RCSfile: AbstractDefaultGUIElement.java,v $
2// Version   : $Revision: 0.0 $  $Author: Patrick $  $Date: 27.11.2011 17:21:28 $
3// Project   : TaskTreePerformanceTest
4// Creation  : 2011 by Patrick
5// Copyright : Patrick Harms, 2011
6
7package de.ugoe.cs.quest.eventcore.guimodel;
8
9import java.util.IdentityHashMap;
10import java.util.LinkedList;
11import java.util.List;
12
13/**
14 * TODO comment
15 *
16 * @version $Revision: $ $Date: $
17 * @author 2011, last modified by $Author: $
18 */
19public abstract class AbstractDefaultGUIElement implements IGUIElement {
20   
21    /**  */
22    public static final long serialVersionUID = 1L;
23
24    /** the reference to equal GUI element manager (needed to preserve singleton behavior) */
25    private static final EqualGUIElementManager equalGUIElementManager =
26        new EqualGUIElementManager();
27
28    /** the specification of the GUI element */
29    private IGUIElementSpec specification;
30
31    /** the reference to the parent element */
32    private IGUIElement parent;
33
34    /**
35     * <p>
36     * TODO: comment
37     * </p>
38     *
39     * @param specification
40     */
41    public AbstractDefaultGUIElement(IGUIElementSpec specification, IGUIElement parent) {
42        this.specification = specification;
43        this.parent = parent;
44    }
45
46    /*
47     * (non-Javadoc)
48     *
49     * @see de.ugoe.cs.tasktree.guimodel.GUIElement#getSpecification()
50     */
51    @Override
52    public IGUIElementSpec getSpecification() {
53        return specification;
54    }
55
56    /* (non-Javadoc)
57     * @see de.ugoe.cs.quest.eventcore.guimodel.IGUIElement#getParent()
58     */
59    @Override
60    public IGUIElement getParent() {
61        return parent;
62    }
63
64    /* (non-Javadoc)
65     * @see de.ugoe.cs.quest.eventcore.guimodel.IGUIElement#addEqualGUIElement(IGUIElement)
66     */
67    @Override
68    public void addEqualGUIElement(IGUIElement equalElement)
69    {
70        equalGUIElementManager.addEqualGUIElements(this, equalElement);
71    }
72
73    /*
74     * (non-Javadoc)
75     *
76     * @see GUIElement#equals(GUIElement)
77     */
78    public final boolean equals(Object other) {
79        // implement final, as GUI elements are all singletons and they equal only if they are the
80        // same object or if they are in the list of equal GUI elements
81        return super.equals(other) || equalGUIElementManager.equals(this, other);
82    }
83
84    /* (non-Javadoc)
85     * @see java.lang.Object#hashCode()
86     */
87    @Override
88    public final int hashCode() {
89        // implement final, as GUI elements are all singletons and they equal only if they are the
90        // same object. If there are several GUI element objects that represent the same GUI element
91        // then they are stored in the list of equal elements. In this case, the hash code of the
92        // list is unique within the system
93        return equalGUIElementManager.hashCode(this);
94    }
95
96    /**
97     * <p>
98     * TODO comment
99     * </p>
100     *
101     * @version $Revision: $ $Date: 24.08.2012$
102     * @author 2012, last modified by $Author: pharms$
103     */
104    private static class EqualGUIElementManager {
105
106        /**
107         * <p>
108         * the internal map of GUI elements mapping each registered element to its equal variants.
109         * We use the {@link IdentityHashMap} as a normal hash map would not work because of the
110         * changing of the hash code of GUI elements at runtime.
111         * </p>
112         */
113        private IdentityHashMap<IGUIElement, List<IGUIElement>> identityHashMap =
114            new IdentityHashMap<IGUIElement, List<IGUIElement>>();
115       
116        /**
117         * <p>
118         * TODO: comment
119         * </p>
120         *
121         * @param abstractDefaultGUIElement
122         * @param equalElement
123         */
124        private synchronized void addEqualGUIElements(IGUIElement guiElement1,
125                                                      IGUIElement guiElement2)
126        {
127            List<IGUIElement> list1 = identityHashMap.get(guiElement1);
128            List<IGUIElement> list2 = identityHashMap.get(guiElement2);
129           
130            if (list1 == null) {
131                if (list2 == null) {
132                    list2 = new LinkedList<IGUIElement>();
133                    list2.add(guiElement1);
134                    list2.add(guiElement2);
135                    identityHashMap.put(guiElement1, list2);
136                    identityHashMap.put(guiElement2, list2);
137                }
138                else {
139                    addIfNotContained(list2, guiElement1);
140                    identityHashMap.put(guiElement1, list2);
141                }
142            }
143            else {
144                if (list2 == null) {
145                    addIfNotContained(list1, guiElement2);
146                    identityHashMap.put(guiElement2, list1);
147                }
148                else if (list1 != list2) {
149                    list1.addAll(list2);
150                    identityHashMap.put(guiElement2, list1);
151                }
152                // else
153                //     in this case, both GUI elements should already be registered with the same
154                //     lists.
155            }
156        }
157
158        /**
159         * <p>
160         * TODO: comment
161         * </p>
162         *
163         * @param abstractDefaultGUIElement
164         * @return
165         */
166        private synchronized int hashCode(IGUIElement guiElement) {
167            return System.identityHashCode(getEqualElementsList(guiElement));
168        }
169
170        /**
171         * <p>
172         * TODO: comment
173         * </p>
174         *
175         * @param abstractDefaultGUIElement
176         * @param other
177         * @return
178         */
179        private synchronized boolean equals(IGUIElement guiElement, Object other) {
180            if (other instanceof IGUIElement) {
181                for (IGUIElement candidate : getEqualElementsList(guiElement)) {
182                    if (candidate == other) {
183                        return true;
184                    }
185                }
186            }
187           
188            return false;
189        }
190
191        /**
192         * <p>
193         * TODO: comment
194         * </p>
195         *
196         * @param guiElement
197         * @return
198         */
199        private List<IGUIElement> getEqualElementsList(IGUIElement guiElement) {
200            List<IGUIElement> returnValue = identityHashMap.get(guiElement);
201           
202            if (returnValue == null) {
203                returnValue = new LinkedList<IGUIElement>();
204                returnValue.add(guiElement);
205                identityHashMap.put(guiElement, returnValue);
206            }
207           
208            return returnValue;
209        }
210
211        /**
212         * <p>
213         * TODO: comment
214         * </p>
215         *
216         * @param resultingList
217         * @param guiElement1
218         */
219        private void addIfNotContained(List<IGUIElement> equalElementsList, IGUIElement guiElement)
220        {
221            for (IGUIElement candidate : equalElementsList) {
222                if (candidate == guiElement) {
223                    return;
224                }
225            }
226           
227            equalElementsList.add(guiElement);
228        }
229
230    }
231
232}
Note: See TracBrowser for help on using the repository browser.