use of io.micronaut.data.processor.model.SourcePersistentEntity in project micronaut-data by micronaut-projects.
the class MongoRawQueryMethodMatcher method buildRawQuery.
private void buildRawQuery(@NonNull MethodMatchContext matchContext, MethodMatchInfo methodMatchInfo, ParameterElement entityParameter, ParameterElement entitiesParameter, DataMethod.OperationType operationType) {
MethodElement methodElement = matchContext.getMethodElement();
List<ParameterElement> parameters = Arrays.asList(matchContext.getParameters());
ParameterElement entityParam = null;
SourcePersistentEntity persistentEntity = null;
if (entityParameter != null) {
entityParam = entityParameter;
persistentEntity = matchContext.getEntity(entityParameter.getGenericType());
} else if (entitiesParameter != null) {
entityParam = entitiesParameter;
persistentEntity = matchContext.getEntity(entitiesParameter.getGenericType().getFirstTypeArgument().orElseThrow(IllegalStateException::new));
}
QueryResult queryResult;
if (operationType == DataMethod.OperationType.UPDATE) {
queryResult = getUpdateQueryResult(matchContext, parameters, entityParam, persistentEntity);
} else {
queryResult = getQueryResult(matchContext, parameters, entityParam, persistentEntity);
}
boolean encodeEntityParameters = persistentEntity != null || operationType == DataMethod.OperationType.INSERT;
methodElement.annotate(Query.class, builder -> {
if (queryResult.getUpdate() != null) {
builder.member("update", queryResult.getUpdate());
}
builder.value(queryResult.getQuery());
});
methodMatchInfo.encodeEntityParameters(encodeEntityParameters).queryResult(queryResult).countQueryResult(null);
}
use of io.micronaut.data.processor.model.SourcePersistentEntity in project micronaut-data by micronaut-projects.
the class MappedEntityVisitor method visitClass.
@Override
public void visitClass(ClassElement element, VisitorContext context) {
NamingStrategy namingStrategy = resolveNamingStrategy(element);
Optional<String> targetName = element.stringValue(MappedEntity.class);
SourcePersistentEntity entity = entityResolver.apply(element);
if (isMappedEntity() && !targetName.isPresent()) {
element.annotate(MappedEntity.class, builder -> {
String mappedName = namingStrategy.mappedName(entity);
builder.value(mappedName);
});
}
Map<String, DataType> dataTypes = getConfiguredDataTypes(element);
Map<String, String> dataConverters = getConfiguredDataConverters(element);
List<SourcePersistentProperty> properties = entity.getPersistentProperties();
final List<AnnotationValue<Index>> indexes = properties.stream().filter(x -> ((PersistentProperty) x).findAnnotation(Indexes.class).isPresent()).map(prop -> prop.findAnnotation(Index.class)).flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty)).collect(Collectors.toList());
if (!indexes.isEmpty()) {
element.annotate(Indexes.class, builder -> builder.values(indexes.toArray(new AnnotationValue[] {})));
}
for (PersistentProperty property : properties) {
computeMappingDefaults(namingStrategy, property, dataTypes, dataConverters, context);
}
SourcePersistentProperty identity = entity.getIdentity();
if (identity != null) {
computeMappingDefaults(namingStrategy, identity, dataTypes, dataConverters, context);
}
SourcePersistentProperty[] compositeIdentities = entity.getCompositeIdentity();
if (compositeIdentities != null) {
for (SourcePersistentProperty compositeIdentity : compositeIdentities) {
computeMappingDefaults(namingStrategy, compositeIdentity, dataTypes, dataConverters, context);
}
}
SourcePersistentProperty version = entity.getVersion();
if (version != null) {
computeMappingDefaults(namingStrategy, version, dataTypes, dataConverters, context);
}
}
use of io.micronaut.data.processor.model.SourcePersistentEntity in project micronaut-data by micronaut-projects.
the class RepositoryTypeElementVisitor method visitClass.
@Override
public void visitClass(ClassElement element, VisitorContext context) {
String interfaceName = element.getName();
if (failing) {
return;
}
if (visitedRepositories.contains(interfaceName)) {
// prevent duplicate visits
currentRepository = null;
currentClass = null;
return;
}
this.currentClass = element;
entityResolver = new Function<ClassElement, SourcePersistentEntity>() {
MappedEntityVisitor mappedEntityVisitor = new MappedEntityVisitor();
MappedEntityVisitor embeddedMappedEntityVisitor = new MappedEntityVisitor(false);
@Override
public SourcePersistentEntity apply(ClassElement classElement) {
return entityMap.computeIfAbsent(classElement.getName(), s -> {
if (classElement.hasAnnotation("io.micronaut.data.annotation.Embeddable")) {
embeddedMappedEntityVisitor.visitClass(classElement, context);
} else {
mappedEntityVisitor.visitClass(classElement, context);
}
return new SourcePersistentEntity(classElement, this);
});
}
};
if (element.hasDeclaredStereotype(Repository.class)) {
visitedRepositories.add(interfaceName);
currentRepository = element;
queryEncoder = QueryBuilder.newQueryBuilder(element.getAnnotationMetadata());
this.dataTypes = Utils.getConfiguredDataTypes(currentRepository);
AnnotationMetadata annotationMetadata = element.getAnnotationMetadata();
List<AnnotationValue<TypeRole>> roleArray = annotationMetadata.findAnnotation(RepositoryConfiguration.class).map(av -> av.getAnnotations("typeRoles", TypeRole.class)).orElse(Collections.emptyList());
for (AnnotationValue<TypeRole> parameterRole : roleArray) {
String role = parameterRole.stringValue("role").orElse(null);
AnnotationClassValue cv = parameterRole.get("type", AnnotationClassValue.class).orElse(null);
if (StringUtils.isNotEmpty(role) && cv != null) {
context.getClassElement(cv.getName()).ifPresent(ce -> typeRoles.put(ce.getName(), role));
}
}
if (element.isAssignable(SPRING_REPO)) {
context.getClassElement("org.springframework.data.domain.Pageable").ifPresent(ce -> typeRoles.put(ce.getName(), TypeRole.PAGEABLE));
context.getClassElement("org.springframework.data.domain.Page").ifPresent(ce -> typeRoles.put(ce.getName(), TypeRole.PAGE));
context.getClassElement("org.springframework.data.domain.Slice").ifPresent(ce -> typeRoles.put(ce.getName(), TypeRole.SLICE));
context.getClassElement("org.springframework.data.domain.Sort").ifPresent(ce -> typeRoles.put(ce.getName(), TypeRole.SORT));
}
if (queryEncoder == null) {
context.fail("QueryEncoder not present on annotation processor path", element);
failing = true;
}
}
}
use of io.micronaut.data.processor.model.SourcePersistentEntity in project micronaut-data by micronaut-projects.
the class RepositoryTypeElementVisitor method processMethodInfo.
private void processMethodInfo(MethodMatchContext methodMatchContext, MethodMatchInfo methodInfo) {
QueryBuilder queryEncoder = methodMatchContext.getQueryBuilder();
MethodElement element = methodMatchContext.getMethodElement();
SourcePersistentEntity entity = methodMatchContext.getRootEntity();
ParameterElement[] parameters = methodMatchContext.getParameters();
// populate parameter roles
for (Map.Entry<String, Element> entry : methodMatchContext.getParametersInRole().entrySet()) {
methodInfo.addParameterRole(entry.getKey(), entry.getValue().getName());
}
List<QueryParameterBinding> parameterBinding = null;
boolean encodeEntityParameters = false;
boolean supportsImplicitQueries = methodMatchContext.supportsImplicitQueries();
QueryResult queryResult = methodInfo.getQueryResult();
if (queryResult != null) {
if (methodInfo.isRawQuery()) {
// no need to annotation since already annotated, just replace the
// the computed parameter names
parameterBinding = queryResult.getParameterBindings();
element.annotate(Query.class, (builder) -> builder.member(DataMethod.META_MEMBER_RAW_QUERY, element.stringValue(Query.class).map(q -> addRawQueryParameterPlaceholders(queryEncoder, queryResult.getQuery(), queryResult.getQueryParts())).orElse(null)));
ClassElement genericReturnType = methodMatchContext.getReturnType();
if (methodMatchContext.isTypeInRole(genericReturnType, TypeRole.PAGE) || element.isPresent(Query.class, "countQuery")) {
QueryResult countQueryResult = methodInfo.getCountQueryResult();
if (countQueryResult == null) {
throw new MatchFailedException("Query returns a Page and does not specify a 'countQuery' member.", element);
} else {
element.annotate(Query.class, (builder) -> builder.member(DataMethod.META_MEMBER_RAW_COUNT_QUERY, addRawQueryParameterPlaceholders(queryEncoder, countQueryResult.getQuery(), countQueryResult.getQueryParts())));
}
}
encodeEntityParameters = methodInfo.isEncodeEntityParameters();
} else {
encodeEntityParameters = methodInfo.isEncodeEntityParameters();
parameterBinding = queryResult.getParameterBindings();
bindAdditionalParameters(methodMatchContext, entity, parameterBinding, parameters, queryResult.getAdditionalRequiredParameters());
QueryResult preparedCount = methodInfo.getCountQueryResult();
if (preparedCount != null) {
element.annotate(Query.class, annotationBuilder -> {
annotationBuilder.value(queryResult.getQuery());
annotationBuilder.member(DataMethod.META_MEMBER_COUNT_QUERY, preparedCount.getQuery());
});
} else {
element.annotate(Query.class, annotationBuilder -> {
annotationBuilder.value(queryResult.getQuery());
String update = queryResult.getUpdate();
if (StringUtils.isNotEmpty(update)) {
annotationBuilder.member("update", update);
}
});
}
}
}
ClassElement runtimeInterceptor = methodInfo.getRuntimeInterceptor();
if (runtimeInterceptor == null) {
throw new MatchFailedException("Unable to implement Repository method: " + currentRepository.getSimpleName() + "." + element.getName() + "(..). No possible runtime implementations found.", element);
}
boolean finalEncodeEntityParameters = encodeEntityParameters;
List<QueryParameterBinding> finalParameterBinding = parameterBinding;
element.annotate(DataMethod.class, annotationBuilder -> {
annotationBuilder.member(DataMethod.META_MEMBER_OPERATION_TYPE, methodInfo.getOperationType());
annotationBuilder.member(DataMethod.META_MEMBER_ROOT_ENTITY, new AnnotationClassValue<>(entity.getName()));
// include the roles
methodInfo.getParameterRoles().forEach(annotationBuilder::member);
if (methodInfo.isDto()) {
annotationBuilder.member(DataMethod.META_MEMBER_DTO, true);
}
if (methodInfo.isOptimisticLock()) {
annotationBuilder.member(DataMethod.META_MEMBER_OPTIMISTIC_LOCK, true);
}
TypedElement resultType = methodInfo.getResultType();
if (resultType != null) {
annotationBuilder.member(DataMethod.META_MEMBER_RESULT_TYPE, new AnnotationClassValue<>(resultType.getName()));
ClassElement type = resultType.getType();
if (!TypeUtils.isVoid(type)) {
annotationBuilder.member(DataMethod.META_MEMBER_RESULT_DATA_TYPE, TypeUtils.resolveDataType(type, dataTypes));
}
}
String idType = resolveIdType(entity);
if (idType != null) {
annotationBuilder.member(DataMethod.META_MEMBER_ID_TYPE, idType);
}
annotationBuilder.member(DataMethod.META_MEMBER_INTERCEPTOR, new AnnotationClassValue<>(runtimeInterceptor.getName()));
if (queryResult != null) {
if (finalParameterBinding.stream().anyMatch(QueryParameterBinding::isExpandable)) {
annotationBuilder.member(DataMethod.META_MEMBER_EXPANDABLE_QUERY, queryResult.getQueryParts().toArray(new String[0]));
QueryResult preparedCount = methodInfo.getCountQueryResult();
if (preparedCount != null) {
annotationBuilder.member(DataMethod.META_MEMBER_EXPANDABLE_COUNT_QUERY, preparedCount.getQueryParts().toArray(new String[0]));
}
}
int max = queryResult.getMax();
if (max > -1) {
annotationBuilder.member(DataMethod.META_MEMBER_PAGE_SIZE, max);
}
long offset = queryResult.getOffset();
if (offset > 0) {
annotationBuilder.member(DataMethod.META_MEMBER_PAGE_INDEX, offset);
}
}
Arrays.stream(parameters).filter(p -> p.getGenericType().isAssignable(entity.getName())).findFirst().ifPresent(parameterElement -> annotationBuilder.member(DataMethod.META_MEMBER_ENTITY, parameterElement.getName()));
if (CollectionUtils.isNotEmpty(finalParameterBinding)) {
bindParameters(supportsImplicitQueries, finalParameterBinding, finalEncodeEntityParameters, annotationBuilder);
}
});
}
use of io.micronaut.data.processor.model.SourcePersistentEntity in project micronaut-data by micronaut-projects.
the class UpdateMethodMatcher method batchUpdate.
private UpdateCriteriaMethodMatch batchUpdate(java.util.regex.Matcher matcher, ParameterElement idParameter) {
return new UpdateCriteriaMethodMatch(matcher) {
@Override
protected <T> void applyPredicates(String querySequence, ParameterElement[] parameters, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
super.applyPredicates(querySequence, parameters, root, query, cb);
ParameterElement versionParameter = Arrays.stream(parameters).filter(p -> p.hasAnnotation(Version.class)).findFirst().orElse(null);
Predicate predicate;
if (versionParameter != null) {
predicate = cb.and(cb.equal(root.id(), cb.parameter(idParameter)), cb.equal(root.version(), cb.parameter(versionParameter)));
} else {
predicate = cb.equal(root.id(), cb.parameter(idParameter));
}
query.where(predicate);
}
@Override
protected <T> void applyPredicates(List<ParameterElement> parameters, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
ParameterElement versionParameter = parameters.stream().filter(p -> p.hasAnnotation(Version.class)).findFirst().orElse(null);
Predicate predicate;
if (versionParameter != null) {
predicate = cb.and(cb.equal(root.id(), cb.parameter(idParameter)), cb.equal(root.version(), cb.parameter(versionParameter)));
} else {
predicate = cb.equal(root.id(), cb.parameter(idParameter));
}
query.where(predicate);
}
@Override
protected <T> void addPropertiesToUpdate(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
List<ParameterElement> parameters = matchContext.getParametersNotInRole();
List<ParameterElement> remainingParameters = parameters.stream().filter(p -> !p.hasAnnotation(Id.class) && !p.hasAnnotation(Version.class)).collect(Collectors.toList());
ParameterElement idParameter = parameters.stream().filter(p -> p.hasAnnotation(Id.class)).findFirst().orElse(null);
if (idParameter == null) {
throw new MatchFailedException("ID required for update method, but not specified");
}
SourcePersistentEntity entity = (SourcePersistentEntity) root.getPersistentEntity();
// Validate @IdClass for composite entity
if (entity.hasIdentity()) {
SourcePersistentProperty identity = entity.getIdentity();
String idType = TypeUtils.getTypeName(identity.getType());
String idParameterType = TypeUtils.getTypeName(idParameter.getType());
if (!idType.equals(idParameterType)) {
throw new MatchFailedException("ID type of method [" + idParameterType + "] does not match ID type of entity: " + idType);
}
} else {
throw new MatchFailedException("Cannot update by ID for entity that has no ID");
}
for (ParameterElement parameter : remainingParameters) {
String name = getParameterName(parameter);
SourcePersistentProperty prop = entity.getPropertyByName(name);
if (prop == null) {
throw new MatchFailedException("Cannot update non-existent property: " + name);
} else {
if (prop.isGenerated()) {
throw new MatchFailedException("Cannot update a generated property: " + name);
} else {
query.set(name, cb.parameter(parameter));
}
}
}
}
};
}
Aggregations