001/* A simple implementation of a 3-digit version specification.
002
003   Copyright (c) 2015-2016 The Regents of the University of California; iSencia Belgium NV.
004   All rights reserved.
005
006   Permission is hereby granted, without written agreement and without
007   license or royalty fees, to use, copy, modify, and distribute this
008   software and its documentation for any purpose, provided that the above
009   copyright notice and the following two paragraphs appear in all copies
010   of this software.
011
012   IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA LIABLE TO ANY PARTY
013   FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014   ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015   THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016   SUCH DAMAGE.
017
018   THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021   PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022   CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023   ENHANCEMENTS, OR MODIFICATIONS.
024
025   PT_COPYRIGHT_VERSION_2
026   COPYRIGHTENDKEY
027*/
028package org.ptolemy.commons;
029
030import java.util.Arrays;
031
032/**
033
034 * A simple implementation of a version specification, based on a
035 * merge of OSGi-conventions and Ptolemy (which in turn seems to be
036 * based on JNLP).
037 * <p>
038 * Concretely, this means:</p>
039 * <ul>
040 * <li>Reuse concept of numeric (int) major.minor.micro version number
041 * with optional trailing string-based qua lifier</li>
042 * <li>Don't care about the concrete concatenated format, possible
043 * delimiters etc. (i.e. do not enforce the usage of "."-separated
044 * version formatting)</li>
045 *
046 * <li>Allow an arbitrary count of qualifiers</li>
047 * <li>Compare qualifiers using plain text-compare</li>
048 * </ul>
049 *
050 * @author ErwinDL
051 * @version $Id$
052 * @since Ptolemy II 11.0
053 * @Pt.ProposedRating Yellow (ErwinDL)
054 * @Pt.AcceptedRating Yellow (ErwinDL)
055 */
056public class ThreeDigitVersionSpecification extends VersionSpecification
057        implements Comparable<VersionSpecification> {
058    private static final long serialVersionUID = -383837397410414307L;
059
060    /** Construct a three digit version specification.
061     * @param major The major version number.
062     * @param minor The minor version number.
063     * @param micro The micro version number.
064     * @param qualifiers An optional array of arbitrary version qualifiers.
065     */
066    public ThreeDigitVersionSpecification(int major, int minor, int micro,
067            String... qualifiers) {
068        _major = major;
069        _minor = minor;
070        _micro = micro;
071        if (qualifiers != null) {
072            _qualifiers = qualifiers;
073        }
074    }
075
076    ///////////////////////////////////////////////////////////////////
077    ////                         public methods                    ////
078
079    /** Compare this specification to the argument.
080     *  @param otherVersionSpecification  The version specification to which to compare.
081     *  @return 0 if they have the same major, minor and micro
082     *  versions.  Return 1 if the the argument is null or if the
083     *  qualifiers of the other are greater this one..  Return -1 if
084     *  this version has no qualifiers and the other one does or if
085     *  the qualifiers of the other are less than this one.
086     */
087    @Override
088    public int compareTo(VersionSpecification otherVersionSpecification) {
089        if (otherVersionSpecification == this) {
090            return 0;
091        }
092        if (otherVersionSpecification == null) {
093            return 1;
094        }
095        if (otherVersionSpecification instanceof ThreeDigitVersionSpecification) {
096            ThreeDigitVersionSpecification other = (ThreeDigitVersionSpecification) otherVersionSpecification;
097            int result = _major - other._major;
098            if (result != 0) {
099                return result;
100            }
101            result = _minor - other._minor;
102            if (result != 0) {
103                return result;
104            }
105            result = _micro - other._micro;
106            if (result != 0) {
107                return result;
108            } else if (_qualifiers.length > 0) {
109                if (other._qualifiers.length > 0) {
110                    int maxQualifierCount = Math.max(_qualifiers.length,
111                            other._qualifiers.length);
112                    for (int i = 0; i < maxQualifierCount; ++i) {
113                        String myQualifier = "";
114                        String otherQualifier = "";
115                        if (i < _qualifiers.length) {
116                            myQualifier = _qualifiers[i];
117                        }
118                        if (i < other._qualifiers.length) {
119                            otherQualifier = other._qualifiers[i];
120                        }
121                        int cmp = myQualifier.compareTo(otherQualifier);
122                        if (cmp > 0) {
123                            return 1;
124                        } else if (cmp < 0) {
125                            return -1;
126                        }
127                    }
128                    return 0;
129                } else {
130                    return 1;
131                }
132            } else if (other._qualifiers.length > 0) {
133                return -1;
134            } else {
135                return 0;
136            }
137        } else {
138            return this._versionString
139                    .compareTo(otherVersionSpecification._versionString);
140        }
141    }
142
143    /** Return true of the argument is equal to this object.
144     *  @param object The other object to which to compare.
145     *  @return true if the argument is equal to this object.
146     */
147    @Override
148    public boolean equals(Object object) {
149        if (this == object) {
150            return true;
151        }
152        if (object == null) {
153            return false;
154        }
155        // This test rules out subclasses.
156        if (getClass() != object.getClass()) {
157            return false;
158        }
159        ThreeDigitVersionSpecification other = (ThreeDigitVersionSpecification) object;
160        if (_major != other._major) {
161            return false;
162        }
163        if (_micro != other._micro) {
164            return false;
165        }
166        if (_minor != other._minor) {
167            return false;
168        }
169        if (!Arrays.equals(_qualifiers, other._qualifiers)) {
170            return false;
171        }
172        return true;
173    }
174
175    /** Return the major (leading) verson digit.
176     *
177     * @return the major (leading) version digit
178     */
179    public int getMajor() {
180        return _major;
181    }
182
183    /** Return the minor (middle) verson digit.
184     *
185     * @return the minor (middle) version digit
186     */
187    public int getMinor() {
188        return _minor;
189    }
190
191    /** Return the micro (third) verson digit.
192     *
193     * @return the micro (third) version digit
194     */
195    public int getMicro() {
196        return _micro;
197    }
198
199    /** Return the optional array of version qualifiers.
200     * When no qualifiers are present, this returns an empty array.
201     *
202     * @return the optional array of version qualifiers.
203     */
204    public String[] getQualifiers() {
205        return Arrays.copyOf(_qualifiers, _qualifiers.length);
206    }
207
208    /** Return the hash code of this object.
209     *  @return The hash code.
210     */
211    @Override
212    public int hashCode() {
213        final int prime = 31;
214        int result = 1;
215        result = prime * result + _major;
216        result = prime * result + _micro;
217        result = prime * result + _minor;
218        result = prime * result + _qualifiers.hashCode();
219        return result;
220    }
221
222    /** Return a new version spec with increased micro digit.
223     * This method does not change the current version spec instance.
224     * @return a new version spec with increased micro digit.
225     */
226    public ThreeDigitVersionSpecification increaseMicro() {
227        return new ThreeDigitVersionSpecification(_major, _minor, _micro + 1);
228    }
229
230    /** Return a new version spec with increased minor digit.
231     * This method does not change the current version spec instance.
232     * @return a new version spec with increased minor digit.
233     */
234    public ThreeDigitVersionSpecification increaseMinor() {
235        return new ThreeDigitVersionSpecification(_major, _minor + 1, _micro);
236    }
237
238    /** Return a new version spec with increased major digit.
239     * This method does not change the current version spec instance.
240     * @return a new version spec with increased major digit.
241     */
242    public ThreeDigitVersionSpecification increaseMajor() {
243        return new ThreeDigitVersionSpecification(_major + 1, _minor, _micro);
244    }
245
246    /** Produce a string representation that is itself valid again to
247     * be parsed as a VersionSpecification.
248     * @return The string representation.
249     */
250    @Override
251    public String toString() {
252        if (_versionString == null) {
253            StringBuilder versionStrBldr = new StringBuilder(
254                    _major + "." + _minor + "." + _micro);
255            for (String qualifier : _qualifiers) {
256                versionStrBldr.append("-" + qualifier);
257            }
258            _versionString = versionStrBldr.toString();
259        }
260        return _versionString;
261    }
262
263    ///////////////////////////////////////////////////////////////////
264    ////                         private variables                 ////
265
266    private int _major;
267    private int _minor;
268    private int _micro;
269
270    /** An optional array of arbitrary version qualifiers */
271    private String[] _qualifiers = new String[0];
272}