Commit 446d82be authored by Matija Obreza's avatar Matija Obreza

AccessionOverview: Apply relevant filter on the join path

When filters are applied on Accession it results in a separate join.
With this approach, we apply the InventoryFilter on the Inventory join
parent 08779977
......@@ -18,6 +18,7 @@ package org.gringlobal.service.impl;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -25,6 +26,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.genesys.blocks.model.filters.EmptyModelFilter;
import org.gringlobal.api.InvalidApiUsageException;
import org.gringlobal.api.NotFoundElement;
import org.gringlobal.custom.elasticsearch.SearchException;
......@@ -56,7 +58,9 @@ import org.springframework.transaction.annotation.Transactional;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.CollectionExpression;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BeanPath;
import com.querydsl.core.types.dsl.CollectionPathBase;
import com.querydsl.core.types.dsl.NumberPath;
......@@ -317,16 +321,13 @@ public class AccessionServiceImpl extends FilteredCRUDServiceImpl<Accession, Acc
JPAQuery<?> query = jpaQueryFactory.from(QAccession.accession);
if (filter != null) {
query.where(filter.buildPredicate());
}
PathBuilder<Object> groupBy;
// fields
String[] groups = group.strip().split("\\.");
Object root = QAccession.accession;
Object currentFilter = filter;
PathBuilder<?> sourceProp = new PathBuilder<>(Accession.class, QAccession.accession.getMetadata());
String currentPath = "";
......@@ -358,10 +359,45 @@ public class AccessionServiceImpl extends FilteredCRUDServiceImpl<Accession, Acc
LOG.debug("Got {} and {} for {}", entityType.getName(), qdslType.getName(), field);
// Join
joinQuery(query, entityType, qdslType, (CollectionExpression<?, ?>) field.get(root), "joined" + i);
Path<?> path = (Path<?>) qdslType.getDeclaredConstructor(String.class).newInstance("joined" + i);
joinQuery(query, entityType, qdslType, (CollectionExpression<?, ?>) field.get(root), path);
// Change root
root = qdslType.getDeclaredConstructor(String.class).newInstance("joined" + i);
root = path;
// Apply any filters on the join path, not on query root
// Is there a filter field for this entity?
Field pathFilterField = findPathFilter(fieldName, entityType);
// We found a matching filter, now apply filters on join path
if (pathFilterField != null) {
// If filter has values, skip otherwise
Object filterObj = pathFilterField.get(currentFilter);
if (filterObj != null) {
// We have an entity filter with some values
EmptyModelFilter<?, ?> emf = EmptyModelFilter.class.cast(filterObj);
LOG.warn("Found the filter for {} with values! {}", pathFilterField, emf.getClass().getName());
// Apply filter on path
java.lang.reflect.Method collectPredicates = emf.getClass().getMethod("collectPredicates", qdslType);
// Invoke the `collectPredicates(Q...)` method on join path
if (collectPredicates != null) {
Collection<Predicate> predicates = (Collection<Predicate>) collectPredicates.invoke(emf, path);
LOG.trace("Got", predicates);
query.where(ExpressionUtils.allOf(predicates));
// Clear accession filter for this property
pathFilterField.set(currentFilter, null);
} else {
LOG.warn("No collectPredicates method for {} on {}", qdslType.getName(), emf.getClass().getName());
}
} else {
LOG.trace("Found the filter for {} but it's null. {}", pathFilterField, entityType.getName());
}
}
// update lookup
sourceProp = new PathBuilder<>(entityType, "joined" + i);
......@@ -385,6 +421,10 @@ public class AccessionServiceImpl extends FilteredCRUDServiceImpl<Accession, Acc
LOG.debug("Using field {} for {}", lookupField, group);
groupBy = sourceProp.get(lookupField);
if (filter != null) {
query.where(filter.buildPredicate());
}
JPAQuery<Tuple> select = query.select(groupBy, QAccession.accession.id.count()).groupBy(groupBy);
Map<Object, Number> results = new HashMap<>();
......@@ -395,11 +435,41 @@ public class AccessionServiceImpl extends FilteredCRUDServiceImpl<Accession, Acc
return results;
}
/**
* Find the entity filter field of specified type in AccessionFilter
*/
private Field findPathFilter(String fieldName, Class<?> entityType) throws IllegalArgumentException, IllegalAccessException {
for (Field filterField : AccessionFilter.class.getFields()) {
// Must be a model filter
if (EmptyModelFilter.class.isAssignableFrom(filterField.getType())) {
ResolvableType filterType = ResolvableType.forClass(EmptyModelFilter.class, filterField.getType());
Class<?> gen0 = filterType.resolveGeneric(0);
Class<?> gen1 = filterType.resolveGeneric(1);
LOG.warn("Looking at {} as subfilter {} {}", filterField, gen0, gen1);
// If the filter is for the specified type
if (gen1 != null && gen1.equals(entityType)) {
if (! filterField.getName().equalsIgnoreCase(fieldName)) {
LOG.warn("Potential filter mismatch between {} and {}!", filterField.getName(), fieldName);
// TODO We have multiple SiteFilters in AccessionFilter. Need the right one!
}
return filterField;
}
} else {
// LOG.trace("Not a sub-filter {} {}", filterField, filterField.getType().getName());
}
}
return null;
}
@SuppressWarnings("unchecked")
private <A, E> void joinQuery(JPAQuery<?> query, Class<?> entityType, Class<E> qdslType, CollectionExpression<?, ?> collectionPath, String aliasName)
private <A, E> void joinQuery(JPAQuery<?> query, Class<?> entityType, Class<E> qdslType, CollectionExpression<?, ?> collectionPath, Path<?> alias)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Path<E> alias = (Path<E>) qdslType.getDeclaredConstructor(String.class).newInstance(aliasName);
query.join((CollectionExpression<?, E>) collectionPath, alias);
query.join((CollectionExpression<?, E>) collectionPath, (Path<E>) alias);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment