Created
July 22, 2016 11:51
-
-
Save kwart/4c3d769a8197eb72077264cce47ffae2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"<"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