001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.bpel.project.ui;
020:
021: import java.awt.event.ActionEvent;
022: import java.beans.PropertyChangeEvent;
023: import java.beans.PropertyChangeListener;
024: import java.util.ArrayList;
025: import java.util.Arrays;
026: import java.util.Collections;
027: import java.util.Enumeration;
028: import java.util.List;
029: import java.util.ResourceBundle;
030: import java.util.StringTokenizer;
031:
032: import javax.swing.AbstractAction;
033: import javax.swing.Action;
034: import javax.swing.JSeparator;
035: import org.netbeans.api.project.Sources;
036: import org.netbeans.spi.project.ui.support.DefaultProjectOperations;
037:
038: import org.openide.nodes.*;
039: import org.openide.util.*;
040: import org.openide.util.actions.SystemAction;
041:
042: import org.netbeans.api.project.Project;
043: import org.netbeans.api.project.ProjectUtils;
044: import org.netbeans.api.project.SourceGroup;
045: import org.netbeans.spi.project.ui.support.CommonProjectActions;
046: import org.netbeans.spi.project.ActionProvider;
047: import org.netbeans.spi.project.SubprojectProvider;
048: import org.netbeans.spi.project.support.ant.AntProjectHelper;
049: import org.netbeans.spi.project.support.ant.PropertyEvaluator;
050: import org.netbeans.spi.project.support.ant.ReferenceHelper;
051: import org.netbeans.spi.project.ui.LogicalViewProvider;
052: import org.netbeans.spi.project.ui.support.ProjectSensitiveActions;
053: import org.netbeans.modules.bpel.project.IcanproConstants;
054: import org.netbeans.modules.bpel.project.ProjectConstants;
055: import org.netbeans.modules.compapp.projects.base.ui.customizer.IcanproProjectProperties;
056: import org.openide.filesystems.FileObject;
057: import org.openide.filesystems.FileUtil;
058: import org.openide.filesystems.Repository;
059:
060: import org.openide.loaders.DataFolder;
061: import org.openide.loaders.DataObject;
062: import org.openide.util.Lookup;
063: import org.openide.util.lookup.Lookups;
064:
065: /**
066: * Support for creating logical views.
067: * @author Petr Hrebejk
068: */
069: public class IcanproLogicalViewProvider implements LogicalViewProvider {
070:
071: private final Project project;
072: private final AntProjectHelper helper;
073: private final PropertyEvaluator evaluator;
074: private final SubprojectProvider spp;
075: private final ReferenceHelper resolver;
076:
077: public IcanproLogicalViewProvider(Project project,
078: AntProjectHelper helper, PropertyEvaluator evaluator,
079: SubprojectProvider spp, ReferenceHelper resolver) {
080: this .project = project;
081: assert project != null;
082: this .helper = helper;
083: assert helper != null;
084: this .evaluator = evaluator;
085: assert evaluator != null;
086: this .spp = spp;
087: assert spp != null;
088: this .resolver = resolver;
089: }
090:
091: public Node createLogicalView() {
092: return new IcanLogicalViewRootNode();
093: }
094:
095: /**
096: * {@inheritDoc}
097: * Fix for #83576.
098: * @author ads
099: */
100: public Node findPath(Node root, Object target) {
101: // Check each child node in turn.
102: Node[] children = root.getChildren().getNodes(true);
103: for (Node node : children) {
104: if (target instanceof DataObject
105: || target instanceof FileObject) {
106: DataObject d = (DataObject) node.getLookup().lookup(
107: DataObject.class);
108: if (d == null) {
109: continue;
110: }
111: // Copied from org.netbeans.spi.java.project.support.ui.TreeRootNode.PathFinder.findPath:
112: FileObject kidFO = d.getPrimaryFile();
113: FileObject targetFO = target instanceof DataObject ? ((DataObject) target)
114: .getPrimaryFile()
115: : (FileObject) target;
116: if (kidFO == targetFO) {
117: return node;
118: } else if (FileUtil.isParentOf(kidFO, targetFO)) {
119: String relPath = FileUtil.getRelativePath(kidFO,
120: targetFO);
121: List/*<String>*/path = Collections
122: .list(new StringTokenizer(relPath, "/")); // NOI18N
123: // XXX see original code for justification
124: path.set(path.size() - 1, targetFO.getName());
125: try {
126: Node found = NodeOp.findPath(node, Collections
127: .enumeration(path));
128:
129: // The code below is fix for #84948.
130: if (hasObject(found, target)) {
131: return found;
132: }
133: Node parent = found.getParentNode();
134: Children kids = parent.getChildren();
135: children = kids.getNodes();
136: for (Node child : children) {
137: if (hasObject(child, target)) {
138: return child;
139: }
140: }
141:
142: } catch (NodeNotFoundException e) {
143: return null;
144: }
145: }
146: }
147: }
148: return null;
149:
150: }
151:
152: private boolean hasObject(Node node, Object obj) {
153: if (obj == null) {
154: return false;
155: }
156: DataObject dataObject = (DataObject) node.getLookup().lookup(
157: DataObject.class);
158: if (dataObject == null) {
159: return false;
160: }
161: if (obj instanceof DataObject) {
162: if (dataObject.equals(obj)) {
163: return true;
164: }
165: FileObject fileObject = ((DataObject) obj).getPrimaryFile();
166: return hasObject(node, fileObject);
167: } else if (obj instanceof FileObject) {
168: FileObject fileObject = dataObject.getPrimaryFile();
169: return obj.equals(fileObject);
170: } else {
171: return false;
172: }
173: }
174:
175: private static Lookup createLookup(Project project) {
176: DataFolder rootFolder = DataFolder.findFolder(project
177: .getProjectDirectory());
178: // XXX remove after SimpleTargetChooserPanel rewrite (suggestion if default dir is project dir then it's source dir)
179: Sources sources = ProjectUtils.getSources(project);
180: List<SourceGroup> roots = new ArrayList<SourceGroup>();
181: SourceGroup[] javaRoots = sources
182: .getSourceGroups(ProjectConstants.SOURCES_TYPE_BPELPRO);
183: roots.addAll(Arrays.asList(javaRoots));
184: if (roots.isEmpty()) {
185: SourceGroup[] sourceGroups = sources
186: .getSourceGroups(Sources.TYPE_GENERIC);
187: roots.addAll(Arrays.asList(sourceGroups));
188: }
189: DataFolder folder = DataFolder.findFolder(roots.get(0)
190: .getRootFolder());
191: rootFolder = folder != null ? folder : rootFolder;
192: // \XXX remove after SimpleTargetChooserPanel rewrite (suggestion if default dir is project dir then it's source dir)
193:
194: // XXX Remove root folder after FindAction rewrite
195: return Lookups.fixed(new Object[] { project, rootFolder });
196: }
197:
198: // Private innerclasses ----------------------------------------------------
199:
200: private static final String[] BREAKABLE_PROPERTIES = new String[] {
201: IcanproProjectProperties.JAVAC_CLASSPATH,
202: IcanproProjectProperties.DEBUG_CLASSPATH,
203: IcanproProjectProperties.SRC_DIR, };
204:
205: public static boolean hasBrokenLinks(AntProjectHelper helper,
206: ReferenceHelper resolver) {
207: /*
208: return BrokenReferencesSupport.isBroken(helper, resolver, BREAKABLE_PROPERTIES,
209: new String[] {IcanproProjectProperties.JAVA_PLATFORM});
210: */
211: return false;
212: }
213:
214: /** Filter node containin additional features for the J2SE physical
215: */
216: private final class IcanLogicalViewRootNode extends AbstractNode {
217:
218: private Action brokenLinksAction;
219: private boolean broken;
220:
221: public IcanLogicalViewRootNode() {
222: super (new IcanproViews.LogicalViewChildren(helper,
223: evaluator, project), createLookup(project));
224: setIconBase("org/netbeans/modules/bpel/project/ui/resources/icanproProjectIcon"); // NOI18N
225: super .setName(ProjectUtils.getInformation(project)
226: .getDisplayName());
227: if (hasBrokenLinks(helper, resolver)) {
228: broken = true;
229: brokenLinksAction = new BrokenLinksAction();
230: }
231: }
232:
233: /**
234: * DOCUMENT ME!
235: *
236: * @return DOCUMENT ME!
237: */
238: public HelpCtx getHelpCtx() {
239: return new HelpCtx(IcanproLogicalViewProvider.class);
240: }
241:
242: public Action[] getActions(boolean context) {
243: if (context)
244: return super .getActions(true);
245: else
246: return getAdditionalActions();
247: }
248:
249: public boolean canRename() {
250: return true;
251: }
252:
253: public void setName(String s) {
254: DefaultProjectOperations.performDefaultRenameOperation(
255: project, s);
256: }
257:
258: // Private methods -------------------------------------------------
259:
260: private Action[] getAdditionalActions() {
261:
262: ResourceBundle bundle = NbBundle
263: .getBundle(IcanproLogicalViewProvider.class);
264:
265: List<Action> actions = new ArrayList<Action>();
266:
267: actions.add(CommonProjectActions.newFileAction());
268: actions.add(null);
269: actions.add(ProjectSensitiveActions.projectCommandAction(
270: ActionProvider.COMMAND_BUILD, bundle
271: .getString("LBL_BuildAction_Name"), null)); // NOI18N
272: actions
273: .add(ProjectSensitiveActions.projectCommandAction(
274: ActionProvider.COMMAND_REBUILD,
275: bundle.getString("LBL_RebuildAction_Name"),
276: null)); // NOI18N
277: actions.add(ProjectSensitiveActions.projectCommandAction(
278: ActionProvider.COMMAND_CLEAN, bundle
279: .getString("LBL_CleanAction_Name"), null)); // NOI18N
280: // null,
281: // ProjectSensitiveActions.projectCommandAction( IcanproConstants.COMMAND_REDEPLOY, bundle.getString( "LBL_RedeployAction_Name" ), null ), // NOI18N
282: // ProjectSensitiveActions.projectCommandAction( IcanproConstants.COMMAND_DEPLOY, bundle.getString( "LBL_DeployAction_Name" ), null ), // NOI18N
283: // actions.add(ProjectSensitiveActions.projectCommandAction( IcanproConstants.POPULATE_CATALOG, bundle.getString( "LBL_Populate_Catalog" ), null )); // NOI18N
284: actions.add(null);
285: actions.add(CommonProjectActions.setAsMainProjectAction());
286: actions.add(CommonProjectActions.openSubprojectsAction());
287: actions.add(CommonProjectActions.closeProjectAction());
288: actions.add(null);
289: actions.add(CommonProjectActions.renameProjectAction());
290: actions.add(CommonProjectActions.moveProjectAction());
291: actions.add(CommonProjectActions.copyProjectAction());
292: actions.add(CommonProjectActions.deleteProjectAction());
293: actions.add(null);
294: actions.add(SystemAction
295: .get(org.openide.actions.FindAction.class));
296: // add versioning support
297: addFromLayers(actions, "Projects/Actions"); //NOI18N
298: // null,
299: // SystemAction.get(org.openide.actions.OpenLocalExplorerAction.class),
300: actions.add(null);
301: actions.add(brokenLinksAction);
302: actions.add(CommonProjectActions.customizeProjectAction());
303:
304: return actions.toArray(new Action[actions.size()]);
305: }
306:
307: private void addFromLayers(List<Action> actions, String path) {
308: Lookup look = Lookups.forPath(path);
309: for (Object next : look.lookupAll(Object.class)) {
310: if (next instanceof Action) {
311: actions.add((Action) next);
312: } else if (next instanceof JSeparator) {
313: actions.add(null);
314: }
315: }
316: }
317:
318: /** This action is created only when project has broken references.
319: * Once these are resolved the action is disabled.
320: */
321: private class BrokenLinksAction extends AbstractAction
322: implements PropertyChangeListener {
323:
324: public BrokenLinksAction() {
325: evaluator.addPropertyChangeListener(this );
326: putValue(Action.NAME, NbBundle.getMessage(
327: IcanproLogicalViewProvider.class,
328: "LBL_Fix_Broken_Links_Action"));
329: }
330:
331: public void actionPerformed(ActionEvent e) {
332: /*
333: BrokenReferencesSupport.showCustomizer(helper, resolver, BREAKABLE_PROPERTIES, new String[]{IcanproProjectProperties.JAVA_PLATFORM});
334: if (!hasBrokenLinks(helper, resolver)) {
335: disable();
336: }
337: */
338: // do nothing...
339: }
340:
341: public void propertyChange(PropertyChangeEvent evt) {
342: if (!broken) {
343: disable();
344: return;
345: }
346: broken = hasBrokenLinks(helper, resolver);
347: if (!broken) {
348: disable();
349: }
350: }
351:
352: private void disable() {
353: broken = false;
354: setEnabled(false);
355: evaluator.removePropertyChangeListener(this );
356: fireIconChange();
357: fireOpenedIconChange();
358: }
359:
360: }
361:
362: }
363:
364: /** Factory for project actions.<BR>
365: * XXX This class is a candidate for move to org.netbeans.spi.project.ui.support
366: */
367: public static class Actions {
368:
369: private Actions() {
370: } // This is a factory
371:
372: public static Action createAction(String key, String name,
373: boolean global) {
374: return new ActionImpl(key, name, global ? Utilities
375: .actionsGlobalContext() : null);
376: }
377:
378: private static class ActionImpl extends AbstractAction
379: implements ContextAwareAction {
380:
381: Lookup context;
382: String name;
383: String command;
384:
385: public ActionImpl(String command, String name,
386: Lookup context) {
387: super (name);
388: this .context = context;
389: this .command = command;
390: this .name = name;
391: }
392:
393: public void actionPerformed(ActionEvent e) {
394:
395: Project project = (Project) context
396: .lookup(Project.class);
397: ActionProvider ap = (ActionProvider) project
398: .getLookup().lookup(ActionProvider.class);
399:
400: ap.invokeAction(command, context);
401:
402: }
403:
404: public Action createContextAwareInstance(Lookup lookup) {
405: return new ActionImpl(command, name, lookup);
406: }
407: }
408:
409: }
410:
411: }
|