/*
* Copyright 2015 MovingBlocks
*
* 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.terasology.naming;
import com.google.common.base.Strings;
import org.terasology.naming.exception.VersionParseException;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Wrapper for a semantic version string - for version numbers of the form MAJOR.minor.patch(-SNAPSHOT). Allows the individual
* elements to be retrieved, and for comparison between versions.
*
* @author Immortius
*/
public final class Version implements Comparable<Version> {
/**
* A default version of 1.0.0
*/
public static final Version DEFAULT = new Version(1, 0, 0);
private static final Pattern VERSION_PATTERN = Pattern.compile("(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-SNAPSHOT)?");
private int major;
private int minor;
private int patch;
private boolean snapshot;
/**
* Constructs a version with the given values
*
* @param major The major version number (generally incremented for breaking changes)
* @param minor The minot version number (generally changes for non-breaking feature enhancements)
* @param patch The patch version number (generally changes for non-breaking bug fixes)
* @throws IllegalArgumentException if a version part is negative
*/
public Version(int major, int minor, int patch) {
this(major, minor, patch, false);
}
/**
* Constructs a version with the given values
*
* @param major The major version number (generally incremented for breaking changes)
* @param minor The minot version number (generally changes for non-breaking feature enhancements)
* @param patch The patch version number (generally changes for non-breaking bug fixes)
* @param snapshot Whether this version is a snapshot (work in progress, not yet released)
* @throws IllegalArgumentException if a version part is negative
*/
public Version(int major, int minor, int patch, boolean snapshot) {
if (major < 0 || minor < 0 || patch < 0) {
throw new IllegalArgumentException("Illegal version " + major + "." + minor + "." + patch + " - all version parts must be positive");
}
this.major = major;
this.minor = minor;
this.patch = patch;
this.snapshot = snapshot;
}
/**
* @param version The string of the version
* @throws VersionParseException If the version string is not a valid version.
*/
public Version(String version) {
Matcher matcher = VERSION_PATTERN.matcher(version);
if (matcher.matches()) {
major = Integer.parseInt(matcher.group(1));
minor = Integer.parseInt(matcher.group(2));
patch = Integer.parseInt(matcher.group(3));
snapshot = !Strings.isNullOrEmpty(matcher.group(4));
} else {
throw new VersionParseException("Invalid version '" + version + "' - must be of the form MAJOR.minor.patch");
}
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
/**
* @return Whether this version is a snapshot (work in progress)
*/
public boolean isSnapshot() {
return snapshot;
}
public Version getSnapshot() {
if (snapshot) {
return this;
}
return new Version(major, minor, patch, true);
}
public Version getNextMajorVersion() {
return new Version(major + 1, 0, 0);
}
public Version getNextMinorVersion() {
return new Version(major, minor + 1, 0);
}
public Version getNextPatchVersion() {
return new Version(major, minor, patch + 1);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Version) {
Version other = (Version) obj;
return other.major == major && other.minor == minor && other.patch == patch && other.snapshot == snapshot;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch, snapshot);
}
@Override
public String toString() {
if (isSnapshot()) {
return major + "." + minor + "." + patch + "-SNAPSHOT";
}
return major + "." + minor + "." + patch;
}
@Override
public int compareTo(Version other) {
if (other.major != major) {
return major - other.major;
}
if (other.minor != minor) {
return minor - other.minor;
}
if (other.patch != patch) {
return patch - other.patch;
}
if (other.snapshot && !snapshot) {
return 1;
}
if (!other.snapshot && snapshot) {
return -1;
}
return 0;
}
}