001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * ProjectUtil.java
044: *
045: * Created on May 17, 2005, 7:22 PM
046: *
047: * To change this template, choose Tools | Options and locate the template under
048: * the Source Creation and Management node. Right-click the template and choose
049: * Open. You can then make changes to the template in the Source Editor.
050: */
051:
052: package org.netbeans.modules.uml.project;
053:
054: import java.beans.PropertyVetoException;
055: import java.text.MessageFormat;
056: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
057: import org.netbeans.modules.uml.core.metamodel.structure.IProject;
058: import java.io.File;
059: import java.text.Collator;
060: import java.util.ArrayList;
061: import java.util.Arrays;
062: import java.util.Collection;
063: import java.util.Comparator;
064: import java.util.HashSet;
065: import java.util.Iterator;
066: import java.util.List;
067: import java.util.Set;
068: import java.util.StringTokenizer;
069: import javax.swing.SwingUtilities;
070: import org.netbeans.api.java.classpath.ClassPath;
071: import org.netbeans.api.java.project.JavaProjectConstants;
072: import org.netbeans.api.project.FileOwnerQuery;
073: import org.netbeans.api.project.Project;
074: import org.netbeans.api.project.ProjectUtils;
075: import org.netbeans.api.project.SourceGroup;
076: import org.netbeans.api.project.Sources;
077: import org.netbeans.api.project.ui.OpenProjects;
078: import org.netbeans.modules.uml.common.RelationshipCookie;
079: import org.netbeans.modules.uml.core.metamodel.diagrams.IDiagram;
080: import org.netbeans.modules.uml.project.ui.UMLProjectSettings;
081: import org.netbeans.modules.uml.project.ui.customizer.UMLProjectProperties;
082: import org.netbeans.modules.uml.project.ui.nodes.AbstractModelElementNode;
083: import org.netbeans.modules.uml.project.ui.nodes.ModelRootNodeCookie;
084: import org.netbeans.modules.uml.ui.controls.projecttree.IProjectTreeItem;
085: import org.netbeans.spi.java.classpath.ClassPathProvider;
086: import org.netbeans.spi.project.support.ant.AntProjectHelper;
087: import org.netbeans.spi.project.support.ant.EditableProperties;
088: import org.openide.awt.StatusDisplayer;
089: import org.openide.explorer.ExplorerManager;
090: import org.openide.filesystems.FileObject;
091: import org.openide.filesystems.FileUtil;
092: import org.openide.loaders.DataFolder;
093: import org.openide.loaders.DataObject;
094: import org.openide.nodes.Children;
095: import org.openide.nodes.Node;
096: import org.openide.util.Lookup;
097: import org.openide.util.NbBundle;
098: import org.openide.util.RequestProcessor;
099: import org.openide.util.Utilities;
100: import org.openide.windows.TopComponent;
101: import org.openide.windows.WindowManager;
102:
103: /**
104: *
105: * @author Administrator
106: */
107: public class ProjectUtil {
108: public static final Comparator PROJECT_BY_DISPLAYNAME = new ProjectByDisplayNameComparator();
109:
110: public static Project findElementOwner(IElement element) {
111: Project retVal = null;
112: if (element != null) {
113: //IProject project = element.getProject();
114: IElement owningElement = element.getOwner();
115: if (owningElement != null) { //JM: Fix an NPE
116: IProject project = owningElement.getProject();
117:
118: retVal = findNetBeansProjectForModel(project);
119: } else {
120: retVal = findNetBeansProjectForModel(element
121: .getProject());
122: }
123: }
124:
125: return retVal;
126: }
127:
128: public static Project findReferencingProject(IElement element) {
129: Project retVal = null;
130: if (element != null) {
131: IProject project = element.getProject();
132:
133: retVal = findNetBeansProjectForModel(project);
134: }
135:
136: return retVal;
137: }
138:
139: public static Project findNetBeansProjectForModel(IProject project) {
140: Project retVal = null;
141:
142: if (project != null) {
143: String filename = project.getFileName();
144: if ((filename != null) && (filename.length() > 0)) {
145: FileObject fo = FileUtil
146: .toFileObject(new File(filename));
147: if (fo != null) {
148: retVal = FileOwnerQuery.getOwner(fo);
149: }
150: }
151: }
152:
153: return retVal;
154: }
155:
156: public static boolean findElementInProjectTree(IElement element) {
157: Node selectedNode = findNodeInProjectTree(element);
158: if (selectedNode != null) {
159: selectNodeAsync(selectedNode);
160: return true;
161: }
162: return false;
163: }
164:
165: public static Node findNodeInProjectTree(IElement element) {
166: Project project = findReferencingProject(element);
167:
168: return findNodeInProjectTree(project, element);
169: }
170:
171: public static Node findNodeInProjectTree(Project project,
172: IElement element) {
173: TopComponent tc = WindowManager.getDefault().findTopComponent(
174: "projectTabLogical_tc");
175: if (tc == null)
176: return null;
177:
178: ExplorerManager explorerManager = ((ExplorerManager.Provider) tc)
179: .getExplorerManager();
180: Node root = explorerManager.getRootContext();
181: Children c = root.getChildren();
182: Node[] projectNodes = c.getNodes(true);
183: for (int i = 0; i < projectNodes.length; i++) {
184: Project p = (Project) projectNodes[i].getLookup().lookup(
185: Project.class);
186: if (p == project) {
187: Node selectedNode = findNodeQuick(projectNodes[i],
188: element);
189: if (selectedNode == null) {
190: selectedNode = findNode(projectNodes[i], element);
191: }
192: return selectedNode;
193: }
194: }
195: return null;
196: }
197:
198: public static AntProjectHelper getAntProjectHelper(
199: UMLProject umlProject) {
200: return (AntProjectHelper) ((UMLProjectHelper) umlProject
201: .getLookup().lookup(UMLProjectHelper.class))
202: .getAntProjectHelper();
203: }
204:
205: public static String getTargetJavaProjectName(UMLProject umlProject) {
206: AntProjectHelper umlAntProjectHelper = getAntProjectHelper(umlProject);
207:
208: EditableProperties editableProperties = umlAntProjectHelper
209: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
210:
211: return (String) editableProperties
212: .getProperty(UMLProjectProperties.REFERENCED_JAVA_PROJECT);
213: }
214:
215: private static String getTargetJavaProjectName(IProject iProject) {
216: return ProjectUtil
217: .getTargetJavaProjectName((UMLProject) ProjectUtil
218: .findNetBeansProjectForModel(iProject));
219: }
220:
221: public static String getTargetJavaProjectName(IElement element) {
222: UMLProject umlProject = (UMLProject) ProjectUtil
223: .findReferencingProject(element);
224:
225: return ProjectUtil.getTargetJavaProjectName(umlProject);
226: }
227:
228: public static String getTargetJavaProjectName(Node node) {
229: IElement element = (IElement) node.getCookie(IElement.class);
230: if (element == null)
231: return null;
232:
233: return ProjectUtil.getTargetJavaProjectName(element);
234: }
235:
236: public static boolean hasTargetJavaProject(Node node) {
237: String name = ProjectUtil.getTargetJavaProjectName(node);
238: return name == null || name.length() == 0 ? false : true;
239: }
240:
241: public static boolean hasTargetJavaProject(IProject umlProject) {
242: String name = ProjectUtil.getTargetJavaProjectName(umlProject);
243: return name == null || name.length() == 0 ? false : true;
244: }
245:
246: public static Node findNode(Node root, IElement element) {
247:
248: if (root.isLeaf())
249: return null;
250:
251: Children children = root.getChildren();
252:
253: Node[] nodes = children.getNodes(true);
254: for (int j = 0; j < nodes.length; j++) {
255: IProjectTreeItem item = (IProjectTreeItem) nodes[j]
256: .getCookie(IProjectTreeItem.class);
257: if (item != null) {
258: IElement modelElement = item.getModelElement();
259: if (modelElement == null) // could be a diagram node
260: {
261: if (element instanceof IDiagram) {
262: // the unique diagram file name is used to determine
263: // if two diagram objects are same
264: if (item.getDiagram() != null
265: && item.getDescription().equals(
266: ((IDiagram) element)
267: .getFilename()))
268: return nodes[j];
269: }
270: }
271: if (modelElement != null
272: && element.getXMIID().equals(
273: modelElement.getXMIID())) {
274: if (nodes[j].getCookie(RelationshipCookie.class) != null)
275: continue;
276: return nodes[j];
277: }
278: }
279: }
280: for (int j = 0; j < nodes.length; j++) {
281: if (nodes[j].isLeaf())
282: continue;
283: Node val = findNode(nodes[j], element);
284: if (val != null) {
285: return val;
286: }
287: }
288: return null;
289: }
290:
291: private static Node findNodeQuick(Node root, IElement element) {
292: if (root.isLeaf())
293: return null;
294:
295: if (element == null) {
296: return null;
297: }
298:
299: IElement owner = element.getOwner();
300: if (owner == null) {
301: return findNode(root, element);
302: } else {
303: Node ownerNode = findNodeQuick(root, owner);
304: if (ownerNode != null) {
305: return findNode(ownerNode, element);
306: }
307: }
308: return null;
309: }
310:
311: public static Project[] getSelectedProjects(Class projectClass) {
312: Set result = new HashSet();
313: Lookup lruLookupLocal = Utilities.actionsGlobalContext();
314: // First find out whether there is a project directly in the Lookup
315: Collection currentProjects = lruLookupLocal.lookup(
316: new Lookup.Template(projectClass)).allInstances();
317:
318: for (Iterator it = currentProjects.iterator(); it.hasNext();) {
319: Project p = (Project) it.next();
320: result.add(p);
321: }
322:
323: // Now try to guess the project from dataobjects
324: Collection currentDataObjects = lruLookupLocal.lookup(
325: new Lookup.Template(DataObject.class)).allInstances();
326: for (Iterator it = currentDataObjects.iterator(); it.hasNext();) {
327:
328: DataObject dObj = (DataObject) it.next();
329: FileObject fObj = dObj.getPrimaryFile();
330: if (fObj != null) {
331: Project p = FileOwnerQuery.getOwner(fObj);
332: if (p != null) {
333: result.add(p);
334: }
335: }
336: }
337: Project[] projects = new Project[result.size()];
338: result.toArray(projects);
339: Arrays.sort(projects, PROJECT_BY_DISPLAYNAME);
340: return projects;
341: }
342:
343: public static Project[] getOpenUMLProjects() {
344: Project[] projects = OpenProjects.getDefault()
345: .getOpenProjects();
346: Set result = new HashSet();
347: for (Project p : projects) {
348: if (p.getLookup().lookup(UMLProjectHelper.class) != null)
349: result.add(p);
350: }
351:
352: Project[] umlprojects = new Project[result.size()];
353: result.toArray(umlprojects);
354: Arrays.sort(umlprojects, PROJECT_BY_DISPLAYNAME);
355: return umlprojects;
356: }
357:
358: public static Project[] getOpenJavaProjects() {
359: List result = new ArrayList();
360: Project openProjects[] = OpenProjects.getDefault()
361: .getOpenProjects();
362: for (Project p : openProjects) {
363: Sources srcs = (Sources) p.getLookup()
364: .lookup(Sources.class);
365:
366: if (srcs != null) {
367: // now check for Java sources
368: SourceGroup[] javaSrcGrps = srcs
369: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
370: if (javaSrcGrps.length > 0) {
371: ClassPathProvider cpProvider = (ClassPathProvider) p
372: .getLookup()
373: .lookup(ClassPathProvider.class);
374: if (cpProvider != null)
375: result.add(p);
376: }
377: }
378: }
379: Project[] projects = (Project[]) result
380: .toArray(new Project[result.size()]);
381: Arrays.sort(projects, PROJECT_BY_DISPLAYNAME);
382: return projects;
383: }
384:
385: public final static String DEFAULT_PACKAGE_DISPLAY_NAME = "<default package>"; // NOI18N
386:
387: public static void selectInModel(Project proj, DataObject obj) {
388: String resourceName = "";
389: String className = "";
390: String packageName = DEFAULT_PACKAGE_DISPLAY_NAME;
391: boolean isPackage = obj instanceof DataFolder;
392:
393: if (obj == null)
394: return;
395:
396: FileObject fObj = obj.getPrimaryFile();
397: ClassPath path = ClassPath.getClassPath(fObj, ClassPath.SOURCE);
398: if (path != null)
399: resourceName = path.getResourceName(fObj);
400:
401: if (resourceName.indexOf(".") != -1) // it's a class, otherwise package
402: {
403: resourceName = resourceName.substring(0, resourceName
404: .indexOf("."));
405: className = resourceName.substring(resourceName
406: .lastIndexOf("/") + 1);
407:
408: // cvc - CR 6409539
409: // if class is in default package, the packageName has no slashes
410: // and therefore, the substring call breaks
411: int lastSlashIndex = resourceName.lastIndexOf("/");
412: if (lastSlashIndex > -1)
413: packageName = resourceName.substring(0, lastSlashIndex);
414: }
415:
416: else {
417: packageName = resourceName;
418: }
419:
420: StringTokenizer st = new StringTokenizer(packageName, "/");
421: TopComponent tc = WindowManager.getDefault().findTopComponent(
422: "projectTabLogical_tc");
423:
424: if (tc == null)
425: return;
426:
427: ExplorerManager explorerManager = ((ExplorerManager.Provider) tc)
428: .getExplorerManager();
429:
430: Node root = explorerManager.getRootContext();
431: Children c = root.getChildren();
432: Node[] projectNodes = c.getNodes(true);
433:
434: for (int i = 0; i < projectNodes.length; i++) {
435: Project p = (Project) projectNodes[i].getLookup().lookup(
436: Project.class);
437:
438: Node selected = null;
439:
440: if (p == proj) {
441: Node selectedNode = null;
442:
443: if (st.hasMoreTokens()) {
444: String token = st.nextToken();
445: selectedNode = findNodeByName(projectNodes[i],
446: token, true);
447:
448: while (selectedNode != null && st.hasMoreTokens()) {
449: selectedNode = findNodeByName(selectedNode, st
450: .nextToken(), true);
451: }
452: }
453:
454: if (!isPackage) {
455: selectedNode = findNodeByName(selectedNode,
456: className, false);
457: }
458:
459: final Node node = selectedNode;
460: selectNodeAsync(node);
461: }
462: }
463: return;
464: }
465:
466: public static Node findNodeByName(Node root, String name,
467: boolean isPackage) {
468: if (root.isLeaf())
469: return null;
470:
471: Children children = root.getChildren();
472: Node[] nodes = children.getNodes(true);
473:
474: for (int j = 0; j < nodes.length; j++) {
475: Node curNode = nodes[j];
476:
477: if (curNode.getCookie(ModelRootNodeCookie.class) != null) {
478: // cvc - CR 6409539
479: // if the class source is in the default package, the
480: // findNodeByName doesn't know that Model root node
481: // is the default package
482: if (name.equals(DEFAULT_PACKAGE_DISPLAY_NAME))
483: return curNode;
484:
485: else
486: return findNodeByName(curNode, name, isPackage);
487: }
488:
489: IElement element = (IElement) curNode
490: .getCookie(IElement.class);
491:
492: if (element == null)
493: continue;
494:
495: String type = element.getElementType();
496:
497: if (isPackage) {
498: if (curNode.getName().equals(name)
499: && type
500: .equals(AbstractModelElementNode.ELEMENT_TYPE_PACKAGE)) {
501: return curNode;
502: }
503: }
504:
505: else {
506: if (curNode.getName().equals(name)
507: && (type
508: .equals(AbstractModelElementNode.ELEMENT_TYPE_CLASS))
509: || (type
510: .equals(AbstractModelElementNode.ELEMENT_TYPE_INTERFACE))) {
511: return nodes[j];
512: }
513: }
514: }
515:
516: return null;
517: }
518:
519: private static final RequestProcessor RP = new RequestProcessor();
520:
521: public static void selectNodeAsync(final Node selectedNode) {
522:
523: final TopComponent tc = WindowManager.getDefault()
524: .findTopComponent("projectTabLogical_tc");
525: if (tc == null)
526: return;
527:
528: final ExplorerManager manager = ((ExplorerManager.Provider) tc)
529: .getExplorerManager();
530: tc.setCursor(Utilities.createProgressCursor(tc));
531: tc.open();
532: tc.requestActive();
533:
534: // Do it in different thread than AWT
535: RP.post(new Runnable() {
536: public void run() {
537:
538: // Back to AWT
539: SwingUtilities.invokeLater(new Runnable() {
540: public void run() {
541: if (selectedNode != null) {
542: try {
543: manager
544: .setSelectedNodes(new Node[] { selectedNode });
545: StatusDisplayer.getDefault()
546: .setStatusText(""); // NOI18N
547: } catch (PropertyVetoException e) {
548: // Bad day node found but can't be selected
549: }
550: } else {
551: StatusDisplayer.getDefault().setStatusText(
552: NbBundle.getMessage(
553: ProjectUtil.class,
554: "MSG_NodeNotFound"));
555: }
556: tc.setCursor(null);
557: }
558: });
559: }
560: });
561:
562: }
563:
564: public static String createUniqueProjectName(File location,
565: String baseName, boolean tryNoIndexFirst) {
566: String projectName = null;
567:
568: if (baseName == null || baseName.length() == 0) {
569: baseName = NbBundle.getMessage(ProjectUtil.class,
570: "TXT_UMLProject"); // NOI18N
571: }
572:
573: int baseCount = UMLProjectSettings.getDefault()
574: .getNewProjectCount() + 1;
575:
576: if (tryNoIndexFirst)
577: projectName = validFreeProjectName(location, baseName, -1);
578:
579: while (projectName == null) {
580: projectName = validFreeProjectName(location, baseName
581: + "{0}", baseCount);
582:
583: baseCount++;
584: }
585:
586: return projectName;
587: }
588:
589: private static String validFreeProjectName(final File parentFolder,
590: final String formatter, final int index) {
591: String name = "";
592:
593: if (index == -1)
594: name = formatter;
595:
596: else {
597: name = MessageFormat.format(formatter,
598: new Object[] { new Integer(index) });
599: }
600:
601: File file = new File(parentFolder, name);
602: return file.exists() ? null : name;
603: }
604:
605: public static IProject getOwningProjectOfImportedElement(
606: IElement imported) {
607: IElement owner = imported.getOwner();
608: if (!(owner instanceof IProject))
609: return getOwningProjectOfImportedElement(owner);
610: return (IProject) owner;
611: }
612:
613: public static class ProjectByDisplayNameComparator implements
614: Comparator {
615:
616: private static Comparator COLLATOR = Collator.getInstance();
617:
618: public int compare(Object o1, Object o2) {
619:
620: if (!(o1 instanceof Project)) {
621: return 1;
622: }
623: if (!(o2 instanceof Project)) {
624: return -1;
625: }
626:
627: Project p1 = (Project) o1;
628: Project p2 = (Project) o2;
629:
630: return COLLATOR.compare(ProjectUtils.getInformation(p1)
631: .getDisplayName(), ProjectUtils.getInformation(p2)
632: .getDisplayName());
633: }
634: }
635: }
|