Version.java :  » Database-Client » iSQL-Viewer » org » isqlviewer » util » Java Open Source

Java Open Source » Database Client » iSQL Viewer 
iSQL Viewer » org » isqlviewer » util » Version.java
/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.util;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

/**
 * Version identifier for software bundles and packages.
 * <p>
 * This Version class supports four four components.
 * <ol>
 * <li>Major version. A non-negative integer.</li>
 * <li>Minor version. A non-negative integer.</li>
 * <li>Patch version. A non-negative integer.</li>
 * <li>Qualifier. A text string. See <code>Version(String)</code> for the format of the qualifier string.</li>
 * </ol>
 * <p>
 * All Version object instances are immutable.
 * 
 * @author Mark A. Kobold &lt;mkobold at isqlviewer dot com&gt;
 * @version 1.0
 */
public class Version implements Comparable<Version>, Serializable {

    private static final long serialVersionUID = 1L;
    private static final String SEPARATOR = ".";
    private static final String BUNDLE_IDENTIFIER = "org.isqlviewer.util.ResourceBundle.properties";
    private static final MessageFormat baseFormat = new MessageFormat("{0}.{1}.{2}");

    private final int major;
    private final int minor;
    private final int patch;
    private final String qualifier;
    private LocalMessages messages = new LocalMessages(BUNDLE_IDENTIFIER);

    /**
     * The empty version "0.0.0". Equivalent to calling <code>new Version(0,0,0)</code>.
     */
    public static final Version EMPTY_VERSION = new Version(0, 0, 0);

    /**
     * Creates a version identifier from the specified numerical components.
     * <p>
     * The qualifier is set to the empty string.
     * 
     * @param major Major component of the version identifier.
     * @param minor Minor component of the version identifier.
     * @param micro Micro component of the version identifier.
     * @throws IllegalArgumentException If the numerical components are negative.
     */
    public Version(int major, int minor, int micro) {

        this(major, minor, micro, null);
    }

    /**
     * Creates a version identifier from the specifed components.
     * 
     * @param major Major component of the version identifier.
     * @param minor Minor component of the version identifier.
     * @param micro Micro component of the version identifier.
     * @param qualifier Qualifier component of the version identifier. If <code>null</code> is specified, then the
     *        qualifier will be set to the empty string.
     * @throws IllegalArgumentException If the numerical components are negative or the qualifier string is invalid.
     */
    public Version(int major, int minor, int micro, String qualifier) {

        this.major = major;
        this.minor = minor;
        this.patch = micro;

        if (qualifier == null) {
            this.qualifier = "";
        } else {
            this.qualifier = qualifier;
        }
        validateComponents();
    }

    /**
     * Parses a version identifier from the specified string.
     * <p>
     * Standard format for a version string.
     * 
     * <pre>
     *  VERSION   ::= MAJOR [SEPERATOR MINOR [SEPERATOR PATCH [SEPERATOR QUALIFIER] ] ]
     *  MAJOR     ::= (DIGIT)+
     *  MINOR     ::= (DIGIT)+
     *  PATCH     ::= (DIGIT)+
     *  QUALIFIER ::= (ALPHA|DIGIT|'_'|'-')+
     *  SEPERATOR ::= '.'
     *  DIGIT     ::= {0..9}
     *  ALPHA     ::= {a..zA..Z}
     * </pre>
     * 
     * @param version String representation of the version identifier.
     * @return new Version instance with the respective components from the version text.
     * @throws IllegalArgumentException If version text is not properly formatted.
     */
    public static Version forString(String version) {

        if (version == null) {
            return EMPTY_VERSION;
        }

        String workingCopy = version.trim();
        if (workingCopy.length() == 0) {
            return EMPTY_VERSION;
        }
        int major = 0;
        int minor = 0;
        int micro = 0;
        String qualifier = "";
        StringTokenizer st = new StringTokenizer(workingCopy, SEPARATOR, true);
        try {
            major = Integer.parseInt(st.nextToken());
            if (st.hasMoreTokens()) {
                st.nextToken();
                minor = Integer.parseInt(st.nextToken());
                if (st.hasMoreTokens()) {
                    st.nextToken();
                    micro = Integer.parseInt(st.nextToken());
                    if (st.hasMoreTokens()) {
                        st.nextToken();
                        qualifier = st.nextToken();
                    }
                }
            }
        } catch (NoSuchElementException e) {
            throw new IllegalArgumentException();
        }
        return new Version(major, minor, micro, qualifier);
    }

    /**
     * Returns the major component of this version identifier.
     * 
     * @return The major component.
     */
    public int getMajor() {

        return major;
    }

    /**
     * Returns the minor component of this version identifier.
     * 
     * @return The minor component.
     */
    public int getMinor() {

        return minor;
    }

    /**
     * Returns the patch component of this version identifier.
     * 
     * @return The patch component.
     */
    public int getPatch() {

        return patch;
    }

    /**
     * Returns the qualifier component of this version identifier.
     * 
     * @return The qualifier component.
     */
    public String getQualifier() {

        return qualifier;
    }

    /**
     * Returns the string representation of this version identifier.
     * <p>
     * The format of the version string will be <code>major.minor.micro</code> if qualifier is the empty string or
     * <code>major.minor.micro.qualifier</code> otherwise.
     * 
     * @return The string representation of this version identifier.
     */
    public String toString() {

        Object[] argument = new Object[3];
        argument[0] = Integer.toString(major);
        argument[1] = Integer.toString(minor);
        argument[2] = Integer.toString(patch);
        String versionText = baseFormat.format(argument);
        if (qualifier.length() == 0) {
            return versionText;
        }
        return versionText.concat(SEPARATOR.concat(qualifier));
    }

    /**
     * Returns a hash code value for the object.
     * <p>
     * 
     * @return An integer which is a hash code value for this object.
     */
    public int hashCode() {

        return (major << 24) + (minor << 16) + (patch << 8) + qualifier.hashCode();
    }

    /**
     * Compares this instance to another object.
     * <p>
     * A version is considered to be <b>equal to </b> another version if the version components (major, minor, micro,
     * qualifier) are equal.
     * 
     * @param object to test for equality.
     * @return <tt>true</tt> if object is a Version and is equal to this instance. Otherwise <tt>false</tt>.
     */
    public boolean equals(Object object) {

        if (object instanceof Version) {
            Version other = (Version) object;
            boolean eqMajor = (major == other.major);
            boolean eqMinor = (minor == other.minor);
            boolean eqPatch = (patch == other.patch);
            boolean eqQualifier = qualifier.equals(other.qualifier);
            return eqMajor && eqMinor && eqPatch && eqQualifier;
        }
        return false;
    }

    /**
     * Compares this instance to another version.
     * <p>
     * A version is considered to be <b>less than </b> another version if its major component is less than the other
     * version's major component, or the major components are equal and its minor component is less than the other
     * version's minor component, or the major and minor components are equal and its micro component is less than the
     * other version's micro component, or the major, minor and micro components are equal and it's qualifier component
     * is less than the other version's qualifier component (using <code>String.compareTo</code>).
     * <p>
     * A version is considered to be equal to< another version if the all version components (major, minor, micro, and
     * qualifier) are equal.
     * 
     * @param object The <code>Version</code> object to be compared.
     * @return Comparsion value defined by the comparable interface.
     */
    public int compareTo(Version version) {

        if (version == this) {
            return 0;
        }
        int comparison = -1;

        comparison = (major < version.major ? -1 : (major == version.major ? 0 : 1));
        if (comparison != 0) {
            return comparison;
        }
        comparison = (minor < version.minor ? -1 : (minor == version.minor ? 0 : 1));
        if (comparison != 0) {
            return comparison;
        }
        comparison = (patch < version.patch ? -1 : (patch == version.patch ? 0 : 1));
        if (comparison != 0) {
            return comparison;
        }
        return qualifier.compareTo(version.qualifier);
    }

    /**
     * Called by the constructors to ensure the correctness of the version components.
     * 
     * @throws IllegalArgumentException If the numerical components are negative or the qualifier string is invalid.
     */
    private void validateComponents() {

        if (major < 0) {
            throw new IllegalArgumentException(messages.format("Version.bad_major", Integer.toString(major)));
        }
        if (minor < 0) {
            throw new IllegalArgumentException(messages.format("Version.bad_minor", Integer.toString(minor)));
        }
        if (patch < 0) {
            throw new IllegalArgumentException(messages.format("Version.bad_patch", Integer.toString(patch)));
        }
        int length = qualifier.length();
        for (int i = 0; i < length; i++) {
            char cdata = qualifier.charAt(i);
            if (!Character.isLetterOrDigit(cdata)) {
                switch (cdata) {
                    case '_' :
                    case '-' :
                        break;
                    default :
                        Object[] arguments = new Object[2];
                        arguments[0] = Integer.toString(i);
                        arguments[1] = Character.toString(cdata);
                        throw new IllegalArgumentException(messages.format("Version.bad_text", arguments));
                }
            }
        }
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.