KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > databinding > provisional > observable > set > UnionSet


1 /*******************************************************************************
2  * Copyright (c) 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  ******************************************************************************/

11
12 package org.eclipse.jface.internal.databinding.provisional.observable.set;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.Set JavaDoc;
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 /**
26  * Represents a set consisting of the union of elements from one or more other
27  * sets. This object does not need to be explicitly disposed. If nobody is
28  * listening to the UnionSet, the set will remove its listeners.
29  *
30  * @since 1.0
31  */

32 public final class UnionSet extends ObservableSet {
33
34     /**
35      * child sets
36      */

37     private IObservableSet[] childSets;
38
39     private boolean stale = false;
40
41     /**
42      * Map of elements onto Integer reference counts. This map is constructed
43      * when the first listener is added to the union set. Null if nobody is
44      * listening to the UnionSet.
45      */

46     private HashMap JavaDoc refCounts = null;
47
48     private StalenessTracker stalenessTracker;
49
50     /**
51      * @param childSets
52      */

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 JavaDoc adds, Set JavaDoc removes) {
92         Set JavaDoc addsToFire = new HashSet JavaDoc();
93         Set JavaDoc removesToFire = new HashSet JavaDoc();
94
95         for (Iterator JavaDoc iter = adds.iterator(); iter.hasNext();) {
96             Object JavaDoc added = iter.next();
97
98             Integer JavaDoc refCount = (Integer JavaDoc) refCounts.get(added);
99             if (refCount == null) {
100                 refCounts.put(added, new Integer JavaDoc(1));
101                 addsToFire.add(added);
102             } else {
103                 int refs = refCount.intValue();
104                 refCount = new Integer JavaDoc(refs + 1);
105                 refCounts.put(added, refCount);
106             }
107         }
108
109         for (Iterator JavaDoc iter = removes.iterator(); iter.hasNext();) {
110             Object JavaDoc removed = iter.next();
111
112             Integer JavaDoc refCount = (Integer JavaDoc) 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 JavaDoc(refCount.intValue() - 1);
120                     refCounts.put(removed, refCount);
121                 }
122             }
123         }
124
125         // just in case the removes overlapped with the adds
126
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 JavaDoc();
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 JavaDoc incrementRefCounts(Collection JavaDoc added) {
161         ArrayList JavaDoc adds = new ArrayList JavaDoc();
162
163         for (Iterator JavaDoc iter = added.iterator(); iter.hasNext();) {
164             Object JavaDoc next = iter.next();
165
166             Integer JavaDoc refCount = (Integer JavaDoc) refCounts.get(next);
167             if (refCount == null) {
168                 adds.add(next);
169                 refCount = new Integer JavaDoc(1);
170                 refCounts.put(next, refCount);
171             } else {
172                 refCount = new Integer JavaDoc(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             // no listeners, recompute
183
setWrappedSet(computeElements());
184         }
185     }
186
187     private Set JavaDoc computeElements() {
188         // If there is no cached value, compute the union from scratch
189
if (refCounts == null) {
190             Set JavaDoc result = new HashSet JavaDoc();
191             for (int i = 0; i < childSets.length; i++) {
192                 result.addAll(childSets[i]);
193             }
194             return result;
195         }
196
197         // Else there is a cached value. Return it.
198
return refCounts.keySet();
199     }
200
201 }
202
Popular Tags