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