Skip to content

Commit 4ff3efe

Browse files
mp911dechristophstrobl
authored andcommitted
Adopt to Commons changes.
See: #4939
1 parent 394c807 commit 4ff3efe

File tree

3 files changed

+117
-68
lines changed

3 files changed

+117
-68
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/generated/MongoBlocks.java

+62-37
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818
import java.lang.reflect.Parameter;
1919
import java.util.Arrays;
2020
import java.util.List;
21+
import java.util.Optional;
2122
import java.util.regex.Pattern;
2223
import java.util.stream.Collectors;
2324

2425
import org.bson.Document;
26+
27+
import org.springframework.core.annotation.MergedAnnotation;
2528
import org.springframework.data.mongodb.BindableMongoExpression;
2629
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery;
2730
import org.springframework.data.mongodb.core.ExecutableRemoveOperation.ExecutableRemove;
@@ -33,7 +36,8 @@
3336
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecutionX.Type;
3437
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution;
3538
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution;
36-
import org.springframework.data.repository.aot.generate.AotRepositoryMethodGenerationContext;
39+
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
40+
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
3741
import org.springframework.javapoet.ClassName;
3842
import org.springframework.javapoet.CodeBlock;
3943
import org.springframework.javapoet.CodeBlock.Builder;
@@ -50,25 +54,29 @@ public class MongoBlocks {
5054

5155
private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)");
5256

53-
static QueryBlockBuilder queryBlockBuilder(AotRepositoryMethodGenerationContext context) {
54-
return new QueryBlockBuilder(context);
57+
static QueryBlockBuilder queryBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) {
58+
return new QueryBlockBuilder(context, queryMethod);
5559
}
5660

57-
static QueryExecutionBlockBuilder queryExecutionBlockBuilder(AotRepositoryMethodGenerationContext context) {
58-
return new QueryExecutionBlockBuilder(context);
61+
static QueryExecutionBlockBuilder queryExecutionBlockBuilder(AotQueryMethodGenerationContext context,
62+
MongoQueryMethod queryMethod) {
63+
return new QueryExecutionBlockBuilder(context, queryMethod);
5964
}
6065

61-
static DeleteExecutionBuilder deleteExecutionBlockBuilder(AotRepositoryMethodGenerationContext context) {
62-
return new DeleteExecutionBuilder(context);
66+
static DeleteExecutionBuilder deleteExecutionBlockBuilder(AotQueryMethodGenerationContext context,
67+
MongoQueryMethod queryMethod) {
68+
return new DeleteExecutionBuilder(context, queryMethod);
6369
}
6470

6571
static class DeleteExecutionBuilder {
6672

67-
AotRepositoryMethodGenerationContext context;
73+
private final AotQueryMethodGenerationContext context;
74+
private final MongoQueryMethod queryMethod;
6875
String queryVariableName;
6976

70-
public DeleteExecutionBuilder(AotRepositoryMethodGenerationContext context) {
77+
public DeleteExecutionBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) {
7178
this.context = context;
79+
this.queryMethod = queryMethod;
7280
}
7381

7482
public DeleteExecutionBuilder referencing(String queryVariableName) {
@@ -85,15 +93,16 @@ public CodeBlock build() {
8593
&& !ObjectUtils.nullSafeEquals(TypeName.get(context.getRepositoryInformation().getDomainType()),
8694
context.getActualReturnType());
8795

88-
Object actualReturnType = isProjecting ? context.getActualReturnType()
96+
Object actualReturnType = isProjecting ? context.getActualReturnType().getType()
8997
: context.getRepositoryInformation().getDomainType();
9098

9199
builder.add("\n");
92-
builder.addStatement("$T<$T> remover = $L.remove($T.class)", ExecutableRemove.class, actualReturnType,
100+
builder.addStatement("$T<$T> remover = $L.remove($T.class)", ExecutableRemove.class,
101+
context.getRepositoryInformation().getDomainType(),
93102
mongoOpsRef, context.getRepositoryInformation().getDomainType());
94103

95104
Type type = Type.FIND_AND_REMOVE_ALL;
96-
if (context.returnsSingleValue()) {
105+
if (!queryMethod.isCollectionQuery()) {
97106
if (!ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType())) {
98107
type = Type.FIND_AND_REMOVE_ONE;
99108
} else {
@@ -103,7 +112,7 @@ public CodeBlock build() {
103112

104113
actualReturnType = ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType())
105114
? ClassName.get(context.getMethod().getReturnType())
106-
: context.returnsSingleValue() ? actualReturnType : context.getReturnType();
115+
: queryMethod.isCollectionQuery() ? context.getReturnTypeName() : actualReturnType;
107116

108117
builder.addStatement("return ($T) new $T(remover, $T.$L).execute($L)", actualReturnType, DeleteExecutionX.class,
109118
DeleteExecutionX.Type.class, type.name(), queryVariableName);
@@ -114,11 +123,14 @@ public CodeBlock build() {
114123

115124
static class QueryExecutionBlockBuilder {
116125

117-
AotRepositoryMethodGenerationContext context;
126+
private final AotQueryMethodGenerationContext context;
127+
private final MongoQueryMethod queryMethod;
118128
private String queryVariableName;
129+
private boolean count, exists;
119130

120-
public QueryExecutionBlockBuilder(AotRepositoryMethodGenerationContext context) {
131+
public QueryExecutionBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) {
121132
this.context = context;
133+
this.queryMethod = queryMethod;
122134
}
123135

124136
QueryExecutionBlockBuilder referencing(String queryVariableName) {
@@ -127,16 +139,24 @@ QueryExecutionBlockBuilder referencing(String queryVariableName) {
127139
return this;
128140
}
129141

142+
QueryExecutionBlockBuilder count(boolean count) {
143+
this.count = count;
144+
return this;
145+
}
146+
147+
QueryExecutionBlockBuilder exists(boolean exists) {
148+
this.exists = exists;
149+
return this;
150+
}
151+
130152
CodeBlock build() {
131153

132154
String mongoOpsRef = context.fieldNameOf(MongoOperations.class);
133155

134156
Builder builder = CodeBlock.builder();
135157

136-
boolean isProjecting = context.getActualReturnType() != null
137-
&& !ObjectUtils.nullSafeEquals(TypeName.get(context.getRepositoryInformation().getDomainType()),
138-
context.getActualReturnType());
139-
Object actualReturnType = isProjecting ? context.getActualReturnType()
158+
boolean isProjecting = context.getReturnedType().isProjecting();
159+
Object actualReturnType = isProjecting ? context.getActualReturnType().getType()
140160
: context.getRepositoryInformation().getDomainType();
141161

142162
builder.add("\n");
@@ -150,24 +170,23 @@ CodeBlock build() {
150170
context.getRepositoryInformation().getDomainType());
151171
}
152172

153-
String terminatingMethod = "all()";
154-
if (context.returnsSingleValue()) {
173+
String terminatingMethod;
155174

156-
if (context.returnsOptionalValue()) {
157-
terminatingMethod = "one()";
158-
} else if (context.isCountMethod()) {
159-
terminatingMethod = "count()";
160-
} else if (context.isExistsMethod()) {
161-
terminatingMethod = "exists()";
162-
} else {
163-
terminatingMethod = "oneValue()";
164-
}
175+
if (queryMethod.isCollectionQuery() || queryMethod.isPageQuery() || queryMethod.isSliceQuery()) {
176+
terminatingMethod = "all()";
177+
} else if (count) {
178+
terminatingMethod = "count()";
179+
180+
} else if (exists) {
181+
terminatingMethod = "exists()";
182+
} else {
183+
terminatingMethod = Optional.class.isAssignableFrom(context.getReturnType().toClass()) ? "one()" : "oneValue()";
165184
}
166185

167-
if (context.returnsPage()) {
186+
if (queryMethod.isPageQuery()) {
168187
builder.addStatement("return new $T(finder, $L).execute($L)", PagedExecution.class,
169188
context.getPageableParameterName(), queryVariableName);
170-
} else if (context.returnsSlice()) {
189+
} else if (queryMethod.isSliceQuery()) {
171190
builder.addStatement("return new $T(finder, $L).execute($L)", SlicedExecution.class,
172191
context.getPageableParameterName(), queryVariableName);
173192
} else {
@@ -181,19 +200,22 @@ CodeBlock build() {
181200

182201
static class QueryBlockBuilder {
183202

184-
AotRepositoryMethodGenerationContext context;
203+
private final AotQueryMethodGenerationContext context;
204+
private final MongoQueryMethod queryMethod;
205+
185206
StringQuery source;
186207
List<String> arguments;
187208
private String queryVariableName;
188209

189-
public QueryBlockBuilder(AotRepositoryMethodGenerationContext context) {
210+
public QueryBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) {
190211
this.context = context;
191212
this.arguments = Arrays.stream(context.getMethod().getParameters()).map(Parameter::getName)
192213
.collect(Collectors.toList());
193214

194215
// ParametersSource parametersSource = ParametersSource.of(repositoryInformation, metadata.getRepositoryMethod());
195216
// this.argumentSource = new MongoParameters(parametersSource, false);
196217

218+
this.queryMethod = queryMethod;
197219
}
198220

199221
public QueryBlockBuilder filter(StringQuery query) {
@@ -239,17 +261,20 @@ CodeBlock build() {
239261
}
240262

241263
String pageableParameter = context.getPageableParameterName();
242-
if (StringUtils.hasText(pageableParameter) && !context.returnsPage() && !context.returnsSlice()) {
264+
if (StringUtils.hasText(pageableParameter) && !queryMethod.isPageQuery() && !queryMethod.isSliceQuery()) {
243265
builder.addStatement("$L.with($L)", queryVariableName, pageableParameter);
244266
}
245267

246-
String hint = context.annotationValue(Hint.class, "value");
268+
MergedAnnotation<Hint> hintAnnotation = context.getAnnotation(Hint.class);
269+
String hint = hintAnnotation.isPresent() ? hintAnnotation.getString("value") : null;
247270

248271
if (StringUtils.hasText(hint)) {
249272
builder.addStatement("$L.withHint($S)", queryVariableName, hint);
250273
}
251274

252-
String readPreference = context.annotationValue(ReadPreference.class, "value");
275+
MergedAnnotation<ReadPreference> readPreferenceAnnotation = context.getAnnotation(ReadPreference.class);
276+
String readPreference = readPreferenceAnnotation.isPresent() ? readPreferenceAnnotation.getString("value") : null;
277+
253278
if (StringUtils.hasText(readPreference)) {
254279
builder.addStatement("$L.withReadPreference($T.valueOf($S))", queryVariableName,
255280
com.mongodb.ReadPreference.class, readPreference);

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/generated/MongoRepositoryContributor.java

+49-31
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,27 @@
1515
*/
1616
package org.springframework.data.mongodb.aot.generated;
1717

18+
import java.lang.reflect.Method;
1819
import java.util.regex.Pattern;
1920

21+
import org.jspecify.annotations.Nullable;
22+
2023
import org.springframework.core.annotation.AnnotatedElementUtils;
2124
import org.springframework.data.mongodb.aot.generated.MongoBlocks.QueryBlockBuilder;
2225
import org.springframework.data.mongodb.core.MongoOperations;
26+
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
2327
import org.springframework.data.mongodb.repository.Aggregation;
2428
import org.springframework.data.mongodb.repository.Query;
29+
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
30+
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
2531
import org.springframework.data.repository.aot.generate.AotRepositoryConstructorBuilder;
26-
import org.springframework.data.repository.aot.generate.AotRepositoryMethodBuilder;
27-
import org.springframework.data.repository.aot.generate.AotRepositoryMethodGenerationContext;
32+
import org.springframework.data.repository.aot.generate.MethodContributor;
2833
import org.springframework.data.repository.aot.generate.RepositoryContributor;
2934
import org.springframework.data.repository.config.AotRepositoryContext;
35+
import org.springframework.data.repository.core.RepositoryInformation;
36+
import org.springframework.data.repository.query.QueryMethod;
3037
import org.springframework.data.repository.query.parser.PartTree;
31-
import org.springframework.javapoet.MethodSpec.Builder;
38+
import org.springframework.javapoet.CodeBlock;
3239
import org.springframework.javapoet.TypeName;
3340
import org.springframework.util.StringUtils;
3441

@@ -38,11 +45,13 @@
3845
*/
3946
public class MongoRepositoryContributor extends RepositoryContributor {
4047

41-
private AotQueryCreator queryCreator;
48+
private final AotQueryCreator queryCreator;
49+
private final MongoMappingContext mappingContext;
4250

4351
public MongoRepositoryContributor(AotRepositoryContext repositoryContext) {
4452
super(repositoryContext);
4553
this.queryCreator = new AotQueryCreator();
54+
this.mappingContext = new MongoMappingContext();
4655
}
4756

4857
@Override
@@ -51,36 +60,43 @@ protected void customizeConstructor(AotRepositoryConstructorBuilder constructorB
5160
}
5261

5362
@Override
54-
protected AotRepositoryMethodBuilder contributeRepositoryMethod(
55-
AotRepositoryMethodGenerationContext generationContext) {
56-
57-
// TODO: do not generate stuff for spel expressions
63+
protected @Nullable MethodContributor<? extends QueryMethod> contributeQueryMethod(Method method,
64+
RepositoryInformation repositoryInformation) {
5865

59-
if (AnnotatedElementUtils.hasAnnotation(generationContext.getMethod(), Aggregation.class)) {
66+
if (AnnotatedElementUtils.hasAnnotation(method, Aggregation.class)) {
6067
return null;
6168
}
62-
{
63-
Query queryAnnotation = AnnotatedElementUtils.findMergedAnnotation(generationContext.getMethod(), Query.class);
64-
if (queryAnnotation != null) {
65-
if (StringUtils.hasText(queryAnnotation.value())
66-
&& Pattern.compile("[\\?:][#$]\\{.*\\}").matcher(queryAnnotation.value()).find()) {
67-
return null;
68-
}
69+
70+
Query queryAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
71+
if (queryAnnotation != null) {
72+
if (StringUtils.hasText(queryAnnotation.value())
73+
&& Pattern.compile("[\\?:][#$]\\{.*\\}").matcher(queryAnnotation.value()).find()) {
74+
return null;
6975
}
7076
}
7177

72-
// so the rest should work
73-
return new AotRepositoryMethodBuilder(generationContext).customize((context, body) -> {
78+
MongoQueryMethod queryMethod = new MongoQueryMethod(method, repositoryInformation, getProjectionFactory(),
79+
mappingContext);
80+
81+
return MethodContributor.forQueryMethod(queryMethod).contribute(context -> {
82+
CodeBlock.Builder builder = CodeBlock.builder();
7483

75-
Query queryAnnotation = AnnotatedElementUtils.findMergedAnnotation(context.getMethod(), Query.class);
84+
boolean count, delete, exists;
7685
StringQuery query;
7786
if (queryAnnotation != null && StringUtils.hasText(queryAnnotation.value())) {
7887
query = new StringQuery(queryAnnotation.value());
88+
count = queryAnnotation.count();
89+
delete = queryAnnotation.delete();
90+
exists = queryAnnotation.exists();
7991

8092
} else {
8193
PartTree partTree = new PartTree(context.getMethod().getName(),
8294
context.getRepositoryInformation().getDomainType());
8395
query = queryCreator.createQuery(partTree, context.getMethod().getParameterCount());
96+
count = partTree.isCountProjection();
97+
delete = partTree.isDelete();
98+
exists = partTree.isExistsProjection();
99+
84100
}
85101

86102
if (queryAnnotation != null && StringUtils.hasText(queryAnnotation.sort())) {
@@ -90,29 +106,31 @@ protected AotRepositoryMethodBuilder contributeRepositoryMethod(
90106
query.fields(queryAnnotation.fields());
91107
}
92108

93-
writeStringQuery(context, body, query);
109+
writeStringQuery(context, builder, count, delete, exists, query, queryMethod);
110+
111+
return builder.build();
94112
});
95113
}
96114

97-
private static void writeStringQuery(AotRepositoryMethodGenerationContext context, Builder body, StringQuery query) {
115+
private static void writeStringQuery(AotQueryMethodGenerationContext context, CodeBlock.Builder body, boolean count,
116+
boolean delete, boolean exists, StringQuery query, MongoQueryMethod queryMethod) {
98117

99-
body.addCode(context.codeBlocks().logDebug("invoking [%s]".formatted(context.getMethod().getName())));
100-
QueryBlockBuilder queryBlockBuilder = MongoBlocks.queryBlockBuilder(context).filter(query);
118+
body.add(context.codeBlocks().logDebug("invoking [%s]".formatted(context.getMethod().getName())));
119+
QueryBlockBuilder queryBlockBuilder = MongoBlocks.queryBlockBuilder(context, queryMethod).filter(query);
101120

102-
if (context.isDeleteMethod()) {
121+
if (delete) {
103122

104123
String deleteQueryVariableName = "deleteQuery";
105-
body.addCode(queryBlockBuilder.usingQueryVariableName(deleteQueryVariableName).build());
106-
body.addCode(MongoBlocks.deleteExecutionBlockBuilder(context).referencing(deleteQueryVariableName).build());
124+
body.add(queryBlockBuilder.usingQueryVariableName(deleteQueryVariableName).build());
125+
body.add(
126+
MongoBlocks.deleteExecutionBlockBuilder(context, queryMethod).referencing(deleteQueryVariableName).build());
107127
} else {
108128

109129
String filterQueryVariableName = "filterQuery";
110-
body.addCode(queryBlockBuilder.usingQueryVariableName(filterQueryVariableName).build());
111-
body.addCode(MongoBlocks.queryExecutionBlockBuilder(context).referencing(filterQueryVariableName).build());
130+
body.add(queryBlockBuilder.usingQueryVariableName(filterQueryVariableName).build());
131+
body.add(MongoBlocks.queryExecutionBlockBuilder(context, queryMethod).exists(exists).count(count)
132+
.referencing(filterQueryVariableName).build());
112133
}
113134
}
114135

115-
private static void userAnnotatedQuery(AotRepositoryMethodGenerationContext context, Builder body, Query query) {
116-
writeStringQuery(context, body, new StringQuery(query.value()));
117-
}
118136
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

+6
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.springframework.context.ApplicationContext;
4646
import org.springframework.context.ApplicationContextAware;
4747
import org.springframework.core.CollectionFactory;
48+
import org.springframework.core.ResolvableType;
4849
import org.springframework.core.convert.ConversionService;
4950
import org.springframework.core.convert.TypeDescriptor;
5051
import org.springframework.core.convert.support.DefaultConversionService;
@@ -2223,6 +2224,11 @@ public org.springframework.data.util.TypeInformation<? extends S> specialize(Typ
22232224
public TypeDescriptor toTypeDescriptor() {
22242225
return delegate.toTypeDescriptor();
22252226
}
2227+
2228+
@Override
2229+
public ResolvableType toResolvableType() {
2230+
return delegate.toResolvableType();
2231+
}
22262232
}
22272233

22282234
/**

0 commit comments

Comments
 (0)