package com.comphenix.xp.metrics; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Represents a version that can be compared. The input is expected to take the following form: </br > * <code> * (whitespace) Number1.Number2.Number3(.)NumberN Letter (whitespace) * </code> * <p> * * Examples: * <ul> * <li>1.2.4</li> * <li>1.0</li> * <li>2.3.4b</li> * <li>12.4.5</li> * </ul> * * @author Kristian */ public class Version implements Comparable<Version> { private String version; private Pattern lastElement = Pattern.compile("(\\d+)([a-zA-Z])?"); private Pattern versionFormat = Pattern.compile("\\d+(\\.\\d+)*([a-zA-Z])?"); public Version(String version) { if (version == null) throw new IllegalArgumentException("Version can not be null"); Matcher match = versionFormat.matcher(version); // Make sense of the text if (!match.find()) throw new IllegalArgumentException("Invalid version format: " + version); this.version = match.group(); } @Override public int compareTo(Version that) { if (that == null) return 1; String[] thisParts = this.getVersion().split("\\."); String[] thatParts = that.getVersion().split("\\."); int length = Math.max(thisParts.length, thatParts.length); // The last element may have a letter - check for it String thisLetter = getAndRemoveLetter(thisParts); String thatLetter = getAndRemoveLetter(thatParts); boolean thisHasLetter = thisLetter != null && !thisLetter.isEmpty(); boolean thatHasLetter = thatLetter != null && !thatLetter.isEmpty(); for (int i = 0; i < length; i++) { int thisPart = i < thisParts.length ? Integer.parseInt(thisParts[i]) : 0; int thatPart = i < thatParts.length ? Integer.parseInt(thatParts[i]) : 0; if (thisPart < thatPart) return -1; if (thisPart > thatPart) return 1; } // Compare the letters too if (thisHasLetter ^ thatHasLetter) return thisHasLetter ? -1 : 1; else if (thisHasLetter && thatHasLetter) return thisLetter.compareTo(thatLetter); else return 0; } // Note: Also modifies the array private String getAndRemoveLetter(String[] parts) { Matcher match = lastElement.matcher(parts[parts.length - 1]); // Remove the letter if (match.matches()) { parts[parts.length - 1] = match.group(1); // Retrieve it, if it exists return match.group(2); } else { // Weird return null; } } @Override public String toString() { return version; } public String getVersion() { return this.version; } @Override public boolean equals(Object that) { if (this == that) return true; if (that == null) return false; if (this.getClass() != that.getClass()) return false; return this.compareTo((Version) that) == 0; } }