Skip to content

Commit d4c86a5

Browse files
authored
Merge pull request #100 from fugerit-org/99-create-version-compare-utility
Create version compare utility #99
2 parents 64a95a9 + 7136533 commit d4c86a5

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Create version compare utility <https://github.com/fugerit-org/fj-lib/issues/99>
13+
1014
### Deprecated
1115

1216
- MavenProps.getPropery() method. (flagged for removal in future versions)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.fugerit.java.core.cfg;
2+
3+
/**
4+
* Utility class for comparing version strings in the format "MAJOR.MINOR.PATCH",
5+
* optionally including qualifiers (e.g. "-SNAPSHOT"). Provides a compare method
6+
* that handles versions with different lengths and a convenience method for
7+
* checking if one version is greater than another.
8+
*
9+
* <p>This implementation follows standard Semantic Versioning comparison rules:
10+
* numeric comparison of components, missing components treated as zero.</p>
11+
*
12+
* @author Your Name
13+
* @since 1.0
14+
*/
15+
public class VersionCompare {
16+
17+
private VersionCompare() {
18+
// Prevent instantiation
19+
}
20+
21+
/**
22+
* Extracts the numeric portion of a version string component, ignoring any
23+
* qualifier suffix that begins with a hyphen.
24+
*
25+
* @param part the version component, e.g. "1", "2-SNAPSHOT"
26+
* @return the integer value of the numeric portion
27+
* @throws NumberFormatException if the numeric portion is not a valid integer
28+
*/
29+
private static int convertVersionPart(String part) {
30+
String numeric = part.split("-", 2)[0];
31+
return Integer.parseInt(numeric);
32+
}
33+
34+
/**
35+
* Compares two version strings in "MAJOR.MINOR.PATCH(...)" format.
36+
* Missing components are treated as zero.
37+
*
38+
* @param v1 the first version string to compare
39+
* @param v2 the second version string to compare
40+
* @return a negative integer if {@code v1 < v2}, zero if equal, or a positive
41+
* integer if {@code v1 > v2}
42+
* @throws NumberFormatException if any component is not a valid integer
43+
*
44+
* @since 1.0
45+
*/
46+
public static int compare(String v1, String v2) {
47+
String[] parts1 = v1.split("\\.");
48+
String[] parts2 = v2.split("\\.");
49+
int length = Math.max(parts1.length, parts2.length);
50+
51+
for (int i = 0; i < length; i++) {
52+
int p1 = i < parts1.length ? convertVersionPart(parts1[i]) : 0;
53+
int p2 = i < parts2.length ? convertVersionPart(parts2[i]) : 0;
54+
if (p1 != p2) {
55+
return Integer.compare(p1, p2);
56+
}
57+
}
58+
return 0;
59+
}
60+
61+
/**
62+
* Determines if the first version string represents a version strictly greater
63+
* than the second.
64+
*
65+
* @param v1 the first version string
66+
* @param v2 the second version string
67+
* @return {@code true} if {@code v1} is greater than {@code v2}, {@code false}
68+
* otherwise (including equality)
69+
*
70+
* @since 1.0
71+
*/
72+
public static boolean isGreaterThan(String v1, String v2) {
73+
return compare(v1, v2) > 0;
74+
}
75+
76+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package test.org.fugerit.java.core.cfg;
2+
3+
import org.fugerit.java.core.cfg.VersionCompare;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.*;
7+
8+
class TestVersionCompare {
9+
10+
// Version constants
11+
private static final String V_1_0_0 = "1.0.0";
12+
private static final String V_2_0_0 = "2.0.0";
13+
private static final String V_1_9_9 = "1.9.9";
14+
private static final String V_3_0_0 = "3.0.0";
15+
private static final String V_2_5_6 = "2.5.6";
16+
private static final String V_1_2_0 = "1.2.0";
17+
private static final String V_1_1_9 = "1.1.9";
18+
private static final String V_1_3 = "1.3";
19+
private static final String V_1_2_9 = "1.2.9";
20+
private static final String V_1_0_1 = "1.0.1";
21+
private static final String V_1_0_5 = "1.0.5";
22+
private static final String V_1_0_4 = "1.0.4";
23+
private static final String V_1_0 = "1.0";
24+
private static final String V_1_0_0_SNAPSHOT = "1.0.0-SNAPSHOT";
25+
private static final String V_1_0_1_RC1 = "1.0.1-RC1";
26+
private static final String V_1_A_0 = "1.a.0";
27+
private static final String V_X_Y_Z = "x.y.z";
28+
29+
@Test
30+
void testEqualVersions() {
31+
assertEquals(0, VersionCompare.compare(V_1_0_0, V_1_0_0));
32+
assertFalse(VersionCompare.isGreaterThan(V_1_0_0, V_1_0_0));
33+
}
34+
35+
@Test
36+
void testGreaterMajorVersion() {
37+
assertTrue(VersionCompare.isGreaterThan(V_2_0_0, V_1_9_9));
38+
assertEquals(1, VersionCompare.compare(V_3_0_0, V_2_5_6));
39+
}
40+
41+
@Test
42+
void testGreaterMinorVersion() {
43+
assertTrue(VersionCompare.isGreaterThan(V_1_2_0, V_1_1_9));
44+
assertEquals(1, VersionCompare.compare(V_1_3, V_1_2_9));
45+
}
46+
47+
@Test
48+
void testGreaterPatchVersion() {
49+
assertTrue(VersionCompare.isGreaterThan(V_1_0_1, V_1_0_0));
50+
assertEquals(1, VersionCompare.compare(V_1_0_5, V_1_0_4));
51+
}
52+
53+
@Test
54+
void testVersionWithDifferentLength() {
55+
assertEquals(0, VersionCompare.compare(V_1_0, V_1_0_0));
56+
assertTrue(VersionCompare.isGreaterThan(V_1_0_1, V_1_0));
57+
assertFalse(VersionCompare.isGreaterThan(V_1_0, V_1_0_1));
58+
}
59+
60+
@Test
61+
void testVersionWithQualifierSuffix() {
62+
assertEquals(0, VersionCompare.compare(V_1_0_0_SNAPSHOT, V_1_0_0));
63+
assertTrue(VersionCompare.isGreaterThan(V_1_0_1_RC1, V_1_0_0));
64+
}
65+
66+
@Test
67+
void testInvalidVersionShouldThrowException() {
68+
assertThrows(NumberFormatException.class, () -> VersionCompare.compare(V_1_A_0, V_1_0_0));
69+
assertThrows(NumberFormatException.class, () -> VersionCompare.compare(V_1_0, V_X_Y_Z));
70+
}
71+
72+
}

0 commit comments

Comments
 (0)