Skip to content

Case insensitive Constraints via ignoreCase method per Constraint subtype that can support it #1006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@
*/
package jakarta.data.metamodel;

import jakarta.data.metamodel.constraint.Between;
import jakarta.data.metamodel.constraint.Constraint;
import jakarta.data.metamodel.constraint.EqualTo;
import jakarta.data.metamodel.constraint.GreaterThan;
import jakarta.data.metamodel.constraint.GreaterThanOrEqual;
import jakarta.data.metamodel.constraint.LessThan;
import jakarta.data.metamodel.constraint.LessThanOrEqual;
import jakarta.data.metamodel.constraint.Like;
import jakarta.data.metamodel.constraint.NotBetween;
import jakarta.data.metamodel.constraint.NotEqualTo;
import jakarta.data.metamodel.constraint.NotLike;
import jakarta.data.metamodel.restrict.TextRestriction;

import java.util.Objects;
Expand All @@ -31,7 +41,40 @@ record TextRestrictionRecord<T>(String attribute, Constraint<String> constraint)
}

@Override
public TextRestrictionRecord<T> negate() {
public TextRestriction<T> ignoreCase() {
// TODO: Use a switch statement after we move up to Java 21 minimum
Constraint<String> caseIgnoringConstraint;
if (constraint instanceof Like) {
caseIgnoringConstraint = ((Like) constraint).ignoreCase();
} else if (constraint instanceof NotLike) {
caseIgnoringConstraint = ((NotLike) constraint).ignoreCase();
} else if (constraint instanceof EqualTo) {
caseIgnoringConstraint = ((EqualTo<String>) constraint).ignoreCase();
} else if (constraint instanceof NotEqualTo) {
caseIgnoringConstraint = ((NotEqualTo<String>) constraint).ignoreCase();
} else if (constraint instanceof Between) {
caseIgnoringConstraint = ((Between<String>) constraint).ignoreCase();
} else if (constraint instanceof NotBetween) {
caseIgnoringConstraint = ((NotBetween<String>) constraint).ignoreCase();
} else if (constraint instanceof GreaterThan) {
caseIgnoringConstraint = ((GreaterThan<String>) constraint).ignoreCase();
} else if (constraint instanceof GreaterThanOrEqual) {
caseIgnoringConstraint = ((GreaterThanOrEqual<String>) constraint).ignoreCase();
} else if (constraint instanceof LessThan) {
caseIgnoringConstraint = ((LessThan<String>) constraint).ignoreCase();
} else if (constraint instanceof LessThanOrEqual) {
caseIgnoringConstraint = ((LessThanOrEqual<String>) constraint).ignoreCase();
} else {
throw new UnsupportedOperationException(
"Cannot ignore case of a " +
constraint.getClass().getInterfaces()[0].getName() + " constraint");
}

return new TextRestrictionRecord<>(attribute, caseIgnoringConstraint);
}

@Override
public TextRestriction<T> negate() {
return new TextRestrictionRecord<>(attribute, constraint.negate());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ static <T extends Comparable<T>> Between<T> bounds(T lower, T upper) {
return new BetweenRecord<>(lower, upper);
}

Between<T> ignoreCase();

boolean isCaseSensitive();

T lowerBound();
T upperBound();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,40 @@

import java.util.Objects;

record BetweenRecord<T extends Comparable<T>>(T lowerBound, T upperBound)
implements Between<T> {
record BetweenRecord<T extends Comparable<T>>(
T lowerBound,
T upperBound,
boolean isCaseSensitive) implements Between<T> {

public BetweenRecord {
Objects.requireNonNull(lowerBound);
Objects.requireNonNull(upperBound);
}

@Override
public String toString() {
return "BETWEEN " + lowerBound + " AND " + upperBound;
BetweenRecord(T lowerBound, T upperBound) {
this(lowerBound, upperBound, lowerBound instanceof String);
}

@Override
public boolean equals(Object obj) {
return obj instanceof BetweenRecord<?> that
&& lowerBound.equals(that.lowerBound)
&& upperBound.equals(that.upperBound);
public Between<T> ignoreCase() {
if (!(lowerBound instanceof String)) {
throw new UnsupportedOperationException(
"Cannot ignore case of a " + lowerBound.getClass().getName() +
" typed attribute");
}
return new BetweenRecord<>(lowerBound, upperBound, false);
}

@Override
public int hashCode() {
return Objects.hash(lowerBound, upperBound);
public String toString() {
return lowerBound instanceof String
? "BETWEEN '" + lowerBound + "' AND '" + upperBound + "'" +
(isCaseSensitive ? "" : " IGNORE CASE")
: "BETWEEN " + lowerBound + " AND " + upperBound;
}

@Override
public NotBetween<T> negate() {
return NotBetween.bounds(lowerBound, upperBound);
return new NotBetweenRecord<>(lowerBound, upperBound, isCaseSensitive);
}
}
22 changes: 11 additions & 11 deletions api/src/main/java/jakarta/data/metamodel/constraint/Constraint.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public interface Constraint<T> {

static <T> Constraint<T> equalTo(T value) {
return new EqualToRecord<>(value);
return EqualTo.value(value);
}

@SafeVarargs
Expand All @@ -38,24 +38,24 @@ static <T> Constraint<T> isNull() {
return new NullRecord<>();
}

static <T extends Comparable<T>> Constraint<T> greaterThan(T bound) {
return new GreaterThanRecord<>(bound);
static <T extends Comparable<T>> GreaterThan<T> greaterThan(T bound) {
return GreaterThan.bound(bound);
}

static <T extends Comparable<T>> Constraint<T> lessThan(T bound) {
return new LessThanRecord<>(bound);
static <T extends Comparable<T>> LessThan<T> lessThan(T bound) {
return LessThan.bound(bound);
}

static <T extends Comparable<T>> Constraint<T> greaterThanOrEqual(T bound) {
return new GreaterThanOrEqualRecord<>(bound);
static <T extends Comparable<T>> GreaterThanOrEqual<T> greaterThanOrEqual(T bound) {
return GreaterThanOrEqual.min(bound);
}

static <T extends Comparable<T>> Constraint<T> lessThanOrEqual(T bound) {
return new LessThanOrEqualRecord<>(bound);
static <T extends Comparable<T>> LessThanOrEqual<T> lessThanOrEqual(T bound) {
return LessThanOrEqual.max(bound);
}

static <T extends Comparable<T>> Constraint<T> between(T lowerBound, T upperBound) {
return new BetweenRecord<>(lowerBound, upperBound);
static <T extends Comparable<T>> Between<T> between(T lowerBound, T upperBound) {
return Between.bounds(lowerBound, upperBound);
}

Constraint<T> negate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ static <T> EqualTo<T> value(T value) {
return new EqualToRecord<>(value);
}

EqualTo<T> ignoreCase();

boolean isCaseSensitive();

T value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,34 @@

import java.util.Objects;

record EqualToRecord<T>(T value) implements EqualTo<T> {
record EqualToRecord<T>(T value, boolean isCaseSensitive) implements EqualTo<T> {
public EqualToRecord {
Objects.requireNonNull(value, "Value must not be null");
}

@Override
public NotEqualTo<T> negate() {
return NotEqualTo.value(value);
EqualToRecord(T value) {
this(value, value instanceof String);
}

@Override
public String toString() {
return value instanceof String ? "= '" + value + "'" : "= " + value.toString();
public EqualTo<T> ignoreCase() {
if (!(value instanceof String)) {
throw new UnsupportedOperationException(
"Cannot ignore case of a " + value.getClass().getName() +
" typed attribute");
}
return new EqualToRecord<>(value, false);
}

@Override
public boolean equals(Object obj) {
return obj instanceof EqualToRecord<?> that
&& value.equals(that.value);
public NotEqualTo<T> negate() {
return new NotEqualToRecord<>(value, isCaseSensitive);
}

@Override
public int hashCode() {
return value.hashCode();
public String toString() {
return value instanceof String
? "= '" + value + (isCaseSensitive ? "'" : "' IGNORE CASE")
: "= " + value.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ static <T extends Comparable<T>> GreaterThan<T> bound(T lowerBound) {
return new GreaterThanRecord<>(lowerBound);
}

GreaterThan<T> ignoreCase();

T bound();

boolean isCaseSensitive();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ static <T extends Comparable<T>> GreaterThanOrEqual<T> min(T minimum) {
return new GreaterThanOrEqualRecord<>(minimum);
}

GreaterThanOrEqual<T> ignoreCase();

T bound();

boolean isCaseSensitive();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,34 @@

import java.util.Objects;

record GreaterThanOrEqualRecord<T extends Comparable<T>>(T bound)
record GreaterThanOrEqualRecord<T extends Comparable<T>>(T bound, boolean isCaseSensitive)
implements GreaterThanOrEqual<T> {
public GreaterThanOrEqualRecord {
Objects.requireNonNull(bound, "Lower bound must not be null");
}

@Override
public LessThan<T> negate() {
return LessThan.bound(bound);
GreaterThanOrEqualRecord(T bound) {
this(bound, bound instanceof String);
}

@Override
public String toString() {
return ">= " + bound.toString();
public GreaterThanOrEqual<T> ignoreCase() {
if (!(bound instanceof String)) {
throw new UnsupportedOperationException(
"Cannot ignore case of a " + bound.getClass().getName() +
" typed attribute");
}
return new GreaterThanOrEqualRecord<>(bound, false);
}

@Override
public boolean equals(Object obj) {
return obj instanceof GreaterThanOrEqualRecord<?> that
&& bound.equals(that.bound);
public LessThan<T> negate() {
return new LessThanRecord<>(bound, isCaseSensitive);
}

@Override
public int hashCode() {
return bound.hashCode();
}
public String toString() {
return bound instanceof String
? ">= '" + bound + (isCaseSensitive ? "'" : "' IGNORE CASE")
: ">= " + bound; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,35 @@

import java.util.Objects;

record GreaterThanRecord<T extends Comparable<T>>(T bound)
record GreaterThanRecord<T extends Comparable<T>>(T bound, boolean isCaseSensitive)
implements GreaterThan<T> {
public GreaterThanRecord {
Objects.requireNonNull(bound, "Lower bound must not be null");
}

@Override
public LessThanOrEqual<T> negate() {
return LessThanOrEqual.max(bound);
GreaterThanRecord(T bound) {
this(bound, bound instanceof String);
}

@Override
public String toString() {
return "> " + bound.toString();
public GreaterThan<T> ignoreCase() {
if (!(bound instanceof String)) {
throw new UnsupportedOperationException(
"Cannot ignore case of a " + bound.getClass().getName() +
" typed attribute");
}
return new GreaterThanRecord<>(bound, false);
}

@Override
public boolean equals(Object obj) {
return obj instanceof GreaterThanRecord<?> that
&& bound.equals(that.bound);
public LessThanOrEqual<T> negate() {
return new LessThanOrEqualRecord<>(bound, isCaseSensitive);
}

@Override
public int hashCode() {
return bound.hashCode();
public String toString() {
return bound instanceof String
? "> '" + bound + (isCaseSensitive ? "'" : "' IGNORE CASE")
: "> " + bound;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ static <T extends Comparable<T>> LessThan<T> bound(T upperBound) {
return new LessThanRecord<>(upperBound);
}

LessThan<T> ignoreCase();

T bound();

boolean isCaseSensitive();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ static <T extends Comparable<T>> LessThanOrEqual<T> max(T maximum) {
return new LessThanOrEqualRecord<>(maximum);
}

LessThanOrEqual<T> ignoreCase();

T bound();

boolean isCaseSensitive();
}
Loading