Search in sources :

Example 1 with DataInterceptor

use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.

the class UpdateMethodMatcher method entityUpdate.

private UpdateCriteriaMethodMatch entityUpdate(java.util.regex.Matcher matcher, ParameterElement entityParameter, ParameterElement entitiesParameter) {
    return new UpdateCriteriaMethodMatch(matcher) {

        ParameterElement entityParam = entityParameter == null ? entitiesParameter : entityParameter;

        @Override
        protected <T> void applyPredicates(List<ParameterElement> parameters, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
            final SourcePersistentEntity rootEntity = (SourcePersistentEntity) root.getPersistentEntity();
            Predicate predicate;
            if (rootEntity.getVersion() != null) {
                predicate = cb.and(cb.equal(root.id(), cb.entityPropertyParameter(entityParam)), cb.equal(root.version(), cb.entityPropertyParameter(entityParam)));
            } else {
                predicate = cb.equal(root.id(), cb.entityPropertyParameter(entityParam));
            }
            query.where(predicate);
        }

        @Override
        protected <T> void addPropertiesToUpdate(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
            final SourcePersistentEntity rootEntity = matchContext.getRootEntity();
            Stream.concat(rootEntity.getPersistentProperties().stream(), Stream.of(rootEntity.getVersion())).filter(p -> p != null && !((p instanceof Association) && ((Association) p).isForeignKey()) && !p.isGenerated() && p.findAnnotation(AutoPopulated.class).map(ap -> ap.getRequiredValue(AutoPopulated.UPDATEABLE, Boolean.class)).orElse(true)).forEach(p -> query.set(p.getName(), cb.entityPropertyParameter(entityParam)));
            if (((AbstractPersistentEntityCriteriaUpdate<T>) query).getUpdateValues().isEmpty()) {
                // Workaround for only ID entities
                query.set(rootEntity.getIdentity().getName(), cb.entityPropertyParameter(entityParam));
            }
        }

        @Override
        protected boolean supportedByImplicitQueries() {
            return true;
        }

        @Override
        protected Map.Entry<ClassElement, Class<? extends DataInterceptor>> resolveReturnTypeAndInterceptor(MethodMatchContext matchContext) {
            Map.Entry<ClassElement, Class<? extends DataInterceptor>> e = super.resolveReturnTypeAndInterceptor(matchContext);
            ClassElement returnType = e.getKey();
            if (returnType != null && !TypeUtils.isVoid(returnType) && !TypeUtils.isNumber(returnType) && !returnType.hasStereotype(MappedEntity.class) && !(TypeUtils.isReactiveOrFuture(matchContext.getReturnType()) && TypeUtils.isObjectClass(returnType))) {
                throw new MatchFailedException("Cannot implement update method for specified return type: " + returnType.getName());
            }
            return e;
        }

        @Override
        protected ParameterElement getEntityParameter() {
            return entityParameter;
        }

        @Override
        protected ParameterElement getEntitiesParameter() {
            return entitiesParameter;
        }
    };
}
Also used : SourcePersistentEntityCriteriaBuilder(io.micronaut.data.processor.model.criteria.SourcePersistentEntityCriteriaBuilder) Arrays(java.util.Arrays) Parameter(io.micronaut.context.annotation.Parameter) MappedEntity(io.micronaut.data.annotation.MappedEntity) ParameterExpression(jakarta.persistence.criteria.ParameterExpression) SourcePersistentProperty(io.micronaut.data.processor.model.SourcePersistentProperty) ClassElement(io.micronaut.inject.ast.ClassElement) Internal(io.micronaut.core.annotation.Internal) AbstractPersistentEntityCriteriaUpdate(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaUpdate) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ParameterElement(io.micronaut.inject.ast.ParameterElement) Version(io.micronaut.data.annotation.Version) Map(java.util.Map) Id(io.micronaut.data.annotation.Id) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) UpdateCriteriaMethodMatch(io.micronaut.data.processor.visitors.finders.criteria.UpdateCriteriaMethodMatch) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) Predicate(jakarta.persistence.criteria.Predicate) AutoPopulated(io.micronaut.data.annotation.AutoPopulated) Set(java.util.Set) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) Collectors(java.util.stream.Collectors) PersistentEntityCriteriaUpdate(io.micronaut.data.model.jpa.criteria.PersistentEntityCriteriaUpdate) PersistentEntityRoot(io.micronaut.data.model.jpa.criteria.PersistentEntityRoot) List(java.util.List) Association(io.micronaut.data.model.Association) Stream(java.util.stream.Stream) MethodMatchContext(io.micronaut.data.processor.visitors.MethodMatchContext) MethodElement(io.micronaut.inject.ast.MethodElement) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) MappedEntity(io.micronaut.data.annotation.MappedEntity) ClassElement(io.micronaut.inject.ast.ClassElement) Predicate(jakarta.persistence.criteria.Predicate) SourcePersistentEntityCriteriaBuilder(io.micronaut.data.processor.model.criteria.SourcePersistentEntityCriteriaBuilder) MethodMatchContext(io.micronaut.data.processor.visitors.MethodMatchContext) Association(io.micronaut.data.model.Association) PersistentEntityRoot(io.micronaut.data.model.jpa.criteria.PersistentEntityRoot) AbstractPersistentEntityCriteriaUpdate(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaUpdate) PersistentEntityCriteriaUpdate(io.micronaut.data.model.jpa.criteria.PersistentEntityCriteriaUpdate) UpdateCriteriaMethodMatch(io.micronaut.data.processor.visitors.finders.criteria.UpdateCriteriaMethodMatch) List(java.util.List) ParameterElement(io.micronaut.inject.ast.ParameterElement) Map(java.util.Map) AutoPopulated(io.micronaut.data.annotation.AutoPopulated)

Example 2 with DataInterceptor

use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.

the class UpdateCriteriaMethodMatch method build.

@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
    MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
    PersistentEntityCriteriaUpdate<Object> criteriaQuery = cb.createCriteriaUpdate(null);
    apply(matchContext, criteriaQuery.from(matchContext.getRootEntity()), criteriaQuery, cb);
    Map.Entry<ClassElement, Class<? extends DataInterceptor>> entry = resolveReturnTypeAndInterceptor(matchContext);
    ClassElement resultType = entry.getKey();
    Class<? extends DataInterceptor> interceptorType = entry.getValue();
    AbstractPersistentEntityCriteriaUpdate<?> criteriaUpdate = (AbstractPersistentEntityCriteriaUpdate<?>) criteriaQuery;
    boolean optimisticLock = criteriaUpdate.hasVersionRestriction();
    final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
    QueryBuilder queryBuilder = matchContext.getQueryBuilder();
    Map<String, Object> propertiesToUpdate = criteriaUpdate.getUpdateValues();
    QueryModel queryModel = ((AbstractPersistentEntityCriteriaUpdate) criteriaQuery).getQueryModel();
    QueryResult queryResult = queryBuilder.buildUpdate(annotationMetadataHierarchy, queryModel, propertiesToUpdate);
    return new MethodMatchInfo(DataMethod.OperationType.UPDATE, resultType, getInterceptorElement(matchContext, interceptorType)).optimisticLock(optimisticLock).queryResult(queryResult);
}
Also used : DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ClassElement(io.micronaut.inject.ast.ClassElement) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) QueryModel(io.micronaut.data.model.query.QueryModel) AbstractPersistentEntityCriteriaUpdate(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaUpdate) QueryResult(io.micronaut.data.model.query.builder.QueryResult) MethodMatchInfo(io.micronaut.data.processor.visitors.finders.MethodMatchInfo) MethodMatchSourcePersistentEntityCriteriaBuilderImpl(io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl) Map(java.util.Map)

Example 3 with DataInterceptor

use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.

the class AbstractCriteriaMethodMatch method buildMatchInfo.

@Override
public final MethodMatchInfo buildMatchInfo(MethodMatchContext matchContext) {
    MethodMatchInfo methodMatchInfo;
    if (supportedByImplicitQueries() && matchContext.supportsImplicitQueries() && hasNoWhereAndJoinDeclaration(matchContext)) {
        Map.Entry<ClassElement, Class<? extends DataInterceptor>> entry = resolveReturnTypeAndInterceptor(matchContext);
        methodMatchInfo = new MethodMatchInfo(getOperationType(), entry.getKey(), getInterceptorElement(matchContext, entry.getValue()));
    } else {
        methodMatchInfo = build(matchContext);
    }
    ParameterElement entityParameter = getEntityParameter();
    ParameterElement entitiesParameter = getEntitiesParameter();
    ParameterElement idParameter = Arrays.stream(matchContext.getParameters()).filter(p -> p.hasAnnotation(Id.class)).findFirst().orElse(null);
    if (idParameter != null) {
        methodMatchInfo.addParameterRole(TypeRole.ID, idParameter.stringValue(Parameter.class).orElse(idParameter.getName()));
    }
    if (entityParameter != null) {
        methodMatchInfo.encodeEntityParameters(true);
        methodMatchInfo.addParameterRole(TypeRole.ENTITY, entityParameter.getName());
    } else if (entitiesParameter != null) {
        methodMatchInfo.encodeEntityParameters(true);
        methodMatchInfo.addParameterRole(TypeRole.ENTITIES, entitiesParameter.getName());
    }
    return methodMatchInfo;
}
Also used : DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ClassElement(io.micronaut.inject.ast.ClassElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) Id(io.micronaut.data.annotation.Id) Map(java.util.Map)

Example 4 with DataInterceptor

use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.

the class RawQueryMethodMatcher method match.

@Override
public MethodMatch match(MethodMatchContext matchContext) {
    if (matchContext.getMethodElement().stringValue(Query.class).isPresent()) {
        return new MethodMatch() {

            @Override
            public MethodMatchInfo buildMatchInfo(MethodMatchContext matchContext) {
                MethodElement methodElement = matchContext.getMethodElement();
                ParameterElement[] parameters = matchContext.getParameters();
                ParameterElement entityParameter;
                ParameterElement entitiesParameter;
                if (parameters.length > 1) {
                    entityParameter = null;
                    entitiesParameter = null;
                } else {
                    entityParameter = Arrays.stream(parameters).filter(p -> TypeUtils.isEntity(p.getGenericType())).findFirst().orElse(null);
                    entitiesParameter = Arrays.stream(parameters).filter(p -> TypeUtils.isIterableOfEntity(p.getGenericType())).findFirst().orElse(null);
                }
                boolean readOnly = matchContext.getAnnotationMetadata().booleanValue(Query.class, "readOnly").orElse(true);
                String query = matchContext.getAnnotationMetadata().stringValue(Query.class).orElseThrow(IllegalStateException::new);
                DataMethod.OperationType operationType = findOperationType(methodElement.getName(), query, readOnly);
                Map.Entry<ClassElement, Class<? extends DataInterceptor>> entry = FindersUtils.resolveInterceptorTypeByOperationType(entityParameter != null, entitiesParameter != null, operationType, matchContext);
                ClassElement resultType = entry.getKey();
                Class<? extends DataInterceptor> interceptorType = entry.getValue();
                if (interceptorType.getSimpleName().startsWith("SaveOne")) {
                    // Use `executeUpdate` operation for "insert(String a, String b)" style queries
                    // - custom query doesn't need to use root entity
                    // - we would like to know how many rows were updated
                    operationType = DataMethod.OperationType.UPDATE;
                    Map.Entry<ClassElement, Class<? extends DataInterceptor>> e = FindersUtils.pickUpdateInterceptor(matchContext, matchContext.getReturnType());
                    resultType = e.getKey();
                    interceptorType = e.getValue();
                }
                if (operationType == DataMethod.OperationType.QUERY) {
                    // Entity parameter/parameters only make sense if the operation is based on entity
                    entityParameter = null;
                    entitiesParameter = null;
                }
                boolean isDto = false;
                if (resultType == null) {
                    resultType = matchContext.getRootEntity().getType();
                } else {
                    if (operationType == DataMethod.OperationType.QUERY) {
                        if (resultType.hasAnnotation(Introspected.class)) {
                            if (!resultType.hasAnnotation(MappedEntity.class)) {
                                isDto = true;
                            }
                        }
                    } else if (!isValidReturnType(resultType, operationType)) {
                        throw new MatchFailedException("Invalid result type: " + resultType.getName() + " for '" + operationType + "' operation");
                    }
                }
                MethodMatchInfo methodMatchInfo = new MethodMatchInfo(operationType, resultType, FindersUtils.getInterceptorElement(matchContext, interceptorType));
                methodMatchInfo.dto(isDto);
                buildRawQuery(matchContext, methodMatchInfo, entityParameter, entitiesParameter, operationType);
                if (entityParameter != null) {
                    methodMatchInfo.addParameterRole(TypeRole.ENTITY, entityParameter.getName());
                } else if (entitiesParameter != null) {
                    methodMatchInfo.addParameterRole(TypeRole.ENTITIES, entitiesParameter.getName());
                }
                return methodMatchInfo;
            }
        };
    }
    return null;
}
Also used : QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) Arrays(java.util.Arrays) Parameter(io.micronaut.context.annotation.Parameter) RepositoryConfiguration(io.micronaut.data.annotation.RepositoryConfiguration) TypeRole(io.micronaut.data.annotation.TypeRole) MappedEntity(io.micronaut.data.annotation.MappedEntity) ClassElement(io.micronaut.inject.ast.ClassElement) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) DataMethod(io.micronaut.data.intercept.annotation.DataMethod) Locale(java.util.Locale) Map(java.util.Map) QueryResult(io.micronaut.data.model.query.builder.QueryResult) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) SourceParameterExpressionImpl(io.micronaut.data.processor.model.criteria.impl.SourceParameterExpressionImpl) BindingContext(io.micronaut.data.model.query.BindingParameter.BindingContext) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) Query(io.micronaut.data.annotation.Query) Utils(io.micronaut.data.processor.visitors.Utils) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) Introspected(io.micronaut.core.annotation.Introspected) NonNull(io.micronaut.core.annotation.NonNull) List(java.util.List) MethodMatchContext(io.micronaut.data.processor.visitors.MethodMatchContext) MethodElement(io.micronaut.inject.ast.MethodElement) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Collections(java.util.Collections) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) Query(io.micronaut.data.annotation.Query) MappedEntity(io.micronaut.data.annotation.MappedEntity) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement) MethodMatchContext(io.micronaut.data.processor.visitors.MethodMatchContext) DataMethod(io.micronaut.data.intercept.annotation.DataMethod) ParameterElement(io.micronaut.inject.ast.ParameterElement) Map(java.util.Map)

Example 5 with DataInterceptor

use of io.micronaut.data.intercept.DataInterceptor in project micronaut-coherence by micronaut-projects.

the class CoherenceDataIntroductionAdvice method intercept.

@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    RepositoryMethodKey key = new RepositoryMethodKey(context.getTarget(), context.getExecutableMethod());
    DataInterceptor<Object, Object> dataInterceptor = interceptorMap.get(key);
    if (dataInterceptor == null) {
        String dataSourceName = context.stringValue(Repository.class).orElse(null);
        Class<?> operationsType = context.classValue(RepositoryConfiguration.class, "operations").orElse(PrimaryRepositoryOperations.class);
        Class<?> interceptorType = context.classValue(DataMethod.class, DataMethod.META_MEMBER_INTERCEPTOR).orElse(null);
        if (interceptorType != null && DataInterceptor.class.isAssignableFrom(interceptorType)) {
            DataInterceptor<Object, Object> childInterceptor = findInterceptor(dataSourceName, operationsType, interceptorType);
            interceptorMap.put(key, childInterceptor);
            return childInterceptor.intercept(key, context);
        } else {
            final AnnotationValue<DataMethod> declaredAnnotation = context.getDeclaredAnnotation(DataMethod.class);
            if (declaredAnnotation != null) {
                interceptorType = declaredAnnotation.classValue(DataMethod.META_MEMBER_INTERCEPTOR).orElse(null);
                if (interceptorType != null && DataInterceptor.class.isAssignableFrom(interceptorType)) {
                    DataInterceptor<Object, Object> childInterceptor = findInterceptor(dataSourceName, operationsType, interceptorType);
                    interceptorMap.put(key, childInterceptor);
                    return childInterceptor.intercept(key, context);
                }
            }
            final String interceptorName = context.getAnnotationMetadata().stringValue(DataMethod.class, DataMethod.META_MEMBER_INTERCEPTOR).orElse(null);
            if (interceptorName != null) {
                throw new IllegalStateException("Micronaut Data Interceptor [" + interceptorName + "] is not on" + " the classpath but required by the method: " + context.getExecutableMethod());
            }
            throw new IllegalStateException("Micronaut Data method is missing compilation time query " + "information. Ensure that the Micronaut Data annotation processors are declared in your" + " build and try again with a clean re-build.");
        }
    } else {
        return dataInterceptor.intercept(key, context);
    }
}
Also used : Repository(io.micronaut.data.annotation.Repository) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) DataMethod(io.micronaut.data.intercept.annotation.DataMethod) RepositoryMethodKey(io.micronaut.data.intercept.RepositoryMethodKey) RepositoryConfiguration(io.micronaut.data.annotation.RepositoryConfiguration)

Aggregations

DataInterceptor (io.micronaut.data.intercept.DataInterceptor)11 Map (java.util.Map)10 ClassElement (io.micronaut.inject.ast.ClassElement)9 NonNull (io.micronaut.core.annotation.NonNull)5 DataMethod (io.micronaut.data.intercept.annotation.DataMethod)5 QueryResult (io.micronaut.data.model.query.builder.QueryResult)5 MatchFailedException (io.micronaut.data.processor.visitors.MatchFailedException)5 MethodMatchContext (io.micronaut.data.processor.visitors.MethodMatchContext)5 ParameterElement (io.micronaut.inject.ast.ParameterElement)5 Parameter (io.micronaut.context.annotation.Parameter)4 MappedEntity (io.micronaut.data.annotation.MappedEntity)4 SourcePersistentEntity (io.micronaut.data.processor.model.SourcePersistentEntity)4 MethodElement (io.micronaut.inject.ast.MethodElement)4 List (java.util.List)4 RepositoryConfiguration (io.micronaut.data.annotation.RepositoryConfiguration)3 PersistentPropertyPath (io.micronaut.data.model.PersistentPropertyPath)3 AnnotationMetadataHierarchy (io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy)3 MethodMatchInfo (io.micronaut.data.processor.visitors.finders.MethodMatchInfo)3 Introspected (io.micronaut.core.annotation.Introspected)2 Id (io.micronaut.data.annotation.Id)2