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