All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micronaut.data.runtime.operations.internal.AbstractSyncEntitiesOperations Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2022 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.data.runtime.operations.internal;

import io.micronaut.core.annotation.Internal;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.data.annotation.Relation;
import io.micronaut.data.event.EntityEventContext;
import io.micronaut.data.event.EntityEventListener;
import io.micronaut.data.model.runtime.QueryParameterBinding;
import io.micronaut.data.model.runtime.RuntimePersistentEntity;
import io.micronaut.data.runtime.event.DefaultEntityEventContext;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Abstract synchronous entities operations.
 *
 * @param  The operation context
 * @param    The entity type
 * @param  The exception
 * @author Denis Stepanov
 * @since 3.3
 */
@Internal
public abstract class AbstractSyncEntitiesOperations extends SyncEntitiesOperations {

    protected final Ctx ctx;
    protected final SyncCascadeOperations cascadeOperations;
    protected final ConversionService conversionService;
    protected final List entities;
    protected final boolean insert;
    protected final boolean hasGeneratedId;

    /**
     * Default constructor.
     *
     * @param ctx                 The context
     * @param cascadeOperations   The cascade operations
     * @param conversionService   The conversion service
     * @param entityEventListener The entity event listener
     * @param persistentEntity    The persistent entity
     * @param entities            The entities
     * @param insert              The insert
     */
    protected AbstractSyncEntitiesOperations(Ctx ctx,
                                             SyncCascadeOperations cascadeOperations,
                                             ConversionService conversionService,
                                             EntityEventListener entityEventListener,
                                             RuntimePersistentEntity persistentEntity,
                                             Iterable entities,
                                             boolean insert) {
        super(entityEventListener, persistentEntity, conversionService);
        this.cascadeOperations = cascadeOperations;
        this.conversionService = conversionService;
        this.ctx = ctx;
        this.insert = insert;
        this.hasGeneratedId = insert && persistentEntity.getIdentity() != null && persistentEntity.getIdentity().isGenerated();
        Objects.requireNonNull(entities, "Entities cannot be null");
        Stream stream;
        if (entities instanceof Collection collection) {
            stream = collection.stream();
        } else {
            stream = CollectionUtils.iterableToList(entities).stream();
        }
        this.entities = stream.map(entity -> {
            Data d = new Data();
            d.entity = entity;
            return d;
        }).toList();
    }

    @Override
    protected void cascadePre(Relation.Cascade cascadeType) {
        for (Data d : entities) {
            if (d.vetoed) {
                continue;
            }
            d.entity = cascadeOperations.cascadeEntity(ctx, d.entity, persistentEntity, false, cascadeType);
        }
    }

    @Override
    protected void cascadePost(Relation.Cascade cascadeType) {
        for (Data d : entities) {
            if (d.vetoed) {
                continue;
            }
            d.entity = cascadeOperations.cascadeEntity(ctx, d.entity, persistentEntity, true, cascadeType);
        }
    }

    @Override
    protected void collectAutoPopulatedPreviousValues() {
    }

    @Override
    public void veto(Predicate predicate) {
        for (Data d : entities) {
            if (d.vetoed) {
                continue;
            }
            d.vetoed = predicate.test(d.entity);
        }
    }

    @Override
    protected boolean triggerPre(Function, Boolean> fn) {
        boolean allVetoed = true;
        for (Data d : entities) {
            if (d.vetoed) {
                continue;
            }
            final DefaultEntityEventContext event = new DefaultEntityEventContext<>(persistentEntity, d.entity);
            if (!fn.apply((EntityEventContext) event)) {
                d.vetoed = true;
                continue;
            }
            d.entity = event.getEntity();
            allVetoed = false;
        }
        return allVetoed;
    }

    @Override
    protected void triggerPost(Consumer> fn) {
        for (Data d : entities) {
            if (d.vetoed) {
                continue;
            }
            final DefaultEntityEventContext event = new DefaultEntityEventContext<>(persistentEntity, d.entity);
            fn.accept((EntityEventContext) event);
            d.entity = event.getEntity();
        }
    }

    @Override
    @SuppressWarnings({"java:S6204"})
    public List getEntities() {
        return entities.stream().map(d -> d.entity).collect(Collectors.toList());
    }

    @SuppressWarnings("VisibilityModifier")
    protected class Data {
        public T entity;
        public Map previousValues;
        public boolean vetoed = false;
    }
}