KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > databinding > internal > viewers > LeafNodesSet


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 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 package org.eclipse.jface.internal.databinding.internal.viewers;
12
13 import java.util.Collections JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.core.databinding.observable.Diffs;
20 import org.eclipse.core.databinding.observable.IStaleListener;
21 import org.eclipse.core.databinding.observable.StaleEvent;
22 import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
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 import org.eclipse.core.databinding.observable.set.SetDiff;
27 import org.eclipse.core.internal.databinding.observable.tree.IUnorderedTreeProvider;
28 import org.eclipse.core.internal.databinding.observable.tree.TreePath;
29
30 /**
31  * This set consists of all leaf nodes from the given tree (that is, all nodes
32  * for which ITreeProvider.createChildSet returns null).
33  */

34 public class LeafNodesSet extends AbstractObservableSet {
35
36     private HashSet JavaDoc leafNodes = new HashSet JavaDoc();
37
38     private HashMap JavaDoc mapElementsOntoNodeInfo = new HashMap JavaDoc();
39
40     private IUnorderedTreeProvider tree;
41
42     private Object JavaDoc input;
43
44     private int staleCount = 0;
45
46     private class NodeInfo implements IStaleListener, ISetChangeListener {
47         // Number of times the element occurs in the tree
48
private int count;
49
50         // Element
51
private TreePath treePath;
52
53         // Children set (or null if this is a leaf node)
54
IObservableSet children;
55
56         private boolean wasStale = false;
57
58         /**
59          * @param treePath
60          */

61         public NodeInfo(TreePath treePath) {
62             this.treePath = treePath;
63             children = tree.createChildSet(this.treePath);
64             if (children != null) {
65                 children.addStaleListener(this);
66                 children.addSetChangeListener(this);
67             }
68             count = 1;
69         }
70
71         public void handleSetChange(SetChangeEvent event) {
72             processDiff(treePath, event.diff);
73         }
74
75         public void handleStale(StaleEvent event) {
76             if (wasStale != children.isStale()) {
77                 if (wasStale) {
78                     staleCount--;
79                 } else {
80                     staleCount++;
81                 }
82                 wasStale = !wasStale;
83             }
84             setStale(staleCount > 0);
85         }
86
87         /**
88          *
89          */

90         public void dispose() {
91             if (children != null) {
92                 children.dispose();
93                 children = null;
94                 if (wasStale) {
95                     staleCount--;
96                 }
97             }
98         }
99     }
100
101     /**
102      * Creates a set that will contain the leaf nodes from the given tree
103      *
104      * @param tree
105      * tree whose leaf nodes will be computed
106      */

107     public LeafNodesSet(IUnorderedTreeProvider tree) {
108         this(null, tree);
109     }
110
111     /**
112      * Creates a set that will contain the leaf nodes from the given tree, and
113      * sets the root of the tree to the given element.
114      *
115      * @param initialInput
116      * root of the tree
117      * @param tree
118      * tree whose leaf nodes will be computed
119      */

120     public LeafNodesSet(Object JavaDoc initialInput, IUnorderedTreeProvider tree) {
121         super(tree.getRealm());
122         this.tree = tree;
123         if (initialInput != null) {
124             setInput(initialInput);
125         }
126     }
127
128     private void processDiff(TreePath treePath, SetDiff diff) {
129         Set JavaDoc removals = new HashSet JavaDoc();
130         HashSet JavaDoc additions = new HashSet JavaDoc();
131
132         for (Iterator JavaDoc iter = diff.getRemovals().iterator(); iter.hasNext();) {
133             Object JavaDoc next = iter.next();
134
135             elementRemoved(treePath.createChildPath(next), removals);
136         }
137
138         for (Iterator JavaDoc iter = diff.getAdditions().iterator(); iter.hasNext();) {
139             Object JavaDoc next = iter.next();
140
141             elementDiscovered(treePath.createChildPath(next), additions);
142         }
143
144         HashSet JavaDoc newRemovals = new HashSet JavaDoc();
145         newRemovals.addAll(removals);
146         newRemovals.removeAll(additions);
147
148         HashSet JavaDoc newAdditions = new HashSet JavaDoc();
149         newAdditions.addAll(additions);
150         newAdditions.removeAll(removals);
151
152         leafNodes.addAll(newAdditions);
153         leafNodes.removeAll(newRemovals);
154
155         if (!newAdditions.isEmpty() || !newRemovals.isEmpty()) {
156             setStale(staleCount > 0);
157             fireSetChange(Diffs.createSetDiff(newAdditions, newRemovals));
158         }
159     }
160
161     /**
162      * Sets the root of the tree to the given element.
163      *
164      * @param input
165      * new root of the tree
166      */

167     public void setInput(Object JavaDoc input) {
168         Set JavaDoc removals = Collections.EMPTY_SET;
169         Set JavaDoc additions = Collections.EMPTY_SET;
170         if (this.input != null) {
171             removals = Collections.singleton(this.input);
172         } else if (input != null) {
173             additions = Collections.singleton(input);
174         }
175         this.input = input;
176         processDiff(TreePath.EMPTY, Diffs.createSetDiff(additions, removals));
177     }
178
179     /**
180      * Called when an element is removed from the tree. The given HashSet will
181      * be filled in with all removed leaf nodes.
182      *
183      * @param treePath
184      * @param removals
185      */

186     private void elementRemoved(TreePath treePath, Set JavaDoc removals) {
187         NodeInfo newNode = (NodeInfo) mapElementsOntoNodeInfo.get(treePath);
188
189         if (newNode != null) {
190             newNode = new NodeInfo(treePath);
191             newNode.count--;
192             if (newNode.count == 0) {
193                 mapElementsOntoNodeInfo.remove(treePath);
194                 if (newNode.children != null) {
195                     for (Iterator JavaDoc iter = newNode.children.iterator(); iter
196                             .hasNext();) {
197                         Object JavaDoc next = iter.next();
198
199                         elementRemoved(treePath.createChildPath(next), removals);
200                     }
201                     newNode.children.dispose();
202                 } else {
203                     removals.add(treePath);
204                 }
205             }
206         }
207     }
208
209     /**
210      * Called when a new element is discovered in the tree. The given HashSet
211      * will be filled in with all newly discovered leaf nodes.
212      *
213      * @param treePath
214      * @param additions
215      */

216     private void elementDiscovered(TreePath treePath, HashSet JavaDoc additions) {
217         NodeInfo newNode = (NodeInfo) mapElementsOntoNodeInfo.get(treePath);
218
219         if (newNode == null) {
220             newNode = new NodeInfo(treePath);
221             mapElementsOntoNodeInfo.put(treePath, newNode);
222             if (newNode.children != null) {
223                 for (Iterator JavaDoc iter = newNode.children.iterator(); iter
224                         .hasNext();) {
225                     Object JavaDoc next = iter.next();
226
227                     elementDiscovered(treePath.createChildPath(next), additions);
228                 }
229             } else {
230                 additions.add(treePath);
231             }
232         } else {
233             // If this node was already known, increment the reference count.
234
newNode.count++;
235         }
236     }
237
238     protected Set JavaDoc getWrappedSet() {
239         return leafNodes;
240     }
241
242     public Object JavaDoc getElementType() {
243         return Object JavaDoc.class;
244     }
245
246     public void dispose() {
247         for (Iterator JavaDoc iter = mapElementsOntoNodeInfo.values().iterator(); iter
248                 .hasNext();) {
249             NodeInfo next = (NodeInfo) iter.next();
250
251             if (next.children != null) {
252                 next.dispose();
253             }
254         }
255
256         mapElementsOntoNodeInfo.clear();
257         leafNodes.clear();
258         super.dispose();
259     }
260 }
261
Popular Tags