Add contract annotations.

See #618
Original pull request: #625
This commit is contained in:
Christoph Strobl
2025-02-17 09:52:59 +01:00
committed by Mark Paluch
parent cf6e82df9d
commit af1e078374
7 changed files with 50 additions and 12 deletions

View File

@@ -20,6 +20,9 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;
/**
* Converter capable of transforming a given {@link Iterable} into a collection type.
*
@@ -36,7 +39,12 @@ public final class IterableConverter {
* @param source
* @return {@link Collections#emptyList()} when source is {@literal null}.
*/
public static <T> List<T> toList(Iterable<T> source) {
@Contract("_ -> !null")
public static <T> List<T> toList(@Nullable Iterable<T> source) {
if(source == null) {
return Collections.emptyList();
}
if (source instanceof List) {
return (List<T>) source;

View File

@@ -24,6 +24,7 @@ import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
import org.springframework.lang.Contract;
/**
* {@link QueryEngine} implementation specific for executing {@link Predicate} based {@link KeyValueQuery} against
@@ -78,6 +79,7 @@ public class PredicateQueryEngine extends QueryEngine<KeyValueAdapter, Predicate
return filterMatchingRange(tmp, criteria, offset, rows);
}
@Contract("!null, _, _, _ -> !null")
private static <S> List<S> filterMatchingRange(List<S> source, @Nullable Predicate<?> criteria, long offset, int rows) {
Stream<S> stream = source.stream();

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.lang.Contract;
/**
* {@link Comparator} implementation to compare objects based on a {@link PropertyPath}. This comparator obtains the
@@ -81,6 +82,7 @@ public class PropertyPathComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public PropertyPathComparator<@Nullable T> asc() {
this.asc = true;
return this;
@@ -91,6 +93,7 @@ public class PropertyPathComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public PropertyPathComparator<@Nullable T> desc() {
this.asc = false;
return this;
@@ -101,6 +104,7 @@ public class PropertyPathComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public PropertyPathComparator<@Nullable T> nullsFirst() {
this.nullsFirst = true;
return this;
@@ -111,6 +115,7 @@ public class PropertyPathComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public PropertyPathComparator<@Nullable T> nullsLast() {
this.nullsFirst = false;
return this;

View File

@@ -21,6 +21,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
/**
@@ -63,6 +64,7 @@ public class SpelPropertyComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public SpelPropertyComparator<@Nullable T> asc() {
this.asc = true;
return this;
@@ -73,6 +75,7 @@ public class SpelPropertyComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public SpelPropertyComparator<@Nullable T> desc() {
this.asc = false;
return this;
@@ -83,6 +86,7 @@ public class SpelPropertyComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public SpelPropertyComparator<@Nullable T> nullsFirst() {
this.nullsFirst = true;
return this;
@@ -93,6 +97,7 @@ public class SpelPropertyComparator<T> implements Comparator<T> {
*
* @return
*/
@Contract("-> this")
public SpelPropertyComparator<@Nullable T> nullsLast() {
this.nullsFirst = false;
return this;

View File

@@ -17,6 +17,7 @@ package org.springframework.data.keyvalue.core.query;
import org.jspecify.annotations.Nullable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
/**
@@ -143,6 +144,7 @@ public class KeyValueQuery<T> {
* @param sort must not be {@literal null}.
* @return
*/
@Contract("_ -> this")
public KeyValueQuery<T> orderBy(Sort sort) {
Assert.notNull(sort, "Sort must not be null");
@@ -161,6 +163,7 @@ public class KeyValueQuery<T> {
* @param offset
* @return
*/
@Contract("_ -> this")
public KeyValueQuery<T> skip(long offset) {
setOffset(offset);
@@ -173,6 +176,7 @@ public class KeyValueQuery<T> {
* @param rows
* @return
*/
@Contract("_ -> this")
public KeyValueQuery<T> limit(int rows) {
setRows(rows);
return this;

View File

@@ -35,6 +35,7 @@ import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.Part.IgnoreCaseType;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.lang.Contract;
import org.springframework.util.ObjectUtils;
/**
@@ -124,7 +125,8 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
return new ValueComparingPredicate(part.getProperty(), false);
}
public Predicate<Object> isEqualTo(Object value) {
@Contract("_ -> new")
public Predicate<Object> isEqualTo(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> {
if (!ObjectUtils.nullSafeEquals(IgnoreCaseType.NEVER, part.shouldIgnoreCase())) {
@@ -145,22 +147,27 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
return isNull().negate();
}
public Predicate<Object> isLessThan(Object value) {
@Contract("_ -> new")
public Predicate<Object> isLessThan(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) < 0);
}
public Predicate<Object> isLessThanEqual(Object value) {
@Contract("_ -> new")
public Predicate<Object> isLessThanEqual(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) <= 0);
}
public Predicate<Object> isGreaterThan(Object value) {
@Contract("_ -> new")
public Predicate<Object> isGreaterThan(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) > 0);
}
public Predicate<Object> isGreaterThanEqual(Object value) {
@Contract("_ -> new")
public Predicate<Object> isGreaterThanEqual(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) >= 0);
}
@Contract("!null -> new")
public Predicate<Object> matches(Pattern pattern) {
return new ValueComparingPredicate(part.getProperty(), o -> {
@@ -172,7 +179,8 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
});
}
public Predicate<Object> matches(Object value) {
@Contract("_ -> new")
public Predicate<Object> matches(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> {
if (o == null || value == null) {
@@ -188,10 +196,12 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
});
}
@Contract("!null -> new")
public Predicate<Object> matches(String regex) {
return matches(Pattern.compile(regex));
}
@Contract("!null -> new")
public Predicate<Object> in(Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> {
@@ -207,11 +217,11 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
return ObjectUtils.containsElement(ObjectUtils.toObjectArray(value), value);
}
return false;
});
}
public Predicate<Object> contains(Object value) {
@Contract("_ -> new")
public Predicate<Object> contains(@Nullable Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> {
@@ -245,6 +255,7 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
});
}
@Contract("!null -> new")
public Predicate<Object> startsWith(Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> {
@@ -261,6 +272,7 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
}
@Contract("!null -> new")
public Predicate<Object> endsWith(Object value) {
return new ValueComparingPredicate(part.getProperty(), o -> {
@@ -281,13 +293,13 @@ public class PredicateQueryCreator extends AbstractQueryCreator<KeyValueQuery<Pr
static class ValueComparingPredicate implements Predicate<Object> {
private final PropertyPath path;
private final Function<Object, Boolean> check;
private final Function<@Nullable Object, Boolean> check;
public ValueComparingPredicate(PropertyPath path, Object expected) {
public ValueComparingPredicate(PropertyPath path, @Nullable Object expected) {
this(path, (value) -> ObjectUtils.nullSafeEquals(value, expected));
}
public ValueComparingPredicate(PropertyPath path, Function<Object, Boolean> check) {
public ValueComparingPredicate(PropertyPath path, Function<@Nullable Object, Boolean> check) {
this.path = path;
this.check = check;
}

View File

@@ -22,6 +22,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.querydsl.QSort;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import com.querydsl.core.types.Expression;
@@ -52,6 +53,7 @@ abstract class KeyValueQuerydslUtils {
* @param builder must not be {@literal null}.
* @return empty {@code OrderSpecifier<?>[]} when sort is {@literal null}.
*/
@Contract("!null, !null -> new")
static OrderSpecifier<?>[] toOrderSpecifier(Sort sort, PathBuilder<?> builder) {
Assert.notNull(sort, "Sort must not be null");