KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ant > freeform > ui > FolderNodeFactory


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.ant.freeform.ui;
21
22 import java.awt.Image JavaDoc;
23 import java.awt.event.ActionEvent JavaDoc;
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33 import javax.swing.AbstractAction JavaDoc;
34 import javax.swing.Action JavaDoc;
35 import javax.swing.event.ChangeEvent JavaDoc;
36 import javax.swing.event.ChangeListener JavaDoc;
37 import javax.swing.event.EventListenerList JavaDoc;
38 import org.netbeans.api.project.Project;
39 import org.netbeans.api.project.ProjectInformation;
40 import org.netbeans.api.project.ProjectManager;
41 import org.netbeans.api.project.ProjectUtils;
42 import org.netbeans.api.project.ui.OpenProjects;
43 import org.netbeans.api.project.ui.OpenProjects;
44 import org.netbeans.api.queries.VisibilityQuery;
45 import org.netbeans.modules.ant.freeform.FreeformProject;
46 import org.netbeans.modules.ant.freeform.FreeformProjectType;
47 import org.netbeans.modules.ant.freeform.spi.support.Util;
48 import org.netbeans.modules.ant.freeform.spi.ProjectNature;
49 import org.netbeans.spi.project.support.ant.AntProjectEvent;
50 import org.netbeans.spi.project.support.ant.AntProjectListener;
51 import org.netbeans.spi.project.support.ant.PathMatcher;
52 import org.netbeans.spi.project.ui.support.NodeFactory;
53 import org.netbeans.spi.project.ui.support.NodeList;
54 import org.openide.actions.OpenAction;
55 import org.openide.filesystems.FileObject;
56 import org.openide.filesystems.FileUtil;
57 import org.openide.loaders.ChangeableDataFilter;
58 import org.openide.loaders.DataFolder;
59 import org.openide.loaders.DataObject;
60 import org.openide.loaders.DataObjectNotFoundException;
61 import org.openide.nodes.AbstractNode;
62 import org.openide.nodes.Children;
63 import org.openide.nodes.FilterNode;
64 import org.openide.nodes.Node;
65 import org.openide.util.ContextAwareAction;
66 import org.openide.util.Exceptions;
67 import org.openide.util.Lookup;
68 import org.openide.util.RequestProcessor;
69 import org.openide.util.Utilities;
70 import org.openide.util.actions.SystemAction;
71 import org.openide.util.lookup.Lookups;
72 import org.w3c.dom.Element JavaDoc;
73
74 /**
75  *
76  * @author mkleint
77  */

78 public class FolderNodeFactory implements NodeFactory {
79     
80     /** Creates a new instance of FolderNodeFactory */
81     public FolderNodeFactory() {
82     }
83     
84     public NodeList createNodes(Project p) {
85         FreeformProject project = p.getLookup().lookup(FreeformProject.class);
86         assert project != null;
87         return new RootChildren(project);
88     }
89
90     
91     static boolean synchronous = false; // for ViewTest
92
private static final class RootChildren implements NodeList<Element JavaDoc>, AntProjectListener, PropertyChangeListener JavaDoc {
93         
94         private final FreeformProject p;
95         private List JavaDoc<Element JavaDoc> keys = new ArrayList JavaDoc<Element JavaDoc>();
96         private List JavaDoc<ChangeListener JavaDoc> listeners = new ArrayList JavaDoc<ChangeListener JavaDoc>();
97         
98         public RootChildren(FreeformProject p) {
99             this.p = p;
100         }
101         
102         public void addNotify() {
103             updateKeys(false);
104             p.helper().addAntProjectListener(this);
105             p.evaluator().addPropertyChangeListener(this);
106         }
107         
108         public void removeNotify() {
109             keys = null;
110             p.helper().removeAntProjectListener(this);
111             p.evaluator().removePropertyChangeListener(this);
112         }
113         
114         private void updateKeys(boolean fromListener) {
115             Element JavaDoc genldata = p.getPrimaryConfigurationData();
116             Element JavaDoc viewEl = Util.findElement(genldata, "view", FreeformProjectType.NS_GENERAL); // NOI18N
117
if (viewEl != null) {
118                 Element JavaDoc itemsEl = Util.findElement(viewEl, "items", FreeformProjectType.NS_GENERAL); // NOI18N
119
keys = Util.findSubElements(itemsEl);
120             } else {
121                 keys = Collections.<Element JavaDoc>emptyList();
122             }
123             if (fromListener && !synchronous) {
124                 // #50328, #58491 - post setKeys to different thread to prevent deadlocks
125
RequestProcessor.getDefault().post(new Runnable JavaDoc() {
126                     public void run() {
127                         fireChange();
128                     }
129                 });
130             } else {
131                 fireChange();
132             }
133         }
134         
135
136         public void configurationXmlChanged(AntProjectEvent ev) {
137             updateKeys(true);
138         }
139
140         public void propertiesChanged(AntProjectEvent ev) {
141             // ignore
142
}
143         
144         public void propertyChange(PropertyChangeEvent JavaDoc ev) {
145             updateKeys(true);
146         }
147
148         public List JavaDoc<Element JavaDoc> keys() {
149             return keys;
150         }
151
152         public void addChangeListener(ChangeListener JavaDoc l) {
153             listeners.add(l);
154         }
155
156         public void removeChangeListener(ChangeListener JavaDoc l) {
157             listeners.remove(l);
158         }
159         
160         private void fireChange() {
161             List JavaDoc<ChangeListener JavaDoc> list = new ArrayList JavaDoc<ChangeListener JavaDoc>();
162             list.addAll(listeners);
163             for (ChangeListener JavaDoc ls : listeners) {
164                 ls.stateChanged(new ChangeEvent JavaDoc(this));
165             }
166         }
167
168         public Node node(Element JavaDoc itemEl) {
169             
170             Element JavaDoc locationEl = Util.findElement(itemEl, "location", FreeformProjectType.NS_GENERAL); // NOI18N
171
String JavaDoc location = Util.findText(locationEl);
172             String JavaDoc locationEval = p.evaluator().evaluate(location);
173             if (locationEval == null) {
174                 return null;
175             }
176             FileObject file = p.helper().resolveFileObject(locationEval);
177             if (file == null) {
178                 // Not there... skip this node.
179
return null;
180             }
181             String JavaDoc label;
182             Element JavaDoc labelEl = Util.findElement(itemEl, "label", FreeformProjectType.NS_GENERAL); // NOI18N
183
if (labelEl != null) {
184                 label = Util.findText(labelEl);
185             } else {
186                 label = null;
187             }
188             if (itemEl.getLocalName().equals("source-folder")) { // NOI18N
189
if (!file.isFolder()) {
190                     // Just a file. Skip it.
191
return null;
192                 }
193                 String JavaDoc includes = null;
194                 Element JavaDoc includesEl = Util.findElement(itemEl, "includes", FreeformProjectType.NS_GENERAL); // NOI18N
195
if (includesEl != null) {
196                     includes = p.evaluator().evaluate(Util.findText(includesEl));
197                     if (includes.matches("\\$\\{[^}]+\\}")) { // NOI18N
198
// Clearly intended to mean "include everything".
199
includes = null;
200                     }
201                 }
202                 String JavaDoc excludes = null;
203                 Element JavaDoc excludesEl = Util.findElement(itemEl, "excludes", FreeformProjectType.NS_GENERAL); // NOI18N
204
if (excludesEl != null) {
205                     excludes = p.evaluator().evaluate(Util.findText(excludesEl));
206                 }
207                 String JavaDoc style = itemEl.getAttribute("style"); // NOI18N
208
for (ProjectNature nature : Lookup.getDefault().lookupAll(ProjectNature.class)) {
209                     if (nature.getSourceFolderViewStyles().contains(style)) {
210                         return nature.createSourceFolderView(p, file, includes, excludes, style, location, label);
211                     }
212                 }
213                 if (style.equals("subproject")) { // NOI18N
214
try {
215                         Project subproject = ProjectManager.getDefault().findProject(file);
216                         if (subproject != null) {
217                             return new SubprojectNode(subproject, label);
218                         }
219                     } catch (IOException JavaDoc x) {
220                         Exceptions.printStackTrace(x);
221                     }
222                     return null;
223                 }
224                 if (!style.equals("tree")) { // NOI18N
225
Logger.getLogger(FolderNodeFactory.class.getName()).log(Level.WARNING, "Unrecognized <source-folder> style '{0}' on {1}", new Object JavaDoc[] {style, file});
226                     // ... but show it as a tree anyway (at least ViewTest cares)
227
}
228                 DataObject fileDO;
229                 try {
230                     fileDO = DataObject.find(file);
231                 } catch (DataObjectNotFoundException e) {
232                     throw new AssertionError JavaDoc(e);
233                 }
234                 return new ViewItemNode((DataFolder) fileDO, includes, excludes, location, label);
235             } else {
236                 assert itemEl.getLocalName().equals("source-file") : itemEl; // NOI18N
237
DataObject fileDO;
238                     try {
239                         fileDO = DataObject.find(file);
240                     } catch (DataObjectNotFoundException e) {
241                         throw new AssertionError JavaDoc(e);
242                     }
243                 return new ViewItemNode(fileDO.getNodeDelegate(), location, label);
244             }
245         }
246     }
247     
248     
249     static final class VisibilityQueryDataFilter implements ChangeListener JavaDoc, ChangeableDataFilter {
250         
251         EventListenerList JavaDoc ell = new EventListenerList JavaDoc();
252         private final FileObject root;
253         private final PathMatcher matcher;
254         
255         public VisibilityQueryDataFilter(FileObject root, String JavaDoc includes, String JavaDoc excludes) {
256             this.root = root;
257             matcher = new PathMatcher(includes, excludes, FileUtil.toFile(root));
258             VisibilityQuery.getDefault().addChangeListener( this );
259         }
260                 
261         public boolean acceptDataObject(DataObject obj) {
262             FileObject fo = obj.getPrimaryFile();
263             String JavaDoc path = FileUtil.getRelativePath(root, fo);
264             assert path != null : fo + " not in " + root;
265             if (fo.isFolder()) {
266                 path += "/"; // NOI18N
267
}
268             if (!matcher.matches(path, true)) {
269                 return false;
270             }
271             return VisibilityQuery.getDefault().isVisible( fo );
272         }
273         
274         public void stateChanged( ChangeEvent JavaDoc e) {
275             Object JavaDoc[] listeners = ell.getListenerList();
276             ChangeEvent JavaDoc event = null;
277             for (int i = listeners.length-2; i>=0; i-=2) {
278                 if (listeners[i] == ChangeListener JavaDoc.class) {
279                     if ( event == null) {
280                         event = new ChangeEvent JavaDoc( this );
281                     }
282                     ((ChangeListener JavaDoc)listeners[i+1]).stateChanged( event );
283                 }
284             }
285         }
286     
287         public void addChangeListener( ChangeListener JavaDoc listener ) {
288             ell.add( ChangeListener JavaDoc.class, listener );
289         }
290                         
291         public void removeChangeListener( ChangeListener JavaDoc listener ) {
292             ell.remove( ChangeListener JavaDoc.class, listener );
293         }
294         
295     }
296     
297      private static final class ViewItemNode extends FilterNode {
298         
299         private final String JavaDoc name;
300         
301         private final String JavaDoc displayName;
302        
303         public ViewItemNode(Node orig, String JavaDoc name, String JavaDoc displayName) {
304             super(orig);
305             this.name = name;
306             this.displayName = displayName;
307         }
308         
309         public ViewItemNode(DataFolder folder, String JavaDoc includes, String JavaDoc excludes, String JavaDoc name, String JavaDoc displayName) {
310             super(folder.getNodeDelegate(), folder.createNodeChildren(new VisibilityQueryDataFilter(folder.getPrimaryFile(), includes, excludes)));
311             this.name = name;
312             this.displayName = displayName;
313         }
314         
315         public String JavaDoc getName() {
316             return name;
317         }
318         
319         public String JavaDoc getDisplayName() {
320             if (displayName != null) {
321                 return displayName;
322             } else {
323                 // #50425: show original name incl. annotations
324
return super.getDisplayName();
325             }
326         }
327         
328         public boolean canRename() {
329             return false;
330         }
331         
332         public boolean canDestroy() {
333             return false;
334         }
335         
336         public boolean canCut() {
337             return false;
338         }
339         
340     }
341
342      private static final class SubprojectNode extends AbstractNode { // #97442
343

344          private final Project p;
345          private final String JavaDoc label;
346          private final ProjectInformation info;
347
348          public SubprojectNode(Project p, String JavaDoc label) {
349              super(Children.LEAF, Lookups.singleton(p));
350              this.p = p;
351              this.label = label;
352              info = ProjectUtils.getInformation(p);
353          }
354
355          @Override JavaDoc
356          public String JavaDoc getName() {
357              return info.getName();
358          }
359
360          @Override JavaDoc
361          public String JavaDoc getDisplayName() {
362              return label != null ? label : info.getDisplayName();
363          }
364
365          @Override JavaDoc
366          public Image JavaDoc getIcon(int type) {
367              return Utilities.icon2Image(info.getIcon());
368          }
369
370          @Override JavaDoc
371          public Image JavaDoc getOpenedIcon(int type) {
372              return getIcon(type);
373          }
374
375          private static final class OpenProjectAction extends AbstractAction JavaDoc implements ContextAwareAction {
376              public void actionPerformed(ActionEvent JavaDoc ev) {
377                  assert false;
378              }
379              public Action JavaDoc createContextAwareInstance(Lookup selection) {
380                  final Project[] projects = selection.lookupAll(Project.class).toArray(new Project[0]);
381                  return new AbstractAction JavaDoc(SystemAction.get(OpenAction.class).getName()) {
382                      public void actionPerformed(ActionEvent JavaDoc ev) {
383                          OpenProjects.getDefault().open(projects, false);
384                      }
385                      @Override JavaDoc
386                      public boolean isEnabled() {
387                          return !Arrays.asList(OpenProjects.getDefault().getOpenProjects()).containsAll(Arrays.asList(projects));
388                      }
389                  };
390              }
391          }
392          private static final Action JavaDoc OPEN = new OpenProjectAction();
393          @Override JavaDoc
394          public Action JavaDoc[] getActions(boolean context) {
395              return new Action JavaDoc[] {OPEN};
396          }
397
398      }
399
400 }
401
Popular Tags