com.vectrace.MercurialEclipse.HgFeatures.java Source code

Java tutorial

Introduction

Here is the source code for com.vectrace.MercurialEclipse.HgFeatures.java

Source

/*******************************************************************************
 * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *          Andrei Loskutov - implementation
 *******************************************************************************/
package com.vectrace.MercurialEclipse;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

import org.eclipse.jface.preference.IPreferenceStore;
import org.osgi.framework.Version;

/**
 * Features of the underlined mercurial executable. HgFeatures are version dependent and so will be
 * enabled/disabled based on the currently used mercurial binaries.
 * <p>
 * Note that the right enablement state will be set some time after plugin startup, so that in a
 * short time between plugin activation and {@link MercurialEclipsePlugin#checkHgInstallation()}
 * features might be not yet initialized properly. Initially all features are disabled.
 *
 * @author andrei
 */
public enum HgFeatures {

    /**
     * TODO: find exact version
     */
    COMMAND_SERVER(new Version(2, 0, 0), "command server", true),

    COMMAND_SERVER_RECOMMENDED(new Version(2, 1, 0), "tested version of command server", false),

    /**
     * Whether commmit --amend is supported
     */
    COMMIT_AMEND(new Version(2, 2, 0), "commit --amend", false),

    PHASES(new Version(2, 1, 0), "phase", false);

    private final Version required;
    private final String[] optionalPreferenceKeys;
    private boolean enabled;
    private final String cmd;
    private final boolean mandatory;

    private HgFeatures(Version required, String cmd, boolean mandatory, String... optionalPreferenceKeys) {
        this.required = required;
        this.cmd = cmd;
        this.mandatory = mandatory;
        this.optionalPreferenceKeys = optionalPreferenceKeys;
    }

    @Override
    public String toString() {
        return getHgCmd() + (isEnabled() ? "(enabled)" : "(disabled)") + ", requires " + getRequired()
                + " hg version";
    }

    /**
     * @return true if this is a mandatory command and there is no chance to
     * workaround the absence of the required mercurial version
     */
    public boolean isMandatory() {
        return mandatory;
    }

    public String getHgCmd() {
        return cmd;
    }

    /**
     * @return the (smallest) required version, never null
     */
    public Version getRequired() {
        return required;
    }

    public void applyTo(IPreferenceStore store) {
        for (String key : optionalPreferenceKeys) {
            store.setDefault(key, enabled);
            if (!enabled) {
                store.setValue(key, false);
            }
        }
    }

    /**
     * @param enabled true if the option should be enabled
     */
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    /**
     * Note that the right enablement state will be set some time after plugin startup, so that in a
     * short time between plugin activation and {@link MercurialEclipsePlugin#checkHgInstallation()}
     * features might be not yet initialized properly. Initially all features are disabled.
     *
     * @return true if the option is enabled (supported by mercurial)
     */
    public boolean isEnabled() {
        return enabled;
    }

    /**
     * @param current observed mercurial version
     */
    public static void setToVersion(Version current) {
        HgFeatures[] values = HgFeatures.values();
        for (HgFeatures feature : values) {
            feature.setEnabled(doCompare(feature.getRequired(), current) <= 0);
        }
    }

    /**
     * @param current
     *            observed mercurial version
     * @return true if <b>mandatory</b> options are satisfied with given version, false if at
     *         least one requires greater mercurial version
     */
    public static boolean isSupported(Version current) {
        HgFeatures[] values = HgFeatures.values();
        boolean result = true;
        for (HgFeatures feature : values) {
            if (!feature.isMandatory()) {
                continue;
            }
            result &= doCompare(feature.getRequired(), current) <= 0;
        }
        return result;
    }

    /**
     * @param current
     *            observed mercurial version
     * @return true if <b>all</b> features are satisfied with given version, false if at
     *         least one requires greater mercurial version
     */
    public static boolean isHappyWith(Version current) {
        HgFeatures[] values = HgFeatures.values();
        boolean result = true;
        for (HgFeatures feature : values) {
            result &= doCompare(feature.getRequired(), current) <= 0;
        }
        return result;
    }

    public static void applyAllTo(IPreferenceStore store) {
        HgFeatures[] values = HgFeatures.values();
        for (HgFeatures feature : values) {
            feature.applyTo(store);
        }
    }

    public static Version getPreferredVersion() {
        return Collections.max(Arrays.asList(HgFeatures.values()), new Comparator<HgFeatures>() {
            public int compare(HgFeatures o1, HgFeatures o2) {
                return doCompare(o1.getRequired(), o2.getRequired());
            }
        }).getRequired();
    }

    public static Version getLowestWorkingVersion() {
        return Collections.min(Arrays.asList(HgFeatures.values()), new Comparator<HgFeatures>() {
            public int compare(HgFeatures o1, HgFeatures o2) {
                if (o1.isMandatory() && !o2.isMandatory()) {
                    return -1;
                } else if (!o1.isMandatory() && o2.isMandatory()) {
                    return 1;
                }
                return doCompare(o1.getRequired(), o2.getRequired());
            }
        }).getRequired();
    }

    public static String printSummary() {
        StringBuilder sb = new StringBuilder();
        HgFeatures[] values = HgFeatures.values();
        for (HgFeatures feature : values) {
            sb.append(feature.toString()).append("\n");
        }
        return sb.toString();
    }

    /**
     * Support comparing versions without requiring a particular version of OSGi.
     *
     * See: http://computerfloss.com/2011/11/a-little-problem-in-the-osgi-version-class/
     *
     * Remove after Eclipse 3.6 is not supported.
     *
     * @param v1 The left version
     * @param v2 The right version
     * @return The result of left.compareTo(right)
     * @see Version#compareTo(Version)
     * @see Version#compareTo(Object)
     */
    public static int doCompare(Version v1, Version v2) {
        Class<Version> versionClass = Version.class;
        Method compareToMethod = null;

        try {
            // Works on Eclipse 3.7
            compareToMethod = versionClass.getMethod("compareTo", Version.class);
        } catch (NoSuchMethodException e1) {
            // "We're on Eclipse 3.6 or earlier. Fall back compareTo(Object).";
            try {
                // Works on Eclipse 3.6 and earlier
                compareToMethod = versionClass.getMethod("compareTo", Object.class);
            } catch (NoSuchMethodException e2) {
                MercurialEclipsePlugin.logError("Unexpected error: cannot find compareTo() in Version", e2);
                return 0;
            }
        }

        try {
            return ((Integer) compareToMethod.invoke(v1, v2)).intValue();
        } catch (IllegalArgumentException e) {
            MercurialEclipsePlugin.logError("Unexpected error: comparing version", e);
        } catch (IllegalAccessException e) {
            MercurialEclipsePlugin.logError("Unexpected error: comparing version", e);
        } catch (InvocationTargetException e) {
            MercurialEclipsePlugin.logError("Unexpected error: comparing version", e);
        }

        return 0;
    }
}