Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.crnk.jpa.internal.query.backend.querydsl.QuerydslQueryBackend Maven / Gradle / Ivy
package io.crnk.jpa.internal.query.backend.querydsl;
import com.google.common.collect.ImmutableList;
import com.querydsl.core.support.FetchableSubQueryBase;
import com.querydsl.core.types.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.jpa.JPAQueryBase;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import io.crnk.core.engine.internal.utils.PreconditionUtil;
import io.crnk.core.queryspec.Direction;
import io.crnk.core.queryspec.FilterOperator;
import io.crnk.jpa.internal.query.ComputedAttributeRegistryImpl;
import io.crnk.jpa.internal.query.JoinRegistry;
import io.crnk.jpa.internal.query.MetaComputedAttribute;
import io.crnk.jpa.internal.query.QueryUtil;
import io.crnk.jpa.internal.query.backend.JpaQueryBackend;
import io.crnk.jpa.query.querydsl.QuerydslExpressionFactory;
import io.crnk.jpa.query.querydsl.QuerydslTranslationContext;
import io.crnk.meta.model.MetaAttribute;
import io.crnk.meta.model.MetaAttributePath;
import io.crnk.meta.model.MetaDataObject;
import io.crnk.meta.model.MetaKey;
import javax.annotation.Nullable;
import javax.persistence.criteria.JoinType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@SuppressWarnings({"rawtypes", "unchecked"})
public class QuerydslQueryBackend
implements QuerydslTranslationContext, JpaQueryBackend, OrderSpecifier>, Predicate, Expression>> {
private JoinRegistry, Expression>> joinHelper;
private Path root;
private EntityPath> parentFrom;
private QuerydslQueryImpl queryImpl;
private JPAQueryBase querydslQuery;
private List> orderList = new ArrayList<>();
public QuerydslQueryBackend(QuerydslQueryImpl queryImpl, Class clazz, MetaDataObject parentMeta,
MetaAttribute parentAttr, boolean addParentSelection) {
this.queryImpl = queryImpl;
JPAQueryFactory queryFactory = queryImpl.getQueryFactory();
if (parentMeta != null) {
parentFrom = QuerydslUtils.getEntityPath(parentMeta.getImplementationClass());
root = QuerydslUtils.getEntityPath(clazz);
Path joinPath = (Path) QuerydslUtils.get(parentFrom, parentAttr.getName());
joinHelper = new JoinRegistry<>(this, queryImpl);
joinHelper.putJoin(new MetaAttributePath(), root);
if (addParentSelection) {
Expression parentIdExpr = getParentIdExpression(parentMeta, parentAttr);
querydslQuery = queryFactory.select(parentIdExpr, root);
} else {
querydslQuery = queryFactory.select(root);
}
querydslQuery = querydslQuery.from(parentFrom);
if (joinPath instanceof CollectionExpression) {
querydslQuery = querydslQuery.join((CollectionExpression) joinPath, root);
} else {
querydslQuery = querydslQuery.join((EntityPath) joinPath, root);
}
} else {
root = QuerydslUtils.getEntityPath(clazz);
joinHelper = new JoinRegistry<>(this, queryImpl);
joinHelper.putJoin(new MetaAttributePath(), root);
querydslQuery = queryFactory.select(root);
querydslQuery = querydslQuery.from((EntityPath) root);
}
}
private Expression getParentIdExpression(MetaDataObject parentMeta, MetaAttribute parentAttr) {
MetaKey primaryKey = parentMeta.getPrimaryKey();
PreconditionUtil.assertNotNull("no primary key specified for parentAttribute " + parentAttr.getId(), parentMeta);
List elements = primaryKey.getElements();
PreconditionUtil.assertEquals("composite primary keys not supported yet", 1, elements.size());
MetaAttribute primaryKeyAttr = elements.get(0);
return QuerydslUtils.get(parentFrom, primaryKeyAttr.getName());
}
public JPAQuery getQuery() {
JPAQueryBase finalQuery = querydslQuery;
for (OrderSpecifier> order : orderList) {
finalQuery = (JPAQueryBase) finalQuery.orderBy(order);
}
return (JPAQuery) finalQuery;
}
@Override
public Expression> getAttribute(MetaAttributePath attrPath) {
return joinHelper.getEntityAttribute(attrPath);
}
@Override
public void addPredicate(Predicate predicate) {
querydslQuery = (JPAQueryBase) querydslQuery.where(predicate);
}
@Override
public Path getRoot() {
return root;
}
@Override
public void setOrder(List> list) {
this.orderList = list;
}
@Override
public List> getOrderList() {
return orderList;
}
@Override
public OrderSpecifier> newSort(Expression> expr, Direction dir) {
if (dir == Direction.ASC) {
return new OrderSpecifier(Order.ASC, expr);
} else {
return new OrderSpecifier(Order.DESC, expr);
}
}
@Override
public void distinct() {
querydslQuery = (JPAQueryBase) querydslQuery.distinct();
}
@Override
public void addParentPredicate(MetaAttribute primaryKeyAttr) {
List> parentIds = queryImpl.getParentIds();
SimpleExpression> parentIdPath = (SimpleExpression>) QuerydslUtils.get(parentFrom, primaryKeyAttr.getName());
addPredicate(parentIdPath.in((List) parentIds));
}
@Override
public boolean hasManyRootsFetchesOrJoins() {
return QuerydslUtils.hasManyRootsFetchesOrJoins((JPAQuery>) querydslQuery);
}
@Override
public void addSelection(Expression> expression, String name) {
Expression> selection = querydslQuery.getMetadata().getProjection();
List> newSelection = new ArrayList<>();
if (selection != null) {
if (selection instanceof QTuple) {
newSelection.addAll(((QTuple) selection).getArgs());
} else {
newSelection.add(selection);
}
}
newSelection.add(expression);
querydslQuery = (JPAQuery) querydslQuery.select(newSelection.toArray(new Expression[newSelection.size()]));
}
@Override
public Expression> getExpression(OrderSpecifier> order) {
return order.getTarget();
}
@Override
public boolean containsRelation(Expression> expression) {
return QueryUtil.containsRelation(expression);
}
@Override
public Predicate buildPredicate(FilterOperator operator, MetaAttributePath attrPath, Object value) {
Expression> attr = getAttribute(attrPath);
return buildPredicate(operator, attr, value);
}
public Predicate buildPredicate(FilterOperator operator, Expression> expressionObj, Object value) {
Expression expression = expressionObj;
expression = handleConversions(expression, operator);
return handle(expression, operator, value);
}
private Predicate handle(Expression expression, FilterOperator operator, Object value) { // NOSONAR
// checking multiple comparision implementations is a mess, created
// https://github.com/querydsl/querydsl/issues/2028
if (operator == FilterOperator.EQ || operator == FilterOperator.NEQ) {
return handleEquals(expression, operator, value);
} else if (operator == FilterOperator.LIKE) {
return ((StringExpression) expression).lower().like(value.toString().toLowerCase());
} else if (operator == FilterOperator.GT) {
if (expression instanceof FetchableSubQueryBase) {
return ((FetchableSubQueryBase) expression).gt(value);
} else if (expression instanceof NumberExpression) {
return ((NumberExpression) expression).gt((Number) value);
} else {
return ((ComparableExpression) expression).gt((Comparable) value);
}
} else if (operator == FilterOperator.LT) {
if (expression instanceof FetchableSubQueryBase) {
return ((FetchableSubQueryBase) expression).lt(value);
} else if (expression instanceof NumberExpression) {
return ((NumberExpression) expression).lt((Number) value);
} else {
return ((ComparableExpression) expression).lt((Comparable) value);
}
} else if (operator == FilterOperator.GE) {
if (expression instanceof FetchableSubQueryBase) {
return ((FetchableSubQueryBase) expression).goe(value);
} else if (expression instanceof NumberExpression) {
return ((NumberExpression) expression).goe((Number) value);
} else {
return ((ComparableExpression) expression).goe((Comparable) value);
}
} else if (operator == FilterOperator.LE) {
if (expression instanceof FetchableSubQueryBase) {
return ((FetchableSubQueryBase) expression).loe(value);
} else if (expression instanceof NumberExpression) {
return ((NumberExpression) expression).loe((Number) value);
} else {
return ((ComparableExpression) expression).loe((Comparable) value);
}
} else {
throw new IllegalStateException("unexpected operator " + operator);
}
}
private Predicate handleEquals(Expression> leftExpression, FilterOperator operator, Object value) {
Expression> expression = leftExpression;
if (Collection.class.isAssignableFrom(expression.getType())) {
CollectionPathBase collectionExpr = (CollectionPathBase) expression;
expression = collectionExpr.any();
}
if (value instanceof List) {
Predicate p = ((SimpleExpression) expression).in((List) value);
return negateIfNeeded(p, operator);
} else if (expression instanceof MapExpressionBase) {
MapExpressionBase mapExpression = (MapExpressionBase) expression;
Predicate p = mapExpression.containsValue(value);
return negateIfNeeded(p, operator);
} else if (value == null) {
return negateIfNeeded(((SimpleExpression) expression).isNull(), operator);
}
return negateIfNeeded(((SimpleExpression) expression).eq(value), operator);
}
private Expression> handleConversions(Expression> expression, FilterOperator operator) {
// convert to String for LIKE operators
if (expression.getType() != String.class && (operator == FilterOperator.LIKE)) {
return Expressions.stringOperation(Ops.STRING_CAST, expression);
} else {
return expression;
}
}
@Override
public Predicate and(List predicates) {
if (predicates.size() == 1) {
return predicates.get(0);
} else {
// only two elements for each operation supported, needs querydsl fix?
Predicate result = predicates.get(0);
for (int i = 1; i < predicates.size(); i++) {
result = new BooleanPredicateOperation(Ops.AND, (ImmutableList) ImmutableList.of(result, predicates.get(i)));
}
return result;
}
}
@Override
public Predicate not(Predicate predicate) {
return predicate.not();
}
@Override
public Predicate or(List predicates) {
if (predicates.size() == 1) {
return predicates.get(0);
} else {
// only two elements for each operation supported, needs querydsl fix?
Predicate result = predicates.get(0);
for (int i = 1; i < predicates.size(); i++) {
result = new BooleanPredicateOperation(Ops.OR, (ImmutableList) ImmutableList.of(result, predicates.get(i)));
}
return result;
}
}
private Predicate negateIfNeeded(Predicate p, FilterOperator fc) {
if (fc.equals(FilterOperator.NEQ)) {
return p.not();
}
return p;
}
@Override
public Expression> joinMapValue(Expression> currentCriteriaPath, MetaAttribute pathElement, Object key) {
MapPath mapPath = (MapPath) QuerydslUtils.get(currentCriteriaPath, pathElement.getName());
return mapPath.get(key);
}
@Override
public Class> getJavaElementType(Expression> expression) {
if (expression instanceof CollectionExpressionBase) {
return ((CollectionExpressionBase) expression).getElementType();
}
return expression.getType();
}
@Override
public Expression> getAttribute(final Expression> expression, MetaAttribute pathElement) {
if (pathElement instanceof MetaComputedAttribute) {
ComputedAttributeRegistryImpl virtualAttrs = queryImpl.getComputedAttrs();
QuerydslExpressionFactory expressionFactory = (QuerydslExpressionFactory) virtualAttrs
.get((MetaComputedAttribute) pathElement);
return expressionFactory.getExpression(expression, getQuery());
} else {
return QuerydslUtils.get(expression, pathElement.getName());
}
}
@Override
public Expression> joinSubType(Expression> expression, Class> entityClass) {
BeanPath beanPath = (BeanPath) expression;
Class> queryClass = QuerydslUtils.getQueryClass(entityClass);
return beanPath.as(queryClass);
}
@Override
public Expression> doJoin(MetaAttribute targetAttr, JoinType joinType, Expression> parent) {
if (targetAttr instanceof MetaComputedAttribute) {
MetaComputedAttribute computedAttr = (MetaComputedAttribute) targetAttr;
QuerydslExpressionFactory expressionFactory = (QuerydslExpressionFactory>) queryImpl.getComputedAttrs()
.get(computedAttr);
return expressionFactory.getExpression(parent, getQuery());
} else {
Expression expression = QuerydslUtils.get(parent, targetAttr.getName());
querydslQuery.getMetadata().addJoin(QuerydslUtils.convertJoinType(joinType), expression);
return expression;
}
}
@Override
public JPAQueryFactory getQueryFactory() {
return queryImpl.getQueryFactory();
}
@Override
public EntityPath getParentRoot() {
return parentFrom;
}
@Override
public EntityPath getJoin(MetaAttributePath path) {
return (EntityPath) joinHelper.getOrCreateJoin(path);
}
@Override
public QuerydslTranslationContext castFor(Class type) {
return (QuerydslTranslationContext) this;
}
public final class BooleanPredicateOperation extends OperationImpl implements Predicate {
private static final long serialVersionUID = -5371430939203772072L;
@Nullable
private transient volatile Predicate not;
protected BooleanPredicateOperation(Ops ops, ImmutableList> list) {
super(Boolean.class, ops, list);
if (list.isEmpty()) {
throw new IllegalArgumentException("list cannot be empty");
}
}
@Override
public Predicate not() {
if (not == null) {
not = ExpressionUtils.predicate(Ops.NOT, this);
}
return not;
}
}
}