com.kenshoo.pl.entity.internal.fetch.ExecutionPlan 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.
                
             The newest version!
        
        package com.kenshoo.pl.entity.internal.fetch;
import com.google.common.collect.Lists;
import com.kenshoo.jooq.DataTable;
import com.kenshoo.pl.entity.EntityField;
import com.kenshoo.pl.entity.EntityType;
import org.jooq.lambda.Seq;
import org.jooq.lambda.tuple.Tuple2;
import java.util.*;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toSet;
import static org.jooq.lambda.Seq.seq;
import static org.jooq.lambda.function.Functions.not;
public class ExecutionPlan {
    private final OneToOnePlan oneToOnePlan;
    private final List> manyToOnePlans;
    public ExecutionPlan(DataTable startingTable, Collection extends EntityField, ?>> fieldsToFetch) {
        final Map>> remainingPrimaryTables = targetTableToFieldsOf(fieldsToFetch, startingTable);
        final TreeEdge startingEdge = new TreeEdge(null, startingTable);
        final List oneToOnePaths = Lists.newArrayList();
        final List> manyToOneCandidates = Lists.newArrayList();
        BFS.visit(startingEdge, this::edgesComingOutOf)
                .limitUntil(__ -> remainingPrimaryTables.isEmpty())
                .forEach(currentEdge -> {
                    final DataTable table = currentEdge.target.table;
                    List fields = remainingPrimaryTables.get(table);
                    if (currentEdge != startingEdge && fields != null) {
                        remainingPrimaryTables.remove(table);
                        oneToOnePaths.add(currentEdge);
                    }
                    seq(remainingPrimaryTables).filter(referencing(table)).forEach(manyToOneEntry -> {
                        final TreeEdge sourceEdge = currentEdge == startingEdge ? null : currentEdge;
                        manyToOneCandidates.add(new ManyToOnePlan(new TreeEdge(new TreeNode(sourceEdge, table), manyToOneEntry.v1), manyToOneEntry.v2));
                    });
                });
        if (seq(remainingPrimaryTables.keySet()).anyMatch(notMany(manyToOneCandidates))) {
            throw new IllegalStateException("Some tables " + remainingPrimaryTables + " could not be reached via joins");
        }
        final List extends EntityField, ?>> oneToOneFields = seq(fieldsToFetch).filter(tableIn(oneToOnePaths).or(tableEqual(startingTable))).toList();
        this.oneToOnePlan = new OneToOnePlan(oneToOnePaths, oneToOneFields, oneToOneSecondaryTablesOf(fieldsToFetch));
        this.manyToOnePlans = seq(manyToOneCandidates).filter(notIn(oneToOnePaths)).toList();
    }
    public OneToOnePlan getOneToOnePlan() {
        return oneToOnePlan;
    }
    public List> getManyToOnePlans() {
        return manyToOnePlans;
    }
    private Map>> targetTableToFieldsOf(Collection extends EntityField, ?>> fieldsToFetch, DataTable startingTable) {
        return seq(fieldsToFetch)
                .filter(field -> !field.getEntityType().getPrimaryTable().equals(startingTable))
                .groupBy(this::parimaryTableOf);
    }
    private Set oneToOneSecondaryTablesOf(Collection extends EntityField, ?>> fields) {
        return fields.stream()
                .filter(not(isOfPrimaryTable()))
                .map(field -> com.kenshoo.pl.entity.internal.fetch.OneToOneTableRelation.builder()
                        .secondary(field.getDbAdapter().getTable())
                        .primary(field.getEntityType().getPrimaryTable())
                        .build())
                .collect(toSet());
    }
    private Predicate> isOfPrimaryTable() {
        return field -> field.getDbAdapter().getTable().equals(field.getEntityType().getPrimaryTable());
    }
    private DataTable parimaryTableOf(EntityField, ?> field) {
        return field.getEntityType().getPrimaryTable();
    }
    private Predicate super Tuple2>>> referencing(DataTable table) {
        return entry -> entry.v1.getReferencesTo(table).size() == 1;
    }
    private Predicate> tableIn(List oneToOnePaths) {
        return field -> seq(oneToOnePaths).anyMatch(path -> field.getEntityType().getPrimaryTable().equals(path.target.table));
    }
    private Predicate> tableEqual(DataTable table) {
        return field -> table.equals(field.getEntityType().getPrimaryTable());
    }
    private Predicate notMany(List> manyToOnePlans) {
        return table -> seq(manyToOnePlans).noneMatch(plan -> table.equals(plan.getPath().target.table));
    }
    private Predicate> notIn(List oneToOnePaths) {
        return plan -> seq(oneToOnePaths).noneMatch(path -> plan.getPath().target.table.equals(path.target.table));
    }
    private Seq edgesComingOutOf(TreeEdge edge) {
        return seq(edge.target.table.getReferences()).map(new ToEdgesOf(edge.target));
    }
    public static class ManyToOnePlan> {
        private final TreeEdge path;
        private final List extends EntityField> fields;
        ManyToOnePlan(TreeEdge path, List extends EntityField> fields) {
            this.path = path;
            this.fields = fields;
        }
        public TreeEdge getPath() {
            return path;
        }
        public List extends EntityField> getFields() {
            return fields;
        }
    }
    public static class OneToOnePlan {
        private final List paths;
        private final List extends EntityField, ?>> fields;
        private final Set secondaryTableRelations;
        OneToOnePlan(List paths, List extends EntityField, ?>> fields, Set secondaryTableRelations) {
            this.paths = paths;
            this.fields = fields;
            this.secondaryTableRelations = secondaryTableRelations;
        }
        public List getPaths() {
            return paths;
        }
        public List extends EntityField, ?>> getFields() {
            return fields;
        }
        public Set getSecondaryTableRelations() {
            return secondaryTableRelations;
        }
    }
}
                               © 2015 - 2025 Weber Informatics LLC | Privacy Policy