mirror of
https://github.com/spring-projects/spring-data-mongodb.git
synced 2026-05-02 19:26:45 +01:00
Polishing.
Refactor duplicates, simplify placeholder unwrapping. See #5123 Original pull request: #5124
This commit is contained in:
+27
-6
@@ -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 {
|
||||
* @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 {
|
||||
* @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 {
|
||||
* @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 {
|
||||
* @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 {
|
||||
* @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 {
|
||||
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 {
|
||||
|
||||
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();
|
||||
|
||||
+68
-56
@@ -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;
|
||||
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
|
||||
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
|
||||
@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,64 +198,76 @@ 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
|
||||
public Range<Distance> getDistanceRange() {
|
||||
return Range.unbounded();
|
||||
@@ -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
|
||||
return ((List) placeholders).iterator();
|
||||
}
|
||||
|
||||
public List<Object> getPlaceholders() {
|
||||
public List<Placeholder> getPlaceholders() {
|
||||
return placeholders;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-20
@@ -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 {
|
||||
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 {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
+2
-1
@@ -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 {
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user