18
18
import java .lang .reflect .Parameter ;
19
19
import java .util .Arrays ;
20
20
import java .util .List ;
21
+ import java .util .Optional ;
21
22
import java .util .regex .Pattern ;
22
23
import java .util .stream .Collectors ;
23
24
24
25
import org .bson .Document ;
26
+
27
+ import org .springframework .core .annotation .MergedAnnotation ;
25
28
import org .springframework .data .mongodb .BindableMongoExpression ;
26
29
import org .springframework .data .mongodb .core .ExecutableFindOperation .FindWithQuery ;
27
30
import org .springframework .data .mongodb .core .ExecutableRemoveOperation .ExecutableRemove ;
33
36
import org .springframework .data .mongodb .repository .query .MongoQueryExecution .DeleteExecutionX .Type ;
34
37
import org .springframework .data .mongodb .repository .query .MongoQueryExecution .PagedExecution ;
35
38
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 ;
37
41
import org .springframework .javapoet .ClassName ;
38
42
import org .springframework .javapoet .CodeBlock ;
39
43
import org .springframework .javapoet .CodeBlock .Builder ;
@@ -50,25 +54,29 @@ public class MongoBlocks {
50
54
51
55
private static final Pattern PARAMETER_BINDING_PATTERN = Pattern .compile ("\\ ?(\\ d+)" );
52
56
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 );
55
59
}
56
60
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 );
59
64
}
60
65
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 );
63
69
}
64
70
65
71
static class DeleteExecutionBuilder {
66
72
67
- AotRepositoryMethodGenerationContext context ;
73
+ private final AotQueryMethodGenerationContext context ;
74
+ private final MongoQueryMethod queryMethod ;
68
75
String queryVariableName ;
69
76
70
- public DeleteExecutionBuilder (AotRepositoryMethodGenerationContext context ) {
77
+ public DeleteExecutionBuilder (AotQueryMethodGenerationContext context , MongoQueryMethod queryMethod ) {
71
78
this .context = context ;
79
+ this .queryMethod = queryMethod ;
72
80
}
73
81
74
82
public DeleteExecutionBuilder referencing (String queryVariableName ) {
@@ -85,15 +93,16 @@ public CodeBlock build() {
85
93
&& !ObjectUtils .nullSafeEquals (TypeName .get (context .getRepositoryInformation ().getDomainType ()),
86
94
context .getActualReturnType ());
87
95
88
- Object actualReturnType = isProjecting ? context .getActualReturnType ()
96
+ Object actualReturnType = isProjecting ? context .getActualReturnType (). getType ()
89
97
: context .getRepositoryInformation ().getDomainType ();
90
98
91
99
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 (),
93
102
mongoOpsRef , context .getRepositoryInformation ().getDomainType ());
94
103
95
104
Type type = Type .FIND_AND_REMOVE_ALL ;
96
- if (context . returnsSingleValue ()) {
105
+ if (! queryMethod . isCollectionQuery ()) {
97
106
if (!ClassUtils .isPrimitiveOrWrapper (context .getMethod ().getReturnType ())) {
98
107
type = Type .FIND_AND_REMOVE_ONE ;
99
108
} else {
@@ -103,7 +112,7 @@ public CodeBlock build() {
103
112
104
113
actualReturnType = ClassUtils .isPrimitiveOrWrapper (context .getMethod ().getReturnType ())
105
114
? ClassName .get (context .getMethod ().getReturnType ())
106
- : context . returnsSingleValue () ? actualReturnType : context .getReturnType () ;
115
+ : queryMethod . isCollectionQuery () ? context .getReturnTypeName () : actualReturnType ;
107
116
108
117
builder .addStatement ("return ($T) new $T(remover, $T.$L).execute($L)" , actualReturnType , DeleteExecutionX .class ,
109
118
DeleteExecutionX .Type .class , type .name (), queryVariableName );
@@ -114,11 +123,14 @@ public CodeBlock build() {
114
123
115
124
static class QueryExecutionBlockBuilder {
116
125
117
- AotRepositoryMethodGenerationContext context ;
126
+ private final AotQueryMethodGenerationContext context ;
127
+ private final MongoQueryMethod queryMethod ;
118
128
private String queryVariableName ;
129
+ private boolean count , exists ;
119
130
120
- public QueryExecutionBlockBuilder (AotRepositoryMethodGenerationContext context ) {
131
+ public QueryExecutionBlockBuilder (AotQueryMethodGenerationContext context , MongoQueryMethod queryMethod ) {
121
132
this .context = context ;
133
+ this .queryMethod = queryMethod ;
122
134
}
123
135
124
136
QueryExecutionBlockBuilder referencing (String queryVariableName ) {
@@ -127,16 +139,24 @@ QueryExecutionBlockBuilder referencing(String queryVariableName) {
127
139
return this ;
128
140
}
129
141
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
+
130
152
CodeBlock build () {
131
153
132
154
String mongoOpsRef = context .fieldNameOf (MongoOperations .class );
133
155
134
156
Builder builder = CodeBlock .builder ();
135
157
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 ()
140
160
: context .getRepositoryInformation ().getDomainType ();
141
161
142
162
builder .add ("\n " );
@@ -150,24 +170,23 @@ CodeBlock build() {
150
170
context .getRepositoryInformation ().getDomainType ());
151
171
}
152
172
153
- String terminatingMethod = "all()" ;
154
- if (context .returnsSingleValue ()) {
173
+ String terminatingMethod ;
155
174
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()" ;
165
184
}
166
185
167
- if (context . returnsPage ()) {
186
+ if (queryMethod . isPageQuery ()) {
168
187
builder .addStatement ("return new $T(finder, $L).execute($L)" , PagedExecution .class ,
169
188
context .getPageableParameterName (), queryVariableName );
170
- } else if (context . returnsSlice ()) {
189
+ } else if (queryMethod . isSliceQuery ()) {
171
190
builder .addStatement ("return new $T(finder, $L).execute($L)" , SlicedExecution .class ,
172
191
context .getPageableParameterName (), queryVariableName );
173
192
} else {
@@ -181,19 +200,22 @@ CodeBlock build() {
181
200
182
201
static class QueryBlockBuilder {
183
202
184
- AotRepositoryMethodGenerationContext context ;
203
+ private final AotQueryMethodGenerationContext context ;
204
+ private final MongoQueryMethod queryMethod ;
205
+
185
206
StringQuery source ;
186
207
List <String > arguments ;
187
208
private String queryVariableName ;
188
209
189
- public QueryBlockBuilder (AotRepositoryMethodGenerationContext context ) {
210
+ public QueryBlockBuilder (AotQueryMethodGenerationContext context , MongoQueryMethod queryMethod ) {
190
211
this .context = context ;
191
212
this .arguments = Arrays .stream (context .getMethod ().getParameters ()).map (Parameter ::getName )
192
213
.collect (Collectors .toList ());
193
214
194
215
// ParametersSource parametersSource = ParametersSource.of(repositoryInformation, metadata.getRepositoryMethod());
195
216
// this.argumentSource = new MongoParameters(parametersSource, false);
196
217
218
+ this .queryMethod = queryMethod ;
197
219
}
198
220
199
221
public QueryBlockBuilder filter (StringQuery query ) {
@@ -239,17 +261,20 @@ CodeBlock build() {
239
261
}
240
262
241
263
String pageableParameter = context .getPageableParameterName ();
242
- if (StringUtils .hasText (pageableParameter ) && !context . returnsPage () && !context . returnsSlice ()) {
264
+ if (StringUtils .hasText (pageableParameter ) && !queryMethod . isPageQuery () && !queryMethod . isSliceQuery ()) {
243
265
builder .addStatement ("$L.with($L)" , queryVariableName , pageableParameter );
244
266
}
245
267
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 ;
247
270
248
271
if (StringUtils .hasText (hint )) {
249
272
builder .addStatement ("$L.withHint($S)" , queryVariableName , hint );
250
273
}
251
274
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
+
253
278
if (StringUtils .hasText (readPreference )) {
254
279
builder .addStatement ("$L.withReadPreference($T.valueOf($S))" , queryVariableName ,
255
280
com .mongodb .ReadPreference .class , readPreference );
0 commit comments