KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > spi > project > ui > support > NodeFactorySupport


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.spi.project.ui.support;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.List JavaDoc;
28 import javax.swing.event.ChangeEvent JavaDoc;
29 import javax.swing.event.ChangeListener JavaDoc;
30 import org.netbeans.api.project.Project;
31 import org.openide.filesystems.FileObject;
32 import org.openide.filesystems.Repository;
33 import org.openide.loaders.DataFolder;
34 import org.openide.loaders.FolderLookup;
35 import org.openide.nodes.Children;
36 import org.openide.nodes.Node;
37 import org.openide.util.Lookup;
38 import org.openide.util.LookupEvent;
39 import org.openide.util.LookupListener;
40
41 /**
42  * Support class for creating Project node's children nodes from NodeFactory instances
43  * in layers.
44  * @author mkleint
45  * @since org.netbeans.modules.projectuiapi/1 1.18
46  */

47 public class NodeFactorySupport {
48     
49     private NodeFactorySupport() {
50     }
51     
52     /**
53      * Creates children list that works on top of {@link NodeFactory} instances
54      * in layers.
55      * @param project the project which is being displayed
56      * @param folderPath the path in the System Filesystem that is used as root for subnode composition.
57      * The content of the folder is assumed to be {@link org.netbeans.spi.project.ui.support.NodeFactory} instances
58      * @return a new children list
59      */

60     public static Children createCompositeChildren(Project project, String JavaDoc folderPath) {
61         return new DelegateChildren(project, folderPath);
62     }
63
64     /**
65      * Utility method for creating a non variable NodeList instance.
66      * @param nodes a fixed set of nodes to display
67      * @return a constant node list
68      */

69     public static NodeList fixedNodeList(Node... nodes) {
70         return new FixedNodeList(nodes);
71     }
72     
73     private static class FixedNodeList implements NodeList<Node> {
74         
75         private List JavaDoc<Node> nodes;
76         
77         FixedNodeList(Node... nds) {
78             nodes = Arrays.asList(nds);
79         }
80         public List JavaDoc<Node> keys() {
81             return nodes;
82         }
83         
84         public void addChangeListener(ChangeListener JavaDoc l) { }
85         
86         public void removeChangeListener(ChangeListener JavaDoc l) { }
87         
88         public void addNotify() {
89         }
90         
91         public void removeNotify() {
92         }
93
94         public Node node(Node key) {
95             return key;
96         }
97     }
98     
99     static class DelegateChildren extends Children.Keys<NodeListKeyWrapper> implements LookupListener, ChangeListener JavaDoc {
100         
101         private String JavaDoc folderPath;
102         private Project project;
103         private List JavaDoc<NodeList<?>> nodeLists = new ArrayList JavaDoc<NodeList<?>>();
104         private List JavaDoc<NodeFactory> factories = new ArrayList JavaDoc<NodeFactory>();
105         private Lookup.Result<NodeFactory> result;
106         private HashMap JavaDoc<NodeList<?>, List JavaDoc<NodeListKeyWrapper>> keys;
107         
108         public DelegateChildren(Project proj, String JavaDoc path) {
109             folderPath = path;
110             project = proj;
111         }
112         
113         // protected for tests..
114
protected Lookup createLookup() {
115             FileObject root = Repository.getDefault().getDefaultFileSystem().findResource(folderPath);
116             DataFolder folder = DataFolder.findFolder(root);
117             return new FolderLookup(folder).getLookup();
118         }
119         
120        protected Node[] createNodes(NodeListKeyWrapper key) {
121            Node nd = key.nodeList.node(key.object);
122            if (nd != null) {
123                return new Node[] { nd };
124            }
125            return new Node[0];
126         }
127        
128        private Collection JavaDoc<NodeListKeyWrapper> createKeys() {
129            Collection JavaDoc<NodeListKeyWrapper> col = new ArrayList JavaDoc<NodeListKeyWrapper>();
130            synchronized (keys) {
131                for (NodeList lst : nodeLists) {
132                    List JavaDoc<NodeListKeyWrapper> x = keys.get(lst);
133                    if (x != null) {
134                        col.addAll(x);
135                    }
136                }
137            }
138            return col;
139        }
140       
141         protected void addNotify() {
142             super.addNotify();
143             keys = new HashMap JavaDoc<NodeList<?>, List JavaDoc<NodeListKeyWrapper>>();
144             result = createLookup().lookup(new Lookup.Template<NodeFactory>(NodeFactory.class));
145             for (NodeFactory factory : result.allInstances()) {
146                 NodeList<?> lst = factory.createNodes(project);
147                 assert lst != null;
148                 lst.addNotify();
149                 synchronized (keys) {
150                     nodeLists.add(lst);
151                     addKeys(lst);
152                 }
153                 lst.addChangeListener(this);
154                 factories.add(factory);
155             }
156             result.addLookupListener(this);
157             setKeys(createKeys());
158         }
159         
160         protected void removeNotify() {
161             super.removeNotify();
162             setKeys(Collections.<NodeListKeyWrapper>emptySet());
163             for (NodeList elem : nodeLists) {
164                 elem.removeChangeListener(this);
165                 elem.removeNotify();
166             }
167             synchronized (keys) {
168                 keys.clear();
169                 nodeLists.clear();
170             }
171             factories.clear();
172             if (result != null) {
173                 result.removeLookupListener(this);
174                 result = null;
175             }
176         }
177         
178         public void stateChanged(ChangeEvent JavaDoc e) {
179             NodeList list = (NodeList) e.getSource();
180             synchronized (keys) {
181                 removeKeys(list);
182                 addKeys(list);
183             }
184             setKeys(createKeys());
185         }
186         
187         //to be called under lock.
188
private void addKeys(NodeList list) {
189             List JavaDoc<NodeListKeyWrapper> wrps = new ArrayList JavaDoc<NodeListKeyWrapper>();
190             for (Object JavaDoc key : list.keys()) {
191                 wrps.add(new NodeListKeyWrapper(key, list));
192             }
193             keys.put(list, wrps);
194             
195         }
196         
197         //to be called under lock.
198
private void removeKeys(NodeList list) {
199             keys.remove(list);
200         }
201
202
203         public void resultChanged(LookupEvent ev) {
204             int index = 0;
205             for (NodeFactory factory : result.allInstances()) {
206                 if (!factories.contains(factory)) {
207                     factories.add(index, factory);
208                     NodeList<?> lst = factory.createNodes(project);
209                     assert lst != null;
210                     synchronized (keys) {
211                         nodeLists.add(index, lst);
212                         addKeys(lst);
213                     }
214                     lst.addNotify();
215                     lst.addChangeListener(this);
216                 } else {
217                     while (!factory.equals(factories.get(index))) {
218                         factories.remove(index);
219                         synchronized (keys) {
220                             NodeList<?> lst = nodeLists.remove(index);
221                             removeKeys(lst);
222                             lst.removeNotify();
223                             lst.removeChangeListener(this);
224                         }
225                     }
226                 }
227                 index++;
228             }
229             setKeys(createKeys());
230         }
231         
232
233     }
234     
235     /**
236      * this class makes sure the bond between the NodeList and individial
237      * items is not lost, prevents duplicates about different NodeLists
238      * while allowing for fine-grained updating of nodes on stateChange()
239      *
240      */

241     private static class NodeListKeyWrapper {
242         NodeList nodeList;
243         Object JavaDoc object;
244         NodeListKeyWrapper(Object JavaDoc obj, NodeList list) {
245             nodeList = list;
246             object = obj;
247         }
248         
249         public boolean equals(Object JavaDoc obj) {
250             if (! (obj instanceof NodeListKeyWrapper)) {
251                 return false;
252             }
253             NodeListKeyWrapper other = (NodeListKeyWrapper)obj;
254             if (! nodeList.equals(other.nodeList)) {
255                 return false;
256             }
257             return object.equals(other.object);
258         }
259         
260         public int hashCode() {
261             return (17 * 37 + nodeList.hashCode()) * 37 + object.hashCode();
262                     
263         }
264         
265     }
266     
267 }
268
Popular Tags