Search in sources :

Example 1 with PersistentAssociationPath

use of io.micronaut.data.model.PersistentAssociationPath in project micronaut-data by micronaut-projects.

the class AbstractCascadeOperations method afterCascadedOne.

/**
 * Process after a child element has been cascaded.
 *
 * @param entity       The parent entity.
 * @param associations The association leading to the child
 * @param prevChild    The previous child value
 * @param newChild     The new child value
 * @param <T>          The entity type
 * @return The entity instance
 */
protected <T> T afterCascadedOne(T entity, List<Association> associations, Object prevChild, Object newChild) {
    RuntimeAssociation<Object> association = (RuntimeAssociation<Object>) associations.iterator().next();
    if (associations.size() == 1) {
        if (association.isForeignKey()) {
            PersistentAssociationPath inverse = association.getInversePathSide().orElse(null);
            if (inverse != null) {
                // don't cast to BeanProperty<T..> here because its the inverse, so we want to set the entity onto the newChild
                newChild = inverse.setPropertyValue(newChild, entity);
            }
        }
        if (prevChild != newChild) {
            entity = setProperty((BeanProperty<T, Object>) association.getProperty(), entity, newChild);
        }
        return entity;
    } else {
        BeanProperty<T, Object> property = (BeanProperty<T, Object>) association.getProperty();
        Object innerEntity = property.get(entity);
        Object newInnerEntity = afterCascadedOne(innerEntity, associations.subList(1, associations.size()), prevChild, newChild);
        if (newInnerEntity != innerEntity) {
            innerEntity = convertAndSetWithValue(property, entity, newInnerEntity);
        }
        return (T) innerEntity;
    }
}
Also used : RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) PersistentAssociationPath(io.micronaut.data.model.PersistentAssociationPath) BeanProperty(io.micronaut.core.beans.BeanProperty)

Example 2 with PersistentAssociationPath

use of io.micronaut.data.model.PersistentAssociationPath in project micronaut-data by micronaut-projects.

the class SqlResultEntityTypeMapper method setChildrenAndTriggerPostLoad.

private Object setChildrenAndTriggerPostLoad(Object instance, MappingContext<?> ctx, Object parent) {
    if (ctx.manyAssociations != null) {
        List<Object> values = new ArrayList<>(ctx.manyAssociations.size());
        for (MappingContext associationCtx : ctx.manyAssociations.values()) {
            values.add(setChildrenAndTriggerPostLoad(associationCtx.entity, associationCtx, parent));
        }
        return values;
    } else if (ctx.associations != null) {
        for (Map.Entry<Association, MappingContext> e : ctx.associations.entrySet()) {
            MappingContext associationCtx = e.getValue();
            RuntimeAssociation runtimeAssociation = (RuntimeAssociation) e.getKey();
            BeanProperty beanProperty = runtimeAssociation.getProperty();
            if (runtimeAssociation.getKind().isSingleEnded() && (associationCtx.manyAssociations == null || associationCtx.manyAssociations.isEmpty())) {
                Object value = beanProperty.get(instance);
                Object newValue = setChildrenAndTriggerPostLoad(value, associationCtx, instance);
                if (newValue != value) {
                    instance = setProperty(beanProperty, instance, newValue);
                }
            } else {
                Object newValue = setChildrenAndTriggerPostLoad(null, associationCtx, instance);
                newValue = resultReader.convertRequired(newValue == null ? new ArrayList<>() : newValue, beanProperty.getType());
                instance = setProperty(beanProperty, instance, newValue);
            }
        }
    }
    if (instance != null && (ctx.association == null || ctx.jp != null)) {
        if (parent != null && ctx.association != null && ctx.association.isBidirectional()) {
            PersistentAssociationPath inverse = ctx.association.getInversePathSide().orElseThrow(IllegalStateException::new);
            Association association = inverse.getAssociation();
            if (association.getKind().isSingleEnded()) {
                Object inverseInstance = inverse.getPropertyValue(instance);
                if (inverseInstance != parent) {
                    instance = inverse.setPropertyValue(instance, parent);
                }
            }
        }
        triggerPostLoad(ctx.persistentEntity, instance);
    }
    return instance;
}
Also used : RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) Association(io.micronaut.data.model.Association) ArrayList(java.util.ArrayList) RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) PersistentAssociationPath(io.micronaut.data.model.PersistentAssociationPath) BeanProperty(io.micronaut.core.beans.BeanProperty)

Example 3 with PersistentAssociationPath

use of io.micronaut.data.model.PersistentAssociationPath in project micronaut-data by micronaut-projects.

the class AbstractCascadeOperations method afterCascadedMany.

/**
 * Process after a children element has been cascaded.
 *
 * @param entity       The parent entity.
 * @param associations The association leading to the child
 * @param prevChildren The previous children value
 * @param newChildren  The new children value
 * @param <T>          The entity type
 * @return The entity instance
 */
protected <T> T afterCascadedMany(T entity, List<Association> associations, Iterable<Object> prevChildren, List<Object> newChildren) {
    RuntimeAssociation<Object> association = (RuntimeAssociation<Object>) associations.iterator().next();
    if (associations.size() == 1) {
        for (ListIterator<Object> iterator = newChildren.listIterator(); iterator.hasNext(); ) {
            Object c = iterator.next();
            if (association.isForeignKey()) {
                PersistentAssociationPath inverse = association.getInversePathSide().orElse(null);
                if (inverse != null) {
                    Object newc = inverse.setPropertyValue(c, entity);
                    if (c != newc) {
                        iterator.set(newc);
                    }
                }
            }
        }
        if (prevChildren != newChildren) {
            entity = convertAndSetWithValue((BeanProperty<T, Object>) association.getProperty(), entity, newChildren);
        }
        return entity;
    } else {
        BeanProperty<T, Object> property = (BeanProperty<T, Object>) association.getProperty();
        Object innerEntity = property.get(entity);
        Object newInnerEntity = afterCascadedMany(innerEntity, associations.subList(1, associations.size()), prevChildren, newChildren);
        if (newInnerEntity != innerEntity) {
            innerEntity = convertAndSetWithValue(property, entity, newInnerEntity);
        }
        return (T) innerEntity;
    }
}
Also used : RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) PersistentAssociationPath(io.micronaut.data.model.PersistentAssociationPath) BeanProperty(io.micronaut.core.beans.BeanProperty)

Example 4 with PersistentAssociationPath

use of io.micronaut.data.model.PersistentAssociationPath in project micronaut-data by micronaut-projects.

the class AbstractCascadeOperations method cascade.

/**
 * Cascade on the entity instance and collect cascade operations.
 *
 * @param annotationMetadata The annotationMetadata
 * @param repositoryType     The repositoryType
 * @param fkOnly             Is FK only
 * @param cascadeType        The cascadeType
 * @param ctx                The cascade context
 * @param persistentEntity   The persistent entity
 * @param entity             The entity instance
 * @param cascadeOps         The cascade operations
 * @param <T>                The entity type
 */
protected <T> void cascade(AnnotationMetadata annotationMetadata, Class<?> repositoryType, boolean fkOnly, Relation.Cascade cascadeType, CascadeContext ctx, RuntimePersistentEntity<T> persistentEntity, T entity, List<CascadeOp> cascadeOps) {
    for (RuntimeAssociation<T> association : persistentEntity.getAssociations()) {
        BeanProperty<T, Object> beanProperty = (BeanProperty<T, Object>) association.getProperty();
        Object child = beanProperty.get(entity);
        if (child == null) {
            continue;
        }
        if (association instanceof Embedded) {
            cascade(annotationMetadata, repositoryType, fkOnly, cascadeType, ctx.embedded(association), (RuntimePersistentEntity) association.getAssociatedEntity(), child, cascadeOps);
            continue;
        }
        if (association.doesCascade(cascadeType) && (fkOnly || !association.isForeignKey())) {
            if (association.getInverseSide().map(assoc -> ctx.rootAssociations.contains(assoc) || ctx.associations.contains(assoc)).orElse(false)) {
                continue;
            }
            final RuntimePersistentEntity<Object> associatedEntity = (RuntimePersistentEntity<Object>) association.getAssociatedEntity();
            switch(association.getKind()) {
                case ONE_TO_ONE:
                case MANY_TO_ONE:
                    cascadeOps.add(new CascadeOneOp(annotationMetadata, repositoryType, ctx.relation(association), cascadeType, associatedEntity, child));
                    continue;
                case ONE_TO_MANY:
                case MANY_TO_MANY:
                    final PersistentAssociationPath inverse = association.getInversePathSide().orElse(null);
                    Iterable<Object> children = (Iterable<Object>) association.getProperty().get(entity);
                    if (children == null || !children.iterator().hasNext()) {
                        continue;
                    }
                    if (inverse != null && inverse.getAssociation().getKind() == Relation.Kind.MANY_TO_ONE) {
                        List<Object> entities = new ArrayList<>(CollectionUtils.iterableToList(children));
                        for (ListIterator<Object> iterator = entities.listIterator(); iterator.hasNext(); ) {
                            Object c = iterator.next();
                            Object newC = inverse.setPropertyValue(c, entity);
                            if (c != newC) {
                                iterator.set(newC);
                            }
                        }
                        children = entities;
                    }
                    cascadeOps.add(new CascadeManyOp(annotationMetadata, repositoryType, ctx.relation(association), cascadeType, associatedEntity, children));
                    continue;
                default:
                    throw new IllegalArgumentException("Cannot cascade for relation: " + association.getKind());
            }
        }
    }
}
Also used : ListIterator(java.util.ListIterator) BeanProperty(io.micronaut.core.beans.BeanProperty) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) ConversionErrorException(io.micronaut.core.convert.exceptions.ConversionErrorException) Internal(io.micronaut.core.annotation.Internal) ArrayList(java.util.ArrayList) Embedded(io.micronaut.data.model.Embedded) List(java.util.List) ConversionContext(io.micronaut.core.convert.ConversionContext) Association(io.micronaut.data.model.Association) CollectionUtils(io.micronaut.core.util.CollectionUtils) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Argument(io.micronaut.core.type.Argument) RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) RuntimePersistentEntity(io.micronaut.data.model.runtime.RuntimePersistentEntity) ConversionService(io.micronaut.core.convert.ConversionService) Collections(java.util.Collections) Relation(io.micronaut.data.annotation.Relation) PersistentAssociationPath(io.micronaut.data.model.PersistentAssociationPath) RuntimePersistentEntity(io.micronaut.data.model.runtime.RuntimePersistentEntity) ArrayList(java.util.ArrayList) BeanProperty(io.micronaut.core.beans.BeanProperty) Embedded(io.micronaut.data.model.Embedded) PersistentAssociationPath(io.micronaut.data.model.PersistentAssociationPath)

Aggregations

BeanProperty (io.micronaut.core.beans.BeanProperty)4 PersistentAssociationPath (io.micronaut.data.model.PersistentAssociationPath)4 RuntimeAssociation (io.micronaut.data.model.runtime.RuntimeAssociation)4 Association (io.micronaut.data.model.Association)2 ArrayList (java.util.ArrayList)2 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)1 Internal (io.micronaut.core.annotation.Internal)1 ArgumentConversionContext (io.micronaut.core.convert.ArgumentConversionContext)1 ConversionContext (io.micronaut.core.convert.ConversionContext)1 ConversionService (io.micronaut.core.convert.ConversionService)1 ConversionErrorException (io.micronaut.core.convert.exceptions.ConversionErrorException)1 Argument (io.micronaut.core.type.Argument)1 CollectionUtils (io.micronaut.core.util.CollectionUtils)1 Relation (io.micronaut.data.annotation.Relation)1 Embedded (io.micronaut.data.model.Embedded)1 RuntimePersistentEntity (io.micronaut.data.model.runtime.RuntimePersistentEntity)1 Collections (java.util.Collections)1 List (java.util.List)1 ListIterator (java.util.ListIterator)1