Ignore:
Timestamp:
08/27/12 11:31:27 (12 years ago)
Author:
pharms
Message:
  • implemented equality of GUI elements only for identical objects or registered equal objects to allow for singleton behavior also for objects already referenced elsewhere
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/quest-core-events/src/main/java/de/ugoe/cs/quest/eventcore/guimodel/AbstractDefaultGUIElement.java

    r603 r609  
    66 
    77package de.ugoe.cs.quest.eventcore.guimodel; 
     8 
     9import java.util.IdentityHashMap; 
     10import java.util.LinkedList; 
     11import java.util.List; 
    812 
    913/** 
     
    1822    public static final long serialVersionUID = 1L; 
    1923 
     24    /** the reference to equal GUI element manager (needed to preserve singleton behavior) */ 
     25    private static final EqualGUIElementManager equalGUIElementManager = 
     26        new EqualGUIElementManager(); 
     27 
    2028    /** the specification of the GUI element */ 
    2129    private IGUIElementSpec specification; 
     
    5462    } 
    5563 
     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 
    5673    /* 
    5774     * (non-Javadoc) 
     
    6077     */ 
    6178    public final boolean equals(Object other) { 
    62         // implement final, as GUI elments are all singletons and the equal only if they are the 
    63         // same object 
    64         return super.equals(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); 
    6582    } 
    6683 
     
    7087    @Override 
    7188    public final int hashCode() { 
    72         // implement final, as GUI elments are all singletons and the equal only if they are the 
    73         // same object 
    74         return super.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 
    75230    } 
    76231 
Note: See TracChangeset for help on using the changeset viewer.