KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > project > ProjectUtils


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.api.project;
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28 import javax.swing.Icon JavaDoc;
29 import javax.swing.ImageIcon JavaDoc;
30 import org.netbeans.spi.project.SubprojectProvider;
31 import org.netbeans.spi.project.support.GenericSources;
32 import org.openide.filesystems.FileStateInvalidException;
33 import org.openide.util.Mutex;
34 import org.openide.util.Utilities;
35
36 /**
37  * Utility methods to get information about {@link Project}s.
38  * @author Jesse Glick
39  */

40 public class ProjectUtils {
41
42     private ProjectUtils() {}
43     
44     /**
45      * Get basic information about a project.
46      * If the project has a {@link ProjectInformation} instance in its lookup,
47      * that is used. Otherwise, a basic dummy implementation is returned.
48      * @param p a project
49      * @return some information about it
50      * @see Project#getLookup
51      */

52     public static ProjectInformation getInformation(Project p) {
53         ProjectInformation pi = p.getLookup().lookup(ProjectInformation.class);
54         if (pi != null) {
55             return pi;
56         } else {
57             return new BasicInformation(p);
58         }
59     }
60     
61     /**
62      * Get a list of sources for a project.
63      * If the project has a {@link Sources} instance in its lookup,
64      * that is used. Otherwise, a basic implementation is returned
65      * using {@link GenericSources#genericOnly}.
66      * @param p a project
67      * @return a list of sources for it
68      * @see Project#getLookup
69      */

70     public static Sources getSources(Project p) {
71         Sources s = p.getLookup().lookup(Sources.class);
72         if (s != null) {
73             return s;
74         } else {
75             return GenericSources.genericOnly(p);
76         }
77     }
78     
79     /**
80      * Check whether a project has, or might have, cycles in its subproject graph.
81      * <p>
82      * If the candidate parameter is null, this simply checks whether the master
83      * project's current directed graph of (transitive) subprojects contains any
84      * cycles. If the candidate is also passed, this checks whether the master
85      * project's subproject graph would contain cycles if the candidate were added
86      * as a (direct) subproject of the master project.
87      * </p>
88      * <p>
89      * All cycles are reported even if they do not contain the master project.
90      * </p>
91      * <p>
92      * If the master project already contains the candidate as a (direct) subproject,
93      * the effect is as if the candidate were null.
94      * </p>
95      * <p>
96      * Projects with no {@link SubprojectProvider} are considered to have no
97      * subprojects, just as if the provider returned an empty set.
98      * </p>
99      * <p>
100      * Acquires read access.
101      * </p>
102      * <p class="nonnormative">
103      * Project types which let the user somehow configure subprojects in the GUI
104      * (perhaps indirectly, e.g. via a classpath) should use this call to check
105      * for possible cycles before adding new subprojects.
106      * </p>
107      * @param master a project to root the subproject graph from
108      * @param candidate a potential direct subproject of the master project, or null
109      * @return true if the master project currently has a cycle somewhere in its
110      * subproject graph, regardless of the candidate parameter, or if the
111      * candidate is not null and the master project does not currently have
112      * a cycle but would have one if the candidate were added as a subproject
113      * @see <a HREF="http://www.netbeans.org/issues/show_bug.cgi?id=43845">Issue #43845</a>
114      */

115     public static boolean hasSubprojectCycles(final Project master, final Project candidate) {
116         return ProjectManager.mutex().readAccess(new Mutex.Action<Boolean JavaDoc>() {
117             public Boolean JavaDoc run() {
118                 return visit(new HashSet JavaDoc<Project>(), new HashMap JavaDoc<Project,Set JavaDoc<? extends Project>>(), master, master, candidate);
119             }
120         });
121     }
122     
123     /**
124      * Do a DFS traversal checking for cycles.
125      * @param encountered projects already encountered in the DFS (added and removed as you go)
126      * @param curr current node to visit
127      * @param master the original master project (for use with candidate param)
128      * @param candidate a candidate added subproject for master, or null
129      */

130     private static boolean visit(Set JavaDoc<Project> encountered, Map JavaDoc<Project,Set JavaDoc<? extends Project>> cache, Project curr, Project master, Project candidate) {
131         if (!encountered.add(curr)) {
132             return true;
133         }
134         Set JavaDoc<? extends Project> subprojects = cache.get(curr);
135         if (subprojects == null) {
136             SubprojectProvider spp = curr.getLookup().lookup(SubprojectProvider.class);
137             subprojects = spp != null ? spp.getSubprojects() : Collections.<Project>emptySet();
138             cache.put(curr, subprojects);
139         }
140         for (Project child : subprojects) {
141             if (candidate == child) {
142                 candidate = null;
143             }
144             if (visit(encountered, cache, child, master, candidate)) {
145                 return true;
146             }
147         }
148         if (candidate != null && curr == master) {
149             if (visit(encountered, cache, candidate, master, candidate)) {
150                 return true;
151             }
152         }
153         assert encountered.contains(curr);
154         encountered.remove(curr);
155         return false;
156     }
157     
158     private static final class BasicInformation implements ProjectInformation {
159         
160         private final Project p;
161         
162         public BasicInformation(Project p) {
163             this.p = p;
164         }
165         
166         public String JavaDoc getName() {
167             try {
168                 return p.getProjectDirectory().getURL().toExternalForm();
169             } catch (FileStateInvalidException e) {
170                 return e.toString();
171             }
172         }
173         
174         public String JavaDoc getDisplayName() {
175             return p.getProjectDirectory().getNameExt();
176         }
177         
178         public Icon JavaDoc getIcon() {
179             return new ImageIcon JavaDoc(Utilities.loadImage("org/netbeans/modules/projectapi/resources/empty.gif")); // NOI18N
180
}
181         
182         public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
183             // never changes
184
}
185         
186         public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
187             // never changes
188
}
189         
190         public Project getProject() {
191             return p;
192         }
193         
194     }
195     
196 }
197
Popular Tags