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

com.kenshoo.pl.entity.internal.EntitiesToContextFetcher 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.internal;

import com.google.common.collect.Sets;
import com.kenshoo.pl.entity.*;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

import static com.kenshoo.pl.entity.ChangeOperation.CREATE;
import static com.kenshoo.pl.entity.UniqueKeyValue.concat;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;
import static org.jooq.lambda.Seq.seq;


public class EntitiesToContextFetcher {

    private final EntitiesFetcher entitiesFetcher;

    public EntitiesToContextFetcher(EntitiesFetcher entitiesFetcher) {
        this.entitiesFetcher = entitiesFetcher;
    }

    public > void fetchEntities(Collection> commands, ChangeOperation changeOperation, ChangeContext context, ChangeFlowConfig flow) {

        commands.forEach(c -> context.addEntity(c, CurrentEntityState.EMPTY));

        final Set> fieldsToFetch = context.getFetchRequests().stream().
                filter( r -> r.getWhereToQuery().equals(flow.getEntityType()) && r.supports(changeOperation)).
                map(FieldFetchRequest::getEntityField).
                collect(toSet());

        if (changeOperation == CREATE) {
            fetchEntitiesByForeignKeys(commands, fieldsToFetch, context, flow);
        } else {
            fetchEntitiesByKeys(commands, fieldsToFetch, context, flow);
        }

        populateFieldsFromAllParents(seq(commands).filter(notMissing(context)).toList(), context, flow.getEntityType());
    }

    private > void populateFieldsFromAllParents(List> commands, ChangeContext context, EntityType currentLevel) {

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

        seq(context.getFetchRequests())
                .filter(askedBy(currentLevel).and(not(queriedOn(currentLevel))))
                .groupBy(r -> r.getWhereToQuery())
                .forEach((level, requestedFields) -> {
                    final List parentFields = seq(requestedFields).map(f -> (EntityField)f.getEntityField()).toList();
                    commands.forEach(cmd -> populateFieldsFromOneLevel(context, level, parentFields, cmd));
                });
    }

    private > void populateFieldsFromOneLevel(
            ChangeContext context,
            EntityType parentLevel,
            List parentFields,
            ChangeEntityCommand cmd) {

        final ChangeEntityCommand ancestor = getAncestor(cmd, parentLevel);
        final CurrentEntityMutableState currentState = (CurrentEntityMutableState)context.getEntity(cmd);
        seq(parentFields).forEach(field ->  currentState.set(field, getValue(context, ancestor, field)));
    }


    ChangeEntityCommand getAncestor(ChangeEntityCommand cmd, EntityType level) {
        for (ChangeEntityCommand parent = cmd.getParent(); parent != null; parent = parent.getParent()) {
            if (parent.getEntityType().equals(level)) {
                return parent;
            }
        }
        throw new RuntimeException("didn't find ancestor of level " + level.getName() + " for command with entity " + cmd.getEntityType().getName());
    }

    private Object getValue(ChangeContext context, ChangeEntityCommand cmd, EntityField field) {
        return cmd.containsField(field) ? cmd.get(field) : context.getEntity(cmd).get(field);
    }

    private Predicate askedBy(EntityType e) {
        return r -> r.getWhoAskedForThis().equals(e);
    }

    private  Predicate not(Predicate p) {
        return p.negate();
    }

    private Predicate queriedOn(EntityType e) {
        return r -> r.getWhereToQuery().equals(e);
    }

    private > void fetchEntitiesByKeys(Collection> commands, Set> fieldsToFetch, ChangeContext changeContext, ChangeFlowConfig flowConfig) {
        Map, Identifier> keysByCommand = commands.stream().collect(toMap(
                Function.identity(),
                cmd -> concat(cmd.getIdentifier(), cmd.getKeysToParent())));
        //noinspection ConstantConditions
        UniqueKey uniqueKey = keysByCommand.values().iterator().next().getUniqueKey();
        Map, CurrentEntityState> fetchedEntities = entitiesFetcher.fetchEntitiesByIds(keysByCommand.values(), fieldsToFetch);
        addFetchedEntitiesToChangeContext(fetchedEntities, changeContext, keysByCommand);
    }

    private > void fetchEntitiesByForeignKeys(Collection> commands, Set> fieldsToFetch, ChangeContext context, ChangeFlowConfig flowConfig) {
        E entityType = flowConfig.getEntityType();
        Collection> foreignKeys = entityType.determineForeignKeys(flowConfig.getRequiredRelationFields()).filter(not(new IsFieldReferringToParent<>(context.getHierarchy(), entityType))).collect(toList());
        if (foreignKeys.isEmpty()) {
            CurrentEntityState sharedEntity = new CurrentEntityMutableState();
            commands.forEach(cmd -> context.addEntity(cmd, sharedEntity));
        } else {
            final UniqueKey foreignUniqueKey = new ForeignUniqueKey<>(foreignKeys);
            Map, Identifier> keysByCommand = commands.stream().collect(toMap(identity(), foreignUniqueKey::createValue));
            Map, CurrentEntityState> fetchedEntities = entitiesFetcher.fetchEntitiesByForeignKeys(entityType, foreignUniqueKey, Sets.newHashSet(keysByCommand.values()), fieldsToFetch);
            addFetchedEntitiesToChangeContext(fetchedEntities, context, keysByCommand);
        }
    }

    private > void addFetchedEntitiesToChangeContext(Map, CurrentEntityState> fetchedEntities, ChangeContext changeContext, Map, Identifier> keysByCommand) {
        for (Map.Entry, Identifier> entry : keysByCommand.entrySet()) {
            ChangeEntityCommand command = entry.getKey();
            Identifier identifier = entry.getValue();
            CurrentEntityState currentState = fetchedEntities.get(identifier);
            if (currentState != null) {
                changeContext.addEntity(command, currentState);
            }
        }
    }

    private > Predicate> notMissing(ChangeContext context) {
        return cmd -> context.getEntity(cmd) != CurrentEntityState.EMPTY;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy