com.kenshoo.pl.entity.internal.FalseUpdatesPurger 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.annotations.VisibleForTesting;
import com.kenshoo.pl.entity.ChangeContext;
import com.kenshoo.pl.entity.ChangeEntityCommand;
import com.kenshoo.pl.entity.ChangeOperation;
import com.kenshoo.pl.entity.CurrentEntityState;
import com.kenshoo.pl.entity.EntityField;
import com.kenshoo.pl.entity.EntityType;
import com.kenshoo.pl.entity.FieldChange;
import com.kenshoo.pl.entity.SupportedChangeOperation;
import com.kenshoo.pl.entity.spi.PostFetchCommandEnricher;
import org.jooq.lambda.Seq;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
public class FalseUpdatesPurger> implements PostFetchCommandEnricher {
// Did not want to make ChangeEntityCommand.unset public so getting an accessor to call it
private final BiConsumer, EntityField> fieldUnsetter;
private final Set> deleteIfSetAloneFields;
private final Set> fieldsToRetain;
private FalseUpdatesPurger(
BiConsumer, EntityField> fieldUnsetter,
Set> deleteIfSetAloneFields,
Set> fieldsToRetain) {
this.fieldUnsetter = fieldUnsetter;
this.deleteIfSetAloneFields = deleteIfSetAloneFields;
this.fieldsToRetain = fieldsToRetain;
}
@Override
public void enrich(Collection extends ChangeEntityCommand> commands, ChangeOperation changeOperation, ChangeContext changeContext) {
commands.forEach(command -> {
CurrentEntityState currentState = changeContext.getEntity(command);
// Collect the fields first to avoid modification of command's inner collection while traversing
List> unchangedFields = command.getChanges()
.filter(fieldChange -> areEqual(currentState, fieldChange))
.filter(change -> !fieldsToRetain.contains(change.getField()))
.collect(toList());
unchangedFields.forEach(fieldChange -> fieldUnsetter.accept(command, fieldChange.getField()));
//Contains only ignorable fields
if(command.getChanges().allMatch(fieldChange -> deleteIfSetAloneFields.contains(fieldChange.getField()))) {
deleteIfSetAloneFields.forEach(field -> fieldUnsetter.accept(command, field));
}
});
}
@Override
public Stream> requiredFields(Collection extends EntityField> fieldsToUpdate, ChangeOperation changeOperation) {
return Seq.seq(fieldsToUpdate);
}
@Override
public SupportedChangeOperation getSupportedChangeOperation() {
return SupportedChangeOperation.UPDATE;
}
private boolean areEqual(CurrentEntityState currentState, FieldChange fieldChange) {
if (!currentState.containsField(fieldChange.getField())) {
return false;
}
T v1 = fieldChange.getValue();
T v2 = currentState.get(fieldChange.getField());
return fieldChange.getField().valuesEqual(v1, v2);
}
@VisibleForTesting
public Set> getFieldsToRetain() {
return fieldsToRetain;
}
public static class Builder> {
private BiConsumer, EntityField> fieldUnsetter;
private Set> deleteIfSetAloneFields = emptySet();
private Set> fieldsToRetain = new HashSet<>();
public Builder setFieldUnsetter(BiConsumer, EntityField> fieldUnsetter) {
this.fieldUnsetter = fieldUnsetter;
return this;
}
public Builder setDeleteIfSetAloneFields(Stream> deleteIfSetAloneFields) {
this.deleteIfSetAloneFields = deleteIfSetAloneFields.collect(toSet());
return this;
}
public Builder setDeleteIfSetAloneFields(EntityField... deleteIfSetAloneFields) {
return setDeleteIfSetAloneFields(Stream.of(deleteIfSetAloneFields));
}
public Builder addFieldsToRetain(Stream> fieldsToRetain) {
fieldsToRetain.forEach(this.fieldsToRetain::add);
return this;
}
public Builder addFieldsToRetain(EntityField... fieldsToRetain) {
return addFieldsToRetain(Stream.of(fieldsToRetain));
}
public Builder retainNonNullableFieldsOfSecondaryTables(E entityType) {
return addFieldsToRetain(entityType.getFields()
.filter(belongingToSecondaryTable(entityType))
.filter(f -> isNotNullable(f)));
}
private > boolean isNotNullable(EntityField field) {
return !field.getDbAdapter().getTableFields().anyMatch(tableField -> tableField.getDataType().nullable());
}
private > Predicate> belongingToSecondaryTable(E entityType) {
return f -> f.getDbAdapter().getTable() != entityType.getPrimaryTable();
}
public FalseUpdatesPurger build() {
return new FalseUpdatesPurger<>(fieldUnsetter, deleteIfSetAloneFields, fieldsToRetain);
}
}
}