1 package be
.nikiroo
.utils
;
3 import java
.io
.ByteArrayOutputStream
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
8 * This class describe a program {@link Version}.
12 public class Version
implements Comparable
<Version
> {
13 private String version
;
18 private int tagVersion
;
21 * Create a new, empty {@link Version}.
28 * Create a new {@link Version} with the given values.
37 public Version(int major
, int minor
, int patch
) {
38 this(major
, minor
, patch
, null, -1);
42 * Create a new {@link Version} with the given values.
51 * a tag name for this version
53 public Version(int major
, int minor
, int patch
, String tag
) {
54 this(major
, minor
, patch
, tag
, -1);
58 * Create a new {@link Version} with the given values.
65 * the patch version the patch version
67 * a tag name for this version
69 * the version of the tagged version
71 public Version(int major
, int minor
, int patch
, String tag
, int tagVersion
) {
72 if (tagVersion
>= 0 && tag
== null) {
73 throw new java
.lang
.IllegalArgumentException(
74 "A tag version cannot be used without a tag");
81 this.tagVersion
= tagVersion
;
83 this.version
= generateVersion();
87 * Create a new {@link Version} with the given value, which must be in the
88 * form <tt>MAJOR.MINOR.PATCH(-TAG(TAG_VERSION))</tt>.
91 * the version (<tt>MAJOR.MINOR.PATCH</tt>,
92 * <tt>MAJOR.MINOR.PATCH-TAG</tt> or
93 * <tt>MAJOR.MINOR.PATCH-TAGVERSIONTAG</tt>)
95 public Version(String version
) {
97 String
[] tab
= version
.split("\\.");
98 this.major
= Integer
.parseInt(tab
[0].trim());
99 this.minor
= Integer
.parseInt(tab
[1].trim());
100 if (tab
[2].contains("-")) {
101 int posInVersion
= version
.indexOf('.');
102 posInVersion
= version
.indexOf('.', posInVersion
+ 1);
103 String rest
= version
.substring(posInVersion
+ 1);
105 int posInRest
= rest
.indexOf('-');
106 this.patch
= Integer
.parseInt(rest
.substring(0, posInRest
)
109 posInVersion
= version
.indexOf('-');
110 this.tag
= version
.substring(posInVersion
+ 1).trim();
111 this.tagVersion
= -1;
113 StringBuilder str
= new StringBuilder();
114 while (!tag
.isEmpty() && tag
.charAt(tag
.length() - 1) >= '0'
115 && tag
.charAt(tag
.length() - 1) <= '9') {
116 str
.insert(0, tag
.charAt(tag
.length() - 1));
117 tag
= tag
.substring(0, tag
.length() - 1);
120 if (str
.length() > 0) {
121 this.tagVersion
= Integer
.parseInt(str
.toString());
124 this.patch
= Integer
.parseInt(tab
[2].trim());
126 this.tagVersion
= -1;
129 this.version
= generateVersion();
130 } catch (Exception e
) {
135 this.tagVersion
= -1;
141 * The 'major' version.
143 * This version should only change when API-incompatible changes are made to
146 * @return the major version
148 public int getMajor() {
153 * The 'minor' version.
155 * This version should only change when new, backwards-compatible
156 * functionality has been added to the program.
158 * @return the minor version
160 public int getMinor() {
165 * The 'patch' version.
167 * This version should change when backwards-compatible bugfixes have been
168 * added to the program.
170 * @return the patch version
172 public int getPatch() {
177 * A tag name for this version.
181 public String
getTag() {
186 * The version of the tag, or -1 for no version.
188 * @return the tag version
190 public int getTagVersion() {
195 * Check if this {@link Version} is "empty" (i.e., the version was not
196 * parse-able or not given).
198 * @return TRUE if it is empty
200 public boolean isEmpty() {
201 return version
== null;
205 * Check if we are more recent than the given {@link Version}.
207 * Note that a tagged version is considered newer than a non-tagged version,
208 * but two tagged versions with different tags are not comparable.
210 * Also, an empty version is always considered older.
213 * the other {@link Version}
214 * @return TRUE if this {@link Version} is more recent than the given one
216 public boolean isNewerThan(Version o
) {
219 } else if (o
.isEmpty()) {
223 if (major
> o
.major
) {
227 if (major
== o
.major
&& minor
> o
.minor
) {
231 if (major
== o
.major
&& minor
== o
.minor
&& patch
> o
.patch
) {
235 // a tagged version is considered newer than a non-tagged one
236 if (major
== o
.major
&& minor
== o
.minor
&& patch
== o
.patch
237 && tag
!= null && o
.tag
== null) {
241 // 2 <> tagged versions are not comparable
242 boolean sameTag
= (tag
== null && o
.tag
== null)
243 || (tag
!= null && tag
.equals(o
.tag
));
244 if (major
== o
.major
&& minor
== o
.minor
&& patch
== o
.patch
&& sameTag
245 && tagVersion
> o
.tagVersion
) {
253 * Check if we are older than the given {@link Version}.
255 * Note that a tagged version is considered newer than a non-tagged version,
256 * but two tagged versions with different tags are not comparable.
258 * Also, an empty version is always considered older.
261 * the other {@link Version}
262 * @return TRUE if this {@link Version} is older than the given one
264 public boolean isOlderThan(Version o
) {
267 } else if (isEmpty()) {
271 // 2 <> tagged versions are not comparable
272 boolean sameTag
= (tag
== null && o
.tag
== null)
273 || (tag
!= null && tag
.equals(o
.tag
));
274 if (major
== o
.major
&& minor
== o
.minor
&& patch
== o
.patch
279 return !equals(o
) && !isNewerThan(o
);
283 * Return the version of the running program if it follows the VERSION
284 * convention (i.e., if it has a file called VERSION containing the version
285 * as a {@link String} in its binary root, and if this {@link String}
286 * follows the Major/Minor/Patch convention).
288 * If it does not, return an empty {@link Version} object.
290 * @return the {@link Version} of the program, or an empty {@link Version}
291 * (does not return NULL)
293 public static Version
getCurrentVersion() {
294 String version
= null;
296 InputStream in
= IOUtils
.openResource("VERSION");
299 ByteArrayOutputStream ba
= new ByteArrayOutputStream();
300 IOUtils
.write(in
, ba
);
303 version
= ba
.toString("UTF-8").trim();
304 } catch (IOException e
) {
308 return new Version(version
);
312 public int compareTo(Version o
) {
315 } else if (isNewerThan(o
)) {
323 public boolean equals(Object obj
) {
324 if (obj
instanceof Version
) {
325 Version o
= (Version
) obj
;
330 boolean sameTag
= (tag
== null && o
.tag
== null)
331 || (tag
!= null && tag
.equals(o
.tag
));
332 return o
.major
== major
&& o
.minor
== minor
&& o
.patch
== patch
333 && sameTag
&& o
.tagVersion
== tagVersion
;
340 public int hashCode() {
341 return version
== null ?
0 : version
.hashCode();
345 * Return a user-readable form of this {@link Version}.
348 public String
toString() {
349 return version
== null ?
"[unknown]" : version
;
353 * Generate the clean version {@link String} from the current values.
355 * @return the clean version string
357 private String
generateVersion() {
358 String tagSuffix
= "";
360 tagSuffix
= "-" + tag
361 + (tagVersion
>= 0 ? Integer
.toString(tagVersion
) : "");
364 return String
.format("%d.%d.%d%s", major
, minor
, patch
, tagSuffix
);