Search in sources :

Example 1 with AnnotationMetadataHierarchy

use of io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy 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 2 with AnnotationMetadataHierarchy

use of io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy in project micronaut-data by micronaut-projects.

the class AbstractCriteriaMethodMatch method hasNoWhereAndJoinDeclaration.

protected final boolean hasNoWhereAndJoinDeclaration(@NonNull MethodMatchContext matchContext) {
    if (matchContext.getMethodElement().hasAnnotation(Join.class)) {
        return false;
    }
    final boolean repositoryHasWhere = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass(), matchContext.getMethodElement()).hasAnnotation(Where.class);
    final boolean entityHasWhere = matchContext.getRootEntity().hasAnnotation(Where.class);
    return !repositoryHasWhere && !entityHasWhere;
}
Also used : AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy)

Example 3 with AnnotationMetadataHierarchy

use of io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy in project micronaut-data by micronaut-projects.

the class SaveOneMethodMatcher method match.

@Override
protected MethodMatch match(MethodMatchContext matchContext, java.util.regex.Matcher matcher) {
    List<ParameterElement> parameters = matchContext.getParametersNotInRole();
    if (parameters.size() == 0 || TypeUtils.isEntity(parameters.get(0).getGenericType()) || TypeUtils.isIterableOfEntity(parameters.get(0).getGenericType()) || !isValidSaveReturnType(matchContext, true)) {
        return null;
    }
    return new MethodMatch() {

        @Override
        public MethodMatchInfo buildMatchInfo(MethodMatchContext matchContext) {
            List<ParameterElement> parameters = matchContext.getParametersNotInRole();
            SourcePersistentEntity rootEntity = matchContext.getRootEntity();
            ClassElement returnType = matchContext.getReturnType();
            if (TypeUtils.isReactiveOrFuture(returnType)) {
                returnType = returnType.getFirstTypeArgument().orElse(null);
            }
            if (returnType == null || !TypeUtils.isNumber(returnType) && !rootEntity.getName().equals(returnType.getName())) {
                throw new MatchFailedException("The return type of the save method must be the same as the root entity type: " + rootEntity.getName());
            }
            Set<String> requiredProps = rootEntity.getPersistentProperties().stream().filter(this::isRequiredProperty).map(PersistentProperty::getName).collect(Collectors.toSet());
            ParameterElement[] parameterElements = rootEntity.getClassElement().getPrimaryConstructor().map(MethodElement::getParameters).orElse(null);
            Map<String, ParameterElement> constructorArgs = new HashMap<>(10);
            if (ArrayUtils.isNotEmpty(parameterElements)) {
                for (ParameterElement parameterElement : parameterElements) {
                    constructorArgs.put(getParameterValue(parameterElement), parameterElement);
                }
            }
            for (ParameterElement parameter : parameters) {
                String name = getParameterValue(parameter);
                ClassElement type = parameter.getGenericType();
                SourcePersistentProperty prop = rootEntity.getPropertyByName(name);
                ParameterElement constructorArg = constructorArgs.get(name);
                if (prop == null && constructorArg == null) {
                    throw new MatchFailedException("Cannot save with non-existent property or constructor argument: " + name);
                }
                if (prop != null) {
                    String typeName = prop.getTypeName();
                    if (!type.isAssignable(typeName) && !typeName.equals(type.getName())) {
                        throw new MatchFailedException("Type mismatch. Found parameter of type [" + type.getName() + "]. Required property of type: " + typeName);
                    }
                    requiredProps.remove(name);
                } else {
                    ClassElement argType = constructorArg.getGenericType();
                    String typeName = argType.getName();
                    if (!type.isAssignable(typeName) && !typeName.equals(type.getName())) {
                        throw new MatchFailedException("Type mismatch. Found parameter of type [" + type.getName() + "]. Required constructor argument of: " + typeName);
                    }
                }
                constructorArgs.remove(name);
            }
            if (!requiredProps.isEmpty()) {
                throw new MatchFailedException("Save method missing required properties: " + requiredProps);
            }
            if (!constructorArgs.isEmpty()) {
                Collection<ParameterElement> values = constructorArgs.values();
                Set<String> names = values.stream().filter(pe -> {
                    SourcePersistentProperty prop = rootEntity.getPropertyByName(pe.getName());
                    return prop != null && prop.isRequired() && !prop.getType().isPrimitive();
                }).map(p -> getParameterValue(p)).collect(Collectors.toSet());
                if (CollectionUtils.isNotEmpty(names)) {
                    throw new MatchFailedException("Save method missing required constructor arguments: " + names);
                }
            }
            final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
            Map.Entry<ClassElement, Class<? extends DataInterceptor>> e = FindersUtils.pickSaveOneInterceptor(matchContext, matchContext.getReturnType());
            return new MethodMatchInfo(DataMethod.OperationType.INSERT, e.getKey(), getInterceptorElement(matchContext, e.getValue())).encodeEntityParameters(true).queryResult(matchContext.getQueryBuilder().buildInsert(annotationMetadataHierarchy, matchContext.getRootEntity()));
        }

        private boolean isRequiredProperty(SourcePersistentProperty pp) {
            return pp.isRequired() && !ClassUtils.getPrimitiveType(pp.getTypeName()).isPresent();
        }
    };
}
Also used : Parameter(io.micronaut.context.annotation.Parameter) ArrayUtils(io.micronaut.core.util.ArrayUtils) MappedEntity(io.micronaut.data.annotation.MappedEntity) SourcePersistentProperty(io.micronaut.data.processor.model.SourcePersistentProperty) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ParameterElement(io.micronaut.inject.ast.ParameterElement) DataMethod(io.micronaut.data.intercept.annotation.DataMethod) MatchContext(io.micronaut.data.processor.visitors.MatchContext) Map(java.util.Map) FindersUtils.getInterceptorElement(io.micronaut.data.processor.visitors.finders.FindersUtils.getInterceptorElement) PersistentProperty(io.micronaut.data.model.PersistentProperty) ClassUtils(io.micronaut.core.reflect.ClassUtils) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) Collection(java.util.Collection) Set(java.util.Set) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) Collectors(java.util.stream.Collectors) NonNull(io.micronaut.core.annotation.NonNull) List(java.util.List) MethodMatchContext(io.micronaut.data.processor.visitors.MethodMatchContext) CollectionUtils(io.micronaut.core.util.CollectionUtils) MethodElement(io.micronaut.inject.ast.MethodElement) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) HashMap(java.util.HashMap) ClassElement(io.micronaut.inject.ast.ClassElement) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) MethodMatchContext(io.micronaut.data.processor.visitors.MethodMatchContext) SourcePersistentProperty(io.micronaut.data.processor.model.SourcePersistentProperty) ParameterElement(io.micronaut.inject.ast.ParameterElement) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with AnnotationMetadataHierarchy

use of io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy in project micronaut-data by micronaut-projects.

the class DeleteCriteriaMethodMatch method build.

@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
    MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
    PersistentEntityCriteriaDelete<Object> criteriaQuery = cb.createCriteriaDelete(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();
    boolean optimisticLock = ((AbstractPersistentEntityCriteriaDelete<?>) criteriaQuery).hasVersionRestriction();
    final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
    QueryBuilder queryBuilder = matchContext.getQueryBuilder();
    QueryModel queryModel = ((QueryModelPersistentEntityCriteriaQuery) criteriaQuery).getQueryModel();
    QueryResult queryResult = queryBuilder.buildDelete(annotationMetadataHierarchy, queryModel);
    return new MethodMatchInfo(DataMethod.OperationType.DELETE, 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) QueryModelPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.QueryModelPersistentEntityCriteriaQuery) 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) AbstractPersistentEntityCriteriaDelete(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaDelete) Map(java.util.Map)

Example 5 with AnnotationMetadataHierarchy

use of io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy in project micronaut-data by micronaut-projects.

the class QueryCriteriaMethodMatch method build.

@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
    ClassElement queryResultType = matchContext.getRootEntity().getClassElement();
    MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
    PersistentEntityCriteriaQuery<Object> criteriaQuery = cb.createQuery();
    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();
    boolean optimisticLock = ((AbstractPersistentEntityCriteriaQuery<?>) criteriaQuery).hasVersionRestriction();
    SourcePersistentEntityCriteriaQuery<?> query = (SourcePersistentEntityCriteriaQuery) criteriaQuery;
    String selectedType = query.getQueryResultTypeName();
    if (selectedType != null) {
        queryResultType = matchContext.getVisitorContext().getClassElement(selectedType).orElse(null);
        if (queryResultType == null) {
            try {
                queryResultType = PrimitiveElement.valueOf(selectedType);
            } catch (Exception e) {
            // Ignore
            }
        }
    }
    boolean isDto = resultType != null && !TypeUtils.areTypesCompatible(resultType, queryResultType) && (isDtoType(resultType) || resultType.hasStereotype(Introspected.class) && queryResultType.hasStereotype(MappedEntity.class));
    if (isDto) {
        if (!isDtoType(resultType)) {
            List<SourcePersistentProperty> dtoProjectionProperties = getDtoProjectionProperties(matchContext.getRootEntity(), resultType);
            if (!dtoProjectionProperties.isEmpty()) {
                Root<?> root = query.getRoots().iterator().next();
                query.multiselect(dtoProjectionProperties.stream().map(p -> {
                    if (matchContext.getQueryBuilder().shouldAliasProjections()) {
                        return root.get(p.getName()).alias(p.getName());
                    } else {
                        return root.get(p.getName());
                    }
                }).collect(Collectors.toList()));
            }
        }
    } else {
        if (resultType == null || (!resultType.isAssignable(void.class) && !resultType.isAssignable(Void.class))) {
            if (resultType == null || TypeUtils.areTypesCompatible(resultType, queryResultType)) {
                if (!queryResultType.isPrimitive() || resultType == null) {
                    resultType = queryResultType;
                }
            } else {
                throw new MatchFailedException("Query results in a type [" + queryResultType.getName() + "] whilst method returns an incompatible type: " + resultType.getName());
            }
        }
    }
    final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
    QueryBuilder queryBuilder = matchContext.getQueryBuilder();
    QueryModel queryModel = ((QueryModelPersistentEntityCriteriaQuery) criteriaQuery).getQueryModel();
    QueryResult queryResult = queryBuilder.buildQuery(annotationMetadataHierarchy, queryModel);
    ClassElement genericReturnType = matchContext.getReturnType();
    if (TypeUtils.isReactiveOrFuture(genericReturnType)) {
        genericReturnType = genericReturnType.getFirstTypeArgument().orElse(matchContext.getRootEntity().getType());
    }
    QueryResult countQueryResult = null;
    if (matchContext.isTypeInRole(genericReturnType, TypeRole.PAGE)) {
        // SourcePersistentEntityCriteriaQuery<Object> count = cb.createQuery();
        // count.select(cb.count(query.getRoots().iterator().next()));
        // CommonAbstractCriteria countQueryCriteria = defineQuery(matchContext, matchContext.getRootEntity(), cb);
        QueryModel countQuery = QueryModel.from(queryModel.getPersistentEntity());
        countQuery.projections().count();
        QueryModel.Junction junction = queryModel.getCriteria();
        for (QueryModel.Criterion criterion : junction.getCriteria()) {
            countQuery.add(criterion);
        }
        for (JoinPath joinPath : queryModel.getJoinPaths()) {
            Join.Type joinType = joinPath.getJoinType();
            switch(joinType) {
                case INNER:
                case FETCH:
                    joinType = Join.Type.DEFAULT;
                    break;
                case LEFT_FETCH:
                    joinType = Join.Type.LEFT;
                    break;
                case RIGHT_FETCH:
                    joinType = Join.Type.RIGHT;
                    break;
                default:
            }
            countQuery.join(joinPath.getPath(), joinType, null);
        }
        countQueryResult = queryBuilder.buildQuery(countQuery);
    }
    return new MethodMatchInfo(DataMethod.OperationType.QUERY, resultType, getInterceptorElement(matchContext, interceptorType)).dto(isDto).optimisticLock(optimisticLock).queryResult(queryResult).countQueryResult(countQueryResult);
}
Also used : MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) JoinPath(io.micronaut.data.model.query.JoinPath) ClassElement(io.micronaut.inject.ast.ClassElement) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) QueryModelPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.QueryModelPersistentEntityCriteriaQuery) QueryResult(io.micronaut.data.model.query.builder.QueryResult) SourcePersistentProperty(io.micronaut.data.processor.model.SourcePersistentProperty) MethodMatchSourcePersistentEntityCriteriaBuilderImpl(io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) Join(io.micronaut.data.annotation.Join) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) QueryModel(io.micronaut.data.model.query.QueryModel) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) SourcePersistentEntityCriteriaQuery(io.micronaut.data.processor.model.criteria.SourcePersistentEntityCriteriaQuery) MethodMatchInfo(io.micronaut.data.processor.visitors.finders.MethodMatchInfo) Map(java.util.Map) AbstractPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaQuery)

Aggregations

AnnotationMetadataHierarchy (io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy)5 DataInterceptor (io.micronaut.data.intercept.DataInterceptor)4 ClassElement (io.micronaut.inject.ast.ClassElement)4 Map (java.util.Map)4 QueryModel (io.micronaut.data.model.query.QueryModel)3 QueryBuilder (io.micronaut.data.model.query.builder.QueryBuilder)3 QueryResult (io.micronaut.data.model.query.builder.QueryResult)3 MethodMatchSourcePersistentEntityCriteriaBuilderImpl (io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl)3 MethodMatchInfo (io.micronaut.data.processor.visitors.finders.MethodMatchInfo)3 QueryModelPersistentEntityCriteriaQuery (io.micronaut.data.model.jpa.criteria.impl.QueryModelPersistentEntityCriteriaQuery)2 SourcePersistentProperty (io.micronaut.data.processor.model.SourcePersistentProperty)2 MatchFailedException (io.micronaut.data.processor.visitors.MatchFailedException)2 Parameter (io.micronaut.context.annotation.Parameter)1 NonNull (io.micronaut.core.annotation.NonNull)1 ClassUtils (io.micronaut.core.reflect.ClassUtils)1 ArrayUtils (io.micronaut.core.util.ArrayUtils)1 CollectionUtils (io.micronaut.core.util.CollectionUtils)1 Join (io.micronaut.data.annotation.Join)1 MappedEntity (io.micronaut.data.annotation.MappedEntity)1 DataMethod (io.micronaut.data.intercept.annotation.DataMethod)1