diff --git a/src/main/java/com/suse/saltstack/netapi/datatypes/SaltVersion.java b/src/main/java/com/suse/saltstack/netapi/datatypes/SaltVersion.java new file mode 100644 index 000000000..547b8a4e4 --- /dev/null +++ b/src/main/java/com/suse/saltstack/netapi/datatypes/SaltVersion.java @@ -0,0 +1,152 @@ +package com.suse.saltstack.netapi.datatypes; + +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represents a salt version + */ +public class SaltVersion implements Comparable { + + private static Pattern SALT_VERSION_REGEX = + Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)([Rr][Cc](\\d+))?$"); + + private final int year; + private final int month; + private final int bugfix; + private final Optional releaseCandidate; + + /** + * Parses a salt version string + * @param versionString the salt version string + * @return SaltVersion if the versionString is valid or empty Optional if not. + */ + public static Optional parse(String versionString) { + Matcher matcher = SALT_VERSION_REGEX.matcher(versionString); + if (matcher.matches()) { + int year = Integer.parseInt(matcher.group(1)); + int month = Integer.parseInt(matcher.group(2)); + int bugfix = Integer.parseInt(matcher.group(3)); + Optional rc = Optional.ofNullable(matcher.group(5)) + .map(Integer::parseInt); + return Optional.of(new SaltVersion(year, month, bugfix, rc)); + } else { + return Optional.empty(); + } + } + + /** + * Creates a SaltVersion + * @param year Year of the release + * @param month Month of the release + * @param bugfix Bugfix number incremented withing a feature release + * @param releaseCandidate Optional release candidate tag + */ + public SaltVersion(int year, int month, int bugfix, + Optional releaseCandidate) { + this.year = year; + this.month = month; + this.bugfix = bugfix; + this.releaseCandidate = releaseCandidate; + } + + /** + * Creates a SaltVersion + * @param year Year of the release + * @param month Month of the release + * @param bugfix Bugfix number incremented withing a feature release + * @param releaseCandidate release candidate tag + */ + public SaltVersion(int year, int month, int bugfix, int releaseCandidate) { + this(year, month, bugfix, Optional.of(releaseCandidate)); + } + + /** + * Creates a SaltVersion without release candidate tag + * @param year Year of the release + * @param month Month of the release + * @param bugfix Bugfix number incremented withing a feature release + */ + public SaltVersion(int year, int month, int bugfix) { + this(year, month, bugfix, Optional.empty()); + } + + /** + * Getter for the release candidate of this SaltVersion + * + * @return the optional release candidate + */ + public Optional getReleaseCandidate() { + return releaseCandidate; + } + + /** + * Getter for the year of this SaltVersion + * + * @return the year + */ + public int getYear() { + return year; + } + + /** + * Getter for the month of this SaltVersion + * + * @return the month + */ + public int getMonth() { + return month; + } + + /** + * Getter for the bugfix of this SaltVersion + * + * @return the bugfix number + */ + public int getBugfix() { + return bugfix; + } + + @Override + public String toString() { + return getYear() + "." + getMonth() + "." + getBugfix() + getReleaseCandidate() + .map(rc -> "rc" + rc) + .orElse(""); + } + + @Override + public int compareTo(SaltVersion other) { + if (this == other) { + return 0; + } + + if (this.getYear() > other.getYear()) { + return 1; + } else if (this.getYear() < other.getYear()) { + return -1; + } + + if (this.getMonth() > other.getMonth()) { + return 1; + } else if (this.getMonth() < other.getMonth()) { + return -1; + } + + if (this.getBugfix() > other.getBugfix()) { + return 1; + } else if (this.getBugfix() < other.getBugfix()) { + return -1; + } + + return this.getReleaseCandidate().map(lhsRc -> + other.getReleaseCandidate() + .map(lhsRc::compareTo) + .orElse(-1) + ).orElseGet(() -> + other.getReleaseCandidate() + .map(rhsRc -> 1) + .orElse(0) + ); + } +} diff --git a/src/test/java/com/suse/saltstack/netapi/datatypes/SaltVersionTest.java b/src/test/java/com/suse/saltstack/netapi/datatypes/SaltVersionTest.java new file mode 100644 index 000000000..4b3a43f6b --- /dev/null +++ b/src/test/java/com/suse/saltstack/netapi/datatypes/SaltVersionTest.java @@ -0,0 +1,95 @@ +package com.suse.saltstack.netapi.datatypes; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import java.util.Optional; + + +/** + * SaltVersion class unit-tests. + */ +public class SaltVersionTest { + + @Test + public void testConstructor() { + SaltVersion v1 = new SaltVersion(2015, 8, 0); + + assertEquals(2015, v1.getYear()); + assertEquals(8, v1.getMonth()); + assertEquals(0, v1.getBugfix()); + assertFalse(v1.getReleaseCandidate().isPresent()); + + SaltVersion v1rc2 = new SaltVersion(2015, 8, 0, 2); + + assertEquals(2015, v1rc2.getYear()); + assertEquals(8, v1rc2.getMonth()); + assertEquals(0, v1rc2.getBugfix()); + assertTrue(v1rc2.getReleaseCandidate().map(rc -> rc == 2).orElse(false)); + } + + @Test + public void testParsing() { + SaltVersion v1rc2 = SaltVersion.parse("2015.8.0rc2").get(); + assertEquals(2015, v1rc2.getYear()); + assertEquals(8, v1rc2.getMonth()); + assertEquals(0, v1rc2.getBugfix()); + assertTrue(v1rc2.getReleaseCandidate().map(rc -> rc == 2).orElse(false)); + + SaltVersion v2 = SaltVersion.parse("2013.4.0").get(); + assertEquals(2013, v2.getYear()); + assertEquals(4, v2.getMonth()); + assertEquals(0, v2.getBugfix()); + assertFalse(v2.getReleaseCandidate().isPresent()); + + Optional v3 = SaltVersion.parse("2015.8.0r2"); + assertFalse(v3.isPresent()); + } + + @Test + public void testComparisonRC() { + SaltVersion v1 = new SaltVersion(2015, 8, 0); + SaltVersion v1rc1 = new SaltVersion(2015, 8, 0, 1); + SaltVersion v1rc2 = new SaltVersion(2015, 8, 0, 2); + assertTrue("A version with rc should be smaller then the same version without rc", + v1.compareTo(v1rc1) > 0 && v1rc1.compareTo(v1) < 0); + assertTrue("smaller rc number on the same version should make the version smaller", + v1rc1.compareTo(v1rc2) < 0 && v1rc2.compareTo(v1rc1) > 0); + } + + @Test + public void testComparisonYear() { + SaltVersion v1 = new SaltVersion(2016, 8, 0); + SaltVersion v2 = new SaltVersion(2015, 8, 0); + assertTrue("a smaller year should result in a smaller version", + v1.compareTo(v2) > 0 && v2.compareTo(v1) < 0); + } + + + @Test + public void testComparisonMonth() { + SaltVersion v1 = new SaltVersion(2015, 8, 0); + SaltVersion v2 = new SaltVersion(2015, 6, 0); + assertTrue("a smaller month should result in a smaller version", + v1.compareTo(v2) > 0 && v2.compareTo(v1) < 0); + } + + @Test + public void testComparisonBugfix() { + SaltVersion v1 = new SaltVersion(2015, 8, 3); + SaltVersion v2 = new SaltVersion(2015, 8, 1); + assertTrue("a smaller bugfix should result in a smaller version", + v1.compareTo(v2) > 0 && v2.compareTo(v1) < 0); + } + + @Test + public void testToString() { + SaltVersion v1 = new SaltVersion(2015, 8, 3); + SaltVersion v1rc2 = new SaltVersion(2015, 8, 0, 2); + assertEquals("2015.8.3", v1.toString()); + assertEquals("2015.8.0rc2", v1rc2.toString()); + } +}