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.etl.project.ui;
020:
021: import java.awt.event.ActionEvent;
022: import java.beans.PropertyChangeEvent;
023: import java.beans.PropertyChangeListener;
024: import java.util.Collections;
025: import java.util.List;
026: import java.util.ResourceBundle;
027:
028: import java.util.StringTokenizer;
029: import javax.swing.AbstractAction;
030: import javax.swing.Action;
031:
032: import javax.swing.JSeparator;
033: import net.java.hulp.i18n.Logger;
034: import org.openide.filesystems.FileStateInvalidException;
035: import org.openide.nodes.*;
036: import org.openide.util.*;
037: import org.openide.loaders.DataFolder;
038: import org.openide.util.lookup.Lookups;
039: import org.openide.util.actions.SystemAction;
040:
041: import org.netbeans.api.project.Project;
042: import org.netbeans.api.project.ProjectUtils;
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.LogicalViewProvider;
050: import org.netbeans.spi.project.ui.support.ProjectSensitiveActions;
051: import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport;
052: import org.netbeans.modules.compapp.projects.base.ui.customizer.IcanproProjectProperties;
053: import org.netbeans.modules.compapp.projects.base.ui.IcanproLogicalViewProvider;
054: import org.netbeans.modules.compapp.projects.base.IcanproConstants;
055: import org.netbeans.modules.etl.project.EtlproProject;
056: import org.netbeans.modules.etl.project.EtlproProjectGenerator;
057: import org.netbeans.modules.etl.project.Localizer;
058: import org.netbeans.modules.etl.project.LogUtil;
059: import org.netbeans.modules.mashup.db.wizard.NewFlatfileDatabaseWizardAction;
060: import org.netbeans.modules.mashup.db.wizard.NewFlatfileTableAction;
061: import org.netbeans.modules.mashup.tables.wizard.MashupTableWizardIterator;
062: import org.openide.filesystems.FileObject;
063: import org.openide.filesystems.FileUtil;
064: import org.openide.loaders.DataObject;
065:
066: /**
067: * Support for creating logical views.
068: * @author Petr Hrebejk
069: */
070: public class EtlproLogicalViewProvider implements LogicalViewProvider {
071:
072: private final Project project;
073: private final AntProjectHelper helper;
074: private final PropertyEvaluator evaluator;
075: private final SubprojectProvider spp;
076: private final ReferenceHelper resolver;
077: private static transient final Logger mLogger = LogUtil
078: .getLogger(EtlproLogicalViewProvider.class.getName());
079: private static transient final Localizer mLoc = Localizer.get();
080:
081: public EtlproLogicalViewProvider(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 EtlLogicalViewRootNode();
097: }
098:
099: public Node findPath(Node root, Object target) {
100: // Check each child node in turn.
101: Node[] children = root.getChildren().getNodes(true);
102: for (Node node : children) {
103: if (target instanceof DataObject
104: || target instanceof FileObject) {
105: DataObject d = (DataObject) node.getLookup().lookup(
106: DataObject.class);
107: if (d == null) {
108: continue;
109: }
110: // Copied from org.netbeans.spi.java.project.support.ui.TreeRootNode.PathFinder.findPath:
111: FileObject kidFO = d.getPrimaryFile();
112: FileObject targetFO = target instanceof DataObject ? ((DataObject) target)
113: .getPrimaryFile()
114: : (FileObject) target;
115: if (kidFO == targetFO) {
116: return node;
117: } else if (FileUtil.isParentOf(kidFO, targetFO)) {
118: String relPath = FileUtil.getRelativePath(kidFO,
119: targetFO);
120: List/*<String>*/path = Collections
121: .list(new StringTokenizer(relPath, "/")); // NOI18N
122: // XXX see original code for justification
123: path.set(path.size() - 1, targetFO.getName());
124: try {
125: Node found = NodeOp.findPath(node, Collections
126: .enumeration(path));
127:
128: // The code below is fix for #84948.
129: if (hasObject(found, target)) {
130: return found;
131: }
132: Node parent = found.getParentNode();
133: Children kids = parent.getChildren();
134: children = kids.getNodes();
135: for (Node child : children) {
136: if (hasObject(child, target)) {
137: return child;
138: }
139: }
140:
141: } catch (NodeNotFoundException e) {
142: return null;
143: }
144: }
145: }
146: }
147: return null;
148: }
149:
150: private boolean hasObject(Node node, Object obj) {
151: if (obj == null) {
152: return false;
153: }
154: DataObject dataObject = (DataObject) node.getLookup().lookup(
155: DataObject.class);
156: if (dataObject == null) {
157: return false;
158: }
159: if (obj instanceof DataObject) {
160: if (dataObject.equals(obj)) {
161: return true;
162: }
163: FileObject fileObject = ((DataObject) obj).getPrimaryFile();
164: return hasObject(node, fileObject);
165: } else if (obj instanceof FileObject) {
166: FileObject fileObject = dataObject.getPrimaryFile();
167: return obj.equals(fileObject);
168: } else {
169: return false;
170: }
171: }
172:
173: private static Lookup createLookup(Project project) {
174: DataFolder rootFolder = DataFolder.findFolder(project
175: .getProjectDirectory());
176: // XXX Remove root folder after FindAction rewrite
177: return Lookups.fixed(new Object[] { project, rootFolder });
178:
179: }
180:
181: // Private innerclasses ----------------------------------------------------
182: private static final String[] BREAKABLE_PROPERTIES = new String[] {
183: IcanproProjectProperties.JAVAC_CLASSPATH,
184: IcanproProjectProperties.DEBUG_CLASSPATH,
185: IcanproProjectProperties.SRC_DIR, };
186:
187: public static boolean hasBrokenLinks(AntProjectHelper helper,
188: ReferenceHelper resolver) {
189: return BrokenReferencesSupport
190: .isBroken(
191: helper,
192: resolver,
193: BREAKABLE_PROPERTIES,
194: new String[] { IcanproProjectProperties.JAVA_PLATFORM });
195: }
196:
197: /** Filter node containin additional features for the J2SE physical
198: */
199: private final class EtlLogicalViewRootNode extends AbstractNode {
200:
201: private Action brokenLinksAction;
202: private boolean broken;
203:
204: public EtlLogicalViewRootNode() {
205: super (new EtlproViews.LogicalViewChildren(helper,
206: evaluator, project), createLookup(project));
207: setIconBaseWithExtension("org/netbeans/modules/etl/project/ui/resources/etlproProjectIcon.gif"); // NOI18N
208: setName(ProjectUtils.getInformation(project)
209: .getDisplayName());
210: if (hasBrokenLinks(helper, resolver)) {
211: broken = true;
212: brokenLinksAction = new BrokenLinksAction();
213: }
214: }
215:
216: @Override
217: public Action[] getActions(boolean context) {
218: EtlproProject pro = (EtlproProject) project;
219: String prj_locn = pro.getProjectDirectory().getPath();
220: try {
221: prj_locn = pro.getProjectDirectory().getFileSystem()
222: .getRoot().toString()
223: + prj_locn;
224: } catch (FileStateInvalidException ex) {
225: Exceptions.printStackTrace(ex);
226: }
227: MashupTableWizardIterator.setProjectInfo(pro.getName(),
228: prj_locn, true);
229: if (context) {
230: return super .getActions(true);
231: } else {
232: return getAdditionalActions();
233: }
234: }
235:
236: @Override
237: public boolean canRename() {
238: return true;
239: }
240:
241: @Override
242: public boolean canCopy() {
243: return true;
244: }
245:
246: @Override
247: public boolean canDestroy() {
248: return true;
249: }
250:
251: @Override
252: public boolean canCut() {
253: return true;
254: }
255:
256: @Override
257: public void setName(String arg0) {
258: super .setName(arg0);
259: }
260:
261: @Override
262: protected Sheet createSheet() {
263: Sheet sheet = Sheet.createDefault();
264: Sheet.Set set = Sheet.createPropertiesSet();
265: String nbBundle8 = mLoc.t("PRSR001: Name");
266: String nbBundle9 = mLoc.t("PRSR001: ETL Project Name");
267: Property nameProp = new PropertySupport.Name(this ,
268: Localizer.parse(nbBundle8), Localizer
269: .parse(nbBundle9));
270: set.put(nameProp);
271: sheet.put(set);
272: return sheet;
273: }
274:
275: // Private methods -------------------------------------------------
276: private Action[] getAdditionalActions() {
277:
278: ResourceBundle bundle = NbBundle
279: .getBundle(IcanproLogicalViewProvider.class);
280: String nbBundle1 = mLoc.t("PRSR001: Build Project");
281: String nbBundle2 = mLoc.t("PRSR001: Clean & Build Project");
282: String nbBundle3 = mLoc.t("PRSR001: Clean Project");
283: String nbBundle4 = mLoc.t("PRSR001: Generate WSDL");
284: String nbBundle5 = mLoc.t("PRSR001: Generate Schema");
285: String nbBundle6 = mLoc.t("PRSR001: Redeploy Project");
286: String nbBundle7 = mLoc.t("PRSR001: Deploy Project");
287: String nbBundle10 = mLoc.t("PRSR001: Bulk Loader");
288:
289: return new Action[] {
290: CommonProjectActions.newFileAction(),
291: null,
292: ProjectSensitiveActions.projectCommandAction(
293: ActionProvider.COMMAND_BUILD, Localizer
294: .parse(nbBundle1), null), // NOI18N
295: ProjectSensitiveActions.projectCommandAction(
296: ActionProvider.COMMAND_REBUILD, Localizer
297: .parse(nbBundle2), null), // NOI18N
298: ProjectSensitiveActions.projectCommandAction(
299: ActionProvider.COMMAND_CLEAN, Localizer
300: .parse(nbBundle3), null), // NOI18N
301: null,
302: ProjectSensitiveActions.projectCommandAction(
303: EtlproProject.COMMAND_GENWSDL, Localizer
304: .parse(nbBundle4), null), // NOI18N
305: ProjectSensitiveActions.projectCommandAction(
306: EtlproProject.COMMAND_SCHEMA, Localizer
307: .parse(nbBundle5), null), // NOI18N
308: ProjectSensitiveActions.projectCommandAction(
309: EtlproProject.COMMAND_BULK_LOADER,
310: Localizer.parse(nbBundle10), null), // NOI18N
311: null,
312: SystemAction
313: .get(NewFlatfileDatabaseWizardAction.class),
314: SystemAction.get(NewFlatfileTableAction.class),
315: //SystemAction.get(FlatfileDBViewerAction.class),
316: null,
317: ProjectSensitiveActions.projectCommandAction(
318: IcanproConstants.COMMAND_REDEPLOY,
319: Localizer.parse(nbBundle6), null), // NOI18N
320: ProjectSensitiveActions.projectCommandAction(
321: IcanproConstants.COMMAND_DEPLOY, Localizer
322: .parse(nbBundle7), null), // NOI18N
323: null,
324: CommonProjectActions.setAsMainProjectAction(),
325: CommonProjectActions.openSubprojectsAction(),
326: CommonProjectActions.closeProjectAction(),
327: null,
328: CommonProjectActions.renameProjectAction(),
329: CommonProjectActions.moveProjectAction(),
330: CommonProjectActions.copyProjectAction(),
331: CommonProjectActions.deleteProjectAction(),
332: null,
333: SystemAction
334: .get(org.openide.actions.FindAction.class),
335: addFromLayers(),
336: null,
337: SystemAction
338: .get(org.openide.actions.OpenLocalExplorerAction.class),
339: null, brokenLinksAction,
340: CommonProjectActions.customizeProjectAction(), };
341: }
342:
343: private Action addFromLayers() {
344: Action action = null;
345: Lookup look = Lookups.forPath("Projects/Actions");
346: for (Object next : look.lookupAll(Object.class)) {
347: if (next instanceof Action) {
348: action = (Action) next;
349: } else if (next instanceof JSeparator) {
350: action = null;
351: }
352: }
353: return action;
354: }
355:
356: /** This action is created only when project has broken references.
357: * Once these are resolved the action is disabled.
358: */
359: private class BrokenLinksAction extends AbstractAction
360: implements PropertyChangeListener {
361:
362: public BrokenLinksAction() {
363: evaluator.addPropertyChangeListener(this );
364: String nbBundle1 = mLoc
365: .t("PRSR001: Resolve Reference Problems...");
366: putValue(Action.NAME, Localizer.parse(nbBundle1));
367: }
368:
369: public void actionPerformed(ActionEvent e) {
370: /*BrokenReferencesSupport.showCustomizer(helper, resolver, BREAKABLE_PROPERTIES, new String[]{IcanproProjectProperties.JAVA_PLATFORM});
371: if (!hasBrokenLinks(helper, resolver)) {
372: disable();
373: }*/
374: }
375:
376: public void propertyChange(PropertyChangeEvent evt) {
377: if (!broken) {
378: disable();
379: return;
380: }
381: broken = hasBrokenLinks(helper, resolver);
382: if (!broken) {
383: disable();
384: }
385: }
386:
387: private void disable() {
388: broken = false;
389: setEnabled(false);
390: evaluator.removePropertyChangeListener(this );
391: fireIconChange();
392: fireOpenedIconChange();
393: }
394: }
395: }
396:
397: /** Factory for project actions.<BR>
398: * XXX This class is a candidate for move to org.netbeans.spi.project.ui.support
399: */
400: public static class Actions {
401:
402: private Actions() {
403: } // This is a factory
404:
405: public static Action createAction(String key, String name,
406: boolean global) {
407: return new ActionImpl(key, name, global ? Utilities
408: .actionsGlobalContext() : null);
409: }
410:
411: private static class ActionImpl extends AbstractAction
412: implements ContextAwareAction {
413:
414: Lookup context;
415: String name;
416: String command;
417:
418: public ActionImpl(String command, String name,
419: Lookup context) {
420: super (name);
421: this .context = context;
422: this .command = command;
423: this .name = name;
424: }
425:
426: public void actionPerformed(ActionEvent e) {
427:
428: Project project = (Project) context
429: .lookup(Project.class);
430: ActionProvider ap = (ActionProvider) project
431: .getLookup().lookup(ActionProvider.class);
432: ap.invokeAction(command, context);
433:
434: }
435:
436: public Action createContextAwareInstance(Lookup lookup) {
437: return new ActionImpl(command, name, lookup);
438: }
439: }
440: }
441: }
|