org.netbeans.modules.android.project.configs.AndroidConfigProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.netbeans.modules.android.project.configs.AndroidConfigProvider.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.netbeans.modules.android.project.configs;

import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.modules.android.project.AndroidProject;
import org.netbeans.modules.android.project.SavableAuxiliaryProperties;
import org.netbeans.modules.android.project.launch.LaunchConfiguration;
import org.netbeans.modules.android.project.launch.LaunchConfiguration.Action;
import org.netbeans.modules.android.project.ui.customizer.AndroidCompositePanelProvider;
import org.netbeans.modules.android.project.ui.customizer.AndroidProjectProperties;
import org.netbeans.modules.android.project.ui.customizer.CustomizerProviderImpl;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.AuxiliaryProperties;
import org.netbeans.spi.project.ProjectConfiguration;
import org.netbeans.spi.project.ProjectConfigurationProvider;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
import org.openide.util.MutexException;
import org.openide.util.NbBundle;

/**
 * {@link ProjectConfigurationProvider} for {@link AndroidProject Android project}.
 */
public final class AndroidConfigProvider implements ProjectConfigurationProvider<AndroidConfigProvider.Config> {
    private static final Logger LOG = Logger.getLogger(AndroidConfigProvider.class.getName());

    public static final String DEFAULT_CONFIG_NAME = NbBundle.getMessage(AndroidConfigProvider.class,
            "LBL_DefaultConfig");
    private static final Config DEFAULT_CONFIG = new Config(DEFAULT_CONFIG_NAME, createLaunchConfig(Action.MAIN));

    private static final Comparator<Config> CONFIG_COMPARATOR = new Comparator<Config>() {
        private final Collator collator = Collator.getInstance();

        @Override
        public int compare(Config config1, Config config2) {
            return collator.compare(config1.getDisplayName(), config2.getDisplayName());
        }
    };

    final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
    final Map<String, Config> configs = new ConcurrentHashMap<String, Config>();
    /** Key to configs maps to mark active configuration. */
    String activeConfigName;

    private final AndroidProject project;
    private final SavableAuxiliaryProperties auxProps;

    public AndroidConfigProvider(AndroidProject project, SavableAuxiliaryProperties auxProps) {
        this.project = Preconditions.checkNotNull(project);
        this.auxProps = Preconditions.checkNotNull(auxProps);
        load();
    }

    @Override
    public Collection<Config> getConfigurations() {
        List<Config> configList = new ArrayList<Config>(configs.size());
        configList.addAll(configs.values());
        Collections.sort(configList, CONFIG_COMPARATOR);
        return configList;
    }

    @Override
    public Config getActiveConfiguration() {
        if (configs.containsKey(activeConfigName)) {
            return configs.get(activeConfigName);
        }
        return DEFAULT_CONFIG;
    }

    @Override
    public void setActiveConfiguration(Config config) throws IOException {
        if (config != DEFAULT_CONFIG && !configs.values().contains(config)) {
            throw new IllegalArgumentException("Unknown config: " + config);
        }
        activeConfigName = config.getDisplayName();
        auxProps.put(AndroidProjectProperties.PROP_ACTIVE_CONFIG, config.name, false);
        propertyChangeSupport.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE, null,
                null);
        // TODO need to make sure it is saved
        ProjectManager.getDefault().saveProject(project);
    }

    @Override
    public boolean hasCustomizer() {
        return true;
    }

    @Override
    public void customize() {
        project.getLookup().lookup(CustomizerProviderImpl.class).showCustomizer(AndroidCompositePanelProvider.RUN);
    }

    @Override
    public boolean configurationsAffectAction(String command) {
        return command.equals(ActionProvider.COMMAND_RUN) || command.equals(ActionProvider.COMMAND_DEBUG);
    }

    @Override
    public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) {
        propertyChangeSupport.addPropertyChangeListener(propertyChangeListener);
    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) {
        propertyChangeSupport.removePropertyChangeListener(propertyChangeListener);
    }

    Set<String> getConfigNames() {
        return new HashSet<String>(configs.keySet());
    }

    private void load() {
        ProjectManager.mutex().readAccess(new Mutex.Action<Void>() {
            @Override
            public Void run() {
                configs.clear();
                String propNames = auxProps.get(AndroidProjectProperties.PROP_CONFIG_NAMES, false);
                if (propNames != null) {
                    for (String key : Splitter.on('|').split(propNames)) {
                        Config cfg = configForKey(key);
                        if (cfg != null) {
                            configs.put(cfg.getDisplayName(), cfg);
                        }
                    }
                }
                String active = auxProps.get(AndroidProjectProperties.PROP_ACTIVE_CONFIG, false);
                fixConfigurations(active);
                return null;
            }
        });
    }

    public void setConfigurations(Collection<Config> configurations) {
        configs.clear();
        for (Config cfg : configurations) {
            configs.put(cfg.getDisplayName(), cfg);
        }
        fixConfigurations(activeConfigName);
        propertyChangeSupport.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATIONS, null, null);
        propertyChangeSupport.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE, null,
                null);
    }

    private void fixConfigurations(String activeConfig) {
        if (configs.isEmpty()) {
            configs.put(DEFAULT_CONFIG.getDisplayName(), DEFAULT_CONFIG);
        }
        if (activeConfig != null && configs.containsKey(activeConfig)) {
            activeConfigName = activeConfig;
        } else {
            activeConfigName = Iterables.get(configs.keySet(), 0);
        }
    }

    public void save() {
        try {
            // store properties
            ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
                @Override
                public Void run() throws IOException {
                    for (String key : auxProps.listKeys(false)) {
                        if (key.startsWith(AndroidProjectProperties.PROP_LAUNCH_PREFFIX)) {
                            int lastDot = key.lastIndexOf('.');
                            if (!configs.containsKey(key.substring(lastDot + 1))) {
                                auxProps.put(key, null, false);
                            }
                        }
                    }
                    auxProps.put(AndroidProjectProperties.PROP_CONFIG_NAMES, Joiner.on('|').join(getConfigNames()),
                            false);
                    for (String name : getConfigNames()) {
                        Config cfg = configs.get(name);
                        saveConfig(auxProps, cfg.getLaunchConfiguration(), "." + name);
                    }
                    auxProps.save();
                    return null;
                }

            });
        } catch (MutexException e) {
            Exceptions.printStackTrace((IOException) e.getException());
        }
    }

    //~ Inner classes

    public static final class Config implements ProjectConfiguration {

        /** Human readable name of configuration. */
        private final String name;
        private final LaunchConfiguration launch;

        Config(String displayName, LaunchConfiguration launch) {
            this.name = displayName;
            this.launch = launch;
        }

        @Override
        public String getDisplayName() {
            return name;
        }

        public LaunchConfiguration getLaunchConfiguration() {
            return launch;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Config other = (Config) obj;
            if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
                return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            int hash = 5;
            hash = 79 * hash + (this.name != null ? this.name.hashCode() : 0);
            return hash;
        }

        @Override
        public String toString() {
            return Objects.toStringHelper(this).add("name", name).add("launch", launch).toString();
        }

    }

    public Config configForKey(String key) {
        String suffix = "." + Preconditions.checkNotNull(key);
        String launchAction = auxProps.get(AndroidProjectProperties.PROP_LAUNCH_ACTION + suffix, false);
        if (launchAction == null) {
            return new Config(key, configWithModes(auxProps, key, new LaunchConfigurationBean()));
        }
        if (AndroidProjectProperties.LAUNCH_ACTION_DO_NOTHING.equals(launchAction)) {
            return new Config(key,
                    configWithModes(auxProps, key, createLaunchConfig(LaunchConfiguration.Action.DO_NOTHING)));
        } else if (AndroidProjectProperties.LAUNCH_ACTION_MAIN.equals(launchAction)) {
            return new Config(key, configWithModes(auxProps, key, new LaunchConfigurationBean()));
        }
        LaunchConfigurationBean l = createLaunchConfig(LaunchConfiguration.Action.ACTIVITY);
        l.setActivityName(launchAction);
        return new Config(key, configWithModes(auxProps, key, l));
    }

    private static LaunchConfiguration configWithModes(AuxiliaryProperties props, String key,
            LaunchConfigurationBean c) {
        String suffix = key == null ? "" : "." + key;
        String mode = props.get(AndroidProjectProperties.PROP_LAUNCH_MODE + suffix, false);
        if (mode != null) {
            c.setMode(mode);
        }
        String target = props.get(AndroidProjectProperties.PROP_LAUNCH_TARGET_MODE + suffix, false);
        if (target != null) {
            c.setTargetMode(LaunchConfiguration.TargetMode.valueOf(target));
        }
        String emulatorOptions = props.get(AndroidProjectProperties.PROP_EMULATOR_OPTIONS + suffix, false);
        if (emulatorOptions != null) {
            c.setEmulatorOptions(emulatorOptions);
        }
        return c;
    }

    private static void saveConfig(AuxiliaryProperties props, LaunchConfiguration l, String suffix) {
        Preconditions.checkNotNull(props);
        switch (l.getLaunchAction()) {
        case DO_NOTHING:
            props.put(AndroidProjectProperties.PROP_LAUNCH_ACTION + suffix,
                    AndroidProjectProperties.LAUNCH_ACTION_DO_NOTHING, false);
            break;
        case MAIN:
            props.put(AndroidProjectProperties.PROP_LAUNCH_ACTION + suffix,
                    AndroidProjectProperties.LAUNCH_ACTION_MAIN, false);
            break;
        case ACTIVITY:
            props.put(AndroidProjectProperties.PROP_LAUNCH_ACTION + suffix, l.getActivityName(), false);
            break;
        }
        if (!LaunchConfiguration.MODE_DEBUG.equals(l.getMode())) {
            props.put(AndroidProjectProperties.PROP_LAUNCH_MODE + suffix, l.getMode(), false);
        }
        props.put(AndroidProjectProperties.PROP_LAUNCH_TARGET_MODE + suffix, l.getTargetMode().toString(), false);
        props.put(AndroidProjectProperties.PROP_EMULATOR_OPTIONS + suffix, l.getEmulatorOptions(), false);
    }

    private static LaunchConfigurationBean createLaunchConfig(LaunchConfiguration.Action a) {
        LaunchConfigurationBean config = new LaunchConfigurationBean();
        config.setLaunchAction(a);
        return config;
    }
}