001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.runtime;
023
024import java.io.Serializable;
025
026/**
027 * A version consists of three fields, denoting the major version, the minor version, and the update version. Example:
028 * 3.1.2.
029 *
030 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
031 */
032public class Version implements Serializable, Comparable<Version> {
033
034    public static final Version ZERO = new Version(0, 0, 0);
035
036    public static final Version MIN = ZERO;
037
038    public static final Version MAX = new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
039
040    private static final long serialVersionUID = 4287621413157054503L;
041
042    private final int major;
043
044    private final int minor;
045
046    private final int update;
047
048    /**
049     * Creates a new version object given the major, minor and update version numbers.
050     *
051     * @param major the major version
052     * @param minor the minor version
053     * @param update the update version
054     */
055    public Version(int major, int minor, int update) {
056        this.major = major;
057        this.minor = minor;
058        this.update = update;
059    }
060
061    /**
062     * Creates a new version object given a string representation of the version.
063     *
064     * @param version the version string
065     * @return the version object
066     * @throws NumberFormatException if the version string is invalid
067     */
068    public static Version parseString(String version) {
069        int p = version.indexOf('.', 0);
070        if (p > -1) {
071            int major = Integer.parseInt(version.substring(0, p));
072            int q = version.indexOf('.', p + 1);
073            if (q > -1) {
074                int minor = Integer.parseInt(version.substring(p + 1, q));
075                int update = Integer.parseInt(version.substring(q + 1));
076                return new Version(major, minor, update);
077            } else {
078                return new Version(major, Integer.parseInt(version.substring(p + 1)), 0);
079            }
080        } else {
081            return new Version(Integer.parseInt(version), 0, 0);
082        }
083    }
084
085    /**
086     * Tests if the current version is greater than the given one.
087     *
088     * @param version the version to compare to the current one
089     * @return true if the current version is greater, false otherwise
090     */
091    public boolean isGreaterThan(Version version) {
092        if (major > version.major) {
093            return true;
094        }
095        if (major < version.major) {
096            return false;
097        }
098        if (minor > version.minor) {
099            return true;
100        }
101        if (minor < version.minor) {
102            return false;
103        }
104        return update > version.update;
105    }
106
107    /**
108     * Tests if the current version is greater or equal to the given one.
109     *
110     * @param version the version to compare to the current one
111     * @return if the current version is greater or equal, false otherwise
112     */
113    public boolean isGreaterOrEqualThan(Version version) {
114        if (major > version.major) {
115            return true;
116        }
117        if (major < version.major) {
118            return false;
119        }
120        if (minor > version.minor) {
121            return true;
122        }
123        if (minor < version.minor) {
124            return false;
125        }
126        return update >= version.update;
127    }
128
129    /**
130     * Tests if the current version is equal to the given one.
131     *
132     * @param version the version to compare to the current one
133     * @return if the current version is equal to the given one, false otherwise
134     */
135    public boolean isEqualTo(Version version) {
136        return major == version.major && minor == version.minor && update == version.update;
137    }
138
139    /**
140     * Gets the minor version field.
141     *
142     * @return the minor
143     */
144    public int getMinorVersion() {
145        return minor;
146    }
147
148    /**
149     * Gets the major version field.
150     *
151     * @return the major
152     */
153    public int getMajorVersion() {
154        return major;
155    }
156
157    /**
158     * Gets the update version field.
159     *
160     * @return the update
161     */
162    public int getUpdateVersion() {
163        return update;
164    }
165
166    /**
167     * Gets the string representation of this version.
168     * <p>
169     * The string representation can be used in {@link Version#parseString(String)} to create a version object.
170     */
171    @Override
172    public String toString() {
173        return new StringBuffer().append(major).append('.').append(minor).append('.').append(update).toString();
174    }
175
176    @Override
177    public int hashCode() {
178        return major ^ (minor << 8) ^ (update << 16);
179    }
180
181    @Override
182    public boolean equals(Object object) {
183        if (object == this) {
184            return true;
185        }
186        if (object instanceof Version) {
187            return isEqualTo((Version) object);
188        }
189        return false;
190    }
191
192    @Override
193    public int compareTo(Version v) {
194        if (v == null) {
195            return -1;
196        }
197        if (isEqualTo(v)) {
198            return 0;
199        } else {
200            return isGreaterThan(v) ? 1 : 0;
201        }
202    }
203
204}