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

com.kenshoo.pl.entity.FieldsToFetchBuilder Maven / Gradle / Ivy

Go to download

A Java persistence layer based on JOOQ for high performance and business flow support.

There is a newer version: 0.1.121-jooq-3.16.3
Show newest version
package com.kenshoo.pl.entity;

import com.kenshoo.pl.entity.spi.CurrentStateConsumer;
import com.kenshoo.pl.entity.spi.PostFetchCommandEnricher;
import org.jooq.lambda.Seq;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.kenshoo.pl.entity.ChangeOperation.*;
import static com.kenshoo.pl.entity.FieldFetchRequest.newRequest;
import static com.kenshoo.pl.entity.spi.CurrentStateConsumer.supporting;
import static java.util.stream.Collectors.toList;
import static org.jooq.lambda.Seq.seq;
import static org.jooq.lambda.function.Functions.not;

public class FieldsToFetchBuilder> {

    public Collection build(Collection> commands, ChangeFlowConfig flowConfig) {
        return prepareFieldsToFetchRecursive(Hierarchy.build(flowConfig), commands, flowConfig)
                .toList();
    }

    private > Seq prepareFieldsToFetchRecursive(
            Hierarchy hierarchy,
            Collection> commands,
            ChangeFlowConfig flow) {

        return Seq.concat(
                getForOneLevel(hierarchy, only(commands, withOperator(UPDATE)), UPDATE, flow),
                getForOneLevel(hierarchy, only(commands, withOperator(CREATE).or(withAllowMissingEntity())), CREATE, flow),
                getForOneLevel(hierarchy, only(commands, withOperator(DELETE)), DELETE, flow),
                seq(flow.childFlows()).flatMap(childFlow -> prepareChildFieldsToFetchRecursive(hierarchy, commands, childFlow))
        );
    }

    private , CHILD extends EntityType> Seq prepareChildFieldsToFetchRecursive(Hierarchy hierarchy, Collection> commands, ChangeFlowConfig childFlow) {
        return prepareFieldsToFetchRecursive(hierarchy, commands.stream().flatMap(parent -> parent.getChildren(childFlow.getEntityType())).collect(toList()), childFlow);
    }

    private > Seq getForOneLevel(
            Hierarchy hierarchy,
            Collection> commands,
            ChangeOperation operation,
            ChangeFlowConfig flow) {

        if (commands.isEmpty()) {
            return Seq.empty();
        }

        final EntityType currentLevel = flow.getEntityType();

        final Stream> currentStateConsumers =
                Stream.concat(flow.currentStateConsumers(), consumerOf(commands))
                        .filter(supporting(operation));

        final Seq> fields = Seq.concat(
                fieldsConsumedBy(commands, operation, flow, currentStateConsumers),
                foreignKeyFieldsRelatedByChildrenOf(commands, flow, hierarchy, operation),
                fieldsOfIdentifiersOf(commands, operation));

        return fields.flatMap(field -> {
            if (isSameLevel(flow, field)) {
                return Seq.of(newRequest().field(field).queryOn(currentLevel).askedBy(currentLevel).build());
            } else if (hierarchy.contains(field)) {
                return Seq.of(newRequest().field(field).queryOn(field.getEntityType()).askedBy(currentLevel).build());
            } else {
                return Seq.of(newRequest().field(field).queryOn(hierarchy.root()).askedBy(currentLevel).build());
            }
        });
    }

    private > Stream> fieldsConsumedBy(Collection> commands, ChangeOperation operation, ChangeFlowConfig flow, Stream> currentStateConsumers) {
        Stream> fieldsByCommands = commands.stream().flatMap(ChangeEntityCommand::getChangedFields);
        Stream> fieldsToEnrich = flow.getPostFetchCommandEnrichers().stream().filter(enricher -> enricher.shouldRun(commands)).flatMap(PostFetchCommandEnricher::fieldsToEnrich);
        Set> fieldsToUpdate = Stream.concat(fieldsByCommands, fieldsToEnrich).collect(Collectors.toSet());
        return currentStateConsumers.flatMap(
                consumer -> filterFieldsByOperator(flow, operation, consumer.requiredFields(fieldsToUpdate, operation), consumer)
        );
    }

    private > Stream> fieldsOfIdentifiersOf(Collection> commands, ChangeOperation operation) {
        if(!commands.isEmpty() && SupportedChangeOperation.UPDATE_AND_DELETE.supports(operation)) {
            ChangeEntityCommand cmd = commands.stream().findFirst().get();
            return uniqueFields(cmd);
        } else {
            return Stream.empty();
        }
    }

    private > Stream> foreignKeyFieldsRelatedByChildrenOf(Collection> commands, ChangeFlowConfig flow, Hierarchy hierarchy, ChangeOperation operation) {
        if(SupportedChangeOperation.UPDATE_AND_DELETE.supports(operation) && hasAnyChildCommand(commands)) {
            E entityType = flow.getEntityType();
            Collection> children = hierarchy.childrenTypes(entityType);
            return children.stream().map(child -> child.getKeyTo(entityType).to()).flatMap(Collection::stream);
        } else {
            return Stream.empty();
        }
    }

    private > Stream> uniqueFields(ChangeEntityCommand cmd) {
        return Arrays.stream(cmd.getIdentifier().getUniqueKey().getFields());
    }


    private > boolean hasAnyChildCommand(Collection> commands) {
        return commands.stream().flatMap(ChangeEntityCommand::getChildren).findAny().isPresent();
    }

    private > boolean isSameLevel(ChangeFlowConfig flow, EntityField field) {
        return flow.getEntityType().equals(field.getEntityType());
    }

    private  List only(Iterable items, Predicate predicate) {
        return seq(items).filter(predicate).toList();
    }

    private Predicate> withOperator(ChangeOperation op) {
        return cmd -> op == cmd.getChangeOperation();
    }

    private Predicate> withAllowMissingEntity() {
        return EntityChange::allowMissingEntity;
    }

    private > Stream> consumerOf(Collection> commands) {
        return commands.stream()
                .flatMap(ChangeEntityCommand::getCurrentStateConsumers);
    }

    private , EF extends EntityField> Stream filterFieldsByOperator(ChangeFlowConfig flowConfig, ChangeOperation changeOperation, Stream fieldsToFetch, CurrentStateConsumer consumer) {
        if(changeOperation == CREATE) {
            return fieldsToFetch.filter(not(ofEntity(flowConfig.getEntityType())));
        } else {
            return fieldsToFetch;
        }
    }

    private , EF extends EntityField> Predicate ofEntity(EntityType entityType) {
        return entityField -> entityField.getEntityType().equals(entityType);
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy