alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.ant.freeform;

import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.apache.tools.ant.module.api.support.ActionUtils;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.ui.support.CommonProjectActions;
import org.netbeans.spi.project.ui.support.ProjectSensitiveActions;
import org.openide.ErrorManager;
import org.openide.actions.FindAction;
import org.openide.actions.ToolsAction;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.actions.SystemAction;
import org.w3c.dom.Element;

/**
 * Action bindings for a freeform project.
 * @author Jesse Glick
 */
public final class Actions implements ActionProvider {
    
    private final FreeformProject project;
    
    public Actions(FreeformProject project) {
        this.project = project;
    }
    
    public String[] getSupportedActions() {
        Element genldata = project.helper().getPrimaryConfigurationData(true);
        Element actionsEl = Util.findElement(genldata, "ide-actions", FreeformProjectType.NS_GENERAL); // NOI18N
        if (actionsEl == null) {
            return new String[0];
        }
        List/**/ actions = Util.findSubElements(actionsEl);
        // Use a set, not a list, since when using context you can define one action several times:
        Set/**/ names = new LinkedHashSet(actions.size());
        Iterator it = actions.iterator();
        while (it.hasNext()) {
            Element actionEl = (Element)it.next();
            names.add(actionEl.getAttribute("name")); // NOI18N
        }
        return (String[])names.toArray(new String[names.size()]);
    }
    
    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
        Element genldata = project.helper().getPrimaryConfigurationData(true);
        Element actionsEl = Util.findElement(genldata, "ide-actions", FreeformProjectType.NS_GENERAL); // NOI18N
        if (actionsEl == null) {
            throw new IllegalArgumentException("No commands supported"); // NOI18N
        }
        List/**/ actions = Util.findSubElements(actionsEl);
        Iterator it = actions.iterator();
        boolean foundAction = false;
        while (it.hasNext()) {
            Element actionEl = (Element)it.next();
            if (actionEl.getAttribute("name").equals(command)) { // NOI18N
                foundAction = true;
                // XXX perhaps check also existence of script
                Element contextEl = Util.findElement(actionEl, "context", FreeformProjectType.NS_GENERAL); // NOI18N
                if (contextEl != null) {
                    // Check whether the context contains files all in this folder,
                    // matching the pattern if any, and matching the arity (single/multiple).
                    Map/**/ selection = findSelection(contextEl, context, project);
                    if (selection.size() == 1) {
                        // Definitely enabled.
                        return true;
                    } else if (!selection.isEmpty()) {
                        // Multiple selection; check arity.
                        Element arityEl = Util.findElement(contextEl, "arity", FreeformProjectType.NS_GENERAL); // NOI18N
                        assert arityEl != null : "No  in  for " + command;
                        if (Util.findElement(arityEl, "separated-files", FreeformProjectType.NS_GENERAL) != null) { // NOI18N
                            // Supports multiple selection, take it.
                            return true;
                        }
                    }
                } else {
                    // Not context-sensitive.
                    return true;
                }
            }
        }
        if (foundAction) {
            // Was at least one context-aware variant but did not match.
            return false;
        } else {
            throw new IllegalArgumentException("Unrecognized command: " + command); // NOI18N
        }
    }
    
    public void invokeAction(String command, Lookup context) throws IllegalArgumentException {
        Element genldata = project.helper().getPrimaryConfigurationData(true);
        Element actionsEl = Util.findElement(genldata, "ide-actions", FreeformProjectType.NS_GENERAL); // NOI18N
        if (actionsEl == null) {
            throw new IllegalArgumentException("No commands supported"); // NOI18N
        }
        List/**/ actions = Util.findSubElements(actionsEl);
        Iterator it = actions.iterator();
        boolean foundAction = false;
        while (it.hasNext()) {
            Element actionEl = (Element)it.next();
            if (actionEl.getAttribute("name").equals(command)) { // NOI18N
                foundAction = true;
                runConfiguredAction(project, actionEl, context);
            }
        }
        if (!foundAction) {
            throw new IllegalArgumentException("Unrecognized command: " + command); // NOI18N
        }
    }
    
    /**
     * Find a file selection in a lookup context based on a project.xml  declaration.
     * If all DataObject's (or FileObject's) in the lookup match the folder named in the declaration,
     * and match any optional pattern declaration, then they are returned as a map from relative
     * path to actual file object. Otherwise an empty map is returned.
     */
    private static Map/**/ findSelection(Element contextEl, Lookup context, FreeformProject project) {
        Collection/**/ files = context.lookup(new Lookup.Template(FileObject.class)).allInstances();
        if (files.isEmpty()) {
            // Try again with DataObject's.
            Collection/**/ filesDO = context.lookup(new Lookup.Template(DataObject.class)).allInstances();
            if (filesDO.isEmpty()) {
                 return Collections.EMPTY_MAP;
            }
            files = new ArrayList(filesDO.size());
            Iterator it = filesDO.iterator();
            while (it.hasNext()) {
                files.add(((DataObject) it.next()).getPrimaryFile());
            }
        }
        Element folderEl = Util.findElement(contextEl, "folder", FreeformProjectType.NS_GENERAL); // NOI18N
        assert folderEl != null : "Must have  in ";
        String rawtext = Util.findText(folderEl);
        assert rawtext != null : "Must have text contents in ";
        String evaltext = project.evaluator().evaluate(rawtext);
        if (evaltext == null) {
            return Collections.EMPTY_MAP;
        }
        FileObject folder = project.helper().resolveFileObject(evaltext);
        if (folder == null) {
            return Collections.EMPTY_MAP;
        }
        Pattern pattern = null;
        Element patternEl = Util.findElement(contextEl, "pattern", FreeformProjectType.NS_GENERAL); // NOI18N
        if (patternEl != null) {
            String text = Util.findText(patternEl);
            assert text != null : "Must have text contents in ";
            try {
                pattern = Pattern.compile(text);
            } catch (PatternSyntaxException e) {
                Util.err.annotate(e, ErrorManager.UNKNOWN, "From  in " + FileUtil.getFileDisplayName(project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_XML_PATH)), null, null, null); // NOI18N
                Util.err.notify(e);
                return Collections.EMPTY_MAP;
            }
        }
        Map/**/ result = new HashMap();
        Iterator it = files.iterator();
        while (it.hasNext()) {
            FileObject file = (FileObject) it.next();
            String path = FileUtil.getRelativePath(folder, file);
            if (path == null) {
                return Collections.EMPTY_MAP;
            }
            if (pattern != null && !pattern.matcher(path).find()) {
                return Collections.EMPTY_MAP;
            }
            result.put(path, file);
        }
        return result;
    }
    
    /**
     * Run a project action as described by subelements