Browse Source

Polishing.

Refactor duplicates, simplify placeholder unwrapping.

See #5123
Original pull request: #5124
5.0.x
Mark Paluch 3 weeks ago
parent
commit
7ab7d310da
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 33
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotPlaceholders.java
  2. 120
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotQueryCreator.java
  3. 30
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotStringQuery.java
  4. 3
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/DocumentSerializerUnitTests.java

33
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotPlaceholders.java

@ -53,7 +53,7 @@ class AotPlaceholders { @@ -53,7 +53,7 @@ class AotPlaceholders {
* @param type
* @return
*/
static Shape geoJson(int index, String type) {
static Placeholder geoJson(int index, String type) {
return new GeoJsonPlaceholder(index, type);
}
@ -63,7 +63,7 @@ class AotPlaceholders { @@ -63,7 +63,7 @@ class AotPlaceholders {
* @param index zero-based index referring to the bindable method parameter.
* @return
*/
static Point point(int index) {
static Placeholder point(int index) {
return new PointPlaceholder(index);
}
@ -73,7 +73,7 @@ class AotPlaceholders { @@ -73,7 +73,7 @@ class AotPlaceholders {
* @param index zero-based index referring to the bindable method parameter.
* @return
*/
static Shape circle(int index) {
static Placeholder circle(int index) {
return new CirclePlaceholder(index);
}
@ -83,7 +83,7 @@ class AotPlaceholders { @@ -83,7 +83,7 @@ class AotPlaceholders {
* @param index zero-based index referring to the bindable method parameter.
* @return
*/
static Shape box(int index) {
static Placeholder box(int index) {
return new BoxPlaceholder(index);
}
@ -93,7 +93,7 @@ class AotPlaceholders { @@ -93,7 +93,7 @@ class AotPlaceholders {
* @param index zero-based index referring to the bindable method parameter.
* @return
*/
static Shape sphere(int index) {
static Placeholder sphere(int index) {
return new SpherePlaceholder(index);
}
@ -103,7 +103,7 @@ class AotPlaceholders { @@ -103,7 +103,7 @@ class AotPlaceholders {
* @param index zero-based index referring to the bindable method parameter.
* @return
*/
static Shape polygon(int index) {
static Placeholder polygon(int index) {
return new PolygonPlaceholder(index);
}
@ -140,6 +140,17 @@ class AotPlaceholders { @@ -140,6 +140,17 @@ class AotPlaceholders {
interface Placeholder {
String getValue();
/**
* Unwrap the current {@link Placeholder} to the given target type if possible.
*
* @param targetType
* @return
* @param <T>
*/
default <T extends Placeholder> @Nullable T unwrap(Class<? extends T> targetType) {
return targetType.isInstance(this) ? targetType.cast(this) : null;
}
}
/**
@ -317,6 +328,16 @@ class AotPlaceholders { @@ -317,6 +328,16 @@ class AotPlaceholders {
record AsListPlaceholder(Placeholder placeholder) implements Placeholder {
@Override
public @Nullable <T extends Placeholder> T unwrap(Class<? extends T> targetType) {
if (targetType.isInstance(placeholder)) {
return targetType.cast(placeholder);
}
return Placeholder.super.unwrap(targetType);
}
@Override
public String toString() {
return getValue();

120
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotQueryCreator.java

@ -24,6 +24,7 @@ import java.util.regex.Pattern; @@ -24,6 +24,7 @@ import java.util.regex.Pattern;
import org.bson.conversions.Bson;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Range;
@ -61,7 +62,6 @@ import org.springframework.data.repository.query.parser.Part; @@ -61,7 +62,6 @@ import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.Part.IgnoreCaseType;
import org.springframework.data.repository.query.parser.Part.Type;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.ClassUtils;
import com.mongodb.DBRef;
@ -132,8 +132,8 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext @@ -132,8 +132,8 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext
return criteria.raw("$regex", param);
}
if (param instanceof AsListPlaceholder asListPlaceholder && !property.isCollectionLike()) {
return super.createContainingCriteria(part, property, criteria, asListPlaceholder.placeholder());
if (param instanceof AsListPlaceholder asList && !property.isCollectionLike()) {
return super.createContainingCriteria(part, property, criteria, asList.placeholder());
}
return super.createContainingCriteria(part, property, criteria, param);
@ -176,10 +176,11 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext @@ -176,10 +176,11 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext
@NullUnmarked
static class PlaceholderParameterAccessor implements MongoParameterAccessor {
private final List<Object> placeholders;
private final List<Placeholder> placeholders;
@Nullable
Part getPartForIndex(PartTree partTree, Parameter parameter) {
if (!parameter.isBindable()) {
return null;
}
@ -197,62 +198,74 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext @@ -197,62 +198,74 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext
public PlaceholderParameterAccessor(PartTree partTree, QueryMethod queryMethod) {
if (queryMethod.getParameters().getNumberOfParameters() == 0) {
Parameters<?, ?> parameters = queryMethod.getParameters();
if (parameters.getNumberOfParameters() == 0) {
placeholders = List.of();
} else {
placeholders = new ArrayList<>();
Parameters<?, ?> parameters = queryMethod.getParameters();
placeholders = new ArrayList<>(parameters.getNumberOfParameters());
for (Parameter parameter : parameters.toList()) {
if (ClassUtils.isAssignable(GeoJson.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.geoJson(parameter.getIndex(), ""));
} else if (ClassUtils.isAssignable(Point.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.point(parameter.getIndex()));
} else if (ClassUtils.isAssignable(Circle.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.circle(parameter.getIndex()));
} else if (ClassUtils.isAssignable(Box.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.box(parameter.getIndex()));
} else if (ClassUtils.isAssignable(Sphere.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.sphere(parameter.getIndex()));
} else if (ClassUtils.isAssignable(Polygon.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.polygon(parameter.getIndex()));
} else if (ClassUtils.isAssignable(Pattern.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.regex(parameter.getIndex(), null));
} else {
Part partForIndex = getPartForIndex(partTree, parameter);
if (partForIndex != null
&& (partForIndex.getType().equals(Type.LIKE) || partForIndex.getType().equals(Type.NOT_LIKE))) {
placeholders
.add(parameter.getIndex(),
AotPlaceholders
.regex(parameter.getIndex(),
partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS)
|| partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.WHEN_POSSIBLE) ? "i"
: null));
} else if (partForIndex != null && (partForIndex.getType().equals(Type.IN)
|| partForIndex.getType().equals(Type.NOT_IN) || partForIndex.getType().equals(Type.CONTAINING)
|| partForIndex.getType().equals(Type.NOT_CONTAINING))) {
if (partForIndex.getProperty().isCollection()
&& !TypeInformation.of(parameter.getType()).isCollectionLike()) {
if (partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS)) {
placeholders.add(parameter.getIndex(),
AotPlaceholders.asList(AotPlaceholders.regex(parameter.getIndex(), "i")));
} else {
placeholders.add(parameter.getIndex(), AotPlaceholders.asList(parameter.getIndex()));
}
} else {
placeholders.add(parameter.getIndex(), AotPlaceholders.indexed(parameter.getIndex()));
}
}
else {
placeholders.add(parameter.getIndex(), AotPlaceholders.indexed(parameter.getIndex()));
int index = parameter.getIndex();
placeholders.add(index, getPlaceholder(index, parameter, partTree));
}
}
}
private Placeholder getPlaceholder(int index, Parameter parameter, PartTree partTree) {
Class<?> type = parameter.getType();
if (GeoJson.class.isAssignableFrom(type)) {
return AotPlaceholders.geoJson(index, "");
} else if (Point.class.isAssignableFrom(type)) {
return AotPlaceholders.point(index);
} else if (Circle.class.isAssignableFrom(type)) {
return AotPlaceholders.circle(index);
} else if (Box.class.isAssignableFrom(type)) {
return AotPlaceholders.box(index);
} else if (Sphere.class.isAssignableFrom(type)) {
return AotPlaceholders.sphere(index);
} else if (Polygon.class.isAssignableFrom(type)) {
return AotPlaceholders.polygon(index);
} else if (Pattern.class.isAssignableFrom(type)) {
return AotPlaceholders.regex(index, null);
}
Part partForIndex = getPartForIndex(partTree, parameter);
if (partForIndex != null) {
IgnoreCaseType ignoreCaseType = partForIndex.shouldIgnoreCase();
if (isLike(partForIndex.getType())) {
boolean ignoreCase = !ignoreCaseType.equals(IgnoreCaseType.NEVER);
return AotPlaceholders.regex(index, ignoreCase ? "i" : null);
}
if (isContaining(partForIndex.getType())) {
if (partForIndex.getProperty().isCollection() && !TypeInformation.of(type).isCollectionLike()) {
if (ignoreCaseType.equals(IgnoreCaseType.ALWAYS)) {
return AotPlaceholders.asList(AotPlaceholders.regex(index, "i"));
} else {
return AotPlaceholders.asList(index);
}
}
return AotPlaceholders.indexed(index);
}
}
return AotPlaceholders.indexed(index);
}
private static boolean isContaining(Part.Type type) {
return type.equals(Type.IN) || type.equals(Type.NOT_IN) //
|| type.equals(Type.CONTAINING) || type.equals(Type.NOT_CONTAINING);
}
private static boolean isLike(Part.Type type) {
return type.equals(Type.LIKE) || type.equals(Type.NOT_LIKE);
}
@Override
@ -322,8 +335,7 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext @@ -322,8 +335,7 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext
@Override
public @Nullable Object getBindableValue(int index) {
return placeholders.get(index) instanceof Placeholder placeholder ? placeholder.getValue()
: placeholders.get(index);
return placeholders.get(index).getValue();
}
@Override
@ -337,7 +349,7 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext @@ -337,7 +349,7 @@ record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext
return ((List) placeholders).iterator();
}
public List<Object> getPlaceholders() {
public List<Placeholder> getPlaceholders() {
return placeholders;
}
}

30
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotStringQuery.java

@ -22,12 +22,12 @@ import java.util.Set; @@ -22,12 +22,12 @@ import java.util.Set;
import org.bson.Document;
import org.jspecify.annotations.Nullable;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.core.query.Field;
import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.AsListPlaceholder;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.RegexPlaceholder;
import org.springframework.util.StringUtils;
@ -47,9 +47,9 @@ class AotStringQuery extends Query { @@ -47,9 +47,9 @@ class AotStringQuery extends Query {
private @Nullable String sort;
private @Nullable String fields;
private List<Object> placeholders = new ArrayList<>();
private List<AotPlaceholders.Placeholder> placeholders = new ArrayList<>();
public AotStringQuery(Query query, List<Object> placeholders) {
public AotStringQuery(Query query, List<AotPlaceholders.Placeholder> placeholders) {
this.delegate = query;
this.placeholders = placeholders;
}
@ -79,34 +79,24 @@ class AotStringQuery extends Query { @@ -79,34 +79,24 @@ class AotStringQuery extends Query {
}
boolean isRegexPlaceholderAt(int index) {
if (this.placeholders.isEmpty()) {
return false;
}
return obtainAndPotentiallyUnwrapPlaceholder(index) instanceof RegexPlaceholder;
return getRegexPlaceholder(index) != null;
}
@Nullable
String getRegexOptions(int index) {
if (this.placeholders.isEmpty()) {
return null;
}
Object placeholderValue = obtainAndPotentiallyUnwrapPlaceholder(index);
return placeholderValue instanceof RegexPlaceholder rgp ? rgp.regexOptions() : null;
RegexPlaceholder placeholder = getRegexPlaceholder(index);
return placeholder != null ? placeholder.regexOptions() : null;
}
@Nullable Object obtainAndPotentiallyUnwrapPlaceholder(int index) {
@Nullable
RegexPlaceholder getRegexPlaceholder(int index) {
if (this.placeholders.isEmpty()) {
if (index >= this.placeholders.size()) {
return null;
}
Object placeholerValue = this.placeholders.get(index);
if (placeholerValue instanceof AsListPlaceholder asListPlaceholder) {
placeholerValue = asListPlaceholder.placeholder();
}
return placeholerValue;
return this.placeholders.get(index).unwrap(RegexPlaceholder.class);
}
@Override

3
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/DocumentSerializerUnitTests.java

@ -22,6 +22,7 @@ import java.util.List; @@ -22,6 +22,7 @@ import java.util.List;
import org.bson.Document;
import org.junit.jupiter.api.Test;
import org.springframework.data.geo.Shape;
import org.springframework.data.mongodb.core.query.GeoCommand;
/**
@ -35,7 +36,7 @@ class DocumentSerializerUnitTests { @@ -35,7 +36,7 @@ class DocumentSerializerUnitTests {
void writesGeoCommandToJson() {
Document source = new Document();
source.append("foo", new GeoCommand(AotPlaceholders.box(1)));
source.append("foo", new GeoCommand((Shape) AotPlaceholders.box(1)));
String jsonString = DocumentSerializer.toJson(source);

Loading…
Cancel
Save