diff --git a/api/src/main/java/jakarta/data/metamodel/Attribute.java b/api/src/main/java/jakarta/data/metamodel/Attribute.java index 220c501a0..c5963091a 100644 --- a/api/src/main/java/jakarta/data/metamodel/Attribute.java +++ b/api/src/main/java/jakarta/data/metamodel/Attribute.java @@ -22,6 +22,7 @@ import java.util.Set; import jakarta.data.Sort; +import jakarta.data.metamodel.Restrict.BasicRestriction; import jakarta.data.metamodel.Restriction.Operator; /** @@ -31,16 +32,16 @@ */ public interface Attribute { - default Restriction.Single equal(V value) { - return new Restriction.Single<>(name(), Operator.EQUAL, value); + default BasicRestriction equal(V value) { + return new BasicRestriction<>(name(), Operator.EQUAL, value); } - default Restriction.Single> in(@SuppressWarnings("unchecked") V... values) { - return new Restriction.Single<>(name(), Operator.IN, Set.of(values)); + default BasicRestriction> in(@SuppressWarnings("unchecked") V... values) { + return new BasicRestriction<>(name(), Operator.IN, Set.of(values)); } - default Restriction.Single isNull() { - return new Restriction.Single<>(name(), Operator.EQUAL, null); + default BasicRestriction isNull() { + return new BasicRestriction<>(name(), Operator.EQUAL, null); } /** @@ -51,15 +52,15 @@ default Restriction.Single isNull() { */ String name(); - default Restriction.Single not(V value) { - return new Restriction.Single<>(name(), NOT, Operator.EQUAL, value); + default BasicRestriction not(V value) { + return new BasicRestriction<>(name(), NOT, Operator.EQUAL, value); } - default Restriction.Single> notIn(@SuppressWarnings("unchecked") V... values) { - return new Restriction.Single<>(name(), NOT, Operator.IN, Set.of(values)); + default BasicRestriction> notIn(@SuppressWarnings("unchecked") V... values) { + return new BasicRestriction<>(name(), NOT, Operator.IN, Set.of(values)); } - default Restriction.Single notNull() { - return new Restriction.Single<>(name(), NOT, Operator.EQUAL, null); + default BasicRestriction notNull() { + return new BasicRestriction<>(name(), NOT, Operator.EQUAL, null); } } diff --git a/api/src/main/java/jakarta/data/metamodel/Restrict.java b/api/src/main/java/jakarta/data/metamodel/Restrict.java index d77d6c940..0ef5d8ebc 100644 --- a/api/src/main/java/jakarta/data/metamodel/Restrict.java +++ b/api/src/main/java/jakarta/data/metamodel/Restrict.java @@ -29,14 +29,49 @@ public enum Restrict { @SafeVarargs static Restriction all(Restriction... restrictions) { - return new Restriction.Multiple<>(All, List.of(restrictions)); + return new CompositeRestriction<>(All, List.of(restrictions)); } @SafeVarargs static Restriction any(Restriction... restrictions) { - return new Restriction.Multiple<>(Any, List.of(restrictions)); + return new CompositeRestriction<>(Any, List.of(restrictions)); } // TODO Need to think more about how to best cover negation of multiple // and then make negation of Single consistent with it + + // The following are internal implementation classes. + // The proper way for users to obtain instances is via the static metamodel. + + record BasicRestriction( + String field, + boolean negated, + Operator comparison, + boolean ignoreCase, + V value) implements Restriction.Basic { + + BasicRestriction(String field, boolean negated, Operator comparison, V value) { + this(field, negated, comparison, false, value); + } + + BasicRestriction(String field, Operator comparison, V value) { + this(field, false, comparison, false, value); + } + + BasicRestriction(String field, Operator comparison, boolean ignoreCase, V value) { + this(field, false, comparison, ignoreCase, value); + } + } + + record CompositeRestriction( + Restrict type, + List> restrictions, + boolean negated) implements Restriction.Composite { + + CompositeRestriction( + Restrict type, + List> restrictions) { + this(type, restrictions, false); + } + } } diff --git a/api/src/main/java/jakarta/data/metamodel/Restriction.java b/api/src/main/java/jakarta/data/metamodel/Restriction.java index d0fb8ffa0..f58fbad98 100644 --- a/api/src/main/java/jakarta/data/metamodel/Restriction.java +++ b/api/src/main/java/jakarta/data/metamodel/Restriction.java @@ -20,40 +20,33 @@ import java.util.List; public interface Restriction { - record Multiple( - Restrict type, - List> list) implements Restriction { + interface Basic extends Restriction { + Operator comparison(); + + String field(); + + boolean ignoreCase(); + + boolean negated(); + + V value(); } - record Single( - String name, - boolean negated, - Operator comparison, - boolean ignoreCase, - V value) implements Restriction { - Single(String name, boolean negated, Operator comparison, V value) { - this(name, negated, comparison, false, value); - } - - Single(String name, Operator comparison, V value) { - this(name, false, comparison, false, value); - } - - Single(String name, Operator comparison, boolean ignoreCase, V value) { - this(name, false, comparison, ignoreCase, value); - } + interface Composite extends Restriction { + List> restrictions(); + + Restrict type(); + + boolean negated(); } enum Operator { - CONTAINS, - ENDS_WITH, EQUAL, GREATER_THAN, GREATER_THAN_EQUAL, IN, LESS_THAN, LESS_THAN_EQUAL, - LIKE, - STARTS_WITH + LIKE } } diff --git a/api/src/main/java/jakarta/data/metamodel/SortableAttribute.java b/api/src/main/java/jakarta/data/metamodel/SortableAttribute.java index a57168bb5..bde4607ed 100644 --- a/api/src/main/java/jakarta/data/metamodel/SortableAttribute.java +++ b/api/src/main/java/jakarta/data/metamodel/SortableAttribute.java @@ -18,6 +18,7 @@ package jakarta.data.metamodel; import jakarta.data.Sort; +import jakarta.data.metamodel.Restrict.BasicRestriction; import jakarta.data.metamodel.Restriction.Operator; /** @@ -50,19 +51,19 @@ public interface SortableAttribute extends Attribute { */ Sort desc(); - default Restriction.Single greaterThan(V value) { - return new Restriction.Single<>(name(), Operator.GREATER_THAN, value); + default BasicRestriction greaterThan(V value) { + return new BasicRestriction<>(name(), Operator.GREATER_THAN, value); } - default Restriction.Single greaterThanEqual(V value) { - return new Restriction.Single<>(name(), Operator.GREATER_THAN_EQUAL, value); + default BasicRestriction greaterThanEqual(V value) { + return new BasicRestriction<>(name(), Operator.GREATER_THAN_EQUAL, value); } - default Restriction.Single lessThan(V value) { - return new Restriction.Single<>(name(), Operator.LESS_THAN, value); + default BasicRestriction lessThan(V value) { + return new BasicRestriction<>(name(), Operator.LESS_THAN, value); } - default Restriction.Single lessThanEqual(V value) { - return new Restriction.Single<>(name(), Operator.LESS_THAN_EQUAL, value); + default BasicRestriction lessThanEqual(V value) { + return new BasicRestriction<>(name(), Operator.LESS_THAN_EQUAL, value); } } diff --git a/api/src/main/java/jakarta/data/metamodel/TextAttribute.java b/api/src/main/java/jakarta/data/metamodel/TextAttribute.java index bc8119bc2..664df8706 100644 --- a/api/src/main/java/jakarta/data/metamodel/TextAttribute.java +++ b/api/src/main/java/jakarta/data/metamodel/TextAttribute.java @@ -21,6 +21,7 @@ import static jakarta.data.metamodel.Restrict.NOT; import jakarta.data.Sort; +import jakarta.data.metamodel.Restrict.BasicRestriction; import jakarta.data.metamodel.Restriction.Operator; /** @@ -37,12 +38,12 @@ public interface TextAttribute extends SortableAttribute { */ Sort ascIgnoreCase(); - default Restriction.Single contains(String pattern) { - return new Restriction.Single<>(name(), Operator.CONTAINS, pattern); + default BasicRestriction contains(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, '%' + pattern + '%'); } - default Restriction.Single containsIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), Operator.CONTAINS, IGNORE_CASE, pattern); + default BasicRestriction containsIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, IGNORE_CASE, '%' + pattern + '%'); } /** @@ -52,68 +53,68 @@ default Restriction.Single containsIgnoreCase(String pattern) { */ Sort descIgnoreCase(); - default Restriction.Single endsWith(String pattern) { - return new Restriction.Single<>(name(), Operator.ENDS_WITH, pattern); + default BasicRestriction endsWith(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, '%' + pattern); } - default Restriction.Single endsWithIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), Operator.ENDS_WITH, IGNORE_CASE, pattern); + default BasicRestriction endsWithIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, IGNORE_CASE, '%' + pattern); } - default Restriction.Single equalIgnoreCase(String value) { - return new Restriction.Single<>(name(), Operator.EQUAL, IGNORE_CASE, value); + default BasicRestriction equalIgnoreCase(String value) { + return new BasicRestriction<>(name(), Operator.EQUAL, IGNORE_CASE, value); } - default Restriction.Single like(String pattern) { - return new Restriction.Single<>(name(), Operator.LIKE, pattern); + default BasicRestriction like(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, pattern); } - default Restriction.Single likeIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), Operator.LIKE, IGNORE_CASE, pattern); + default BasicRestriction likeIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, IGNORE_CASE, pattern); } - default Restriction.Single notContains(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.CONTAINS, pattern); + default BasicRestriction notContains(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, '%' + pattern + '%'); } - default Restriction.Single notContainsIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.CONTAINS, IGNORE_CASE, pattern); + default BasicRestriction notContainsIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, IGNORE_CASE, '%' + pattern + '%'); } - default Restriction.Single notEndsWith(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.ENDS_WITH, pattern); + default BasicRestriction notEndsWith(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, '%' + pattern); } - default Restriction.Single notEndsWithIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.ENDS_WITH, IGNORE_CASE, pattern); + default BasicRestriction notEndsWithIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, IGNORE_CASE, '%' + pattern); } - default Restriction.Single notIgnoreCase(String value) { - return new Restriction.Single<>(name(), NOT, Operator.EQUAL, IGNORE_CASE, value); + default BasicRestriction notIgnoreCase(String value) { + return new BasicRestriction<>(name(), NOT, Operator.EQUAL, IGNORE_CASE, value); } - default Restriction.Single notLike(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.LIKE, pattern); + default BasicRestriction notLike(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, pattern); } - default Restriction.Single notLikeIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.LIKE, IGNORE_CASE, pattern); + default BasicRestriction notLikeIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, IGNORE_CASE, pattern); } - default Restriction.Single notStartsWith(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.STARTS_WITH, pattern); + default BasicRestriction notStartsWith(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, pattern + '%'); } - default Restriction.Single notStartsWithIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), NOT, Operator.STARTS_WITH, IGNORE_CASE, pattern); + default BasicRestriction notStartsWithIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), NOT, Operator.LIKE, IGNORE_CASE, pattern + '%'); } - default Restriction.Single startsWith(String pattern) { - return new Restriction.Single<>(name(), Operator.STARTS_WITH, pattern); + default BasicRestriction startsWith(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, pattern + '%'); } - default Restriction.Single startsWithIgnoreCase(String pattern) { - return new Restriction.Single<>(name(), Operator.STARTS_WITH, IGNORE_CASE, pattern); + default BasicRestriction startsWithIgnoreCase(String pattern) { + return new BasicRestriction<>(name(), Operator.LIKE, IGNORE_CASE, pattern + '%'); } }