diff --git a/api/src/main/java/jakarta/data/BasicRestriction.java b/api/src/main/java/jakarta/data/BasicRestriction.java index f7c3b167..0cc17338 100644 --- a/api/src/main/java/jakarta/data/BasicRestriction.java +++ b/api/src/main/java/jakarta/data/BasicRestriction.java @@ -22,5 +22,8 @@ public interface BasicRestriction extends Restriction { String field(); + @Override + BasicRestriction negate(); + Object value(); } diff --git a/api/src/main/java/jakarta/data/BasicRestrictionRecord.java b/api/src/main/java/jakarta/data/BasicRestrictionRecord.java index e58ca18f..dfedc845 100644 --- a/api/src/main/java/jakarta/data/BasicRestrictionRecord.java +++ b/api/src/main/java/jakarta/data/BasicRestrictionRecord.java @@ -25,7 +25,6 @@ record BasicRestrictionRecord( String field, - boolean isNegated, Operator comparison, Object value) implements BasicRestriction { @@ -33,7 +32,11 @@ record BasicRestrictionRecord( Objects.requireNonNull(field, "Field must not be null"); } - BasicRestrictionRecord(String field, Operator comparison, Object value) { - this(field, false, comparison, value); + @Override + public BasicRestriction negate() { + return new BasicRestrictionRecord<>( + field, + comparison.negate(), + value); } } diff --git a/api/src/main/java/jakarta/data/CompositeRestriction.java b/api/src/main/java/jakarta/data/CompositeRestriction.java index 1eeffbf9..5c5a8ab6 100644 --- a/api/src/main/java/jakarta/data/CompositeRestriction.java +++ b/api/src/main/java/jakarta/data/CompositeRestriction.java @@ -20,6 +20,11 @@ import java.util.List; public interface CompositeRestriction extends Restriction { + boolean isNegated(); + + @Override + CompositeRestriction negate(); + List> restrictions(); Type type(); diff --git a/api/src/main/java/jakarta/data/CompositeRestrictionRecord.java b/api/src/main/java/jakarta/data/CompositeRestrictionRecord.java index a8cd5e0f..40b8d612 100644 --- a/api/src/main/java/jakarta/data/CompositeRestrictionRecord.java +++ b/api/src/main/java/jakarta/data/CompositeRestrictionRecord.java @@ -38,4 +38,9 @@ record CompositeRestrictionRecord( CompositeRestrictionRecord(Type type, List> restrictions) { this(type, restrictions, false); } + + @Override + public CompositeRestriction negate() { + return new CompositeRestrictionRecord<>(type, restrictions, !isNegated); + } } \ No newline at end of file diff --git a/api/src/main/java/jakarta/data/Operator.java b/api/src/main/java/jakarta/data/Operator.java index a8d448c8..003357ef 100644 --- a/api/src/main/java/jakarta/data/Operator.java +++ b/api/src/main/java/jakarta/data/Operator.java @@ -24,5 +24,28 @@ public enum Operator { IN, LESS_THAN, LESS_THAN_EQUAL, - LIKE + LIKE, + NOT_EQUAL, + NOT_IN, + NOT_LIKE; + + /** + * Returns the operator that is the negation of this operator. + * + * @return the operator that is the negation of this operator. + */ + Operator negate() { + return switch (this) { + case EQUAL -> NOT_EQUAL; + case GREATER_THAN -> LESS_THAN_EQUAL; + case GREATER_THAN_EQUAL -> LESS_THAN; + case IN -> NOT_IN; + case LESS_THAN -> GREATER_THAN_EQUAL; + case LESS_THAN_EQUAL -> GREATER_THAN; + case LIKE -> NOT_LIKE; + case NOT_EQUAL -> EQUAL; + case NOT_IN -> IN; + case NOT_LIKE -> LIKE; + }; + } } diff --git a/api/src/main/java/jakarta/data/Restrict.java b/api/src/main/java/jakarta/data/Restrict.java index 96b24d8e..c9e402ad 100644 --- a/api/src/main/java/jakarta/data/Restrict.java +++ b/api/src/main/java/jakarta/data/Restrict.java @@ -18,6 +18,7 @@ package jakarta.data; import java.util.List; +import java.util.Objects; import java.util.Set; // TODO document @@ -31,7 +32,6 @@ public class Restrict { // used internally for more readable code private static final boolean ESCAPED = true; - private static final boolean NOT = true; private static final char STRING_WILDCARD = '%'; @@ -132,30 +132,36 @@ public static TextRestriction like(String pattern, return new TextRestrictionRecord<>(field, Operator.LIKE, ESCAPED, p); } + // convenience method for those who would prefer to avoid .negate() + public static Restriction not(Restriction restriction) { + Objects.requireNonNull(restriction, "Restriction must not be null"); + return restriction.negate(); + } + public static Restriction notEqualTo(Object value, String field) { - return new BasicRestrictionRecord<>(field, NOT, Operator.EQUAL, value); + return new BasicRestrictionRecord<>(field, Operator.NOT_EQUAL, value); } public static TextRestriction notEqualTo(String value, String field) { - return new TextRestrictionRecord<>(field, NOT, Operator.EQUAL, value); + return new TextRestrictionRecord<>(field, Operator.NOT_EQUAL, value); } public static TextRestriction notContains(String substring, String field) { String pattern = toLikeEscaped(CHAR_WILDCARD, STRING_WILDCARD, true, substring, true); - return new TextRestrictionRecord<>(field, NOT, Operator.LIKE, ESCAPED, pattern); + return new TextRestrictionRecord<>(field, Operator.NOT_LIKE, ESCAPED, pattern); } public static TextRestriction notEndsWith(String suffix, String field) { String pattern = toLikeEscaped(CHAR_WILDCARD, STRING_WILDCARD, true, suffix, false); - return new TextRestrictionRecord<>(field, NOT, Operator.LIKE, ESCAPED, pattern); + return new TextRestrictionRecord<>(field, Operator.NOT_LIKE, ESCAPED, pattern); } public static Restriction notIn(Set values, String field) { - return new BasicRestrictionRecord<>(field, NOT, Operator.IN, values); + return new BasicRestrictionRecord<>(field, Operator.NOT_IN, values); } public static TextRestriction notLike(String pattern, String field) { - return new TextRestrictionRecord<>(field, NOT, Operator.LIKE, pattern); + return new TextRestrictionRecord<>(field, Operator.NOT_LIKE, pattern); } public static TextRestriction notLike(String pattern, @@ -163,12 +169,12 @@ public static TextRestriction notLike(String pattern, char stringWildcard, String field) { String p = toLikeEscaped(charWildcard, stringWildcard, false, pattern, false); - return new TextRestrictionRecord<>(field, NOT, Operator.LIKE, ESCAPED, p); + return new TextRestrictionRecord<>(field, Operator.NOT_LIKE, ESCAPED, p); } public static TextRestriction notStartsWith(String prefix, String field) { String pattern = toLikeEscaped(CHAR_WILDCARD, STRING_WILDCARD, false, prefix, true); - return new TextRestrictionRecord<>(field, NOT, Operator.LIKE, ESCAPED, pattern); + return new TextRestrictionRecord<>(field, Operator.NOT_LIKE, ESCAPED, pattern); } public static TextRestriction startsWith(String prefix, String field) { diff --git a/api/src/main/java/jakarta/data/Restriction.java b/api/src/main/java/jakarta/data/Restriction.java index 0548fb4f..91504c71 100644 --- a/api/src/main/java/jakarta/data/Restriction.java +++ b/api/src/main/java/jakarta/data/Restriction.java @@ -18,5 +18,5 @@ package jakarta.data; public interface Restriction { - boolean isNegated(); + Restriction negate(); } diff --git a/api/src/main/java/jakarta/data/TextRestriction.java b/api/src/main/java/jakarta/data/TextRestriction.java index b6c9850c..d1a44fa8 100644 --- a/api/src/main/java/jakarta/data/TextRestriction.java +++ b/api/src/main/java/jakarta/data/TextRestriction.java @@ -18,7 +18,7 @@ package jakarta.data; public interface TextRestriction extends BasicRestriction { - Restriction ignoreCase(); + TextRestriction ignoreCase(); // TODO can mention in the JavaDoc that a value of true will be ignored // if the database is not not capable of case sensitive comparisons @@ -26,6 +26,9 @@ public interface TextRestriction extends BasicRestriction { boolean isEscaped(); + @Override + TextRestriction negate(); + @Override String value(); } diff --git a/api/src/main/java/jakarta/data/TextRestrictionRecord.java b/api/src/main/java/jakarta/data/TextRestrictionRecord.java index 831fec41..c957860e 100644 --- a/api/src/main/java/jakarta/data/TextRestrictionRecord.java +++ b/api/src/main/java/jakarta/data/TextRestrictionRecord.java @@ -25,7 +25,6 @@ record TextRestrictionRecord( String field, - boolean isNegated, Operator comparison, boolean isCaseSensitive, boolean isEscaped, @@ -35,24 +34,27 @@ record TextRestrictionRecord( Objects.requireNonNull(field, "Field must not be null"); } - TextRestrictionRecord(String field, boolean negated, Operator comparison, boolean escaped, String value) { - this(field, negated, comparison, true, escaped, value); - } - - TextRestrictionRecord(String field, boolean negated, Operator comparison, String value) { - this(field, negated, comparison, true, false, value); - } - TextRestrictionRecord(String field, Operator comparison, boolean escaped, String value) { - this(field, false, comparison, true, escaped, value); + this(field, comparison, true, escaped, value); } TextRestrictionRecord(String field, Operator comparison, String value) { - this(field, false, comparison, true, false, value); + this(field, comparison, true, false, value); + } + + @Override + public TextRestriction ignoreCase() { + return new TextRestrictionRecord<>(field, comparison, false, isEscaped, value); } @Override - public Restriction ignoreCase() { - return new TextRestrictionRecord<>(field, isNegated, comparison, false, isEscaped, value); + public TextRestriction negate() { + + return new TextRestrictionRecord<>( + field, + comparison.negate(), + isCaseSensitive, + isEscaped, + value); } } diff --git a/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java b/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java index c46bfb0d..e0c3c2c1 100644 --- a/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java +++ b/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java @@ -24,6 +24,9 @@ class BasicRestrictionRecordTest { + // A mock entity class for tests + static class Book { + } @Test void shouldCreateBasicRestrictionWithDefaultNegation() { @@ -31,7 +34,6 @@ void shouldCreateBasicRestrictionWithDefaultNegation() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("title"); - soft.assertThat(restriction.isNegated()).isFalse(); soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); soft.assertThat(restriction.value()).isEqualTo("Java Guide"); }); @@ -39,12 +41,13 @@ void shouldCreateBasicRestrictionWithDefaultNegation() { @Test void shouldCreateBasicRestrictionWithExplicitNegation() { - BasicRestrictionRecord restriction = new BasicRestrictionRecord<>("title", true, Operator.EQUAL, "Java Guide"); + BasicRestriction restriction = + (BasicRestriction) Restrict.equalTo("Java Guide", "title") + .negate(); SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("title"); - soft.assertThat(restriction.isNegated()).isTrue(); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_EQUAL); soft.assertThat(restriction.value()).isEqualTo("Java Guide"); }); } @@ -56,21 +59,63 @@ void shouldCreateBasicRestrictionWithNullValue() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("title"); - soft.assertThat(restriction.isNegated()).isFalse(); soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); soft.assertThat(restriction.value()).isNull(); }); } + @Test + void shouldNegateLTERestriction() { + Restriction numChaptersLTE10 = Restrict.lessThanEqual(10, "numChapters"); + BasicRestriction numChaptersLTE10Basic = (BasicRestriction) numChaptersLTE10; + BasicRestriction numChaptersGT10Basic = (BasicRestriction) numChaptersLTE10Basic.negate(); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(numChaptersLTE10Basic.comparison()).isEqualTo(Operator.LESS_THAN_EQUAL); + soft.assertThat(numChaptersLTE10Basic.value()).isEqualTo(10); + + soft.assertThat(numChaptersGT10Basic.comparison()).isEqualTo(Operator.GREATER_THAN); + soft.assertThat(numChaptersGT10Basic.value()).isEqualTo(10); + }); + } + + @Test + void shouldNegateNegatedRestriction() { + Restriction titleRestriction = + Restrict.equalTo("A Developer's Guide to Jakarta Data", "title"); + BasicRestriction titleRestrictionBasic = + (BasicRestriction) titleRestriction; + BasicRestriction negatedTitleRestrictionBasic = + (BasicRestriction) titleRestriction.negate(); + BasicRestriction negatedNegatedTitleRestrictionBasic = + (BasicRestriction) negatedTitleRestrictionBasic.negate(); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(titleRestrictionBasic.comparison()) + .isEqualTo(Operator.EQUAL); + soft.assertThat(titleRestrictionBasic.value()) + .isEqualTo("A Developer's Guide to Jakarta Data"); + + soft.assertThat(negatedTitleRestrictionBasic.comparison()) + .isEqualTo(Operator.NOT_EQUAL); + soft.assertThat(negatedTitleRestrictionBasic.value()) + .isEqualTo("A Developer's Guide to Jakarta Data"); + + soft.assertThat(negatedNegatedTitleRestrictionBasic.comparison()) + .isEqualTo(Operator.EQUAL); + soft.assertThat(negatedNegatedTitleRestrictionBasic.value()) + .isEqualTo("A Developer's Guide to Jakarta Data"); + }); + } + @Test void shouldSupportNegatedRestrictionUsingDefaultConstructor() { - BasicRestrictionRecord restriction = new BasicRestrictionRecord<>("author", Operator.EQUAL, "Unknown"); - BasicRestrictionRecord negatedRestriction = new BasicRestrictionRecord<>(restriction.field(), true, restriction.comparison(), restriction.value()); + BasicRestriction negatedRestriction = + (BasicRestriction) Restrict.notEqualTo((Object) "Unknown", "author"); SoftAssertions.assertSoftly(soft -> { soft.assertThat(negatedRestriction.field()).isEqualTo("author"); - soft.assertThat(negatedRestriction.isNegated()).isTrue(); - soft.assertThat(negatedRestriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(negatedRestriction.comparison()).isEqualTo(Operator.NOT_EQUAL); soft.assertThat(negatedRestriction.value()).isEqualTo("Unknown"); }); } diff --git a/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java b/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java index 79764f64..67e3f9df 100644 --- a/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java +++ b/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java @@ -27,7 +27,9 @@ class CompositeRestrictionRecordTest { - + // A mock entity class for tests + static class Person { + } @Test void shouldCreateCompositeRestrictionWithDefaultNegation() { @@ -71,6 +73,44 @@ void shouldFailIfEmptyRestrictions() { .hasMessage("Cannot create a composite restriction without any restrictions to combine."); } + @Test + void shouldNegateCompositeRestriction() { + Restriction ageLessThan50 = Restrict.lessThan(50, "age"); + Restriction nameStartsWithDuke = Restrict.startsWith("Duke ", "name"); + CompositeRestriction all = + (CompositeRestriction) Restrict.all(ageLessThan50, nameStartsWithDuke); + CompositeRestriction allNegated = all.negate(); + CompositeRestriction notAll = + (CompositeRestriction) Restrict.not(all); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(all.isNegated()).isEqualTo(false); + + soft.assertThat(allNegated.isNegated()).isEqualTo(true); + + soft.assertThat(notAll.isNegated()).isEqualTo(true); + }); + } + + @Test + void shouldNegateNegatedCompositeRestriction() { + Restriction ageBetween20and30 = Restrict.between(20, 30, "age"); + Restriction nameContainsDuke = Restrict.contains("Duke", "name"); + CompositeRestriction any = + (CompositeRestriction) Restrict.any(ageBetween20and30, nameContainsDuke); + CompositeRestriction anyNegated = any.negate(); + CompositeRestriction anyNotNegated = + (CompositeRestriction) Restrict.not(anyNegated); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(any.isNegated()).isEqualTo(false); + + soft.assertThat(anyNegated.isNegated()).isEqualTo(true); + + soft.assertThat(anyNotNegated.isNegated()).isEqualTo(false); + }); + } + @Test void shouldPreserveRestrictionsOrder() { Restriction restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide"); diff --git a/api/src/test/java/jakarta/data/RestrictTest.java b/api/src/test/java/jakarta/data/RestrictTest.java index d2914e08..04113be8 100644 --- a/api/src/test/java/jakarta/data/RestrictTest.java +++ b/api/src/test/java/jakarta/data/RestrictTest.java @@ -37,7 +37,6 @@ void shouldCreateEqualToRestriction() { soft.assertThat(basic.field()).isEqualTo("field"); soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); soft.assertThat(basic.value()).isEqualTo("value"); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -50,9 +49,8 @@ void shouldCreateNotEqualToRestriction() { TextRestrictionRecord basic = (TextRestrictionRecord) restriction; SoftAssertions.assertSoftly(soft -> { soft.assertThat(basic.field()).isEqualTo("field"); - soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(basic.comparison()).isEqualTo(Operator.NOT_EQUAL); soft.assertThat(basic.value()).isEqualTo("value"); - soft.assertThat(basic.isNegated()).isTrue(); }); } @@ -81,7 +79,6 @@ void shouldCreateContainsRestriction() { soft.assertThat(restriction.field()).isEqualTo("field"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); soft.assertThat(restriction.value()).isEqualTo("%substring%"); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -91,9 +88,8 @@ void shouldCreateNegatedContainsRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("field"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); soft.assertThat(restriction.value()).isEqualTo("%substring%"); - soft.assertThat(restriction.isNegated()).isTrue(); }); } @@ -105,7 +101,6 @@ void shouldCreateStartsWithRestriction() { soft.assertThat(restriction.field()).isEqualTo("field"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); soft.assertThat(restriction.value()).isEqualTo("prefix%"); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -115,9 +110,8 @@ void shouldCreateNegatedStartsWithRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("field"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); soft.assertThat(restriction.value()).isEqualTo("prefix%"); - soft.assertThat(restriction.isNegated()).isTrue(); }); } @@ -129,7 +123,6 @@ void shouldCreateEndsWithRestriction() { soft.assertThat(restriction.field()).isEqualTo("field"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); soft.assertThat(restriction.value()).isEqualTo("%suffix"); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -139,9 +132,8 @@ void shouldCreateNegatedEndsWithRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("field"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); soft.assertThat(restriction.value()).isEqualTo("%suffix"); - soft.assertThat(restriction.isNegated()).isTrue(); }); } diff --git a/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java b/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java index 5b7dcb2a..14b7f2b2 100644 --- a/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java +++ b/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java @@ -20,6 +20,8 @@ import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; +import jakarta.data.BasicRestrictionRecordTest.Book; + import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; @@ -35,7 +37,6 @@ void shouldCreateTextRestrictionWithDefaultValues() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("title"); - soft.assertThat(restriction.isNegated()).isFalse(); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); soft.assertThat(restriction.value()).isEqualTo("%Java%"); soft.assertThat(restriction.isCaseSensitive()).isTrue(); @@ -47,15 +48,13 @@ void shouldCreateTextRestrictionWithDefaultValues() { void shouldCreateTextRestrictionWithExplicitNegation() { TextRestrictionRecord restriction = new TextRestrictionRecord<>( "title", - true, - Operator.LIKE, + Operator.NOT_LIKE, "%Java%" ); SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("title"); - soft.assertThat(restriction.isNegated()).isTrue(); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); soft.assertThat(restriction.value()).isEqualTo("%Java%"); soft.assertThat(restriction.isCaseSensitive()).isTrue(); soft.assertThat(restriction.isEscaped()).isFalse(); @@ -76,7 +75,6 @@ void shouldIgnoreCaseForTextRestriction() { soft.assertThat(caseInsensitiveRestriction).isInstanceOf(TextRestrictionRecord.class); TextRestrictionRecord textRestriction = (TextRestrictionRecord) caseInsensitiveRestriction; soft.assertThat(textRestriction.field()).isEqualTo("title"); - soft.assertThat(textRestriction.isNegated()).isFalse(); soft.assertThat(textRestriction.comparison()).isEqualTo(Operator.LIKE); soft.assertThat(textRestriction.value()).isEqualTo("%Java%"); soft.assertThat(textRestriction.isCaseSensitive()).isFalse(); @@ -95,7 +93,6 @@ void shouldCreateTextRestrictionWithEscapedValue() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("title"); - soft.assertThat(restriction.isNegated()).isFalse(); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); soft.assertThat(restriction.value()).isEqualTo("%Java%"); soft.assertThat(restriction.isCaseSensitive()).isTrue(); @@ -103,19 +100,57 @@ void shouldCreateTextRestrictionWithEscapedValue() { }); } + @Test + void shouldNegateLikeRestriction() { + TextRestriction likeJakartaEE = Restrict.like("%Jakarta EE%", "title"); + TextRestriction notLikeJakartaEE = likeJakartaEE.negate(); + TextRestriction anyCaseNotLikeJakartaEE = likeJakartaEE.ignoreCase().negate(); + TextRestriction notLikeJakartaEEAnyCase = likeJakartaEE.negate().ignoreCase(); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(likeJakartaEE.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(likeJakartaEE.isCaseSensitive()).isTrue(); + + soft.assertThat(notLikeJakartaEE.comparison()).isEqualTo(Operator.NOT_LIKE); + soft.assertThat(notLikeJakartaEE.isCaseSensitive()).isTrue(); + + soft.assertThat(anyCaseNotLikeJakartaEE.comparison()).isEqualTo(Operator.NOT_LIKE); + soft.assertThat(anyCaseNotLikeJakartaEE.isCaseSensitive()).isFalse(); + + soft.assertThat(notLikeJakartaEEAnyCase.comparison()).isEqualTo(Operator.NOT_LIKE); + soft.assertThat(notLikeJakartaEEAnyCase.isCaseSensitive()).isFalse(); + }); + } + + @Test + void shouldNegateNegatedRestriction() { + TextRestriction endsWithJakartaEE = Restrict.endsWith("Jakarta EE", "title"); + TextRestriction notEndsWithJakartaEE = endsWithJakartaEE.negate(); + TextRestriction notNotEndsWithJakartaEE = notEndsWithJakartaEE.negate(); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(endsWithJakartaEE.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(endsWithJakartaEE.value()).isEqualTo("%Jakarta EE"); + + soft.assertThat(notEndsWithJakartaEE.comparison()).isEqualTo(Operator.NOT_LIKE); + soft.assertThat(notEndsWithJakartaEE.value()).isEqualTo("%Jakarta EE"); + + soft.assertThat(notNotEndsWithJakartaEE.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(notNotEndsWithJakartaEE.value()).isEqualTo("%Jakarta EE"); + }); + } + @Test void shouldSupportNegationForTextRestriction() { TextRestrictionRecord restriction = new TextRestrictionRecord<>( "author", - true, - Operator.EQUAL, + Operator.NOT_EQUAL, "John Doe" ); SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("author"); - soft.assertThat(restriction.isNegated()).isTrue(); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_EQUAL); soft.assertThat(restriction.value()).isEqualTo("John Doe"); soft.assertThat(restriction.isCaseSensitive()).isTrue(); soft.assertThat(restriction.isEscaped()).isFalse(); diff --git a/api/src/test/java/jakarta/data/metamodel/AttributeTest.java b/api/src/test/java/jakarta/data/metamodel/AttributeTest.java index f087674c..e1a962b9 100644 --- a/api/src/test/java/jakarta/data/metamodel/AttributeTest.java +++ b/api/src/test/java/jakarta/data/metamodel/AttributeTest.java @@ -40,7 +40,6 @@ void shouldCreateEqualToRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo("testValue"); soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -53,8 +52,7 @@ void shouldCreateNotEqualToRestriction() { BasicRestriction basic = (BasicRestriction) restriction; soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo("testValue"); - soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); - soft.assertThat(basic.isNegated()).isTrue(); + soft.assertThat(basic.comparison()).isEqualTo(Operator.NOT_EQUAL); }); } @@ -68,7 +66,6 @@ void shouldCreateInRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo(Set.of("value1", "value2")); soft.assertThat(basic.comparison()).isEqualTo(Operator.IN); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -88,8 +85,7 @@ void shouldCreateNotInRestriction() { BasicRestriction basic = (BasicRestriction) restriction; soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo(Set.of("value1", "value2")); - soft.assertThat(basic.comparison()).isEqualTo(Operator.IN); - soft.assertThat(basic.isNegated()).isTrue(); + soft.assertThat(basic.comparison()).isEqualTo(Operator.NOT_IN); }); } @@ -110,7 +106,6 @@ void shouldCreateIsNullRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isNull(); soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -123,8 +118,7 @@ void shouldCreateNotNullRestriction() { BasicRestriction basic = (BasicRestriction) restriction; soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isNull(); - soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); - soft.assertThat(basic.isNegated()).isTrue(); + soft.assertThat(basic.comparison()).isEqualTo(Operator.NOT_EQUAL); }); } } diff --git a/api/src/test/java/jakarta/data/metamodel/SortableAttributeTest.java b/api/src/test/java/jakarta/data/metamodel/SortableAttributeTest.java index 697284cd..fcc204ce 100644 --- a/api/src/test/java/jakarta/data/metamodel/SortableAttributeTest.java +++ b/api/src/test/java/jakarta/data/metamodel/SortableAttributeTest.java @@ -56,7 +56,6 @@ void shouldCreateGreaterThanRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo(10); soft.assertThat(basic.comparison()).isEqualTo(Operator.GREATER_THAN); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -70,7 +69,6 @@ void shouldCreateGreaterThanEqualRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo(10); soft.assertThat(basic.comparison()).isEqualTo(Operator.GREATER_THAN_EQUAL); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -84,7 +82,6 @@ void shouldCreateLessThanRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo(10); soft.assertThat(basic.comparison()).isEqualTo(Operator.LESS_THAN); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -98,7 +95,6 @@ void shouldCreateLessThanOrEqualRestriction() { soft.assertThat(basic.field()).isEqualTo("testAttribute"); soft.assertThat(basic.value()).isEqualTo(10); soft.assertThat(basic.comparison()).isEqualTo(Operator.LESS_THAN_EQUAL); - soft.assertThat(basic.isNegated()).isFalse(); }); } @@ -118,7 +114,6 @@ void shouldCreateBetweenRestriction() { soft.assertThat(lower.field()).isEqualTo("testAttribute"); soft.assertThat(lower.value()).isEqualTo(5); soft.assertThat(lower.comparison()).isEqualTo(Operator.GREATER_THAN_EQUAL); - soft.assertThat(lower.isNegated()).isFalse(); Restriction upperBound = composite.restrictions().get(1); soft.assertThat(upperBound).isInstanceOf(BasicRestriction.class); @@ -126,7 +121,6 @@ void shouldCreateBetweenRestriction() { soft.assertThat(upper.field()).isEqualTo("testAttribute"); soft.assertThat(upper.value()).isEqualTo(15); soft.assertThat(upper.comparison()).isEqualTo(Operator.LESS_THAN_EQUAL); - soft.assertThat(upper.isNegated()).isFalse(); }); } } diff --git a/api/src/test/java/jakarta/data/metamodel/TextAttributeTest.java b/api/src/test/java/jakarta/data/metamodel/TextAttributeTest.java index b14f15a7..453f509d 100644 --- a/api/src/test/java/jakarta/data/metamodel/TextAttributeTest.java +++ b/api/src/test/java/jakarta/data/metamodel/TextAttributeTest.java @@ -61,7 +61,6 @@ void shouldCreateContainsRestriction() { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("%testValue%"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -73,7 +72,6 @@ void shouldCreateStartsWithRestriction() { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("testValue%"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -85,7 +83,6 @@ void shouldCreateEndsWithRestriction() { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("%testValue"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -97,7 +94,6 @@ void shouldCreateLikeRestriction() { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("%test%"); soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isFalse(); }); } @@ -108,8 +104,7 @@ void shouldCreateNotContainsRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("%testValue%"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); }); } @@ -120,8 +115,7 @@ void shouldCreateNotLikeRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("%test%"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); }); } @@ -132,8 +126,7 @@ void shouldCreateNotStartsWithRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("testValue%"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); }); } @@ -144,8 +137,7 @@ void shouldCreateNotEndsWithRestriction() { SoftAssertions.assertSoftly(soft -> { soft.assertThat(restriction.field()).isEqualTo("testAttribute"); soft.assertThat(restriction.value()).isEqualTo("%testValue"); - soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); - soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.NOT_LIKE); }); } }