package com.breeze.jpa;
import java.util.List;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import com.breeze.metadata.IEntityType;
import com.breeze.query.BinaryPredicate;
import com.breeze.query.EntityQuery;
import com.breeze.query.Expression;
import com.breeze.query.LitExpression;
import com.breeze.query.Operator;
import com.breeze.query.Predicate;
import com.breeze.query.PropExpression;
public class JPACriteriaBuilder {
// private CriteriaAliasBuilder _aliasBuilder;
@SuppressWarnings("unused")
private EntityQuery _entityQuery;
private IEntityType _entityType;
private int _subqCount = 0;
private CriteriaBuilder _cb;
private Root<?> _root;
private JPACriteriaBuilder() {
}
public static JPACriteriaBuilder create(CriteriaQuery<?> crit, CriteriaBuilder criteriaBuilder, IEntityType entityType, EntityQuery entityQuery) {
JPACriteriaBuilder critBuilder = new JPACriteriaBuilder();
critBuilder.updateCriteria(crit, criteriaBuilder, entityType, entityQuery);
return critBuilder;
}
/**
* @param crit
* a Criteria object that will be updated to match the entityQuery
* @param entityQuery
* the EntityQuery object from which the criteria should be updated.
*/
private void updateCriteria(CriteriaQuery<?> crit, CriteriaBuilder criteriaBuilder, IEntityType entityType, EntityQuery entityQuery) {
_entityType = entityType;
_entityQuery = entityQuery;
_cb = criteriaBuilder;
// _aliasBuilder = new CriteriaAliasBuilder();
_root = crit.from(crit.getResultType());
addWhere(crit, entityQuery.getWherePredicate());
// addSelect(crit, entityQuery.getSelectClause());
// addOrderBy(crit, entityQuery.getOrderByClause());
}
@SuppressWarnings("unchecked")
private void addWhere(CriteriaQuery<?> crit, Predicate wherePred) {
if (wherePred == null) return;
// CriteriaWrapper critWrapper = new CriteriaWrapper(crit, _entityType);
// Criterion cr = toCriterion(crit, wherePred, null);
// crit.add(cr);
// nested path translate, ?Task???"user.name"?filedName, ???Task.user.name??
// String[] names = StringUtils.split(filter.fieldName, ".");
// Path expression = root.get(names[0]);
// for (int i = 1; i < names.length; i++) {
// expression = expression.get(names[i]);
// }
BinaryPredicate breezePred = (BinaryPredicate) wherePred;
Operator op = breezePred.getOperator();
String symbol = op.getName();
Expression expr1 = breezePred.getExpr1();
Expression expr2 = breezePred.getExpr2();
String contextAlias = null;
javax.persistence.criteria.Predicate xpred;
if (expr1 instanceof PropExpression) {
PropExpression pexpr1 = (PropExpression) expr1;
String propPath = pexpr1.getPropertyPath();
String propName;
if (pexpr1.getProperty().getParentType().isComplexType()) {
// don't process the property path in this case.
propName = propPath;
} else {
propName = propPath; //crit. _aliasBuilder.getPropertyName(crit, propPath);
}
propName = (contextAlias == null) ? propName : contextAlias + "." + propName;
Path path = _root.get(propName);
if (expr2 instanceof LitExpression) {
Object value = ((LitExpression) expr2).getValue();
if (value == null) {
if (op == Operator.Equals) {
xpred = _cb.isNull(path);
} else if (op == Operator.NotEquals) {
xpred = _cb.isNotNull(path);
} else {
throw new RuntimeException("Binary Predicate with a null value and the "
+ op.getName() + "operator is not supported .");
}
} else if (op == Operator.Equals) {
xpred = _cb.equal(path, value);
} else if (op == Operator.NotEquals) {
xpred = _cb.notEqual(path, value);
} else if (op == Operator.GreaterThan) {
xpred = _cb.greaterThan(_root.<Comparable>get(propName), (Comparable) value);
} else if (op == Operator.GreaterThanOrEqual) {
xpred = _cb.greaterThanOrEqualTo(_root.<Comparable>get(propName), (Comparable) value);
} else if (op == Operator.LessThan) {
xpred = _cb.lessThan(_root.<Comparable>get(propName), (Comparable) value);
} else if (op == Operator.LessThanOrEqual) {
xpred = _cb.lessThanOrEqualTo(_root.<Comparable>get(propName), (Comparable) value);
} else if (op == Operator.In) {
xpred = path.in((List) value);
} else if (op == Operator.StartsWith) {
xpred = _cb.like(path, "" + value + "%");
} else if (op == Operator.EndsWith) {
xpred = _cb.like(path, "%" + value);
} else if (op == Operator.Contains) {
xpred = _cb.like(path, "%" + value + "%");
} else {
throw new RuntimeException("Binary Predicate with the "
+ op.getName() + "operator is not yet supported.");
}
} else {
String otherPropPath = ((PropExpression) expr2).getPropertyPath();
Path otherPath = _root.get(otherPropPath);
if (op == Operator.Equals) {
xpred = _cb.equal(path, otherPath);
} else if (op == Operator.NotEquals) {
xpred = _cb.notEqual(path, otherPath);
} else if (op == Operator.GreaterThan) {
xpred = _cb.greaterThan(_root.<Comparable>get(propName), _root.<Comparable>get(otherPropPath));
} else if (op == Operator.GreaterThanOrEqual) {
xpred = _cb.greaterThanOrEqualTo(_root.<Comparable>get(propName), _root.<Comparable>get(otherPropPath));
} else if (op == Operator.LessThan) {
xpred = _cb.lessThan(_root.<Comparable>get(propName), _root.<Comparable>get(otherPropPath));
} else if (op == Operator.LessThanOrEqual) {
xpred = _cb.lessThanOrEqualTo(_root.<Comparable>get(propName), _root.<Comparable>get(otherPropPath));
} else if (op == Operator.StartsWith) {
xpred = _cb.like(path, _cb.concat(otherPath, "%"));
} else if (op == Operator.EndsWith) {
xpred = _cb.like(path, _cb.concat("%", otherPath));
} else if (op == Operator.Contains) {
xpred = _cb.like(path, _cb.concat(_cb.concat("%", otherPath), "%"));
} else {
throw new RuntimeException("Property comparison with the "
+ op.getName() + "operator is not yet supported.");
}
}
crit.where(xpred);
return;
} else {
throw new RuntimeException(
"Function expressions not yet supported.");
}
}
}