package rocks.inspectit.shared.all.version;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import rocks.inspectit.shared.all.exception.enumeration.VersioningErrorCodeEnum;
/**
* Mirrors the version scheme of inspectIT.
*
* A version string is connected by dots. It provides the major, minor and micro version followed by
* an unique and always increasing build number.
*
* <p>
* Use the inner class StringConverter to create versions from string based representations: <code>
* Version version = Version.StringConverter.create("1.6.2.234")
* </code>
* <p>
*
* Examples: "1.6.3.234" -> major: 1, minor: 6, micro: 3, build 234
*
* @author Stefan Siegl
*/
public final class Version implements Comparable<Version> {
/**
* The major version.
*/
private int major;
/**
* The minor version.
*/
private int minor;
/**
* The micro version.
*/
private int micro;
/**
* The build number.
*/
private int buildno;
/**
* Constructor.
*/
public Version() {
}
/**
* Constructor.
*
* @param major
* major.
* @param minor
* minor.
* @param buildno
* buildno.
*/
public Version(int major, int minor, int buildno) {
this.major = major;
this.minor = minor;
this.buildno = buildno;
}
/**
* Constructor.
*
* @param major
* major.
* @param minor
* minor.
* @param micro
* micro.
* @param buildno
* buildno.
*/
public Version(int major, int minor, int micro, int buildno) {
this.major = major;
this.minor = minor;
this.micro = micro;
this.buildno = buildno;
}
/**
* Gets {@link #major}.
*
* @return {@link #major}
*/
public int getMajor() {
return major;
}
/**
* Sets {@link #major}.
*
* @param major
* New value for {@link #major}
*/
public void setMajor(int major) {
this.major = major;
}
/**
* Gets {@link #minor}.
*
* @return {@link #minor}
*/
public int getMinor() {
return minor;
}
/**
* Sets {@link #minor}.
*
* @param minor
* New value for {@link #minor}
*/
public void setMinor(int minor) {
this.minor = minor;
}
/**
* Gets {@link #micro}.
*
* @return {@link #micro}
*/
public int getMicro() {
return micro;
}
/**
* Sets {@link #micro}.
*
* @param micro
* New value for {@link #micro}
*/
public void setMicro(int micro) {
this.micro = micro;
}
/**
* Gets {@link #buildno}.
*
* @return {@link #buildno}
*/
public int getBuildno() {
return buildno;
}
/**
* Sets {@link #buildno}.
*
* @param buildno
* New value for {@link #buildno}
*/
public void setBuildno(int buildno) {
this.buildno = buildno;
}
/**
* {@inheritDoc}
*/
@Override
public int compareTo(Version o) {
return new CompareToBuilder().append(major, o.major).append(minor, o.minor).append(micro, o.micro).append(buildno, o.buildno).toComparison();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Version other = (Version) obj;
if (buildno != other.buildno) {
return false;
}
if (major != other.major) {
return false;
}
if (micro != other.micro) {
return false;
}
if (minor != other.minor) {
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + buildno;
result = (prime * result) + major;
result = (prime * result) + micro;
result = (prime * result) + minor;
return result;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return major + "." + minor + "." + micro + "." + buildno;
}
/**
* Creates a new Version and checks for correctness.
*
* @param stringRepresentation
* the string based representation.
* @return a version object that represent the version string.
* @throws InvalidVersionException
* in case the version string is not valid.
*/
public static Version verifyAndCreate(String stringRepresentation) throws InvalidVersionException {
Version version = new Version();
if (StringUtils.isEmpty(stringRepresentation)) {
throw new InvalidVersionException(VersioningErrorCodeEnum.VERSION_INVALID, null);
}
String[] splitByDot = StringUtils.split(stringRepresentation, ".");
switch (splitByDot.length) {
case 3:
// micro is optional for historical reasons. This is basically a safeguard if an
// older version is passed.
version.major = getIntFromString(splitByDot[0]);
version.minor = getIntFromString(splitByDot[1]);
version.buildno = getIntFromString(splitByDot[2]);
break;
case 4:
version.major = getIntFromString(splitByDot[0]);
version.minor = getIntFromString(splitByDot[1]);
version.micro = getIntFromString(splitByDot[2]);
version.buildno = getIntFromString(splitByDot[3]);
break;
default:
throw new InvalidVersionException("The version " + stringRepresentation + " does not follow the format major.minor[.micro].build", VersioningErrorCodeEnum.VERSION_INVALID, null);
}
return version;
}
/**
* Tries to convert one string element of the version to Integer.
*
* @param element
* the sub element of the version.
* @return the integer representation
* @throws InvalidVersionException
* if the conversion cannot be performed.
*/
private static int getIntFromString(String element) throws InvalidVersionException {
try {
return Integer.parseInt(element);
} catch (NumberFormatException e) {
throw new InvalidVersionException("Cannot convert sub element of the version to String", VersioningErrorCodeEnum.VERSION_INVALID, e);
}
}
}