Changeset 1121
- Timestamp:
- 03/18/13 11:43:33 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/AbstractDefaultGUIElement.java
r1115 r1121 15 15 package de.ugoe.cs.autoquest.eventcore.guimodel; 16 16 17 import java.util.IdentityHashMap;18 17 import java.util.LinkedList; 19 18 import java.util.List; … … 38 37 /** 39 38 * <p> 40 * The reference to equal GUI element manager (needed to preserve singleton behavior, even41 * though the objects are not singleton).42 * </p>43 */44 private static final EqualGUIElementManager equalGUIElementManager =45 new EqualGUIElementManager();46 47 /**48 * <p>49 39 * Specification of the GUI element 50 40 * </p> … … 58 48 */ 59 49 private final IGUIElement parent; 50 51 /** 52 * <p> 53 * List of other GUI elements being equal to this 54 * </p> 55 */ 56 private List<AbstractDefaultGUIElement> equalGUIElements = null; 60 57 61 58 /** … … 109 106 @Override 110 107 public void addEqualGUIElement(IGUIElement equalElement) { 111 equalGUIElementManager.addEqualGUIElements(this, equalElement); 108 if (!(equalElement instanceof AbstractDefaultGUIElement)) { 109 throw new IllegalArgumentException 110 ("this implementation can only handle other AbstractDefaultGUIElements"); 111 } 112 113 AbstractDefaultGUIElement other = (AbstractDefaultGUIElement) equalElement; 114 115 synchronized (AbstractDefaultGUIElement.class) { 116 if (this.equalGUIElements == null) { 117 if (other.equalGUIElements == null) { 118 this.equalGUIElements = new LinkedList<AbstractDefaultGUIElement>(); 119 this.equalGUIElements.add(this); 120 this.equalGUIElements.add(other); 121 other.equalGUIElements = this.equalGUIElements; 122 } 123 else { 124 addIfNotContained(other.equalGUIElements, this); 125 this.equalGUIElements = other.equalGUIElements; 126 } 127 } 128 else { 129 if (other.equalGUIElements == null) { 130 addIfNotContained(this.equalGUIElements, other); 131 other.equalGUIElements = this.equalGUIElements; 132 } 133 else if (this.equalGUIElements != other.equalGUIElements) { 134 this.equalGUIElements.addAll(other.equalGUIElements); 135 136 // we also have to set this new list for all other elements for which so 137 // far list2 was registered 138 for (AbstractDefaultGUIElement candidate : other.equalGUIElements) { 139 candidate.equalGUIElements = this.equalGUIElements; 140 } 141 142 other.equalGUIElements = this.equalGUIElements; 143 } 144 // else 145 // in this case, both GUI elements should already be registered with the same 146 // lists. 147 } 148 } 112 149 } 113 150 … … 140 177 // implement final, as GUI elements are all singletons and they equal only if they are the 141 178 // same object or if they are in the list of equal GUI elements 142 return super.equals(other) || equalGUIElementManager.equals(this, other); 179 if (super.equals(other)) { 180 return true; 181 } 182 else if (other instanceof AbstractDefaultGUIElement) { 183 synchronized (AbstractDefaultGUIElement.class) { 184 if (equalGUIElements != null) { 185 for (IGUIElement candidate : equalGUIElements) { 186 if (candidate == other) { 187 return true; 188 } 189 } 190 } 191 } 192 } 193 194 return false; 143 195 } 144 196 … … 154 206 // then they are stored in the list of equal elements. In this case, the hash code of the 155 207 // list is unique within the system 156 return equalGUIElementManager.hashCode(this); 208 synchronized (AbstractDefaultGUIElement.class) { 209 if (this.equalGUIElements == null) { 210 this.equalGUIElements = new LinkedList<AbstractDefaultGUIElement>(); 211 this.equalGUIElements.add(this); 212 } 213 214 return System.identityHashCode(this.equalGUIElements); 215 } 157 216 } 158 217 159 218 /** 160 219 * <p> 161 * This internal helper class manages equal GUI elements. This is necessary, as we often first 162 * identify many GUI elements as different and later use a heuristic to determine that they are 163 * the same. This class provides the means to preserve the singleton behavior of the GUI 164 * elements after we merge two GUI elements. 165 * </p> 166 * 167 * @version 1.0 168 * @author Patrick Harms 169 */ 170 private static class EqualGUIElementManager { 171 172 /** 173 * <p> 174 * The internal map of GUI elements mapping each registered element to its equal variants. 175 * We use the {@link IdentityHashMap} as a normal hash map would not work because of the 176 * changing of the hash code of GUI elements at runtime. 177 * </p> 178 */ 179 private IdentityHashMap<IGUIElement, List<IGUIElement>> identityHashMap = 180 new IdentityHashMap<IGUIElement, List<IGUIElement>>(); 181 182 /** 183 * <p> 184 * Adds a new equals relationship between two {@link IGUIElement}s to the equality manager. 185 * </p> 186 * 187 * @param guiElement1 188 * first equal GUI element 189 * @param guiElement2 190 * second equal GUI element 191 */ 192 private synchronized void addEqualGUIElements(IGUIElement guiElement1, 193 IGUIElement guiElement2) 194 { 195 List<IGUIElement> list1 = identityHashMap.get(guiElement1); 196 List<IGUIElement> list2 = identityHashMap.get(guiElement2); 197 198 if (list1 == null) { 199 if (list2 == null) { 200 list2 = new LinkedList<IGUIElement>(); 201 list2.add(guiElement1); 202 list2.add(guiElement2); 203 identityHashMap.put(guiElement1, list2); 204 identityHashMap.put(guiElement2, list2); 205 } 206 else { 207 addIfNotContained(list2, guiElement1); 208 identityHashMap.put(guiElement1, list2); 209 } 210 } 211 else { 212 if (list2 == null) { 213 addIfNotContained(list1, guiElement2); 214 identityHashMap.put(guiElement2, list1); 215 } 216 else if (list1 != list2) { 217 list1.addAll(list2); 218 identityHashMap.put(guiElement2, list1); 219 220 // we also have to set this new list for all other elements for which so 221 // far list2 was registered 222 for (IGUIElement candidate : list2) { 223 identityHashMap.put(candidate, list1); 224 } 225 } 226 // else 227 // in this case, both GUI elements should already be registered with the same 228 // lists. 229 } 230 } 231 232 /** 233 * <p> 234 * Returns the object hash of a {@link IGUIElement}. 235 * </p> 236 * 237 * @param guiElement 238 * gui element whose object hash is determined 239 * @return the object hash 240 */ 241 private synchronized int hashCode(IGUIElement guiElement) { 242 return System.identityHashCode(getEqualElementsList(guiElement)); 243 } 244 245 /** 246 * <p> 247 * Determines the equality of two {@link IGUIElement}s based on the information of the 248 * identify manager. Two elements are equal, if they have been added as equal using 249 * {@link #addEqualGUIElements(IGUIElement, IGUIElement)}. 250 * </p> 251 * 252 * @param guiElement 253 * GUI element to which the object is compared 254 * @param other 255 * object that is compared to the GUI element 256 * @return 257 */ 258 private synchronized boolean equals(IGUIElement guiElement, Object other) { 259 if (other instanceof IGUIElement) { 260 for (IGUIElement candidate : getEqualElementsList(guiElement)) { 261 if (candidate == other) { 262 return true; 263 } 264 } 265 } 266 267 return false; 268 } 269 270 /** 271 * <p> 272 * Returns the equal {@link IGUIElement} of a given {@link IGUIElement}. 273 * </p> 274 * 275 * @param guiElement 276 * GUI element of which the equal elements are returned 277 * @return the equal GUI elements 278 */ 279 private List<IGUIElement> getEqualElementsList(IGUIElement guiElement) { 280 List<IGUIElement> returnValue = identityHashMap.get(guiElement); 281 282 if (returnValue == null) { 283 returnValue = new LinkedList<IGUIElement>(); 284 returnValue.add(guiElement); 285 identityHashMap.put(guiElement, returnValue); 286 } 287 288 return returnValue; 289 } 290 291 /** 292 * <p> 293 * Adds {@link IGUIElement} as equal to a list of {@link IGUIElement} if and only if it is 294 * not already contained. 295 * </p> 296 * 297 * @param equalElementsList 298 * list of {@link IGUIElement} to which the GUI element is added 299 * @param guiElement 300 * GUI element to be added 301 */ 302 private void addIfNotContained(List<IGUIElement> equalElementsList, IGUIElement guiElement) 303 { 304 for (IGUIElement candidate : equalElementsList) { 305 if (candidate == guiElement) { 306 return; 307 } 308 } 309 310 equalElementsList.add(guiElement); 311 } 312 220 * Adds an {@link AbstractDefaultGUIElement} as equal to a list of 221 * {@link AbstractDefaultGUIElement}s if and only if it is not already contained. 222 * </p> 223 * 224 * @param equalElementsList 225 * list of {@link AbstractDefaultGUIElement} to which the GUI element is added 226 * @param guiElement 227 * GUI element to be added 228 */ 229 private void addIfNotContained(List<AbstractDefaultGUIElement> equalElementsList, 230 AbstractDefaultGUIElement guiElement) 231 { 232 for (IGUIElement candidate : equalElementsList) { 233 if (candidate == guiElement) { 234 return; 235 } 236 } 237 238 equalElementsList.add(guiElement); 313 239 } 314 240
Note: See TracChangeset
for help on using the changeset viewer.