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.
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 OneToOnePlan oneToOnePlan;
private List> manyToOnePlans = Lists.newArrayList();
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 extends EntityField, ?>> oneToOneFields = Lists.newArrayList(fieldsToFetch);
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);
this.manyToOnePlans.removeIf(plan -> plan.getPath().target.table == table);
}
seq(remainingPrimaryTables).filter(referencing(table)).forEach(manyToOneEntry -> {
final TreeEdge sourceEdge = currentEdge == startingEdge ? null : currentEdge;
List extends EntityField, ?>> manyToOneFields = manyToOneEntry.v2;
oneToOneFields.removeAll(manyToOneFields);
populateManyToOnePlans(sourceEdge, table, manyToOneEntry.v1, (List)manyToOneFields);
});
});
if (seq(remainingPrimaryTables.keySet()).anyMatch(notIn(this.manyToOnePlans))) {
throw new IllegalStateException("Some tables " + remainingPrimaryTables + " could not be reached via joins");
}
this.oneToOnePlan = new OneToOnePlan(oneToOnePaths, oneToOneFields, oneToOneSecondaryTablesOf(fieldsToFetch));
}
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 super DataTable> notIn(List> manyToOnePlans) {
return table -> seq(manyToOnePlans).noneMatch(plan -> plan.getPath().target.table == table);
}
private Seq edgesComingOutOf(TreeEdge edge) {
return seq(edge.target.table.getReferences()).map(new ToEdgesOf(edge.target));
}
private > void populateManyToOnePlans(TreeEdge sourceEdge, DataTable targetTable, DataTable manyToOneTable , List extends EntityField> fields) {
this.manyToOnePlans.add(new ManyToOnePlan<>(new TreeEdge(new TreeNode(sourceEdge, targetTable), manyToOneTable), fields));
}
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