Sitelet https://github.com/KrailOrg/q3c-util/commit/73834ee92d01969b5818b8934fa797fbe0c5ecd4
Skip to content

Commit 73834ee

Browse files
author
David Sowerby
committed
VersionNumber added
1 parent 6b76839 commit 73834ee

3 files changed

Lines changed: 445 additions & 3 deletions

File tree

‎build.gradle‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildscript {
2-
ext.kotlin_version = '1.1.3-2'
2+
ext.kotlin_version = '1.1.4-2'
33
ext.kaytee_plugin_version = "0.16.0.0"
44

55
repositories {
@@ -20,9 +20,11 @@ apply plugin: 'uk.q3c.kaytee'
2020
group='uk.q3c.util'
2121

2222
kaytee {
23-
baseVersion = "0.12.0.0"
23+
baseVersion = "0.13.0.0"
2424
}
2525

26+
version="0.13.0.0"
27+
2628
bintray {
2729
user = 'dsowerby'
2830
}
@@ -31,7 +33,7 @@ compileKotlin {
3133
kotlinOptions.jvmTarget = "1.8"
3234
}
3335

34-
ext.assertjVersion = '3.3.0'
36+
ext.assertjVersion = '3.8.0'
3537
ext.commonsLangVersion = '3.3.2'
3638
ext.guavaVersion = '23.0'
3739
ext.guiceVersion = '4.1.0'
@@ -59,6 +61,7 @@ dependencies {
5961
compile 'com.google.guava:guava:' + guavaVersion
6062
compile 'org.apache.commons:commons-collections4:4.1'
6163

64+
testCompile 'junit:junit:4.12'
6265
testCompile 'org.assertj:assertj-core:' + assertjVersion
6366
testCompile 'org.assertj:assertj-guava:1.3.1'
6467
compile 'org.mockito:mockito-all:1.10.19'
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
package uk.q3c.util.version
2+
3+
4+
/**
5+
* Created by David Sowerby on 24 Aug 2017
6+
*/
7+
8+
data class VersionNumber @JvmOverloads constructor(
9+
val major: Int = 0,
10+
val minor: Int = 0,
11+
val patch: Int = 0,
12+
val nonFunctional: Int = 0,
13+
val qualifier: String = "",
14+
val buildMetaData: String = "",
15+
val scheme: Scheme = Scheme()) : Comparable<VersionNumber> {
16+
17+
/**
18+
* The [major],[minor].[patch].[nonFunctional] version elements are compared to a depth determined by [Scheme.depth].
19+
* The [qualifier] element is ignored
20+
* The [buildMetaData] element is ignored
21+
*/
22+
fun isSameBaseVersionAs(other: VersionNumber): Boolean {
23+
return compareTo(other) == 0
24+
}
25+
26+
fun isLaterBaseVersionThan(other: VersionNumber): Boolean {
27+
return compareVersion(other, false) > 0
28+
}
29+
30+
31+
/**
32+
* The [major],[minor].[patch].[nonFunctional] version elements are compared to a depth determined by [Scheme.depth].
33+
* The [qualifier] elements are lexically compared (case insensitive)
34+
* The [buildMetaData] element is ignored
35+
*/
36+
fun isSameVersionAs(other: VersionNumber): Boolean {
37+
return (compareTo(other) == 0) && (qualifier.compareTo(other.qualifier, true) == 0)
38+
}
39+
40+
fun isLaterVersionThan(other: VersionNumber): Boolean {
41+
return compareVersion(other, false) > 0 || (compareTo(other) == 0 && (qualifier.compareTo(other.qualifier, true) < 0))
42+
}
43+
44+
/**
45+
* The [major],[minor].[patch].[nonFunctional] version elements are compared to a depth determined by [Scheme.depth].
46+
* The [qualifier] element is lexically compared (case insensitive)
47+
* The [buildMetaData] element is lexically compared (case insensitive)
48+
*/
49+
fun isSameBuildAs(other: VersionNumber): Boolean {
50+
return (compareTo(other) == 0) && (qualifier.compareTo(other.qualifier, true) == 0) && (buildMetaData.compareTo(other.buildMetaData) == 0)
51+
}
52+
53+
fun isLaterBuildThan(other: VersionNumber): Boolean {
54+
return isLaterVersionThan(other) || (isSameVersionAs(other) && (buildMetaData.compareTo(other.buildMetaData) > 0))
55+
}
56+
57+
/**
58+
* The [major],[minor].[patch] version elements are compared to a depth determined by [Scheme.depth].
59+
* The [nonFunctional] element is ignored
60+
* The [qualifier] element is ignored
61+
* The [buildMetaData] is ignored
62+
*/
63+
fun isSameFunctionalVersionAs(other: VersionNumber): Boolean {
64+
return (compareVersion(other, true) == 0) && (qualifier.compareTo(other.qualifier, true) == 0)
65+
}
66+
67+
fun isLaterFunctionalVersionThan(other: VersionNumber): Boolean {
68+
return compareVersion(other, true) > 0 || (compareTo(other) == 0 && (qualifier.compareTo(other.qualifier, true) < 0))
69+
}
70+
71+
/**
72+
* Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer
73+
* as this object is less than, equal to, or greater than the specified object.
74+
*
75+
*
76+
* The depth to which the version is compared is set by [Scheme.depth].
77+
* The [qualifier] element is lexically compared (case insensitive) using [String.compareTo]
78+
* The [buildMetaData] element is ignored by this method
79+
*/
80+
override fun compareTo(other: VersionNumber): Int {
81+
return compareVersion(other, false)
82+
}
83+
84+
fun compareVersion(other: VersionNumber, ignoreNonfunctional: Boolean): Int {
85+
val depth = if (ignoreNonfunctional && scheme.depth == 4) {
86+
3
87+
} else {
88+
scheme.depth
89+
}
90+
if (major != other.major) {
91+
return major - other.major
92+
}
93+
if (depth == 1) {
94+
return 0
95+
}
96+
if (minor != other.minor) {
97+
return minor - other.minor
98+
}
99+
if (depth == 2) {
100+
return 0
101+
}
102+
if (patch != other.patch) {
103+
return patch - other.patch
104+
}
105+
if (depth == 3) {
106+
return 0
107+
}
108+
if (nonFunctional != other.nonFunctional) {
109+
return nonFunctional - other.nonFunctional
110+
}
111+
return 0
112+
}
113+
114+
/**
115+
* Returns a new instance with [major] incremented, and ALL other elements reset to 0 (empty String for [buildMetaData] and [qualifier])
116+
*/
117+
fun incMajor(): VersionNumber {
118+
return VersionNumber(major = major + 1)
119+
}
120+
121+
/**
122+
* Returns a new instance with [minor] incremented, and all lower order elements reset to 0 (empty String for [buildMetaData] and [qualifier])
123+
*/
124+
fun incMinor(): VersionNumber {
125+
return VersionNumber(major = major, minor = minor + 1)
126+
}
127+
128+
/**
129+
* Returns a new instance with [patch] incremented, and all lower order elements reset to 0 (empty String for [buildMetaData] and [qualifier])
130+
*/
131+
fun incPatch(): VersionNumber {
132+
return VersionNumber(major = major, minor = minor, patch = patch + 1)
133+
}
134+
135+
/**
136+
* Returns a new instance with [nonFunctional] incremented, [buildMetaData] and [qualifier] rest to empty String
137+
*/
138+
fun incNonFunctional(): VersionNumber {
139+
return VersionNumber(major = major, minor = minor, patch = patch, nonFunctional = nonFunctional + 1)
140+
}
141+
142+
override fun toString(): String {
143+
val buf = StringBuilder()
144+
buf.append(major)
145+
if (scheme.depth > 1) {
146+
buf.append(".")
147+
buf.append(minor)
148+
}
149+
if (scheme.depth > 2) {
150+
buf.append(".")
151+
buf.append(patch)
152+
}
153+
if (scheme.depth > 3) {
154+
buf.append(".")
155+
buf.append(nonFunctional)
156+
}
157+
if (qualifier.isNotBlank()) {
158+
buf.append(scheme.qualifierSeparator)
159+
buf.append(qualifier)
160+
}
161+
if (buildMetaData.isNotBlank()) {
162+
buf.append(scheme.buildMetaDataSeparator)
163+
buf.append(buildMetaData)
164+
}
165+
return buf.toString()
166+
}
167+
168+
169+
}
170+
171+
172+
/**
173+
* Parses a full version number, that is one which contains all the elements, including qualifier and build meta data, in one string
174+
* The format of that string must comply with the selected [scheme]
175+
*
176+
* @return a [VersionNumber] constructed from the input
177+
*/
178+
@JvmOverloads
179+
fun parseFullVersionNumber(input: String, scheme: Scheme = Scheme()): VersionNumber {
180+
val buildSplit = input.split(scheme.buildMetaDataSeparator)
181+
var buildMeta = ""
182+
// if there is a buildMeta element
183+
if (buildSplit.size > 1) {
184+
buildMeta = buildSplit[1]
185+
}
186+
val qualifierSplit = buildSplit[0].split(scheme.qualifierSeparator)
187+
var qualifier = ""
188+
if (qualifierSplit.size > 1) {
189+
qualifier = qualifierSplit[1]
190+
}
191+
val baseVersion = qualifierSplit[0]
192+
val bv = parseBaseVersion(baseVersion)
193+
return VersionNumber(bv.major, bv.minor, bv.patch, bv.nonFunctional, qualifier, buildMeta, scheme)
194+
}
195+
196+
/**
197+
* Parses a version number, from its 3 constituent parst, [baseVersion] (for example 1.2.3.4), [qualifier] and [buildMetaData]
198+
*
199+
* The format of that string must comply with the selected [scheme]
200+
*
201+
* @return a [VersionNumber] constructed from the input
202+
*/
203+
@JvmOverloads
204+
fun parseVersion(baseVersion: String, qualifier: String = "", buildMetaData: String = "", scheme: Scheme = Scheme()): VersionNumber {
205+
val bv = parseBaseVersion(baseVersion)
206+
return VersionNumber(bv.major, bv.minor, bv.patch, bv.nonFunctional, qualifier, buildMetaData, scheme)
207+
}
208+
209+
/**
210+
* Parses just the base version identifier (for example 1.2.3.4) into a simple data object containing the elements in numeric form
211+
*/
212+
fun parseBaseVersion(baseVersion: String): BaseVersion {
213+
val versionSplit = baseVersion.split(".")
214+
var index = 0
215+
val bv = BaseVersion()
216+
for (element in versionSplit) {
217+
when (index) {
218+
0 -> bv.major = element.toInt()
219+
1 -> bv.minor = element.toInt()
220+
2 -> bv.patch = element.toInt()
221+
3 -> bv.nonFunctional = element.toInt()
222+
223+
}
224+
index++
225+
}
226+
return bv
227+
}
228+
229+
230+
data class Scheme @JvmOverloads constructor(val depth: Int = 4, val qualifierSeparator: String = "-", val buildMetaDataSeparator: String = "+") {
231+
init {
232+
if (depth < 1 || depth > 4) {
233+
throw SchemeException("Scheme depth must be in the range 1 - 4 inclusive")
234+
}
235+
}
236+
}
237+
238+
data class BaseVersion(var major: Int = 0,
239+
var minor: Int = 0,
240+
var patch: Int = 0,
241+
var nonFunctional: Int = 0)
242+
243+
class SchemeException(msg: String) : RuntimeException(msg)

0 commit comments

Comments
 (0)