Skip to content

Commit

Permalink
Introduce VersionRange
Browse files Browse the repository at this point in the history
This introduces a predicate that can be used for comparing if given a version is contained inside a version range pattern
  • Loading branch information
gastaldi committed Jul 17, 2024
1 parent 7617780 commit 61748b0
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,7 @@ interface Messages {

@Message(id = 3010, value = "Build string may not be empty")
VersionSyntaxException emptyBuild();

@Message(id = 3011, value = "Invalid range pattern: %s")
VersionSyntaxException invalidRangePattern(String pattern);
}
61 changes: 61 additions & 0 deletions version/src/main/java/io/smallrye/common/version/VersionRange.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.smallrye.common.version;

import static io.smallrye.common.version.Messages.msg;

import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* A {@link VersionRange} is a predicate that tests if a version string is within a specified range.
*/
public class VersionRange implements Predicate<String> {

/**
* Range in format "[1.0,2.0)"
*/
private static final Pattern RANGE_PATTERN = Pattern.compile("([\\[\\(])(.*),(.*)([\\]\\)])");

private final VersionScheme versionScheme;
private final Bound lowerBound;
private final Bound upperBound;

public VersionRange(VersionScheme versionScheme, String rangePattern) {
this.versionScheme = versionScheme;
// Range pattern is in format "[1.0,2.0)"
Matcher matcher = RANGE_PATTERN.matcher(rangePattern);
if (!matcher.matches()) {
throw msg.invalidRangePattern(rangePattern);
}
this.lowerBound = new Bound(matcher.group(2), matcher.group(1).charAt(0) == '[');
this.upperBound = new Bound(matcher.group(3), matcher.group(4).charAt(0) == ']');
}

@Override
public boolean test(String s) {
if (lowerBound != null && !lowerBound.version.isBlank()) {
int comparison = versionScheme.compare(s, lowerBound.version);
if (comparison < 0 || (!lowerBound.inclusive && comparison == 0)) {
return false;
}
}
if (upperBound != null && !upperBound.version.isBlank()) {
int comparison = versionScheme.compare(s, upperBound.version);
if (comparison > 0 || (!upperBound.inclusive && comparison == 0)) {
return false;
}
}
return true;
}

private class Bound {

private final String version;
private final boolean inclusive;

public Bound(String version, boolean inclusive) {
this.version = version;
this.inclusive = inclusive;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.smallrye.common.version;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class VersionRangeTest {

@Test
void testVersionRangeWithInclusive() {
VersionRange versionRange = new VersionRange(VersionScheme.MAVEN, "[1.0,2.0]");
assertTrue(versionRange.test("1.0.0"));
assertTrue(versionRange.test("1.1.0"));
assertTrue(versionRange.test("1.899.0"));
assertTrue(versionRange.test("2.0"));
assertTrue(versionRange.test("2.0.0"));
assertFalse(versionRange.test("2.0.1"));
}

@Test
void testVersionRangeWithExclusive() {
VersionRange versionRange = new VersionRange(VersionScheme.MAVEN, "(1.0,2.0)");
assertFalse(versionRange.test("1.0.0"));
assertTrue(versionRange.test("1.1.0"));
assertTrue(versionRange.test("1.899.0"));
assertFalse(versionRange.test("2.0"));
assertFalse(versionRange.test("2.0.0"));
assertFalse(versionRange.test("2.0.1"));
}

@Test
void testVersionRangeWithLowerBoundExclusive() {
VersionRange versionRange = new VersionRange(VersionScheme.MAVEN, "(1.0,2.0]");
assertFalse(versionRange.test("1.0.0"));
assertTrue(versionRange.test("1.1.0"));
assertTrue(versionRange.test("1.899.0"));
assertTrue(versionRange.test("2.0"));
assertTrue(versionRange.test("2.0.0"));
assertFalse(versionRange.test("2.0.1"));
}

@Test
void testVersionRangeWithUpperBoundExclusive() {
VersionRange versionRange = new VersionRange(VersionScheme.MAVEN, "[1.0,2.0)");
assertTrue(versionRange.test("1.0.0"));
assertTrue(versionRange.test("1.1.0"));
assertTrue(versionRange.test("1.899.0"));
assertFalse(versionRange.test("2.0"));
assertFalse(versionRange.test("2.0.0"));
assertFalse(versionRange.test("2.0.1"));
}

@Test
public void testVersionRangeWithInvalidRangePattern() {
assertThrows(VersionSyntaxException.class, () -> new VersionRange(VersionScheme.MAVEN, "1.0,2.0"),
"Invalid range pattern: 1.0,2.0");
}
}

0 comments on commit 61748b0

Please sign in to comment.