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

com.kenshoo.pl.entity.internal.FalseUpdatesPurger 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.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> 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> 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);
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy