Skip to content

Commit

Permalink
Implement the "complement" and "isNotEmpty" methods. Provide examples…
Browse files Browse the repository at this point in the history
… in the Javadoc for the "intersect", "union", and "difference" methods.
  • Loading branch information
baron1405 committed Jun 28, 2024
1 parent 9e8f0ee commit ea9a154
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
72 changes: 71 additions & 1 deletion src/main/java/org/cthing/versionparser/VersionConstraint.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ public boolean isEmpty() {
return this.ranges.isEmpty();
}

/**
* Indicates whether this constraint contains any versions.
*
* @return {@code true} if this constraint contains at least one version.
*/
public boolean isNotEmpty() {
return !this.ranges.isEmpty();
}

/**
* Indicates whether this constraint allows all versions.
*
Expand Down Expand Up @@ -175,7 +184,7 @@ public boolean isSingleVersion() {
* @return {@code true} if the specified version is allowed by this constraint.
*/
public boolean allows(final Version version) {
return !isEmpty() && this.ranges.stream().anyMatch(range -> range.allows(version));
return isNotEmpty() && this.ranges.stream().anyMatch(range -> range.allows(version));
}

/**
Expand Down Expand Up @@ -245,6 +254,21 @@ public boolean allowsAny(final VersionConstraint other) {

/**
* Creates a constraint that only allows versions allowed by both this and the specified constraints.
* The following examples show the intersection of this constraint T and the specified constraint C:
* <pre>
* T = [] C = [] T &#8745; C = []
* T = [] C = (,) T &#8745; C = []
* T = [1.5] C = [] T &#8745; C = []
* T = [1.5,2.0] C = [1.7] T &#8745; C = [1.7]
* T = [1.5,2.0] C = [1.6,1.9] T &#8745; C = [1.6,1.9]
* T = [1.5,) C = [1.2,1.8] T &#8745; C = [1.5,1.8]
* T = (,3.0) C = (,1.8] T &#8745; C = (,1.8]
* T = [1.5,2.0) C = [1.6],[1.8] T &#8745; C = [1.6],[1.8]
* T = [1.5,2.0),[3.0,4.0) C = [] T &#8745; C = []
* T = [1.5,2.0),[3.0,4.0) C = [1.6,1.6] T &#8745; C = [1.6,1.6]
* T = [1.5,2.0),[3.0,4.0) C = [1.6,1.8] T &#8745; C = [1.6,1.8]
* T = [1.5,2.0),[3.0,4.0) C = [1.6,1.8],[3.2,3.4] T &#8745; C = [1.6,1.8],[3.2,3.4]
* </pre>
*
* @param other Constraint to intersect with this constraint
* @return A new constraint that only allows versions allowed by both this and the specified constraints.
Expand Down Expand Up @@ -285,6 +309,21 @@ public VersionConstraint intersect(final VersionConstraint other) {

/**
* Creates a constraint that allows versions allowed by either this or the specified constraint.
* The following examples show the union of this constraint T and the specified constraint C:
* <pre>
* T = [] C = [] T &#8746; C = []
* T = [] C= (,) T &#8746; C = (,)
* T = [1.5] C = [] T &#8746; C = [1.5]
* T = [1.5] C = [1.5] T &#8746; C = [1.5]
* T = [1.5] C = [1.6] T &#8746; C = [1.5],[1.6]
* T = [1.5,1.7) C = [1.6] T &#8746; C = [1.5,1.7)
* T = (1.5,) C = [1.3,2.0] T &#8746; C = [1.3,)
* T = (,1.7] C = [1.5,2.0] T &#8746; C = (,2.0]
* T = (,) C = [1.5,2.0] T &#8746; C = (,)
* T = [1.2,2.0) C = (,) T &#8746; C = (,)
* T = (1.0,2.0) C = (2.0,3.0) T &#8746; C = (1.0,2.0),(2.0,3.0)
* T = [1.5,2.0),[3.0,4.0) C = [1.6,1.6] T &#8746; C = [1.5,2.0),[3.0,4.0)
* </pre>
*
* @param other Constraint to for a union with this constraint
* @return A new constraint that allows versions allowed by either this or the specified constraint.
Expand Down Expand Up @@ -327,6 +366,20 @@ public VersionConstraint union(final VersionConstraint other) {

/**
* Creates a constraint that allows versions allowed by this constraint but not by the specified constraint.
* The following examples show the difference between this constraint T and the specified constraint C:
* <pre>
* T = [1.5] C = [] T - C = [1.5]
* T = [1.5] C = [1.5] T - C = []
* T = [1.2,2.0) C = [1.5,1.5] T - C = [1.2,1.5),(1.5,2.0)
* T = [1.2,2.0) C = [1.2,1.2] T - C = (1.2,2.0)
* T = [1.2,2.0) C = (,) T - C = []
* T = [1.2,2.0) C = [1.5,1.5],[1.7,1.7] T - C = [1.2,1.5),(1.5,1.7),(1.7,2.0)
* T = [1.5],[2.0,3.0) C = [] T - C = [1.5],[2.0,3.0)
* T = [1.5],[2.0,3.0) C = [1.5,1.5] T - C = [2.0,3.0)
* T = [1.0,3.0),(4.0,6.0) C = [2.0],[7.0,8.0) T - C = [1.0,2.0),(2.0,3.0),(4.0,6.0)
* T = [] C = [] T - C = []
* T = [] C = [1.2,2.0) T - C = []
* </pre>
*
* @param other Constraint to form the difference with this constraint
* @return A new constraint that allows versions allowed by this constraint but not by the specified constraint.
Expand Down Expand Up @@ -433,6 +486,23 @@ public VersionConstraint difference(final VersionConstraint other) {
return differenceRanges.isEmpty() ? EMPTY : new VersionConstraint(differenceRanges);
}

/**
* Creates a constraint that is the complement of this constraint. The following examples show the constraint C
* and its complement C':
* <pre>
* C = [] C' = (,)
* C = [1.5] C' = (,1.5),(1.5,)
* C = [1.2,2.0) C' = (,1.2),[2.0,)
* C = [1.5],[2.0,3.0) C' = (,1.5),(1.5,2.0),[3.0,)
* C = [1.5],[2.0,3.0),[4.0,7.0) C' = (,1.5),(1.5,2.0),[3.0,4.0),[7.0,)
* </pre>
*
* @return Complement of this constraint.
*/
public VersionConstraint complement() {
return ANY.difference(this);
}

@Override
public boolean equals(final Object obj) {
if (this == obj) {
Expand Down
33 changes: 33 additions & 0 deletions src/test/java/org/cthing/versionparser/VersionConstraintTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class VersionConstraintTest {
@Test
public void testAny() throws VersionParsingException {
assertThat(ANY.isEmpty()).isFalse();
assertThat(ANY.isNotEmpty()).isTrue();
assertThat(ANY.isAny()).isTrue();
assertThat(ANY.isWeak()).isFalse();
assertThat(ANY.isSingleVersion()).isFalse();
Expand All @@ -45,6 +46,7 @@ public void testEmpty() {
when(constraint.isEmpty()).thenReturn(true);

assertThat(EMPTY.isEmpty()).isTrue();
assertThat(EMPTY.isNotEmpty()).isFalse();
assertThat(EMPTY.isAny()).isFalse();
assertThat(EMPTY.isWeak()).isFalse();
assertThat(EMPTY.isSingleVersion()).isFalse();
Expand All @@ -63,13 +65,15 @@ public void testConstructionSingleVersion() {

VersionConstraint constraint = new VersionConstraint(version);
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isFalse();
assertThat(constraint.isSingleVersion()).isTrue();
assertThat(constraint).hasToString("[1.2.3]");

constraint = new VersionConstraint(version, true);
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isTrue();
assertThat(constraint.isSingleVersion()).isTrue();
Expand All @@ -82,6 +86,7 @@ public void testConstructionSingleRange() {
final Version version2 = version("3.0");
VersionConstraint constraint = new VersionConstraint(version1, version2, true, false);
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isFalse();
assertThat(constraint.isSingleVersion()).isFalse();
Expand All @@ -90,13 +95,15 @@ public void testConstructionSingleRange() {
final Version version3 = version("1.2.3");
constraint = new VersionConstraint(version3, version3, false, false);
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isFalse();
assertThat(constraint.isSingleVersion()).isFalse();
assertThat(constraint).hasToString("(1.2.3,1.2.3)");

constraint = new VersionConstraint(version3, version3, false, false, true);
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isTrue();
assertThat(constraint.isSingleVersion()).isFalse();
Expand All @@ -111,20 +118,23 @@ public void testConstructionMultipleRanges() {

VersionConstraint constraint = new VersionConstraint(List.of(range2, range1));
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isFalse();
assertThat(constraint.isSingleVersion()).isFalse();
assertThat(constraint).hasToString("[1.5,2.0),(3.0,5.0)");

constraint = new VersionConstraint(List.of(range2, range1), true);
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isTrue();
assertThat(constraint.isSingleVersion()).isFalse();
assertThat(constraint).hasToString("[1.5,2.0),(3.0,5.0)");

constraint = new VersionConstraint(List.of(range3));
assertThat(constraint.isEmpty()).isFalse();
assertThat(constraint.isNotEmpty()).isTrue();
assertThat(constraint.isAny()).isFalse();
assertThat(constraint.isWeak()).isFalse();
assertThat(constraint.isSingleVersion()).isTrue();
Expand Down Expand Up @@ -304,6 +314,11 @@ public void testAllowsAny() throws VersionParsingException {

@Test
public void testIntersect() throws VersionParsingException {
assertThat(EMPTY.intersect(EMPTY)).isEmpty();
assertThat(EMPTY.intersect(ANY)).isEmpty();
assertThat(ANY.intersect(EMPTY)).isEmpty();
assertThat(ANY.intersect(ANY)).isAny();

assertThat(constraint("[1.5]").intersect(EMPTY)).isEmpty();

assertThat(constraint("[1.5]").intersect(constraint("[1.5]"))).isConstraint("[1.5]");
Expand Down Expand Up @@ -355,6 +370,11 @@ public void testIntersect() throws VersionParsingException {

@Test
public void testUnion() throws VersionParsingException {
assertThat(EMPTY.union(EMPTY)).isEmpty();
assertThat(EMPTY.union(ANY)).isAny();
assertThat(ANY.union(EMPTY)).isAny();
assertThat(ANY.union(ANY)).isAny();

assertThat(constraint("[1.5]").union(EMPTY)).isConstraint("[1.5]");

assertThat(constraint("[1.5]").union(constraint("[1.5]"))).isConstraint("[1.5]");
Expand Down Expand Up @@ -437,9 +457,22 @@ public void testDifference() throws VersionParsingException {
.isConstraint("[1.0,2.0),(2.0,3.0),(4.0,6.0)");

assertThat(EMPTY.difference(EMPTY)).isEmpty();
assertThat(EMPTY.difference(ANY)).isEmpty();
assertThat(ANY.difference(EMPTY)).isAny();
assertThat(EMPTY.difference(constraint("[1.2,2.0)"))).isEmpty();
}

@Test
public void testComplement() throws VersionParsingException {
assertThat(EMPTY.complement()).isEqualTo(ANY);
assertThat(ANY.complement()).isEqualTo(EMPTY);
assertThat(constraint("[1.5]").complement()).isConstraint("(,1.5),(1.5,)");
assertThat(constraint("[1.2,2.0)").complement()).isConstraint("(,1.2),[2.0,)");
assertThat(constraint("[1.5],[2.0,3.0)").complement()).isConstraint("(,1.5),(1.5,2.0),[3.0,)");
assertThat(constraint("[1.5],[2.0,3.0),[4.0,7.0)").complement())
.isConstraint("(,1.5),(1.5,2.0),[3.0,4.0),[7.0,)");
}

@Test
public void testEquality() {
final VersionConstraint constraint1 = new VersionConstraint(version("1.2.3"));
Expand Down

0 comments on commit ea9a154

Please sign in to comment.