1 11 12 package org.eclipse.core.databinding.observable.map; 13 14 import java.util.AbstractSet ; 15 import java.util.Collections ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.databinding.observable.Diffs; 23 import org.eclipse.core.databinding.observable.set.IObservableSet; 24 import org.eclipse.core.databinding.observable.set.ISetChangeListener; 25 import org.eclipse.core.databinding.observable.set.SetChangeEvent; 26 27 31 public abstract class ComputedObservableMap extends AbstractObservableMap { 32 33 private final IObservableSet keySet; 34 35 private ISetChangeListener setChangeListener = new ISetChangeListener() { 36 public void handleSetChange(SetChangeEvent event) { 37 Set addedKeys = new HashSet (event.diff.getAdditions()); 38 Set removedKeys = new HashSet (event.diff.getRemovals()); 39 Map oldValues = new HashMap (); 40 Map newValues = new HashMap (); 41 for (Iterator it = removedKeys.iterator(); it.hasNext();) { 42 Object removedKey = it.next(); 43 Object oldValue = doGet(removedKey); 44 unhookListener(removedKey); 45 if (oldValue != null) { 46 oldValues.put(removedKey, oldValue); 47 } 48 } 49 for (Iterator it = addedKeys.iterator(); it.hasNext();) { 50 Object addedKey = it.next(); 51 hookListener(addedKey); 52 Object newValue = doGet(addedKey); 53 newValues.put(addedKey, newValue); 54 } 55 fireMapChange(Diffs.createMapDiff(addedKeys, removedKeys, 56 Collections.EMPTY_SET, oldValues, newValues)); 57 } 58 }; 59 60 private Set entrySet = new EntrySet(); 61 62 private class EntrySet extends AbstractSet { 63 64 public Iterator iterator() { 65 final Iterator keyIterator = keySet.iterator(); 66 return new Iterator () { 67 68 public boolean hasNext() { 69 return keyIterator.hasNext(); 70 } 71 72 public Object next() { 73 final Object key = keyIterator.next(); 74 return new Map.Entry () { 75 76 public Object getKey() { 77 return key; 78 } 79 80 public Object getValue() { 81 return get(getKey()); 82 } 83 84 public Object setValue(Object value) { 85 return put(getKey(), value); 86 } 87 }; 88 } 89 90 public void remove() { 91 keyIterator.remove(); 92 } 93 }; 94 } 95 96 public int size() { 97 return keySet.size(); 98 } 99 100 } 101 102 105 public ComputedObservableMap(IObservableSet keySet) { 106 super(keySet.getRealm()); 107 this.keySet = keySet; 108 this.keySet.addSetChangeListener(setChangeListener); 109 } 110 111 protected void init() { 112 for (Iterator it = this.keySet.iterator(); it.hasNext();) { 113 Object key = it.next(); 114 hookListener(key); 115 } 116 } 117 118 protected final void fireSingleChange(Object key, Object oldValue, 119 Object newValue) { 120 fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue, newValue)); 121 } 122 123 public Set entrySet() { 124 return entrySet; 125 } 126 127 public Set keySet() { 128 return keySet; 129 } 130 131 final public Object get(Object key) { 132 return doGet(key); 133 } 134 135 final public Object put(Object key, Object value) { 136 return doPut(key, value); 137 } 138 139 142 protected abstract void unhookListener(Object removedKey); 143 144 147 protected abstract void hookListener(Object addedKey); 148 149 153 protected abstract Object doGet(Object key); 154 155 160 protected abstract Object doPut(Object key, Object value); 161 } 162 | Popular Tags |