com.kenshoo.pl.entity.internal.EntitiesToContextFetcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of persistence-layer Show documentation
Show all versions of persistence-layer Show documentation
A Java persistence layer based on JOOQ for high performance and business flow support.
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 extends ChangeEntityCommand> 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 extends ChangeEntityCommand> 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 extends ChangeEntityCommand> commands, Set> fieldsToFetch, ChangeContext changeContext, ChangeFlowConfig flowConfig) {
Map extends ChangeEntityCommand, 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 extends ChangeEntityCommand> 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 extends ChangeEntityCommand, 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 extends ChangeEntityCommand, Identifier> keysByCommand) {
for (Map.Entry extends ChangeEntityCommand, 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