1 11 12 package org.eclipse.core.databinding.observable.set; 13 14 import java.util.ArrayList ; 15 import java.util.Collection ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.Set ; 20 21 import org.eclipse.core.databinding.observable.Diffs; 22 import org.eclipse.core.databinding.observable.Realm; 23 import org.eclipse.core.internal.databinding.observable.IStalenessConsumer; 24 import org.eclipse.core.internal.databinding.observable.StalenessTracker; 25 26 39 public final class UnionSet extends ObservableSet { 40 41 44 private IObservableSet[] childSets; 45 46 private boolean stale = false; 47 48 53 private HashMap refCounts = null; 54 55 private StalenessTracker stalenessTracker; 56 57 60 public UnionSet(IObservableSet[] childSets) { 61 super(childSets[0].getRealm(), null, childSets[0].getElementType()); 62 this.childSets = childSets; 63 this.stalenessTracker = new StalenessTracker(childSets, 64 stalenessConsumer); 65 } 66 67 private ISetChangeListener childSetChangeListener = new ISetChangeListener() { 68 public void handleSetChange(SetChangeEvent event) { 69 processAddsAndRemoves(event.diff.getAdditions(), event.diff.getRemovals()); 70 } 71 }; 72 73 private IStalenessConsumer stalenessConsumer = new IStalenessConsumer() { 74 public void setStale(boolean stale) { 75 boolean oldStale = UnionSet.this.stale; 76 UnionSet.this.stale = stale; 77 if (stale && !oldStale) { 78 fireStale(); 79 } 80 } 81 }; 82 83 public boolean isStale() { 84 checkRealm(); 85 if (refCounts != null) { 86 return stale; 87 } 88 89 for (int i = 0; i < childSets.length; i++) { 90 IObservableSet childSet = childSets[i]; 91 92 if (childSet.isStale()) { 93 return true; 94 } 95 } 96 return false; 97 } 98 99 private void processAddsAndRemoves(Set adds, Set removes) { 100 Set addsToFire = new HashSet (); 101 Set removesToFire = new HashSet (); 102 103 for (Iterator iter = adds.iterator(); iter.hasNext();) { 104 Object added = iter.next(); 105 106 Integer refCount = (Integer ) refCounts.get(added); 107 if (refCount == null) { 108 refCounts.put(added, new Integer (1)); 109 addsToFire.add(added); 110 } else { 111 int refs = refCount.intValue(); 112 refCount = new Integer (refs + 1); 113 refCounts.put(added, refCount); 114 } 115 } 116 117 for (Iterator iter = removes.iterator(); iter.hasNext();) { 118 Object removed = iter.next(); 119 120 Integer refCount = (Integer ) refCounts.get(removed); 121 if (refCount != null) { 122 int refs = refCount.intValue(); 123 if (refs <= 1) { 124 removesToFire.add(removed); 125 refCounts.remove(removed); 126 } else { 127 refCount = new Integer (refCount.intValue() - 1); 128 refCounts.put(removed, refCount); 129 } 130 } 131 } 132 133 addsToFire.removeAll(removesToFire); 135 136 if (addsToFire.size() > 0 || removesToFire.size() > 0) { 137 fireSetChange(Diffs.createSetDiff(addsToFire, removesToFire)); 138 } 139 } 140 141 protected void firstListenerAdded() { 142 super.firstListenerAdded(); 143 144 refCounts = new HashMap (); 145 for (int i = 0; i < childSets.length; i++) { 146 IObservableSet next = childSets[i]; 147 next.addSetChangeListener(childSetChangeListener); 148 incrementRefCounts(next); 149 } 150 stalenessTracker = new StalenessTracker(childSets, stalenessConsumer); 151 setWrappedSet(refCounts.keySet()); 152 } 153 154 protected void lastListenerRemoved() { 155 super.lastListenerRemoved(); 156 157 for (int i = 0; i < childSets.length; i++) { 158 IObservableSet next = childSets[i]; 159 160 next.removeSetChangeListener(childSetChangeListener); 161 stalenessTracker.removeObservable(next); 162 } 163 refCounts = null; 164 stalenessTracker = null; 165 setWrappedSet(null); 166 } 167 168 private ArrayList incrementRefCounts(Collection added) { 169 ArrayList adds = new ArrayList (); 170 171 for (Iterator iter = added.iterator(); iter.hasNext();) { 172 Object next = iter.next(); 173 174 Integer refCount = (Integer ) refCounts.get(next); 175 if (refCount == null) { 176 adds.add(next); 177 refCount = new Integer (1); 178 refCounts.put(next, refCount); 179 } else { 180 refCount = new Integer (refCount.intValue() + 1); 181 refCounts.put(next, refCount); 182 } 183 } 184 return adds; 185 } 186 187 protected void getterCalled() { 188 super.getterCalled(); 189 if (refCounts == null) { 190 setWrappedSet(computeElements()); 192 } 193 } 194 195 private Set computeElements() { 196 if (refCounts == null) { 198 Set result = new HashSet (); 199 for (int i = 0; i < childSets.length; i++) { 200 result.addAll(childSets[i]); 201 } 202 return result; 203 } 204 205 return refCounts.keySet(); 207 } 208 209 } 210 | Popular Tags |