Skip to content

Instantly share code, notes, and snippets.

@kwart
Created July 22, 2016 11:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwart/4c3d769a8197eb72077264cce47ffae2 to your computer and use it in GitHub Desktop.
Save kwart/4c3d769a8197eb72077264cce47ffae2 to your computer and use it in GitHub Desktop.
package cz.cacek.javlog.Version;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This class represents a (number-based) version. It allows to compare the versions. Find the comparison algorithm details in
* {@link #compareTo(Version)} description.
*
* @author Josef Cacek
*/
public final class Version implements Comparable<Version> {
private static final Pattern PATTERN_DIGITS = Pattern.compile("\\d+");
private final String versionStr;
/**
* @param version must not be <code>null</code>
*/
public Version(String version) {
this.versionStr = Objects.requireNonNull(version, "Version must not be null.");
}
/**
* Returns the original version string.
*/
public String get() {
return this.versionStr;
}
/**
* Returns count of digit groups (i.e. numbers - version parts) in the version string.<br/>
* E.g. <code>new Version("1.8.0u101").length() == 4</code>
*/
public int length() {
int count = 0;
final Matcher thisMatcher = PATTERN_DIGITS.matcher(versionStr);
while (thisMatcher.find()) {
count++;
}
return count;
}
/**
* Compares Versions with following rules:
* <ul>
* <li>only numbers (digit groups) in given string are compared</li>
* <li>leading zeroes in numbers don't matter (<code>"1.002" == "01.2"</code>)</li>
* <li>any non-digit string is just a separator (<code>"Hello 2001 world 09/11" == "2001-09-11"</code>)</li>
* <li>comparison is from left to right (<code>"1.2"&lt;"2.1"</code>)</li>
* <li>when count of numbers in version string is not same and numbers from one Version are prefix of numbers from the
* second then the version with more numbers is the greater (<code>"1.8" < "1.8.0"</code>)</li>
* </ul>
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(Version other) {
Objects.requireNonNull(other);
Matcher thisMatcher = PATTERN_DIGITS.matcher(versionStr);
Matcher otherMatcher = PATTERN_DIGITS.matcher(other.versionStr);
while (thisMatcher.find()) {
if (!otherMatcher.find()) {
return 1;
}
final int result = Integer.parseInt(thisMatcher.group()) - Integer.parseInt(otherMatcher.group());
if (result != 0) {
return result;
}
}
return otherMatcher.find() ? -1 : 0;
}
@Override
public String toString() {
return "Version '" + versionStr + "'";
}
@Override
public int hashCode() {
int hash = 1;
Matcher thisMatcher = PATTERN_DIGITS.matcher(versionStr);
while (thisMatcher.find()) {
hash = hash * 31 + Integer.parseInt(thisMatcher.group());
}
return hash;
}
/**
* Equals consistent with {@link #compareTo(Version)}
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (this.getClass() != other.getClass())
return false;
return this.compareTo((Version) other) == 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment