Author: tchemit Date: 2012-01-16 17:32:34 +0100 (Mon, 16 Jan 2012) New Revision: 2280 Url: http://nuiton.org/repositories/revision/nuiton-utils/2280 Log: Anomalie #1893: VersionUtil should be able to take account of SNAPSHOT Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/Version.java trunk/nuiton-utils/src/main/java/org/nuiton/util/VersionUtil.java trunk/nuiton-utils/src/test/java/org/nuiton/util/VersionUtilTest.java Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/Version.java =================================================================== --- trunk/nuiton-utils/src/main/java/org/nuiton/util/Version.java 2012-01-16 14:39:04 UTC (rev 2279) +++ trunk/nuiton-utils/src/main/java/org/nuiton/util/Version.java 2012-01-16 16:32:34 UTC (rev 2280) @@ -25,74 +25,76 @@ package org.nuiton.util; -import static org.nuiton.i18n.I18n._; - import java.io.Serializable; import java.util.regex.Matcher; +import static org.nuiton.i18n.I18n._; + /** * A class to represent an application version with possible classifier. - * + * <p/> * Replace previously org.nuiton.util.VersionNumber class. - * + * <p/> * Simple version number is defined like this : * <pre> * 1.0.0 or 1 * </pre> - * + * <p/> * A version can be more complex, with a classifier like this : * <pre> * 1.0.0-alpha-1, 1.0.0-beta-2, 1.0.0-rc-1 * </pre> - * + * <p/> * A classifier (alpha, beta, rc, ...) must be follwed by a classifier number. - * - * Note : - * + * <p/> + * Note : + * <p/> * - initial value is 0 - * + * <p/> * - the equals order is defined on {@link #getVersion()} property. - * + * <p/> * - the class is comparable, using the natural version order : - * - * <pre>0 < 0.1 < 1 < 1.0 < 1.1-alpha-0 < 1.1-alpha-1 < 1.1-beta-0 < + * <p/> + * <pre>0 < 0.1 < 1 < 1.0 < 1.1-alpha-0 < 1.1-alpha-1 < 1.1-beta-0 < * 1.1-rc-1 < 1.1 </pre> + * <p/> + * - the class is immutable, you should not instanciate directly a Version, + * but prefer use the factory static methods + * <code>VersionUtil.valueOf(...)</code> instead. * - * - the class is immutable, you should not instanciate directly a Version, - * but prefer use the factory static methods - * <code>VersionUtil.valueOf(...)</code> instead. - * * @author tchemit <chemit@codelutin.com> * @since 1.1.0 */ public class Version implements Comparable<Version>, Serializable { private static final long serialVersionUID = 1L; - /** - * Version V0 - */ + + /** Version V0 */ public static final Version VZERO = new Version(); - /** - * optional classifier - */ + + /** optional classifier */ protected final String classifier; - /** - * optional classifier number (if no classifier should be null) - */ + + /** optional classifier number (if no classifier should be null) */ protected final Integer classifierNumber; + + /** main numbers of the version */ + protected final int[] numbers; + /** - * main numbers of the version + * boolean to define if version is a snapshot (if so a -SNAPSHOT is + * added at the end of the textual representation of the version). + * + * @since 2.4.3 */ - protected final int[] numbers; + protected final boolean snapshot; /** * representation textuelle de la version (celle utilisee dans le * {@link #toString()}. */ protected transient String version; - /** - * Constructeur par defaut, definit la version par defaut, i.e 0 - */ + /** Constructeur par defaut, definit la version par defaut, i.e 0 */ public Version() { this(0); } @@ -103,23 +105,39 @@ * @param numbers les nombres de la version */ public Version(int... numbers) { - this(null, null, numbers); + this(null, null, false, numbers); } /** * Constructeur d'une version (simple ou avec classifier) * - * @param classifier le classifier (peut-être null) + * @param classifier le classifier (peut-être null) * @param classiferNumber la version du classifier (doit etre null si le * classifier est null) - * @param numbers les nombres de la version + * @param numbers les nombres de la version */ public Version(String classifier, Integer classiferNumber, int... numbers) { + this(classifier, classiferNumber, false, numbers); + } + + /** + * Constructeur d'une version (simple ou avec classifier) + * + * @param classifier le classifier (peut-être null) + * @param classiferNumber la version du classifier (doit etre null si le + * classifier est null) + * @param snapshot boolean pour renseigner le champ {@link #snapshot}. + * @param numbers les nombres de la version + * @since 2.4.3 + */ + public Version(String classifier, Integer classiferNumber, + boolean snapshot, int... numbers) { this.numbers = numbers.length == 0 ? new int[]{0} : numbers; // always keep a lower case classifier this.classifier = classifier == null ? null : - classifier.trim().toLowerCase(); + classifier.trim().toLowerCase(); classifierNumber = classiferNumber; + this.snapshot = snapshot; } /** @@ -146,9 +164,10 @@ String[] strNumbers = matcher.group(1).split("\\."); String strClassifier = matcher.group(2); String strClassifierNumber = matcher.group(3); + String strSnapshot = matcher.group(4); Integer intClassifierNumber = null; - if (matcher.group(2) != null) { + if (strClassifier != null) { // possede un classifier @@ -156,6 +175,8 @@ intClassifierNumber = Integer.valueOf(strClassifierNumber); } + snapshot = strSnapshot != null; + // numbers numbers = new int[strNumbers.length]; @@ -187,6 +208,10 @@ return classifierNumber; } + public boolean isSnapshot() { + return snapshot; + } + public int getNbComponents() { return numbers.length; } @@ -195,7 +220,7 @@ if (level < 0 || level >= numbers.length) { throw new IllegalArgumentException( "not a valid level " + level + " for the VersionNumber " + - this); + this); } return numbers[level]; } @@ -212,6 +237,9 @@ sb.append('-'); sb.append(classifierNumber); } + if (isSnapshot()) { + sb.append(VersionUtil.SNAPSHOT_SUFFIX); + } version = sb.substring(1); } return version; @@ -219,9 +247,10 @@ /** * Convertit la representation textuelle de la version en identifiant java valide : - * - en java : "." interdit - * - en mysql, h2 ... : "." interdit - * @return la valeur ou les carateres interdits sont remplaces par '_' + * - en java : "." interdit + * - en mysql, h2 ... : "." interdit + * + * @return la valeur ou les carateres interdits sont remplaces par '_' */ public String getValidName() { String validName = getVersion(); @@ -265,7 +294,7 @@ @Override public boolean equals(Object obj) { return obj != null && obj instanceof Version && - getVersion().equals(((Version) obj).getVersion()); + getVersion().equals(((Version) obj).getVersion()); } @Override Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/VersionUtil.java =================================================================== --- trunk/nuiton-utils/src/main/java/org/nuiton/util/VersionUtil.java 2012-01-16 14:39:04 UTC (rev 2279) +++ trunk/nuiton-utils/src/main/java/org/nuiton/util/VersionUtil.java 2012-01-16 16:32:34 UTC (rev 2280) @@ -61,11 +61,15 @@ * - Le groupe 1 est le nombre de la version * - Le groupe 2 est le classifier (peut-etre null) * - Le groupe 3 est le numéro de classifier (peut-etre null) + * - Le groupe 4 est le suffix -SNAPSHOT (peut-etre null) * <p/> - * Dans le cas d'une version simple (sans classifier), le groupe 2 et 3 sont null. + * Dans le cas d'une version simple (sans classifier), le groupe 2, 3 et + * 4 sont null. + * <p/> + * Dans le cas d'une version non snapshot, le groupe 4 est null. */ public static final Pattern VERSION_PATTERN = - Pattern.compile("^(\\d+(?:\\.(?:\\d+))*)(?:-(\\w+?)-(\\d+?)){0,1}$"); + Pattern.compile("^(\\d+(?:\\.(?:\\d+))*)(?:-(\\w+?)-(\\d+?)){0,1}(-SNAPSHOT){0,1}$"); /** * Shared instance of default version comparator. @@ -81,11 +85,23 @@ /** * Recuperation d'une instance de version simple (sans classifier). * + * @param numbers les nombres de la version + * @param snapshot boolean pour indiquer que la version es une snapshot ou pas + * @return l'instance de la version requise + */ + public static Version valueOf(boolean snapshot, int... numbers) { + Version version = valueOf(null, null, snapshot, numbers); + return version; + } + + /** + * Recuperation d'une instance de version simple (sans classifier). + * * @param numbers les nombres de la version * @return l'instance de la version requise */ public static Version valueOf(int... numbers) { - Version version = valueOf(null, null, numbers); + Version version = valueOf(null, null, false, numbers); return version; } @@ -100,11 +116,29 @@ */ public static Version valueOf(String classifier, Integer classifierNumber, int... numbers) { - Version v = new Version(classifier, classifierNumber, numbers); + Version v = valueOf(classifier, classifierNumber, false, numbers); return v; } /** + * Recuperation d'une instance de version. + * + * @param classifier le classifier (peut-etre null) + * @param classifierNumber la version du classifier (doit etre null si le + * classifier est null) + * @param snapshot boolean pour indiquer que la version es une snapshot ou pas + * @param numbers les nombres de la version + * @return l'instance de la version requise + */ + public static Version valueOf(String classifier, + Integer classifierNumber, + boolean snapshot, + int... numbers) { + Version v = new Version(classifier, classifierNumber, snapshot, numbers); + return v; + } + + /** * Recuperation d'une instance de version a partir de sa version textuelle. * * @param version la representation textuelle de la version @@ -143,8 +177,10 @@ throw new IllegalArgumentException( "version " + version + "contains already a classifier "); } - - result = valueOf(classifier, classifierNumber, version.getNumbers()); + result = valueOf(classifier, + classifierNumber, + version.isSnapshot(), + version.getNumbers()); return result; } @@ -164,10 +200,28 @@ throw new IllegalArgumentException( "version " + version + "does no contain a classifier "); } - result = valueOf(version.getNumbers()); + result = valueOf(version.isSnapshot(), version.getNumbers()); return result; } + public static Version addSnapshot(Version version) { + if (version.isSnapshot()) { + throw new IllegalArgumentException( + "version " + version + "is already a snapshot"); + } + Version result = valueOf(version.getClassifier(), version.getClassifierNumber(), true, version.getNumbers()); + return result; + } + + public static Version removeSnapshot(Version version) { + if (!version.isSnapshot()) { + throw new IllegalArgumentException( + "version " + version + "is already a snapshot"); + } + Version result = valueOf(version.getClassifier(), version.getClassifierNumber(), false, version.getNumbers()); + return result; + } + /** * Incremente le numero de version donnee, seul le dernier constituant est * incremente: 1.2.3.4 -> 1.2.3.5; null -> 1; 0 -> 1. @@ -191,6 +245,7 @@ } Version result = valueOf(newClassifier, newClassifierNumber, + v.isSnapshot(), newNumbers); return result; } @@ -289,6 +344,7 @@ if (result != 0) { + // compare snapshot return result; } @@ -304,10 +360,19 @@ // classifier are equals - // compre on classifierNumber + // compare on classifierNumber result = compareClassifierNumber(o1, o2); + if (result != 0) { + return result; + } + + // classifierNumber are equals + + // compare on snapshot + result = compareSnapshot(o1, o2); + return result; } @@ -338,6 +403,11 @@ return o1.classifier.compareTo(o2.classifier); } + if (!o1.hasClassifier() && !o2.hasClassifier()) { + // o1 et o2 n'ont un classifier + return 0; + } + if (!o1.hasClassifier()) { // o1 n'a pas de classifier, o1 est donc plus recent return 1; @@ -355,8 +425,27 @@ public int compareClassifierNumber(Version o1, Version o2) { + if (!o1.hasClassifier() && !o2.hasClassifier()) { + // o1 et o2 n'ont un classifier + return 0; + } return o1.classifierNumber - o2.classifierNumber; } + + public int compareSnapshot(Version o1, Version o2) { + + boolean snapshot1 = o1.isSnapshot(); + boolean snapshot2 = o2.isSnapshot(); + if ((snapshot1 && snapshot2) || (!snapshot1 && !snapshot2)) { + // equals + return 0; + } + if (snapshot1) { + // !snapshot2, so v1 est before v2 + return -1; + } + return 1; + } } /** Modified: trunk/nuiton-utils/src/test/java/org/nuiton/util/VersionUtilTest.java =================================================================== --- trunk/nuiton-utils/src/test/java/org/nuiton/util/VersionUtilTest.java 2012-01-16 14:39:04 UTC (rev 2279) +++ trunk/nuiton-utils/src/test/java/org/nuiton/util/VersionUtilTest.java 2012-01-16 16:32:34 UTC (rev 2280) @@ -25,6 +25,11 @@ package org.nuiton.util; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -33,16 +38,21 @@ import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; -import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** - * * @author tchemit <chemit@codelutin.com> * @since 1.1.0 */ public class VersionUtilTest { + /** Logger. */ + private static final Log log = LogFactory.getLog(VersionUtilTest.class); + protected static final List<Version> VERSIONS = Collections.unmodifiableList(Arrays.asList( new Version(), new Version(0, 0, 1), @@ -95,15 +105,17 @@ assertPattern("a-alpha-1", false); assertPattern("-alpha-1-", false); - assertPattern("1.2.3.4", true, "1.2.3.4", null, null); + assertPattern("1.2.3.4", true, "1.2.3.4", null, null, null); + assertPattern("1.2.3.4-SNAPSHOT", true, "1.2.3.4", null, null, "-SNAPSHOT"); - assertPattern("1.2.3.4-alpha-1", true, "1.2.3.4", "alpha", "1"); - assertPattern("1.2.3.4-classifier-9", true, "1.2.3.4", "classifier", "9"); + assertPattern("1.2.3.4-alpha-1", true, "1.2.3.4", "alpha", "1", null); + assertPattern("1.2.3.4-alpha-1-SNAPSHOT", true, "1.2.3.4", "alpha", "1", "-SNAPSHOT"); + + assertPattern("1.2.3.4-classifier-9", true, "1.2.3.4", "classifier", "9", null); + assertPattern("1.2.3.4-classifier-9-SNAPSHOT", true, "1.2.3.4", "classifier", "9", "-SNAPSHOT"); } - /** - * Test of the {@link VersionUtil#DEFAULT_VERSION_COMPARATOR}. - */ + /** Test of the {@link VersionUtil#DEFAULT_VERSION_COMPARATOR}. */ @Test public void testVersionComparotor() { @@ -238,9 +250,7 @@ } } - /** - * Test of filterVersions method, of class VersionUtil. - */ + /** Test of filterVersions method, of class VersionUtil. */ @Test public void testFilterVersions() { @@ -324,6 +334,26 @@ } + @Test + public void testSnapshot() { + Version v = VersionUtil.valueOf("1"); + Assert.assertFalse(v.isSnapshot()); + + Version v2 = VersionUtil.addSnapshot(v); + Assert.assertTrue(v2.isSnapshot()); + + Assert.assertTrue(v2.before(v)); + + Version v3 = VersionUtil.removeSnapshot(v2); + Assert.assertFalse(v3.isSnapshot()); + + Version v4 = VersionUtil.addClassifier(v2, "a", 1); + + Assert.assertTrue(v4.isSnapshot()); + Assert.assertTrue(v4.before(v2)); + + } + protected static void compareVersions(int order, Iterable<Version> versions) { Iterator<Version> iterator = versions.iterator(); @@ -340,7 +370,7 @@ assertTrue(order != 0 || result2 == 0); if (order != 0) { assertTrue("not good order : required = " + order + " but find " + result + " between " + previous + " and " + current, order * result > 0); - assertTrue("not good order : required = " + (-order) + " but find " + result2 + " between " + current + " and " + previous, order * result2 < 0); + assertTrue("not good order : required = " + -order + " but find " + result2 + " between " + current + " and " + previous, order * result2 < 0); if (order > 0) { assertTrue(current.before(previous)); } else { @@ -353,7 +383,9 @@ } protected void assertPattern(String t, boolean match, String... groups) { - System.out.println("convert " + t + ", mustMatch : " + match); + if (log.isDebugEnabled()) { + log.debug("convert " + t + ", mustMatch : " + match); + } Matcher m = VersionUtil.VERSION_PATTERN.matcher(t); assertEquals(match, m.matches()); @@ -364,7 +396,9 @@ String group = m.group(i); assertEquals(groups[i - 1], group); if (group != null) { - System.out.println("group " + i + " : " + group); + if (log.isDebugEnabled()) { + log.debug("group " + i + " : " + group); + } } } }