diff --git a/src/main/java/org/springframework/data/keyvalue/core/IterableConverter.java b/src/main/java/org/springframework/data/keyvalue/core/IterableConverter.java index 23527eb..5a32b3d 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/IterableConverter.java +++ b/src/main/java/org/springframework/data/keyvalue/core/IterableConverter.java @@ -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 List toList(Iterable source) { + @Contract("_ -> !null") + public static List toList(@Nullable Iterable source) { + + if(source == null) { + return Collections.emptyList(); + } if (source instanceof List) { return (List) source; diff --git a/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java b/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java index b8bb755..1577a7a 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java +++ b/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java @@ -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 !null") private static List filterMatchingRange(List source, @Nullable Predicate criteria, long offset, int rows) { Stream stream = source.stream(); diff --git a/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java b/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java index ff28cb3..ce2c121 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java @@ -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 implements Comparator { * * @return */ + @Contract("-> this") public PropertyPathComparator<@Nullable T> asc() { this.asc = true; return this; @@ -91,6 +93,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ + @Contract("-> this") public PropertyPathComparator<@Nullable T> desc() { this.asc = false; return this; @@ -101,6 +104,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ + @Contract("-> this") public PropertyPathComparator<@Nullable T> nullsFirst() { this.nullsFirst = true; return this; @@ -111,6 +115,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ + @Contract("-> this") public PropertyPathComparator<@Nullable T> nullsLast() { this.nullsFirst = false; return this; diff --git a/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java b/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java index 3aafcf0..5e3d4d1 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java @@ -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 implements Comparator { * * @return */ + @Contract("-> this") public SpelPropertyComparator<@Nullable T> asc() { this.asc = true; return this; @@ -73,6 +75,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ + @Contract("-> this") public SpelPropertyComparator<@Nullable T> desc() { this.asc = false; return this; @@ -83,6 +86,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ + @Contract("-> this") public SpelPropertyComparator<@Nullable T> nullsFirst() { this.nullsFirst = true; return this; @@ -93,6 +97,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ + @Contract("-> this") public SpelPropertyComparator<@Nullable T> nullsLast() { this.nullsFirst = false; return this; diff --git a/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java b/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java index 0cf1a3f..9931d45 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java +++ b/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java @@ -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 { * @param sort must not be {@literal null}. * @return */ + @Contract("_ -> this") public KeyValueQuery orderBy(Sort sort) { Assert.notNull(sort, "Sort must not be null"); @@ -161,6 +163,7 @@ public class KeyValueQuery { * @param offset * @return */ + @Contract("_ -> this") public KeyValueQuery skip(long offset) { setOffset(offset); @@ -173,6 +176,7 @@ public class KeyValueQuery { * @param rows * @return */ + @Contract("_ -> this") public KeyValueQuery limit(int rows) { setRows(rows); return this; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java b/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java index a1b6361..efb4ff9 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java @@ -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 isEqualTo(Object value) { + @Contract("_ -> new") + public Predicate 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 isLessThan(Object value) { + @Contract("_ -> new") + public Predicate isLessThan(@Nullable Object value) { return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) < 0); } - public Predicate isLessThanEqual(Object value) { + @Contract("_ -> new") + public Predicate isLessThanEqual(@Nullable Object value) { return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) <= 0); } - public Predicate isGreaterThan(Object value) { + @Contract("_ -> new") + public Predicate isGreaterThan(@Nullable Object value) { return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) > 0); } - public Predicate isGreaterThanEqual(Object value) { + @Contract("_ -> new") + public Predicate isGreaterThanEqual(@Nullable Object value) { return new ValueComparingPredicate(part.getProperty(), o -> comparator().compare(o, value) >= 0); } + @Contract("!null -> new") public Predicate matches(Pattern pattern) { return new ValueComparingPredicate(part.getProperty(), o -> { @@ -172,7 +179,8 @@ public class PredicateQueryCreator extends AbstractQueryCreator matches(Object value) { + @Contract("_ -> new") + public Predicate matches(@Nullable Object value) { return new ValueComparingPredicate(part.getProperty(), o -> { if (o == null || value == null) { @@ -188,10 +196,12 @@ public class PredicateQueryCreator extends AbstractQueryCreator new") public Predicate matches(String regex) { return matches(Pattern.compile(regex)); } + @Contract("!null -> new") public Predicate in(Object value) { return new ValueComparingPredicate(part.getProperty(), o -> { @@ -207,11 +217,11 @@ public class PredicateQueryCreator extends AbstractQueryCreator contains(Object value) { + @Contract("_ -> new") + public Predicate contains(@Nullable Object value) { return new ValueComparingPredicate(part.getProperty(), o -> { @@ -245,6 +255,7 @@ public class PredicateQueryCreator extends AbstractQueryCreator new") public Predicate startsWith(Object value) { return new ValueComparingPredicate(part.getProperty(), o -> { @@ -261,6 +272,7 @@ public class PredicateQueryCreator extends AbstractQueryCreator new") public Predicate endsWith(Object value) { return new ValueComparingPredicate(part.getProperty(), o -> { @@ -281,13 +293,13 @@ public class PredicateQueryCreator extends AbstractQueryCreator { private final PropertyPath path; - private final Function 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 check) { + public ValueComparingPredicate(PropertyPath path, Function<@Nullable Object, Boolean> check) { this.path = path; this.check = check; } diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueQuerydslUtils.java b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueQuerydslUtils.java index e2d256b..7e41e3d 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueQuerydslUtils.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueQuerydslUtils.java @@ -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");