X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2FVersion.java;fp=src%2Fbe%2Fnikiroo%2Futils%2FVersion.java;h=269edb6fc1e6914d4233bc01d6410337c115fe00;hb=5584adbbbf5444c0039fed2b35dc7d5bb57b71b1;hp=0000000000000000000000000000000000000000;hpb=ad207feb2815e429ae32484bc6930990099f8ea4;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/Version.java b/src/be/nikiroo/utils/Version.java new file mode 100644 index 0000000..269edb6 --- /dev/null +++ b/src/be/nikiroo/utils/Version.java @@ -0,0 +1,366 @@ +package be.nikiroo.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * This class describe a program {@link Version}. + * + * @author niki + */ +public class Version implements Comparable { + private String version; + private int major; + private int minor; + private int patch; + private String tag; + private int tagVersion; + + /** + * Create a new, empty {@link Version}. + * + */ + public Version() { + } + + /** + * Create a new {@link Version} with the given values. + * + * @param major + * the major version + * @param minor + * the minor version + * @param patch + * the patch version + */ + public Version(int major, int minor, int patch) { + this(major, minor, patch, null, -1); + } + + /** + * Create a new {@link Version} with the given values. + * + * @param major + * the major version + * @param minor + * the minor version + * @param patch + * the patch version + * @param tag + * a tag name for this version + */ + public Version(int major, int minor, int patch, String tag) { + this(major, minor, patch, tag, -1); + } + + /** + * Create a new {@link Version} with the given values. + * + * @param major + * the major version + * @param minor + * the minor version + * @param patch + * the patch version the patch version + * @param tag + * a tag name for this version + * @param tagVersion + * the version of the tagged version + */ + public Version(int major, int minor, int patch, String tag, int tagVersion) { + if (tagVersion >= 0 && tag == null) { + throw new java.lang.IllegalArgumentException( + "A tag version cannot be used without a tag"); + } + + this.major = major; + this.minor = minor; + this.patch = patch; + this.tag = tag; + this.tagVersion = tagVersion; + + this.version = generateVersion(); + } + + /** + * Create a new {@link Version} with the given value, which must be in the + * form MAJOR.MINOR.PATCH(-TAG(TAG_VERSION)). + * + * @param version + * the version (MAJOR.MINOR.PATCH, + * MAJOR.MINOR.PATCH-TAG or + * MAJOR.MINOR.PATCH-TAGVERSIONTAG) + */ + public Version(String version) { + try { + String[] tab = version.split("\\."); + this.major = Integer.parseInt(tab[0].trim()); + this.minor = Integer.parseInt(tab[1].trim()); + if (tab[2].contains("-")) { + int posInVersion = version.indexOf('.'); + posInVersion = version.indexOf('.', posInVersion + 1); + String rest = version.substring(posInVersion + 1); + + int posInRest = rest.indexOf('-'); + this.patch = Integer.parseInt(rest.substring(0, posInRest) + .trim()); + + posInVersion = version.indexOf('-'); + this.tag = version.substring(posInVersion + 1).trim(); + this.tagVersion = -1; + + StringBuilder str = new StringBuilder(); + while (!tag.isEmpty() && tag.charAt(tag.length() - 1) >= '0' + && tag.charAt(tag.length() - 1) <= '9') { + str.insert(0, tag.charAt(tag.length() - 1)); + tag = tag.substring(0, tag.length() - 1); + } + + if (str.length() > 0) { + this.tagVersion = Integer.parseInt(str.toString()); + } + } else { + this.patch = Integer.parseInt(tab[2].trim()); + this.tag = null; + this.tagVersion = -1; + } + + this.version = generateVersion(); + } catch (Exception e) { + this.major = 0; + this.minor = 0; + this.patch = 0; + this.tag = null; + this.tagVersion = -1; + this.version = null; + } + } + + /** + * The 'major' version. + *

+ * This version should only change when API-incompatible changes are made to + * the program. + * + * @return the major version + */ + public int getMajor() { + return major; + } + + /** + * The 'minor' version. + *

+ * This version should only change when new, backwards-compatible + * functionality has been added to the program. + * + * @return the minor version + */ + public int getMinor() { + return minor; + } + + /** + * The 'patch' version. + *

+ * This version should change when backwards-compatible bugfixes have been + * added to the program. + * + * @return the patch version + */ + public int getPatch() { + return patch; + } + + /** + * A tag name for this version. + * + * @return the tag + */ + public String getTag() { + return tag; + } + + /** + * The version of the tag, or -1 for no version. + * + * @return the tag version + */ + public int getTagVersion() { + return tagVersion; + } + + /** + * Check if this {@link Version} is "empty" (i.e., the version was not + * parse-able or not given). + * + * @return TRUE if it is empty + */ + public boolean isEmpty() { + return version == null; + } + + /** + * Check if we are more recent than the given {@link Version}. + *

+ * Note that a tagged version is considered newer than a non-tagged version, + * but two tagged versions with different tags are not comparable. + *

+ * Also, an empty version is always considered older. + * + * @param o + * the other {@link Version} + * @return TRUE if this {@link Version} is more recent than the given one + */ + public boolean isNewerThan(Version o) { + if (isEmpty()) { + return false; + } else if (o.isEmpty()) { + return true; + } + + if (major > o.major) { + return true; + } + + if (major == o.major && minor > o.minor) { + return true; + } + + if (major == o.major && minor == o.minor && patch > o.patch) { + return true; + } + + // a tagged version is considered newer than a non-tagged one + if (major == o.major && minor == o.minor && patch == o.patch + && tag != null && o.tag == null) { + return true; + } + + // 2 <> tagged versions are not comparable + boolean sameTag = (tag == null && o.tag == null) + || (tag != null && tag.equals(o.tag)); + if (major == o.major && minor == o.minor && patch == o.patch && sameTag + && tagVersion > o.tagVersion) { + return true; + } + + return false; + } + + /** + * Check if we are older than the given {@link Version}. + *

+ * Note that a tagged version is considered newer than a non-tagged version, + * but two tagged versions with different tags are not comparable. + *

+ * Also, an empty version is always considered older. + * + * @param o + * the other {@link Version} + * @return TRUE if this {@link Version} is older than the given one + */ + public boolean isOlderThan(Version o) { + if (o.isEmpty()) { + return false; + } else if (isEmpty()) { + return true; + } + + // 2 <> tagged versions are not comparable + boolean sameTag = (tag == null && o.tag == null) + || (tag != null && tag.equals(o.tag)); + if (major == o.major && minor == o.minor && patch == o.patch + && !sameTag) { + return false; + } + + return !equals(o) && !isNewerThan(o); + } + + /** + * Return the version of the running program if it follows the VERSION + * convention (i.e., if it has a file called VERSION containing the version + * as a {@link String} in its binary root, and if this {@link String} + * follows the Major/Minor/Patch convention). + *

+ * If it does not, return an empty {@link Version} object. + * + * @return the {@link Version} of the program, or an empty {@link Version} + * (does not return NULL) + */ + public static Version getCurrentVersion() { + String version = null; + + InputStream in = IOUtils.openResource("VERSION"); + if (in != null) { + try { + ByteArrayOutputStream ba = new ByteArrayOutputStream(); + IOUtils.write(in, ba); + in.close(); + + version = ba.toString("UTF-8").trim(); + } catch (IOException e) { + } + } + + return new Version(version); + } + + @Override + public int compareTo(Version o) { + if (equals(o)) { + return 0; + } else if (isNewerThan(o)) { + return 1; + } else { + return -1; + } + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Version) { + Version o = (Version) obj; + if (isEmpty()) { + return o.isEmpty(); + } + + boolean sameTag = (tag == null && o.tag == null) + || (tag != null && tag.equals(o.tag)); + return o.major == major && o.minor == minor && o.patch == patch + && sameTag && o.tagVersion == tagVersion; + } + + return false; + } + + @Override + public int hashCode() { + return version == null ? 0 : version.hashCode(); + } + + /** + * Return a user-readable form of this {@link Version}. + */ + @Override + public String toString() { + return version == null ? "[unknown]" : version; + } + + /** + * Generate the clean version {@link String} from the current values. + * + * @return the clean version string + */ + private String generateVersion() { + String tagSuffix = ""; + if (tag != null) { + tagSuffix = "-" + tag + + (tagVersion >= 0 ? Integer.toString(tagVersion) : ""); + } + + return String.format("%d.%d.%d%s", major, minor, patch, tagSuffix); + } +}