|
|
|
@ -18,10 +18,13 @@ package org.springframework.data.mongodb.aot.generated; |
|
|
|
import java.lang.reflect.Parameter; |
|
|
|
import java.lang.reflect.Parameter; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
import java.util.Optional; |
|
|
|
import java.util.regex.Pattern; |
|
|
|
import java.util.regex.Pattern; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
|
|
import org.bson.Document; |
|
|
|
import org.bson.Document; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.core.annotation.MergedAnnotation; |
|
|
|
import org.springframework.data.mongodb.BindableMongoExpression; |
|
|
|
import org.springframework.data.mongodb.BindableMongoExpression; |
|
|
|
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; |
|
|
|
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; |
|
|
|
import org.springframework.data.mongodb.core.ExecutableRemoveOperation.ExecutableRemove; |
|
|
|
import org.springframework.data.mongodb.core.ExecutableRemoveOperation.ExecutableRemove; |
|
|
|
@ -33,7 +36,8 @@ import org.springframework.data.mongodb.repository.query.MongoQueryExecution.Del |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecutionX.Type; |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecutionX.Type; |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution; |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution; |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution; |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution; |
|
|
|
import org.springframework.data.repository.aot.generate.AotRepositoryMethodGenerationContext; |
|
|
|
import org.springframework.data.mongodb.repository.query.MongoQueryMethod; |
|
|
|
|
|
|
|
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext; |
|
|
|
import org.springframework.javapoet.ClassName; |
|
|
|
import org.springframework.javapoet.ClassName; |
|
|
|
import org.springframework.javapoet.CodeBlock; |
|
|
|
import org.springframework.javapoet.CodeBlock; |
|
|
|
import org.springframework.javapoet.CodeBlock.Builder; |
|
|
|
import org.springframework.javapoet.CodeBlock.Builder; |
|
|
|
@ -50,25 +54,29 @@ public class MongoBlocks { |
|
|
|
|
|
|
|
|
|
|
|
private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)"); |
|
|
|
private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)"); |
|
|
|
|
|
|
|
|
|
|
|
static QueryBlockBuilder queryBlockBuilder(AotRepositoryMethodGenerationContext context) { |
|
|
|
static QueryBlockBuilder queryBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) { |
|
|
|
return new QueryBlockBuilder(context); |
|
|
|
return new QueryBlockBuilder(context, queryMethod); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static QueryExecutionBlockBuilder queryExecutionBlockBuilder(AotRepositoryMethodGenerationContext context) { |
|
|
|
static QueryExecutionBlockBuilder queryExecutionBlockBuilder(AotQueryMethodGenerationContext context, |
|
|
|
return new QueryExecutionBlockBuilder(context); |
|
|
|
MongoQueryMethod queryMethod) { |
|
|
|
|
|
|
|
return new QueryExecutionBlockBuilder(context, queryMethod); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static DeleteExecutionBuilder deleteExecutionBlockBuilder(AotRepositoryMethodGenerationContext context) { |
|
|
|
static DeleteExecutionBuilder deleteExecutionBlockBuilder(AotQueryMethodGenerationContext context, |
|
|
|
return new DeleteExecutionBuilder(context); |
|
|
|
MongoQueryMethod queryMethod) { |
|
|
|
|
|
|
|
return new DeleteExecutionBuilder(context, queryMethod); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static class DeleteExecutionBuilder { |
|
|
|
static class DeleteExecutionBuilder { |
|
|
|
|
|
|
|
|
|
|
|
AotRepositoryMethodGenerationContext context; |
|
|
|
private final AotQueryMethodGenerationContext context; |
|
|
|
|
|
|
|
private final MongoQueryMethod queryMethod; |
|
|
|
String queryVariableName; |
|
|
|
String queryVariableName; |
|
|
|
|
|
|
|
|
|
|
|
public DeleteExecutionBuilder(AotRepositoryMethodGenerationContext context) { |
|
|
|
public DeleteExecutionBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) { |
|
|
|
this.context = context; |
|
|
|
this.context = context; |
|
|
|
|
|
|
|
this.queryMethod = queryMethod; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public DeleteExecutionBuilder referencing(String queryVariableName) { |
|
|
|
public DeleteExecutionBuilder referencing(String queryVariableName) { |
|
|
|
@ -85,15 +93,16 @@ public class MongoBlocks { |
|
|
|
&& !ObjectUtils.nullSafeEquals(TypeName.get(context.getRepositoryInformation().getDomainType()), |
|
|
|
&& !ObjectUtils.nullSafeEquals(TypeName.get(context.getRepositoryInformation().getDomainType()), |
|
|
|
context.getActualReturnType()); |
|
|
|
context.getActualReturnType()); |
|
|
|
|
|
|
|
|
|
|
|
Object actualReturnType = isProjecting ? context.getActualReturnType() |
|
|
|
Object actualReturnType = isProjecting ? context.getActualReturnType().getType() |
|
|
|
: context.getRepositoryInformation().getDomainType(); |
|
|
|
: context.getRepositoryInformation().getDomainType(); |
|
|
|
|
|
|
|
|
|
|
|
builder.add("\n"); |
|
|
|
builder.add("\n"); |
|
|
|
builder.addStatement("$T<$T> remover = $L.remove($T.class)", ExecutableRemove.class, actualReturnType, |
|
|
|
builder.addStatement("$T<$T> remover = $L.remove($T.class)", ExecutableRemove.class, |
|
|
|
|
|
|
|
context.getRepositoryInformation().getDomainType(), |
|
|
|
mongoOpsRef, context.getRepositoryInformation().getDomainType()); |
|
|
|
mongoOpsRef, context.getRepositoryInformation().getDomainType()); |
|
|
|
|
|
|
|
|
|
|
|
Type type = Type.FIND_AND_REMOVE_ALL; |
|
|
|
Type type = Type.FIND_AND_REMOVE_ALL; |
|
|
|
if (context.returnsSingleValue()) { |
|
|
|
if (!queryMethod.isCollectionQuery()) { |
|
|
|
if (!ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType())) { |
|
|
|
if (!ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType())) { |
|
|
|
type = Type.FIND_AND_REMOVE_ONE; |
|
|
|
type = Type.FIND_AND_REMOVE_ONE; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
@ -103,7 +112,7 @@ public class MongoBlocks { |
|
|
|
|
|
|
|
|
|
|
|
actualReturnType = ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType()) |
|
|
|
actualReturnType = ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType()) |
|
|
|
? ClassName.get(context.getMethod().getReturnType()) |
|
|
|
? ClassName.get(context.getMethod().getReturnType()) |
|
|
|
: context.returnsSingleValue() ? actualReturnType : context.getReturnType(); |
|
|
|
: queryMethod.isCollectionQuery() ? context.getReturnTypeName() : actualReturnType; |
|
|
|
|
|
|
|
|
|
|
|
builder.addStatement("return ($T) new $T(remover, $T.$L).execute($L)", actualReturnType, DeleteExecutionX.class, |
|
|
|
builder.addStatement("return ($T) new $T(remover, $T.$L).execute($L)", actualReturnType, DeleteExecutionX.class, |
|
|
|
DeleteExecutionX.Type.class, type.name(), queryVariableName); |
|
|
|
DeleteExecutionX.Type.class, type.name(), queryVariableName); |
|
|
|
@ -114,11 +123,14 @@ public class MongoBlocks { |
|
|
|
|
|
|
|
|
|
|
|
static class QueryExecutionBlockBuilder { |
|
|
|
static class QueryExecutionBlockBuilder { |
|
|
|
|
|
|
|
|
|
|
|
AotRepositoryMethodGenerationContext context; |
|
|
|
private final AotQueryMethodGenerationContext context; |
|
|
|
|
|
|
|
private final MongoQueryMethod queryMethod; |
|
|
|
private String queryVariableName; |
|
|
|
private String queryVariableName; |
|
|
|
|
|
|
|
private boolean count, exists; |
|
|
|
|
|
|
|
|
|
|
|
public QueryExecutionBlockBuilder(AotRepositoryMethodGenerationContext context) { |
|
|
|
public QueryExecutionBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) { |
|
|
|
this.context = context; |
|
|
|
this.context = context; |
|
|
|
|
|
|
|
this.queryMethod = queryMethod; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QueryExecutionBlockBuilder referencing(String queryVariableName) { |
|
|
|
QueryExecutionBlockBuilder referencing(String queryVariableName) { |
|
|
|
@ -127,16 +139,24 @@ public class MongoBlocks { |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QueryExecutionBlockBuilder count(boolean count) { |
|
|
|
|
|
|
|
this.count = count; |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QueryExecutionBlockBuilder exists(boolean exists) { |
|
|
|
|
|
|
|
this.exists = exists; |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeBlock build() { |
|
|
|
CodeBlock build() { |
|
|
|
|
|
|
|
|
|
|
|
String mongoOpsRef = context.fieldNameOf(MongoOperations.class); |
|
|
|
String mongoOpsRef = context.fieldNameOf(MongoOperations.class); |
|
|
|
|
|
|
|
|
|
|
|
Builder builder = CodeBlock.builder(); |
|
|
|
Builder builder = CodeBlock.builder(); |
|
|
|
|
|
|
|
|
|
|
|
boolean isProjecting = context.getActualReturnType() != null |
|
|
|
boolean isProjecting = context.getReturnedType().isProjecting(); |
|
|
|
&& !ObjectUtils.nullSafeEquals(TypeName.get(context.getRepositoryInformation().getDomainType()), |
|
|
|
Object actualReturnType = isProjecting ? context.getActualReturnType().getType() |
|
|
|
context.getActualReturnType()); |
|
|
|
|
|
|
|
Object actualReturnType = isProjecting ? context.getActualReturnType() |
|
|
|
|
|
|
|
: context.getRepositoryInformation().getDomainType(); |
|
|
|
: context.getRepositoryInformation().getDomainType(); |
|
|
|
|
|
|
|
|
|
|
|
builder.add("\n"); |
|
|
|
builder.add("\n"); |
|
|
|
@ -150,24 +170,23 @@ public class MongoBlocks { |
|
|
|
context.getRepositoryInformation().getDomainType()); |
|
|
|
context.getRepositoryInformation().getDomainType()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String terminatingMethod = "all()"; |
|
|
|
String terminatingMethod; |
|
|
|
if (context.returnsSingleValue()) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (context.returnsOptionalValue()) { |
|
|
|
if (queryMethod.isCollectionQuery() || queryMethod.isPageQuery() || queryMethod.isSliceQuery()) { |
|
|
|
terminatingMethod = "one()"; |
|
|
|
terminatingMethod = "all()"; |
|
|
|
} else if (context.isCountMethod()) { |
|
|
|
} else if (count) { |
|
|
|
terminatingMethod = "count()"; |
|
|
|
terminatingMethod = "count()"; |
|
|
|
} else if (context.isExistsMethod()) { |
|
|
|
|
|
|
|
|
|
|
|
} else if (exists) { |
|
|
|
terminatingMethod = "exists()"; |
|
|
|
terminatingMethod = "exists()"; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
terminatingMethod = "oneValue()"; |
|
|
|
terminatingMethod = Optional.class.isAssignableFrom(context.getReturnType().toClass()) ? "one()" : "oneValue()"; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (context.returnsPage()) { |
|
|
|
if (queryMethod.isPageQuery()) { |
|
|
|
builder.addStatement("return new $T(finder, $L).execute($L)", PagedExecution.class, |
|
|
|
builder.addStatement("return new $T(finder, $L).execute($L)", PagedExecution.class, |
|
|
|
context.getPageableParameterName(), queryVariableName); |
|
|
|
context.getPageableParameterName(), queryVariableName); |
|
|
|
} else if (context.returnsSlice()) { |
|
|
|
} else if (queryMethod.isSliceQuery()) { |
|
|
|
builder.addStatement("return new $T(finder, $L).execute($L)", SlicedExecution.class, |
|
|
|
builder.addStatement("return new $T(finder, $L).execute($L)", SlicedExecution.class, |
|
|
|
context.getPageableParameterName(), queryVariableName); |
|
|
|
context.getPageableParameterName(), queryVariableName); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
@ -181,12 +200,14 @@ public class MongoBlocks { |
|
|
|
|
|
|
|
|
|
|
|
static class QueryBlockBuilder { |
|
|
|
static class QueryBlockBuilder { |
|
|
|
|
|
|
|
|
|
|
|
AotRepositoryMethodGenerationContext context; |
|
|
|
private final AotQueryMethodGenerationContext context; |
|
|
|
|
|
|
|
private final MongoQueryMethod queryMethod; |
|
|
|
|
|
|
|
|
|
|
|
StringQuery source; |
|
|
|
StringQuery source; |
|
|
|
List<String> arguments; |
|
|
|
List<String> arguments; |
|
|
|
private String queryVariableName; |
|
|
|
private String queryVariableName; |
|
|
|
|
|
|
|
|
|
|
|
public QueryBlockBuilder(AotRepositoryMethodGenerationContext context) { |
|
|
|
public QueryBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) { |
|
|
|
this.context = context; |
|
|
|
this.context = context; |
|
|
|
this.arguments = Arrays.stream(context.getMethod().getParameters()).map(Parameter::getName) |
|
|
|
this.arguments = Arrays.stream(context.getMethod().getParameters()).map(Parameter::getName) |
|
|
|
.collect(Collectors.toList()); |
|
|
|
.collect(Collectors.toList()); |
|
|
|
@ -194,6 +215,7 @@ public class MongoBlocks { |
|
|
|
// ParametersSource parametersSource = ParametersSource.of(repositoryInformation, metadata.getRepositoryMethod());
|
|
|
|
// ParametersSource parametersSource = ParametersSource.of(repositoryInformation, metadata.getRepositoryMethod());
|
|
|
|
// this.argumentSource = new MongoParameters(parametersSource, false);
|
|
|
|
// this.argumentSource = new MongoParameters(parametersSource, false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.queryMethod = queryMethod; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public QueryBlockBuilder filter(StringQuery query) { |
|
|
|
public QueryBlockBuilder filter(StringQuery query) { |
|
|
|
@ -239,17 +261,20 @@ public class MongoBlocks { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String pageableParameter = context.getPageableParameterName(); |
|
|
|
String pageableParameter = context.getPageableParameterName(); |
|
|
|
if (StringUtils.hasText(pageableParameter) && !context.returnsPage() && !context.returnsSlice()) { |
|
|
|
if (StringUtils.hasText(pageableParameter) && !queryMethod.isPageQuery() && !queryMethod.isSliceQuery()) { |
|
|
|
builder.addStatement("$L.with($L)", queryVariableName, pageableParameter); |
|
|
|
builder.addStatement("$L.with($L)", queryVariableName, pageableParameter); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String hint = context.annotationValue(Hint.class, "value"); |
|
|
|
MergedAnnotation<Hint> hintAnnotation = context.getAnnotation(Hint.class); |
|
|
|
|
|
|
|
String hint = hintAnnotation.isPresent() ? hintAnnotation.getString("value") : null; |
|
|
|
|
|
|
|
|
|
|
|
if (StringUtils.hasText(hint)) { |
|
|
|
if (StringUtils.hasText(hint)) { |
|
|
|
builder.addStatement("$L.withHint($S)", queryVariableName, hint); |
|
|
|
builder.addStatement("$L.withHint($S)", queryVariableName, hint); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String readPreference = context.annotationValue(ReadPreference.class, "value"); |
|
|
|
MergedAnnotation<ReadPreference> readPreferenceAnnotation = context.getAnnotation(ReadPreference.class); |
|
|
|
|
|
|
|
String readPreference = readPreferenceAnnotation.isPresent() ? readPreferenceAnnotation.getString("value") : null; |
|
|
|
|
|
|
|
|
|
|
|
if (StringUtils.hasText(readPreference)) { |
|
|
|
if (StringUtils.hasText(readPreference)) { |
|
|
|
builder.addStatement("$L.withReadPreference($T.valueOf($S))", queryVariableName, |
|
|
|
builder.addStatement("$L.withReadPreference($T.valueOf($S))", queryVariableName, |
|
|
|
com.mongodb.ReadPreference.class, readPreference); |
|
|
|
com.mongodb.ReadPreference.class, readPreference); |
|
|
|
|