org.nuiton.util.version.Version 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) 2014 CodeLutin, Tony Chemit
* %%
* 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.version;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.ObjectUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A class to represent a version.
* Replace previously {@code org.nuiton.util.Version} class.
* Definition
* A version is defined of n {@code componants} separated by {@code componantSeparator}.
* Componants
* Componants can be of two types:
*
* - Number componant: a strict positive integer value
* - String componant: a sequence of characters which can't be either number nor componant separators
*
* Componant separators
*
* Componant separator are characters which can't be alphanumeric and can be {@code empty character}.
*
*
* Componant separators are optional and componants will be detected as soon as a character changed from a numeric string sequence to a alpha (none numeric!) sequence.
*
*
* For example, version {@code 1a2} is composed of three componants: {code 1}, {@code a} and {@code 3}.
*
* Snapshot flag
* Additionnaly version can be qualifed as a {@code SNAPSHOT} (see below section about ordering).
* Examples
*
* 0 (one componant 0)
* 0-SNAPSHOT (one componant 0 + SNAPSHOT flag)
* 1.0 (two componants 1,0)
* 1.1 (two componants 1,1)
* 1.1-alpha-1 (four componants 1,1,alpha,1)
* 1.1-beta (three componants 1,1,beta)
* 1.1-rc-1 (four componants 1,1,rc,1)
* 1.1-a (three componants 1,1,a)
* 1.1-a12-4.45_6432 (seven componants 1,1,a,12,4,45,643)
*
* Ordering
* A version is comparable, to have all the detail of order see {@link VersionComparator}.
* Immutability
* The version is immutable, to create or modify a version, use the {@link VersionBuilder} API
* or shortcut methods in {@link Versions}.
*
* @author Tony Chemit - [email protected]
* @see VersionBuilder
* @see VersionComparator
* @since 3.0
* @deprecated since 3.0, use now Nuiton version
*/
@Deprecated
public class Version implements Comparable, Serializable {
private static final long serialVersionUID = 1L;
/**
* Suffix of a {@code SNAPSHOT} version in the text representation.
*/
public static final String SNAPSHOT_SUFFIX = "-SNAPSHOT";
/**
* Version V0.
*/
public static final Version VZERO = VersionBuilder.create().build();
/**
* Comparator of version used internaly to fulfill the compoarator contract.
*/
protected static final VersionComparator VERSION_COMPARATOR = new VersionComparator();
public static final char DEFAULT_JOIN_COMPONANT_SEPARATOR = '.';
/**
* List of componants of the version.
*/
protected final List componants;
/**
* List of separators of the version.
*/
protected final List componantSeparators;
/**
* flag to define if version is a snapshot (if so a -SNAPSHOT is
* added at the end of the textual representation of the version).
*/
protected final boolean snapshot;
/**
* string represention of the version.
*/
protected transient String version;
protected Version(List componants, List componantSeparators, boolean snapshot) {
this.componantSeparators = Collections.unmodifiableList(new ArrayList(componantSeparators));
this.componants = Collections.unmodifiableList(new ArrayList(componants));
this.snapshot = snapshot;
}
public List getComponants() {
return componants;
}
public List getComponantSeparators() {
return componantSeparators;
}
public boolean isSnapshot() {
return snapshot;
}
public int getComponantCount() {
return componants.size();
}
public int getNumberComponant(int componantPosition) {
VersionComponant comparable = getComponant(componantPosition);
Preconditions.checkState(comparable instanceof NumberVersionComponant, "componant at " + componantPosition + " for version " + this + " is not a number (" + comparable + ")");
return (Integer) comparable.getValue();
}
public String getTextComponant(int componantPosition) {
VersionComponant comparable = getComponant(componantPosition);
Preconditions.checkState(comparable instanceof StringVersionComponant, "componant at " + componantPosition + " for version " + this + " is not a string (" + comparable + ")");
return (String) comparable.getValue();
}
public VersionComponant getComponant(int level) {
Preconditions.checkArgument(level > 0 || level < getComponantCount(), "not a valid level " + level + " for the Version " + this);
return componants.get(level);
}
/**
* @return the string represention value of the version
*/
public String getVersion() {
if (version == null) {
version = String.valueOf(componants.get(0).getValue());
for (int i = 0, nb = componantSeparators.size(); i < nb; i++) {
version += componantSeparators.get(i);
version += componants.get(i + 1).getValue();
}
if (snapshot) {
version += SNAPSHOT_SUFFIX;
}
}
return version;
}
/**
* Convert the string representation to a java identifier compliant.
*
*
* - in java: {@code .} is forbidden
* - in database (mysql, h2 ...): {@code .} is forbidden
*
*
* Forbidden values are replaced by {@code _} character.
*
* @return the java compilant string representation of the version
*/
public String getValidName() {
String validName = getVersion();
// replace ". et -"
validName = validName.replaceAll("\\.|-", "_");
return validName;
}
/**
* Creates a new version from this one incremented.
*
* If the last componant is a number, then just increments this number; otherwise add a new
* number componant with value 1.
*
* Example:
*
* - 1 → 2
* - 1-a → 1-a.1
*
*
* @return the incremented version
* @deprecated use instead {@link Versions#increments(Version)}
*/
@Deprecated
public Version increments() {
Version newVersion = Versions.increments(this);
return newVersion;
}
/**
* Creates a new version from this one incremented.
*
* If the last componant is a number, then just increments this number; otherwise add a new
* number componant with value 1.
*
* Example:
*
* - 1 → 2
* - 1-a → 1-a.1
*
*
* @param componantSeperator the componant separator to use the last componant is a classifier
* @return the incremented version
* @deprecated use instead {@link Versions#increments(Version, char)}
*/
@Deprecated
public Version increments(char componantSeperator) {
Version newVersion = Versions.increments(this, componantSeperator);
return newVersion;
}
/**
* Creates a new version from this one with the number componant incremented at the given position.
*
* Note:
* Will fail if the componant at the required position is not a number.
*
* @param componantPosition position of the version componant to increment
* @return the incremented version
* @deprecated use instead {@link Versions#increments(Version, int)}
*/
@Deprecated
public Version increments(int componantPosition) {
Version newVersion = Versions.increments(this, componantPosition);
return newVersion;
}
/**
* Creates a new version from this one with the number componant decremented at the given position.
*
* Note:
* Will fail if the componant at the required position is not a number, or his value is 0.
*
* @param componantPosition position of the version componant to increment
* @return the decremented version
* @deprecated use {@link Versions#decrements(Version, int)} instead
*/
@Deprecated
public Version decrements(int componantPosition) {
Version newVersion = Versions.decrements(this, componantPosition);
return newVersion;
}
@Override
public int compareTo(Version o) {
int result = VERSION_COMPARATOR.compare(this, o);
return result;
}
/**
* @param o the other version to test
* @return {@code true} if current version is before or equals the given one
*/
public boolean beforeOrequals(Version o) {
int result = compareTo(o);
return result <= 0;
}
/**
* @param o the other version to test
* @return {@code true} if current version is before the given one
*/
public boolean before(Version o) {
int result = compareTo(o);
return result < 0;
}
/**
* @param o the other version to test
* @return {@code true} if current version is after or equals the given one
*/
public boolean afterOrEquals(Version o) {
int result = compareTo(o);
return result >= 0;
}
/**
* @param o the other version to test
* @return {@code true} if current version is after the given one
*/
public boolean after(Version o) {
int result = compareTo(o);
return result > 0;
}
@Override
public String toString() {
return getVersion();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Version)) return false;
return compareTo((Version) o) == 0;
}
@Override
public int hashCode() {
int result = componants.hashCode();
result = 31 * result + (snapshot ? 1 : 0);
return result;
}
protected VersionComponant getLastComponant() {
return componants.get(getComponantCount() - 1);
}
public interface VersionComponant, V extends VersionComponant> extends Serializable, Comparable {
C getValue();
}
public static class NumberVersionComponant implements VersionComponant {
private static final long serialVersionUID = 1L;
protected final Integer value;
public NumberVersionComponant(Integer value) {
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NumberVersionComponant)) return false;
return compareTo((NumberVersionComponant) o) == 0;
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public int compareTo(NumberVersionComponant o) {
return value.compareTo(o.value);
}
}
public static class StringVersionComponant implements VersionComponant {
private static final long serialVersionUID = 1L;
protected final boolean preRelease;
protected final String value;
protected final String lowerCaseValue;
public StringVersionComponant(boolean preRelease, String value) {
this.preRelease = preRelease;
this.value = value;
this.lowerCaseValue = value.toLowerCase();
}
@Override
public String getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StringVersionComponant)) return false;
return compareTo((StringVersionComponant) o) == 0;
}
@Override
public int hashCode() {
int result = preRelease ? 1 : 0;
result = 31 * result + value.hashCode();
return result;
}
public boolean isPreRelease() {
return preRelease;
}
@Override
public int compareTo(StringVersionComponant o) {
int result;
if (ObjectUtils.notEqual(preRelease, o.preRelease)) {
// compare on preRelease flag
if (preRelease) {
// preRelease is before any other string componant
result = -1;
} else {
result = 1;
}
} else {
// on same preRelease flag
// compare on lowerCaseValue
result = lowerCaseValue.compareTo(o.lowerCaseValue);
}
return result;
}
}
}