KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > project > ui > groups > Group


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.modules.project.ui.groups;
21
22 import java.awt.EventQueue JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.net.URL JavaDoc;
25 import java.text.Collator JavaDoc;
26 import java.util.Arrays JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.Comparator JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.SortedSet JavaDoc;
32 import java.util.TreeSet JavaDoc;
33 import java.util.logging.Level JavaDoc;
34 import java.util.logging.LogRecord JavaDoc;
35 import java.util.logging.Logger JavaDoc;
36 import java.util.prefs.BackingStoreException JavaDoc;
37 import java.util.prefs.Preferences JavaDoc;
38 import org.netbeans.api.progress.ProgressHandle;
39 import org.netbeans.api.progress.ProgressHandleFactory;
40 import org.netbeans.api.project.Project;
41 import org.netbeans.api.project.ProjectManager;
42 import org.netbeans.api.project.ProjectUtils;
43 import org.netbeans.api.project.ui.OpenProjects;
44 import org.netbeans.modules.project.ui.ProjectTab;
45 import org.openide.filesystems.FileObject;
46 import org.openide.filesystems.FileStateInvalidException;
47 import org.openide.filesystems.URLMapper;
48 import org.openide.util.Exceptions;
49 import org.openide.util.NbBundle;
50 import org.openide.util.NbPreferences;
51
52 /**
53  * Represents a project group.
54  * Static methods represent set of groups and group selection.
55  * @author Jesse Glick
56  */

57 public abstract class Group {
58
59     private static final Logger JavaDoc LOG = Logger.getLogger(Group.class.getName());
60     private static final Logger JavaDoc UILOG = Logger.getLogger("org.netbeans.ui.project.groups");
61
62     protected static final Preferences JavaDoc NODE = NbPreferences.forModule(Group.class).node("groups");
63     /** Preferences key for the active group ID. */
64     private static final String JavaDoc KEY_ACTIVE = "active"; // NOI18N
65
/** Preferences key for whether to use "basic" or "advanced" mode. */
66     private static final String JavaDoc KEY_ADVANCED_MODE = "advancedMode"; // NOI18N
67
/** Preferences key for display name of group. */
68     protected static final String JavaDoc KEY_NAME = "name"; // NOI18N
69
/** Preferences key for kind of group (see constants in subclasses). */
70     protected static final String JavaDoc KEY_KIND = "kind"; // NOI18N
71
/** Preferences key for path (space-separated) of project URLs for AdHocGroup, or single project dir URL for SubprojectsGroup, or dir URL for DirectoryGroup. */
72     protected static final String JavaDoc KEY_PATH = "path"; // NOI18N
73
/** Preferences key for main project path URL for AdHocGroup or DirectoryGroup. */
74     protected static final String JavaDoc KEY_MAIN = "main"; // NOI18N
75

76     private static Group load(String JavaDoc id) {
77         if (id == null) {
78             return null;
79         }
80         String JavaDoc kind = NODE.node(id).get(KEY_KIND, null);
81         if (AdHocGroup.KIND.equals(kind)) {
82             return new AdHocGroup(id);
83         } else if (SubprojectsGroup.KIND.equals(kind)) {
84             return new SubprojectsGroup(id);
85         } else if (DirectoryGroup.KIND.equals(kind)) {
86             return new DirectoryGroup(id);
87         } else {
88             LOG.log(Level.WARNING, "Cannot find project group kind for id={0}", id);
89             return null;
90         }
91     }
92
93     /**
94      * Find all groups.
95      * Sorted by display name.
96      */

97     public static SortedSet JavaDoc<Group> allGroups() {
98         SortedSet JavaDoc<Group> groups = new TreeSet JavaDoc<Group>(displayNameComparator());
99         try {
100             for (String JavaDoc id : NODE.childrenNames()) {
101                 LOG.log(Level.FINER, "Considering project group id={0}", id);
102                 Group g = load(id);
103                 if (g != null) {
104                     groups.add(g);
105                 }
106             }
107         } catch (BackingStoreException JavaDoc x) {
108             Exceptions.printStackTrace(x);
109         }
110         return groups;
111     }
112
113     /**
114      * Find the currently active group (or null).
115      */

116     public static Group getActiveGroup() {
117         return load(NODE.get(KEY_ACTIVE, null));
118     }
119
120     /**
121      * Set the currently active group (or null).
122      */

123     public static void setActiveGroup(Group nue) {
124         LOG.log(Level.FINE, "set active group: {0}", nue);
125         if (UILOG.isLoggable(Level.FINER)) {
126             LogRecord JavaDoc rec = new LogRecord JavaDoc(Level.FINER, "Group.UI.setActiveGroup");
127             rec.setParameters(new Object JavaDoc[] {nue != null ? nue.toString(true) : null});
128             rec.setResourceBundle(NbBundle.getBundle(Group.class));
129             rec.setLoggerName(UILOG.getName());
130             UILOG.log(rec);
131         }
132         Group old = getActiveGroup();
133         if (old != null) {
134             old.closed();
135         }
136         if (nue != null) {
137             NODE.put(KEY_ACTIVE, nue.id);
138         } else {
139             NODE.remove(KEY_ACTIVE);
140         }
141         // OK if g == old; still want to fix open projects.
142
open(nue);
143     }
144
145     public static boolean isAdvancedMode() {
146         return NODE.getBoolean(KEY_ADVANCED_MODE, false);
147     }
148
149     public static void setAdvancedMode(boolean b) {
150         NODE.putBoolean(KEY_ADVANCED_MODE, b);
151         if (UILOG.isLoggable(Level.FINE)) {
152             LogRecord JavaDoc rec = new LogRecord JavaDoc(Level.FINE, "Group.UI.setAdvancedMode");
153             rec.setParameters(new Object JavaDoc[] {b});
154             rec.setResourceBundle(NbBundle.getBundle(Group.class));
155             rec.setLoggerName(UILOG.getName());
156             UILOG.log(rec);
157         }
158     }
159
160     protected static String JavaDoc sanitizeNameAndUniquifyForId(String JavaDoc name) {
161         String JavaDoc id = name.replaceAll("[^a-zA-Z0-9_.-]+", "_");
162         Set JavaDoc<String JavaDoc> existing;
163         try {
164             existing = new HashSet JavaDoc<String JavaDoc>(Arrays.asList(NODE.childrenNames()));
165         } catch (BackingStoreException JavaDoc x) {
166             Exceptions.printStackTrace(x);
167             return id;
168         }
169         if (existing.contains(id)) {
170             for (int i = 2; ; i++) {
171                 String JavaDoc candidate = id + "_" + i;
172                 if (!existing.contains(candidate)) {
173                     return candidate;
174                 }
175             }
176         } else {
177             return id;
178         }
179     }
180
181     protected final String JavaDoc id;
182
183     protected Group(String JavaDoc id) {
184         this.id = id;
185         assert id.indexOf('/') == -1;
186     }
187
188     protected Preferences JavaDoc prefs() {
189         return NODE.node(id);
190     }
191
192     /**
193      * The name of a group; may be used for display purposes.
194      */

195     public String JavaDoc getName() {
196         String JavaDoc n = getNameOrNull();
197         if (n == null) {
198             n = id;
199         }
200         return n;
201     }
202
203     protected String JavaDoc getNameOrNull() {
204         return prefs().get(KEY_NAME, null);
205     }
206
207     /**
208      * Change the current display name.
209      */

210     public void setName(String JavaDoc n) {
211         prefs().put(KEY_NAME, n);
212         if (this.equals(getActiveGroup())) {
213             EventQueue.invokeLater(new Runnable JavaDoc() {
214                 public void run() {
215                     ProjectTab.findDefault(ProjectTab.ID_LOGICAL).setGroup(Group.this);
216                 }
217             });
218         }
219     }
220
221     protected static Project projectForPath(String JavaDoc path) {
222         if (path != null) {
223             try {
224                 FileObject fo = URLMapper.findFileObject(new URL JavaDoc(path));
225                 if (fo != null && fo.isFolder()) {
226                     return ProjectManager.getDefault().findProject(fo);
227                 }
228             } catch (IOException JavaDoc x) {
229                 Exceptions.printStackTrace(x);
230             }
231         }
232         return null;
233     }
234
235     /**
236      * The projects (currently) contained in the group.
237      */

238     public Set JavaDoc<Project> getProjects() {
239         return getProjects(null, 0, 0);
240     }
241     private Set JavaDoc<Project> getProjects(ProgressHandle h, int start, int end) {
242         if (h != null) {
243             h.progress("", start);
244         }
245         Set JavaDoc<Project> projects = new HashSet JavaDoc<Project>();
246         findProjects(projects, h, start, end);
247         if (h != null) {
248             h.progress("", end);
249         }
250         assert !projects.contains(null) : "Found null in " + projects + " from " + this;
251         return projects;
252     }
253
254     protected abstract void findProjects(Set JavaDoc<Project> projects, ProgressHandle h, int start, int end);
255
256     protected static String JavaDoc progressMessage(Project p) {
257         return NbBundle.getMessage(Group.class, "Group.progress_project", ProjectUtils.getInformation(p).getDisplayName());
258     }
259
260     /**
261      * The main project for this group (if any).
262      */

263     public Project getMainProject() {
264         return projectForPath(prefs().get(KEY_MAIN, null));
265     }
266
267     /**
268      * Change the main project in the group.
269      * @throws IllegalArgumentException unless the main project is among {@link #getProjects}
270      */

271     public void setMainProject(Project mainProject) throws IllegalArgumentException JavaDoc {
272         LOG.log(Level.FINE, "updating main project for {0} to {1}", new Object JavaDoc[] {id, mainProject});
273         URL JavaDoc f = null;
274         if (mainProject != null && getProjects().contains(mainProject)) {
275             try {
276                 f = mainProject.getProjectDirectory().getURL();
277             } catch (FileStateInvalidException x) {
278                 LOG.log(Level.WARNING, null, x);
279             }
280         }
281         if (f != null) {
282             prefs().put(KEY_MAIN, f.toExternalForm());
283         } else {
284             if (mainProject != null) {
285                 LOG.log(Level.WARNING, "...but not an open project or disk path not found");
286             }
287             prefs().remove(KEY_MAIN);
288         }
289     }
290
291     /**
292      * Open a group, replacing any open projects with this group's project set.
293      */

294     private static void open(final Group g) {
295         EventQueue.invokeLater(new Runnable JavaDoc() {
296             public void run() {
297                 ProjectTab.findDefault(ProjectTab.ID_LOGICAL).setGroup(g);
298             }
299         });
300         String JavaDoc handleLabel;
301         if (g != null) {
302             handleLabel = NbBundle.getMessage(Group.class, "Group.open_handle", g.getName());
303         } else {
304             handleLabel = NbBundle.getMessage(Group.class, "Group.close_handle");
305         }
306         ProgressHandle h = ProgressHandleFactory.createHandle(handleLabel);
307         h.start(200);
308         OpenProjects op = OpenProjects.getDefault();
309         Set JavaDoc<Project> oldOpen = new HashSet JavaDoc<Project>(Arrays.asList(op.getOpenProjects()));
310         Set JavaDoc<Project> newOpen = g != null ? g.getProjects(h, 10, 100) : Collections.<Project>emptySet();
311         Set JavaDoc<Project> toClose = new HashSet JavaDoc<Project>(oldOpen);
312         toClose.removeAll(newOpen);
313         Set JavaDoc<Project> toOpen = new HashSet JavaDoc<Project>(newOpen);
314         toOpen.removeAll(oldOpen);
315         assert !toClose.contains(null) : toClose;
316         assert !toOpen.contains(null) : toOpen;
317         h.progress(NbBundle.getMessage(Group.class, "Group.progress_closing", toClose.size()), 120);
318         op.close(toClose.toArray(new Project[toClose.size()]));
319         h.progress(NbBundle.getMessage(Group.class, "Group.progress_opening", toOpen.size()), 140);
320         op.open(toOpen.toArray(new Project[toOpen.size()]), false);
321         if (g != null) {
322             op.setMainProject(g.getMainProject());
323         }
324         h.finish();
325     }
326
327     /**
328      * Called before a group is closed.
329      */

330     protected void closed() {
331         setMainProject(OpenProjects.getDefault().getMainProject());
332     }
333
334     /**
335      * Delete this group.
336      */

337     public void destroy() {
338         LOG.log(Level.FINE, "destroying: {0}", id);
339         if (equals(getActiveGroup())) {
340             setActiveGroup(null);
341         }
342         try {
343             Preferences JavaDoc p = prefs();
344             p.removeNode();
345             assert !p.nodeExists("") : "failed to destroy " + id;
346         } catch (BackingStoreException JavaDoc x) {
347             Exceptions.printStackTrace(x);
348         }
349     }
350
351     public abstract GroupEditPanel createPropertiesPanel();
352
353     /**
354      * Compares groups according to display name.
355      */

356     public static Comparator JavaDoc<Group> displayNameComparator() {
357         return new Comparator JavaDoc<Group>() {
358             Collator JavaDoc COLLATOR = Collator.getInstance();
359             public int compare(Group g1, Group g2) {
360                 return COLLATOR.compare(g1.getName(), g2.getName());
361             }
362         };
363     }
364
365     public int hashCode() {
366         return id.hashCode();
367     }
368
369     public boolean equals(Object JavaDoc obj) {
370         return obj instanceof Group && id.equals(((Group) obj).id);
371     }
372
373     public String JavaDoc toString() {
374         return toString(false);
375     }
376     protected String JavaDoc toString(boolean scrubPersonalInfo) {
377         return getClass().getName().replaceFirst("^.+\\.", "") + "[id=" + (scrubPersonalInfo ? "#" + id.hashCode() : id) + ",|projects|=" + getProjects().size() + "]";
378     }
379
380     /**
381      * True if the projects specified by this group are exactly those open at the moment.
382      * More precisely, true if closing and reopening this group would leave you with the same
383      * set of projects (incl. main project) as you currently have.
384      */

385     public boolean isPristine() {
386         return getProjects().equals(new HashSet JavaDoc<Project>(Arrays.asList(OpenProjects.getDefault().getOpenProjects())));
387     }
388
389 }
390
Popular Tags