/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.toolbox; import java.util.Comparator; import java.util.StringTokenizer; import org.openflexo.xmlcode.StringConvertable; import org.openflexo.xmlcode.StringEncoder; import org.openflexo.xmlcode.StringEncoder.Converter; public class FlexoVersion implements StringConvertable<FlexoVersion> { public static final StringEncoder.Converter<FlexoVersion> converter = new Converter<FlexoVersion>(FlexoVersion.class) { @Override public FlexoVersion convertFromString(String value) { return new FlexoVersion(value); } @Override public String convertToString(FlexoVersion value) { return value.toString(); } }; public FlexoVersion copy() { return new FlexoVersion(major, minor, patch, rc, isAlpha, isBeta); } public static boolean isValidVersionString(String version) { StringTokenizer st = new StringTokenizer(version, "."); if (st.hasMoreTokens()) { String next = st.nextToken(); try { Integer.valueOf(next); } catch (NumberFormatException e) { return false; } } if (st.hasMoreTokens()) { String next = st.nextToken(); try { Integer.valueOf(next); } catch (NumberFormatException e) { try { new FlexoVersion(version).parseAlphaBetaRC(version, next); } catch (NumberFormatException e2) { return false; } } } if (st.hasMoreTokens()) { String next = st.nextToken(); try { new FlexoVersion(version).parseAlphaBetaRC(version, next); } catch (NumberFormatException e2) { return false; } } return true; } public int major = 0; public int minor = 0; public int patch = 0; public int rc = -1; public boolean isAlpha = false; public boolean isBeta = false; public FlexoVersion(int major, int minor, int patch, int rc, boolean isAlpha, boolean isBeta) { this.major = major; this.minor = minor; this.patch = patch; this.rc = rc; this.isAlpha = isAlpha; this.isBeta = isBeta; } public FlexoVersion(String versionAsString) { super(); StringTokenizer st = new StringTokenizer(versionAsString, "."); if (st.hasMoreTokens()) { String next = st.nextToken(); try { major = Integer.valueOf(next).intValue(); } catch (NumberFormatException e) { System.err.println("Invalid major number: " + next + " is not valid (" + versionAsString + ")"); major = 0; } } if (st.hasMoreTokens()) { String next = st.nextToken(); try { minor = Integer.valueOf(next).intValue(); } catch (NumberFormatException e) { try { minor = parseAlphaBetaRC(versionAsString, next); } catch (NumberFormatException e2) { minor = 0; new NumberFormatException("Invalid minor number: " + next + " is not valid (" + versionAsString + ")") .printStackTrace(); } } } if (st.hasMoreTokens()) { String next = st.nextToken(); try { patch = parseAlphaBetaRC(versionAsString, next); } catch (NumberFormatException e) { e.printStackTrace(); } } } private int parseAlphaBetaRC(String versionAsString, String token) throws NumberFormatException { int returned = 0; if (token.toLowerCase().indexOf("rc") > -1) { try { returned = Integer.parseInt(token.substring(0, token.toLowerCase().indexOf("rc"))); } catch (NumberFormatException e) { throw new NumberFormatException("Invalid patch number: " + token.substring(0, token.toLowerCase().indexOf("rc")) + " is not valid (" + versionAsString + ")"); } try { rc = Integer.parseInt(token.substring(token.toLowerCase().indexOf("rc") + 2)); } catch (NumberFormatException e) { rc = -1; throw new NumberFormatException("Invalid RC number: " + token.substring(token.toLowerCase().indexOf("rc") + 2) + " is not valid (" + versionAsString + ")"); } } else { if (token.toLowerCase().indexOf("alpha") > -1) { isAlpha = true; try { returned = Integer.parseInt(token.substring(0, token.toLowerCase().indexOf("alpha"))); } catch (NumberFormatException e) { throw new NumberFormatException("Invalid patch number: " + token.substring(0, token.toLowerCase().indexOf("alpha")) + " is not valid (" + versionAsString + ")"); } } else if (token.toLowerCase().indexOf("beta") > -1) { isBeta = true; try { returned = Integer.parseInt(token.substring(0, token.toLowerCase().indexOf("beta"))); } catch (NumberFormatException e) { throw new NumberFormatException("Invalid patch number: " + token.substring(0, token.toLowerCase().indexOf("beta")) + " is not valid (" + versionAsString + ")"); } } else { returned = Integer.valueOf(token).intValue(); rc = -1; } } return returned; } @Override public String toString() { return toString(false); } public String toString(boolean forceDisplayPatch) { String v = String.valueOf(major) + "." + String.valueOf(minor) + (patch > 0 || forceDisplayPatch ? "." + patch : ""); if (rc > -1) { return v + "RC" + String.valueOf(rc); } if (isAlpha) { return v + "alpha"; } if (isBeta) { return v + "beta"; } return v; } @Override public boolean equals(Object anObject) { if (anObject instanceof FlexoVersion) { return toString().equals(anObject.toString()); } else if (anObject instanceof String) { return toString().equals(new FlexoVersion((String) anObject).toString()); } else { return super.equals(anObject); } } public boolean isLesserThan(FlexoVersion version) { return comparator.compare(this, version) < 0; } public boolean isGreaterThan(FlexoVersion version) { return comparator.compare(this, version) > 0; } @Override public int hashCode() { return toString().hashCode(); } @Override public StringEncoder.Converter<FlexoVersion> getConverter() { return converter; } public static final VersionComparator comparator = new VersionComparator(); /** * Version have the following format MAJOR.MINOR.PATCH(RCX|alpha|beta) members in parenthesis are optional and are called additional * members Priority of members is this (bigger the greater, of course): 1) MAJOR 2) MINOR 3) PATCH 4) NO additional member 5) beta 6) * alpha 7) RC (RC2 is bigger than RC1 of course) * * @author gpolet * */ public static class VersionComparator implements Comparator<FlexoVersion> { public VersionComparator() { super(); } @Override public int compare(FlexoVersion v1, FlexoVersion v2) { if (v1.major < v2.major) { return -1; } else if (v1.major > v2.major) { return 1; } else { if (v1.minor < v2.minor) { return -1; } else if (v1.minor > v2.minor) { return 1; } else { if (v1.patch < v2.patch) { return -1; } else if (v1.patch > v2.patch) { return 1; } else { if (v1.rc < 0 && v2.rc < 0) { if (v1.isAlpha) { if (v2.isAlpha) { return 0; } else { return -1; } } else if (v1.isBeta) { if (v2.isAlpha) { return 1; } else if (v2.isBeta) { return 0; } else { return -1; } } else { if (v2.isAlpha || v2.isBeta) { return 1; } else { return 0; } } } else if (v1.rc < 0 && v2.rc > -1 && !v1.isAlpha && !v1.isBeta) { return 1; } else if (v1.rc > -1 && v2.rc < 0 && !v2.isAlpha && !v2.isBeta) { return -1; } else { if (v1.rc < v2.rc) { return -1; } else if (v1.rc > v2.rc) { return 1; } else { // equals object !!! return 0; } } } } } } } public static void main(String[] args) { String[] s = { "0.9.0", "0.9.1", "0.9.0RC1", "0.9.0RC2", "0.9.0alpha", "0.9.0beta", "0.10.0", "0.10.1", "0.10.0RC1", "0.10.0RC2", "0.10.0alpha", "0.10.0beta", "0.9", "1.0alpha", "1.1alpha", "1.1RC8" }; for (int i = 0; i < s.length; i++) { String string = s[i]; FlexoVersion v = new FlexoVersion(string); for (int j = 0; j < s.length; j++) { String s2 = s[j]; FlexoVersion v2 = new FlexoVersion(s2); if (v.isLesserThan(v2)) { System.out.println(string + " is smaller than " + s2 + "[" + v2.toString() + "]"); } if (v.isGreaterThan(v2)) { System.out.println(string + " is bigger than " + s2 + "[" + v2.toString() + "]"); } if (v.equals(v2)) { System.out.println(string + " equals " + s2 + "[" + v2.toString() + "]"); } } } } }