org.nuiton.util.VersionUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nuiton-utils Show documentation
Show all versions of nuiton-utils Show documentation
Library of usefull classes to be used in any project.
/*
* #%L
* Nuiton Utils
* %%
* Copyright (C) 2004 - 2010 CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Class of usefull methods on {@link Version} objects.
*
* There is some factory methods : {@code valueOf(XXX)} to obtain a new
* version.
*
* Some methods to transform a version (since version are immutable, we can not
* modify Version's property) :
*
* - inc(Version) : to increment a version
* - dec(Version) : to decrement a version
* - addClassifier(Version, String, Integer) : to add a classifier to a version
* - removeClassifier(Version) : to remove a classifier from a version
*
*
* @author Tony Chemit - [email protected]
* @since 1.1.0
* @deprecated since 3.0 (use now {@link org.nuiton.util.version.Version}).
*/
@Deprecated
public class VersionUtil {
/**
* Pattern pour detecter une version (avec si classifier et numéro de
* classifier séparé par un -, par exemple : 1.0-beta-1).
*
* Le pattern possède toujours 4 groupes de captures.
*
* - 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)
*
* Dans le cas d'une version simple (sans classifier), le groupe 2, 3 et
* 4 sont null.
*
* 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}(-SNAPSHOT){0,1}$");
/**
* Pattern pour detecter une version (avec si classifier et numéro de
* classifier collé, par exemple : 1.0-rc1).
*
* Le pattern possède toujours 4 groupes de captures.
*
* - 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)
*
* Dans le cas d'une version simple (sans classifier), le groupe 2, 3 et
* 4 sont null.
*
* Dans le cas d'une version non snapshot, le groupe 4 est null.
*/
public static final Pattern VERSION_PATTERN2 =
Pattern.compile("^(\\d+(?:\\.(?:\\d+))*)(?:-(\\w+?)(\\d+?)){0,1}(-SNAPSHOT){0,1}$");
/**
* Shared instance of default version comparator.
*
* @see VersionComparator
*/
public static final VersionComparator DEFAULT_VERSION_COMPARATOR =
new VersionComparator();
/** The snapshot suffix. */
public static final String SNAPSHOT_SUFFIX = "-SNAPSHOT";
/**
* 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, false, numbers);
return version;
}
/**
* 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 numbers les nombres de la version
* @return l'instance de la version requise
*/
public static Version valueOf(String classifier,
Integer classifierNumber, int... 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
* @return l'instance de la version requise
*/
public static Version valueOf(String version) {
Version v = new Version(version);
return v;
}
/**
* Construction d'une nouvelle version avec un classifier a partir d'une
* version donnee.
*
* @param version la version de base (sans classifier)
* @param classifier le classifier a ajouter
* @param classifierNumber la version du classifier a ajouter
* @return l'instance de la version requise
* @throws NullPointerException si le classifier ou le
* classifierNumber est null.
* @throws IllegalArgumentException si la version donnee contient deja un
* classifier.
*/
public static Version addClassifier(Version version,
String classifier,
Integer classifierNumber)
throws NullPointerException, IllegalArgumentException {
Version result;
if (classifier == null) {
throw new NullPointerException("classifier can not be null");
}
if (classifierNumber == null) {
throw new NullPointerException("classifierNumber can not be null");
}
if (version.hasClassifier()) {
throw new IllegalArgumentException(
"version " + version + "contains already a classifier ");
}
result = valueOf(classifier,
classifierNumber,
version.isSnapshot(),
version.getNumbers());
return result;
}
/**
* Construction d'une nouvelle version sans classifier a partir d'une
* version donnee (sans classifier).
*
* @param version la version de base (avec classifier)
* @return l'instance de la version requise
* @throws IllegalArgumentException si la version donnee contient deja
* un classifier.
*/
public static Version removeClassifier(Version version)
throws IllegalArgumentException {
Version result;
if (!version.hasClassifier()) {
throw new IllegalArgumentException(
"version " + version + "does no contain a classifier ");
}
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.
*
* Si la version a un classifier, alors c'est la version du classifier qui
* change : 1.1-alpha-12 → 1.1-alpha-13
*
* @param v la version a incrementer
* @return la nouvelle version
*/
public static Version inc(Version v) {
int nbComponents = v.getNbComponents();
int[] newNumbers = Arrays.copyOf(v.numbers, nbComponents);
String newClassifier = v.classifier;
Integer newClassifierNumber = v.classifierNumber;
if (v.hasClassifier()) {
newClassifierNumber++;
} else {
newNumbers[nbComponents - 1] = newNumbers[nbComponents - 1] + 1;
}
Version result = valueOf(newClassifier, newClassifierNumber,
v.isSnapshot(),
newNumbers);
return result;
}
/**
* Remove the suffix {@code -SNAPSHOT} stamp from a version (if any).
*
* @param version the string representation of the version
* @return the string representation of the given version
* without the {@code -SNAPSHOT} suffix (if any).
* @throws NullPointerException if version is null
*/
public static String removeSnapshot(String version)
throws NullPointerException {
if (version == null) {
throw new NullPointerException("version parameter can not be null");
}
int index = version.indexOf(SNAPSHOT_SUFFIX);
if (index > -1) {
version = version.substring(0, index);
}
return version;
}
/**
* Filter versions.
*
* @param versions versions to filter
* @param min min version to accept
* @param max max version to accept
* @param includeMin flag to include min version
* @param includeMax flag to include max version
* @return versions between min and max
*/
public static List filterVersions(Set versions,
Version min,
Version max,
boolean includeMin,
boolean includeMax) {
List toApply = new ArrayList();
for (Version v : versions) {
int t;
if (min != null) {
t = v.compareTo(min);
if (t < 0 || t == 0 && !includeMin) {
// version trop ancienne
continue;
}
}
if (max != null) {
t = v.compareTo(max);
if (t > 0 || t == 0 && !includeMax) {
// version trop recente
continue;
}
}
toApply.add(v);
}
return toApply;
}
/**
* L'implantation d'un comparateur de versions permettant de controler
* l'ordre du numero de version, classifier et numero de classifer.
*
* Toute implementation de ce contrat devrait suivre cet algorithme :
*
* 1) Si versions égales, on quitte.
*
* 2) On teste l'ordre des nombres {@link #compareNumbers(Version, Version)}
*
* Si différent, alors versions différentes, on quitte
*
* 3) On teste l'ordre des classifiers
* {@link #compareClassifier(Version, Version)}
*
* Si différent, alors versions différentes, on quitte
*
* 4) On teste l'ordre des versions de classifiers
* {@link #compareClassifierNumber(Version, Version)}.
*/
public static class VersionComparator implements Comparator {
@Override
public int compare(Version o1, Version o2) {
if (o1.equals(o2)) {
// versions are equals
return 0;
}
// compare on numbers
int result = compareNumbers(o1, o2);
if (result != 0) {
// compare snapshot
return result;
}
// numbers are equals
// compare on classifier
result = compareClassifier(o1, o2);
if (result != 0) {
return result;
}
// classifier are equals
// compare on classifierNumber
result = compareClassifierNumber(o1, o2);
if (result != 0) {
return result;
}
// classifierNumber are equals
// compare on snapshot
result = compareSnapshot(o1, o2);
return result;
}
public int compareNumbers(Version o1, Version o2) {
int nbComponents1 = o1.numbers.length;
int nbComponents2 = o2.numbers.length;
int minlen = Math.min(nbComponents1, nbComponents2);
for (int i = 0; i < minlen; i++) {
int t1 = o1.numbers[i];
int t2 = o2.numbers[i];
if (t1 == t2) {
continue;
}
return t1 - t2;
}
// common version are equals
// the longer number wins
// example : 1.0.0 > 1.0 > 1
return nbComponents1 - nbComponents2;
}
public int compareClassifier(Version o1, Version o2) {
if (o1.hasClassifier() && o2.hasClassifier()) {
// o1 et o2 ont un classifier
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;
}
if (!o2.hasClassifier()) {
// o2 n'a pas de classifier, o2 est donc plus recent
return -1;
}
// o1 et o2 n'ont pas de classifier, il sont donc egaux
return 0;
}
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;
}
}
/**
* Tests if two versions are equals.
*
* @param version0 the first version
* @param version1 the second version
* @return {@code true} if versions are equals, {@code false} otherwise.
*/
public static boolean equals(String version0, String version1) {
Version v0 = valueOf(version0);
Version v1 = valueOf(version1);
boolean result = v0.equals(v1);
return result;
}
/**
* Tests if the first version is smaller than the second version.
*
* @param version0 the first version
* @param version1 the second version
* @return {@code true} if {@code version0} is before {@code version1},
* {@code false} otherwise.
*/
public static boolean smallerThan(String version0, String version1) {
Version v0 = valueOf(version0);
Version v1 = valueOf(version1);
boolean result = v0.before(v1);
return result;
}
/**
* Tests if the first version is greater than the second version.
*
* @param version0 the first version
* @param version1 the second version
* @return {@code true} if {@code version0} is after {@code version1},
* {@code false} otherwise.
*/
public static boolean greaterThan(String version0, String version1) {
Version v0 = valueOf(version0);
Version v1 = valueOf(version1);
boolean result = v0.after(v1);
return result;
}
/**
* Trier un ensemble de versions données en entrees
*
* On affiche le resultat dans la console
*
* @param args les versions
*/
public static void main(String... args) {
List list = new ArrayList();
List snapshots = new ArrayList();
for (String a : args) {
if (a.endsWith(SNAPSHOT_SUFFIX)) {
snapshots.add(valueOf(
a.substring(0, a.length() - VersionUtil.SNAPSHOT_SUFFIX.length())));
continue;
}
Version v = valueOf(a);
list.add(v);
}
Collections.sort(list);
List asString = new ArrayList();
for (Version v : list) {
asString.add(v.toString());
}
// repositionnement des snapshots
for (Version snap : snapshots) {
String v = snap.toString();
if (list.contains(snap)) {
// on ajoute juste avant
int index = asString.indexOf(v);
asString.add(index, v + SNAPSHOT_SUFFIX);
} else {
// ajout dans la liste initiale
list.add(snap);
Collections.sort(list);
int index = list.indexOf(snap);
if (index == 0) {
asString.add(0, v + SNAPSHOT_SUFFIX);
} else {
Version v2 = list.get(index - 1);
index = asString.indexOf(v2.toString());
asString.add(index + 1, v + SNAPSHOT_SUFFIX);
}
list.remove(snap);
}
}
StringBuilder buffer = new StringBuilder();
for (String s : asString) {
buffer.append(s).append("\n");
}
System.out.println(buffer.toString());
}
}