/*
* Copyright 2010-2020 Redgate Software Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flywaydb.core.api;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
A version of a migration.
Author: Axel Fontaine
/**
* A version of a migration.
*
* @author Axel Fontaine
*/
public final class MigrationVersion implements Comparable<MigrationVersion> {
Version for an empty schema.
/**
* Version for an empty schema.
*/
public static final MigrationVersion EMPTY = new MigrationVersion(null, "<< Empty Schema >>");
Latest version.
/**
* Latest version.
*/
public static final MigrationVersion LATEST = new MigrationVersion(BigInteger.valueOf(-1), "<< Latest Version >>");
Current version. Only a marker. For the real version use Flyway.info().current() instead.
/**
* Current version. Only a marker. For the real version use Flyway.info().current() instead.
*/
public static final MigrationVersion CURRENT = new MigrationVersion(BigInteger.valueOf(-2), "<< Current Version >>");
Regex for matching proper version format
/**
* Regex for matching proper version format
*/
private static final Pattern SPLIT_REGEX = Pattern.compile("\\.(?=\\d)");
The individual parts this version string is composed of. Ex. 1.2.3.4.0 -> [1, 2, 3, 4, 0]
/**
* The individual parts this version string is composed of. Ex. 1.2.3.4.0 -> [1, 2, 3, 4, 0]
*/
private final List<BigInteger> versionParts;
The printable text to represent the version.
/**
* The printable text to represent the version.
*/
private final String displayText;
Create a MigrationVersion from a version String.
Params: - version – The version String. The value
current
will be interpreted as MigrationVersion.CURRENT, a marker for the latest version that has been applied to the database.
Returns: The MigrationVersion
/**
* Create a MigrationVersion from a version String.
*
* @param version The version String. The value {@code current} will be interpreted as MigrationVersion.CURRENT,
* a marker for the latest version that has been applied to the database.
* @return The MigrationVersion
*/
@SuppressWarnings("ConstantConditions")
public static MigrationVersion fromVersion(String version) {
if ("current".equalsIgnoreCase(version)) return CURRENT;
if ("latest".equalsIgnoreCase(version) || LATEST.getVersion().equals(version)) return LATEST;
if (version == null) return EMPTY;
return new MigrationVersion(version);
}
Creates a Version using this version string.
Params: - version – The version in one of the following formats: 6, 6.0, 005, 1.2.3.4, 201004200021.
null
means that this version refers to an empty schema.
/**
* Creates a Version using this version string.
*
* @param version The version in one of the following formats: 6, 6.0, 005, 1.2.3.4, 201004200021. <br/>{@code null}
* means that this version refers to an empty schema.
*/
private MigrationVersion(String version) {
String normalizedVersion = version.replace('_', '.');
this.versionParts = tokenize(normalizedVersion);
this.displayText = normalizedVersion;
}
Creates a Version using this version string.
Params: - version – The version in one of the following formats: 6, 6.0, 005, 1.2.3.4, 201004200021.
null
means that this version refers to an empty schema. - displayText – The alternative text to display instead of the version number.
/**
* Creates a Version using this version string.
*
* @param version The version in one of the following formats: 6, 6.0, 005, 1.2.3.4, 201004200021. <br/>{@code null}
* means that this version refers to an empty schema.
* @param displayText The alternative text to display instead of the version number.
*/
private MigrationVersion(BigInteger version, String displayText) {
this.versionParts = new ArrayList<>();
this.versionParts.add(version);
this.displayText = displayText;
}
Returns: The textual representation of the version.
/**
* @return The textual representation of the version.
*/
@Override
public String toString() {
return displayText;
}
Returns: Numeric version as String
/**
* @return Numeric version as String
*/
public String getVersion() {
if (this.equals(EMPTY)) return null;
if (this.equals(LATEST)) return Long.toString(Long.MAX_VALUE);
return displayText;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MigrationVersion version1 = (MigrationVersion) o;
return compareTo(version1) == 0;
}
@Override
public int hashCode() {
return versionParts == null ? 0 : versionParts.hashCode();
}
Convenience method for quickly checking whether this version is at least as new as this other version.
Params: - otherVersion – The other version.
Returns: true
if this version is equal or newer, false
if it is older.
/**
* Convenience method for quickly checking whether this version is at least as new as this other version.
*
* @param otherVersion The other version.
* @return {@code true} if this version is equal or newer, {@code false} if it is older.
*/
public boolean isAtLeast(String otherVersion) {
return compareTo(MigrationVersion.fromVersion(otherVersion)) >= 0;
}
Convenience method for quickly checking whether this version is newer than this other version.
Params: - otherVersion – The other version.
Returns: true
if this version is newer, false
if it is not.
/**
* Convenience method for quickly checking whether this version is newer than this other version.
*
* @param otherVersion The other version.
* @return {@code true} if this version is newer, {@code false} if it is not.
*/
public boolean isNewerThan(String otherVersion) {
return compareTo(MigrationVersion.fromVersion(otherVersion)) > 0;
}
Convenience method for quickly checking whether this major version is newer than this other major version.
Params: - otherVersion – The other version.
Returns: true
if this major version is newer, false
if it is not.
/**
* Convenience method for quickly checking whether this major version is newer than this other major version.
*
* @param otherVersion The other version.
* @return {@code true} if this major version is newer, {@code false} if it is not.
*/
public boolean isMajorNewerThan(String otherVersion) {
return getMajor().compareTo(MigrationVersion.fromVersion(otherVersion).getMajor()) > 0;
}
Returns: The major version.
/**
* @return The major version.
*/
public BigInteger getMajor() {
return versionParts.get(0);
}
Returns: The major version as a string.
/**
* @return The major version as a string.
*/
public String getMajorAsString() {
return versionParts.get(0).toString();
}
Returns: The minor version as a string.
/**
* @return The minor version as a string.
*/
public String getMinorAsString() {
if (versionParts.size() == 1) {
return "0";
}
return versionParts.get(1).toString();
}
@Override
public int compareTo(MigrationVersion o) {
if (o == null) {
return 1;
}
if (this == EMPTY) {
if (o == EMPTY) return 0;
else return -1;
}
if (this == CURRENT) {
return o == CURRENT ? 0 : -1;
}
if (this == LATEST) {
if (o == LATEST) return 0;
else return 1;
}
if (o == EMPTY) {
return 1;
}
if (o == CURRENT) {
return 1;
}
if (o == LATEST) {
return -1;
}
final List<BigInteger> parts1 = versionParts;
final List<BigInteger> parts2 = o.versionParts;
int largestNumberOfParts = Math.max(parts1.size(), parts2.size());
for (int i = 0; i < largestNumberOfParts; i++) {
final int compared = getOrZero(parts1, i).compareTo(getOrZero(parts2, i));
if (compared != 0) {
return compared;
}
}
return 0;
}
private BigInteger getOrZero(List<BigInteger> elements, int i) {
return i < elements.size() ? elements.get(i) : BigInteger.ZERO;
}
Splits this string into list of Long
Params: - versionStr – The string to split.
Returns: The resulting array.
/**
* Splits this string into list of Long
*
* @param versionStr The string to split.
* @return The resulting array.
*/
private List<BigInteger> tokenize(String versionStr) {
List<BigInteger> parts = new ArrayList<>();
for (String part : SPLIT_REGEX.split(versionStr)) {
parts.add(toBigInteger(versionStr, part));
}
for (int i = parts.size() - 1; i > 0; i--) {
if (!parts.get(i).equals(BigInteger.ZERO)) {
break;
}
parts.remove(i);
}
return parts;
}
private BigInteger toBigInteger(String versionStr, String part) {
try {
return new BigInteger(part);
} catch (NumberFormatException e) {
throw new FlywayException("Version may only contain 0..9 and . (dot). Invalid version: " + versionStr);
}
}
}