package org.malagu.linq.lin.impl; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.Stack; import javax.persistence.EntityManager; import javax.persistence.criteria.CommonAbstractCriteria; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Selection; import javax.persistence.criteria.Subquery; import org.malagu.linq.JpaUtil; import org.malagu.linq.Or; import org.malagu.linq.lin.Lin; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.malagu.linq.And; import org.malagu.linq.Junction; /** * @author Kevin Yang (mailto:[email protected]) * @since 2016年1月31日 */ @SuppressWarnings("unchecked") public abstract class LinImpl<T extends Lin<T, Q>, Q extends CommonAbstractCriteria> implements Lin<T, Q> { protected Class<?> domainClass; protected EntityManager em; protected CriteriaBuilder cb; protected Q criteria; protected Subquery<?> sq; protected Root<?> root; protected Stack<Junction> junctions = new Stack<Junction>(); protected Junction junction; protected T parent; protected Junction having; protected List<String> aliases = new ArrayList<String>(); private Stack<Boolean> ifResult = new Stack<Boolean>(); public LinImpl(Class<?> domainClass) { this(domainClass, null); } public LinImpl(Class<?> domainClass, EntityManager entityManager) { this.domainClass = domainClass; em = entityManager; if (entityManager == null) { em = JpaUtil.getEntityManager(domainClass); } cb = em.getCriteriaBuilder(); junction = new And(); junctions.add(junction); } public LinImpl(T parent, Class<?> domainClass) { this.domainClass = domainClass; this.parent = parent; em = parent.entityManager(); cb = parent.criteriaBuilder(); criteria = parent.criteria(); sq = criteria().subquery(domainClass); root = sq.from(domainClass); junction = new And(); junctions.add(junction); } @Override public T addIf(Object target) { boolean result; if (target instanceof Boolean) { result = (Boolean) target; } else if (target instanceof Collection) { result = !CollectionUtils.isEmpty((Collection<?>) target); } else { result = !StringUtils.isEmpty(target); } ifResult.push(result); return (T) this; } @Override public T addIfNot(Object target) { boolean result; if (target instanceof Boolean) { result = !(Boolean) target; } else if (target instanceof Collection) { result = CollectionUtils.isEmpty((Collection<?>) target); } else { result = StringUtils.isEmpty(target); } ifResult.push(result); return (T) this; } @Override public T endIf() { ifResult.pop(); return (T) this; } protected boolean beforeMethodInvoke() { for (Boolean r : ifResult) { if (!r) { return false; } } return true; } @Override public T selectId() { return select(JpaUtil.getIdName(domainClass)); } @Override public T select(String... selections) { if (!beforeMethodInvoke()) { return (T) this; } List<Selection<?>> list = new ArrayList<Selection<?>>(selections.length); for (String selection : selections) { parseSelectionStr(list, selection); } select(list.toArray(new Selection<?>[list.size()])); return (T) this; } @Override public T select(Object... selections) { if (!beforeMethodInvoke()) { return (T) this; } List<Selection<?>> list = new ArrayList<Selection<?>>(selections.length); for (Object selection : selections) { if (selection instanceof String) { parseSelectionStr(list, (String) selection); } else if (selection instanceof Selection) { list.add((Selection<?>) selection); } } select(list.toArray(new Selection<?>[list.size()])); return (T) this; } private void parseSelectionStr(List<Selection<?>> result, String selection) { String[] ps = selection.split("\\s*,\\s*"); for (String p : ps) { String alias = p.trim(); String[] pa = alias.split("\\s+[aA][sS]\\s+"); if (pa.length > 1) { alias = pa[1]; } else { pa = alias.split("\\s+"); if (pa.length > 1) { alias = pa[1]; } } result.add(root.get(ps[0]).alias(alias)); } } @Override @SuppressWarnings("rawtypes") public T select(Selection<?>... selections) { if (!beforeMethodInvoke()) { return (T) this; } Assert.isTrue(sq == null || selections.length == 1, "selections can only have one in subquery! "); Assert.isTrue(sq == null || selections[0] instanceof Expression, "Elements in the selections must implement the " + Expression.class.getName() + " interface in subquery! "); Assert.isTrue(sq != null || criteria instanceof CriteriaQuery, "Not supported!"); if (sq == null) { ((CriteriaQuery) criteria).multiselect(selections); } else { sq.select((Expression) selections[0]); } for (Selection<?> selection : selections) { aliases.add(selection.getAlias()); } return (T) this; } @Override public T and() { if (!beforeMethodInvoke()) { return (T) this; } And and = new And(); add(and); junctions.push(and); return (T) this; } @Override public T or() { if (!beforeMethodInvoke()) { return (T) this; } Or or = new Or(); add(or); junctions.push(or); return (T) this; } @Override public <Y extends Comparable<? super Y>> T between(Expression<Y> v, String x, String y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); Expression<Y> ye = root.get(y); add(cb.between(v, xe, ye)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T between(String v, Y x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> ve = root.get(v); add(cb.between(ve, x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T between(Expression<? extends Y> v, Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.between(v, x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T between(Expression<? extends Y> v, Y x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.between(v, x, y)); return (T) this; } @Override public T idEqual(Object id) { return equal(JpaUtil.getIdName(domainClass), id); } @Override public T equal(String x, Object y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.equal(root.get(x), y)); return (T) this; } @Override public T equal(Expression<?> x, Object y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.equal(x, y)); return (T) this; } @Override public T equal(Expression<?> x, Expression<?> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.equal(x, y)); return (T) this; } @Override public T equalProperty(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { equal(root.get(property), parent.root().get(otherProperty)); } else { equal(root.get(property), root.get(otherProperty)); } return (T) this; } @Override public T exists(Class<?> domainClass) { if (!beforeMethodInvoke()) { return (T) this; } T lin = createChild(domainClass); lin.select(lin.root()); add(cb.exists(lin.getSubquery())); return lin; } @Override public T notExists(Class<?> domainClass) { if (!beforeMethodInvoke()) { return (T) this; } T lin = createChild(domainClass); lin.select(lin.root()); add(cb.not(cb.exists(lin.getSubquery()))); return lin; } @Override public T ge(String x, Number y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.ge(root.get(x).as(Number.class), y)); return (T) this; } @Override public T ge(Expression<? extends Number> x, Number y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.ge(x, y)); return (T) this; } @Override public T ge(Expression<? extends Number> x, Expression<? extends Number> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.ge(x, y)); return (T) this; } @Override public T ge(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = parent.root().get(otherProperty); ge(x, y); } else { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = root.get(otherProperty); ge(x, y); } return (T) this; } @SuppressWarnings("rawtypes") @Override public T greaterThanProperty(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression x = root.get(property); Expression y = parent.root().get(otherProperty); greaterThan(x, y); } else { Expression x = root.get(property); Expression y = root.get(otherProperty); greaterThan(x, y); } return (T) this; } @Override public <Y extends Comparable<? super Y>> T greaterThan(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.greaterThan(xe, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T greaterThan(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.greaterThan(x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T greaterThan(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.greaterThan(x, y)); return (T) this; } @SuppressWarnings("rawtypes") @Override public T greaterThanOrEqualToProperty(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression x = root.get(property); Expression y = parent.root().get(otherProperty); greaterThanOrEqualTo(x, y); } else { Expression x = root.get(property); Expression y = root.get(otherProperty); greaterThanOrEqualTo(x, y); } return (T) this; } @Override public <Y extends Comparable<? super Y>> T greaterThanOrEqualTo(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.greaterThanOrEqualTo(xe, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T greaterThanOrEqualTo(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.greaterThanOrEqualTo(x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T greaterThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.greaterThanOrEqualTo(x, y)); return (T) this; } @Override public <Y extends Number> T gt(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.gt(xe, y)); return (T) this; } @Override public <Y extends Number> T gt(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.gt(x, y)); return (T) this; } @Override public <Y extends Number> T gt(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.gt(x, y)); return (T) this; } @Override public T gt(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = parent.root().get(otherProperty); gt(x, y); } else { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = root.get(otherProperty); gt(x, y); } return (T) this; } @Override public T in(String property, Class<?> domainClass) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); T lin = createChild(domainClass); add(cb.in(e).value(lin.getSubquery())); return lin; } @Override public T in(Class<?> domainClass) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(JpaUtil.getIdName(this.domainClass)); T lin = createChild(domainClass); add(cb.in(e).value(lin.getSubquery())); return lin; } @Override public T in(String property, Set<?> values) { return in(property, values.toArray()); } @Override public T in(String property, Object... values) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); add(e.in(values)); return (T) this; } @Override public T in(Expression<?> expression, Object... values) { if (!beforeMethodInvoke()) { return (T) this; } add(expression.in(values)); return (T) this; } @Override public T in(String property, Expression<Collection<?>> values) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); add(e.in(values)); return (T) this; } @Override public T in(Expression<?> expression, Expression<Collection<?>> values) { if (!beforeMethodInvoke()) { return (T) this; } add(expression.in(values)); return (T) this; } @Override public T in(String property, Expression<?> ...values) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); add(e.in(values)); return (T) this; } @Override public <E> T in(Expression<E> expression, Expression<?> ...values) { if (!beforeMethodInvoke()) { return (T) this; } add(expression.in(values)); return (T) this; } @Override public T notIn(String property, Set<?> values) { return notIn(property, values.toArray()); } @Override public T notIn(String property, Object... values) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); add(cb.not(e.in(values))); return (T) this; } @Override public T notIn(String property, Expression<Collection<?>> values) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); add(cb.not(e.in(values))); return (T) this; } @Override public <E> T notIn(Expression<E> expression, Expression<Collection<?>> values) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.not(expression.in(values))); return (T) this; } @Override public T notIn(Expression<?> expression, Object... values) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.not(expression.in(values))); return (T) this; } @Override public T notIn(String property, Expression<?> ...values) { if (!beforeMethodInvoke()) { return (T) this; } Expression<?> e = root.get(property); add(cb.not(e.in(values))); return (T) this; } @Override public <E> T notIn(Expression<E> expression, Expression<?> ...values) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.not(expression.in(values))); return (T) this; } @SuppressWarnings("rawtypes") @Override public T isEmpty(String property) { if (!beforeMethodInvoke()) { return (T) this; } Expression e = root.get(property); add(cb.isEmpty(e)); return (T) this; } @Override public <C extends Collection<?>> T isEmpty(Expression<C> collection) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isEmpty(collection)); return (T) this; } @Override public T isFalse(String property) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Boolean> e = root.get(property); add(cb.isFalse(e)); return (T) this; } @Override public T isFalse(Expression<Boolean> expression) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isFalse(expression)); return (T) this; } @SuppressWarnings("rawtypes") @Override public T isMember(String elem, String collection) { if (!beforeMethodInvoke()) { return (T) this; } Expression elemE = root.get(elem); Expression collectionE = root.get(collection); isMember(elemE, collectionE); return (T) this; } @Override public <E, C extends Collection<E>> T isMember(Expression<E> elem, Expression<C> collection) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isMember(elem, collection)); return (T) this; } @SuppressWarnings("rawtypes") @Override public T isNotEmpty(String collection) { if (!beforeMethodInvoke()) { return (T) this; } Expression collectionE = root.get(collection); add(cb.isNotEmpty(collectionE)); return (T) this; } @Override public <C extends Collection<?>> T isNotEmpty(Expression<C> collection) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isNotEmpty(collection)); return (T) this; } @SuppressWarnings("rawtypes") @Override public T isNotMember(String elem, String collection) { if (!beforeMethodInvoke()) { return (T) this; } Expression elemE = root.get(elem); Expression collectionE = root.get(collection); isNotMember(elemE, collectionE); return (T) this; } @Override public <E, C extends Collection<E>> T isNotMember(Expression<E> elem, Expression<C> collection) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isNotMember(elem, collection)); return (T) this; } @Override public T isNull(String property) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isNull(root.get(property))); return (T) this; } @Override public T isNull(Expression<?> expression) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isNull(expression)); return (T) this; } @Override public T isNotNull(String property) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isNotNull(root.get(property))); return (T) this; } @Override public T isNotNull(Expression<?> expression) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isNotNull(expression)); return (T) this; } @Override public T isTrue(String property) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Boolean> e = root.get(property); add(cb.isTrue(e)); return (T) this; } @Override public T isTrue(Expression<Boolean> expression) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.isTrue(expression)); return (T) this; } @Override public <Y extends Number> T le(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.le(xe, y)); return (T) this; } @Override public T le(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = parent.root().get(otherProperty); le(x, y); } else { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = root.get(otherProperty); le(x, y); } return (T) this; } @Override public <Y extends Number> T le(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.le(x, y)); return (T) this; } @Override public <Y extends Number> T le(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.le(x, y)); return (T) this; } @Override public <Y extends Number> T lt(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.lt(xe, y)); return (T) this; } @Override public T lt(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = parent.root().get(otherProperty); lt(x, y); } else { Expression<? extends Number> x = root.get(property); Expression<? extends Number> y = root.get(otherProperty); lt(x, y); } return (T) this; } @Override public <Y extends Number> T lt(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.lt(x, y)); return (T) this; } @Override public <Y extends Number> T lt(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.lt(x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T lessThan(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.lessThan(xe, y)); return (T) this; } @SuppressWarnings("rawtypes") @Override public T lessThanProperty(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression x = root.get(property); Expression y = parent.root().get(otherProperty); lessThan(x, y); } else { Expression x = root.get(property); Expression y = root.get(otherProperty); lessThan(x, y); } return (T) this; } @Override public <Y extends Comparable<? super Y>> T lessThan(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.lessThan(x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T lessThan(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.lessThan(x, y)); return (T) this; } @SuppressWarnings("rawtypes") @Override public T lessThanOrEqualToProperty(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression x = root.get(property); Expression y = parent.root().get(otherProperty); lessThanOrEqualTo(x, y); } else { Expression x = root.get(property); Expression y = root.get(otherProperty); lessThanOrEqualTo(x, y); } return (T) this; } @Override public <Y extends Comparable<? super Y>> T lessThanOrEqualTo(String x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } Expression<Y> xe = root.get(x); add(cb.lessThanOrEqualTo(xe, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T lessThanOrEqualTo(Expression<? extends Y> x, Y y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.lessThanOrEqualTo(x, y)); return (T) this; } @Override public <Y extends Comparable<? super Y>> T lessThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.lessThanOrEqualTo(x, y)); return (T) this; } @Override public T like(Expression<String> x, String pattern) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.like(x, pattern)); return (T) this; } @Override public T like(Expression<String> x, Expression<String> pattern) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.like(x, pattern)); return (T) this; } @Override public T like(String x,String pattern) { if (!beforeMethodInvoke()) { return (T) this; } Expression<String> xe = root.get(x); add(cb.like(xe, pattern)); return (T) this; } @Override public T like(Expression<String> x, Expression<String> pattern, char escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.like(x, pattern, escapeChar)); return (T) this; } @Override public T like(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.like(x, pattern, escapeChar)); return (T) this; } @Override public T like(Expression<String> x, String pattern, char escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.like(x, pattern, escapeChar)); return (T) this; } @Override public T like(Expression<String> x, String pattern, Expression<Character> escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.like(x, pattern, escapeChar)); return (T) this; } @Override public T notLike(Expression<String> x, String pattern) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notLike(x, pattern)); return (T) this; } @Override public T notLike(Expression<String> x, Expression<String> pattern) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notLike(x, pattern)); return (T) this; } @Override public T notLike(String x, String pattern) { if (!beforeMethodInvoke()) { return (T) this; } Expression<String> xe = root.get(x); add(cb.notLike(xe, pattern)); return (T) this; } @Override public T notLike(Expression<String> x, Expression<String> pattern, char escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notLike(x, pattern, escapeChar)); return (T) this; } @Override public T notLike(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notLike(x, pattern, escapeChar)); return (T) this; } @Override public T notLike(Expression<String> x, String pattern, char escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notLike(x, pattern, escapeChar)); return (T) this; } @Override public T notLike(Expression<String> x, String pattern, Expression<Character> escapeChar) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notLike(x, pattern, escapeChar)); return (T) this; } @Override public T not(Expression<Boolean> restriction) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.not(restriction)); return (T) this; } @Override public T notEqual(String x, Object y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notEqual(root.get(x), y)); return (T) this; } @Override public T notEqual(Expression<?> x, Object y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notEqual(x, y)); return (T) this; } @Override public T notEqualProperty(String property, String otherProperty) { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { Expression<?> x = root.get(property); Expression<?> y = parent.root().get(otherProperty); notEqual(x, y); } else { Expression<?> x = root.get(property); Expression<?> y = root.get(otherProperty); notEqual(x, y); } return (T) this; } @Override public T notEqual(Expression<?> x, Expression<?> y) { if (!beforeMethodInvoke()) { return (T) this; } add(cb.notEqual(x, y)); return (T) this; } @Override public T end() { if (!beforeMethodInvoke()) { return (T) this; } if (sq != null) { if (junctions.size() == 1) { Predicate predicate = parsePredicate(junction); if (predicate != null) { sq.where(predicate); } return parent; } } if (!junctions.isEmpty()) { junctions.pop(); } return (T) this; } @Override public T groupBy(String... grouping) { if (!beforeMethodInvoke()) { return (T) this; } List<Expression<?>> expressions = new ArrayList<Expression<?>>(); for (String property : grouping) { expressions.add(root.get(property)); } if (sq != null) { sq.groupBy(expressions); } else { throw new RuntimeException("Not Supported!"); } return (T) this; } @Override public T having() { if (!beforeMethodInvoke()) { return (T) this; } having = new And(); junctions.push(having); return (T) this; } protected Predicate parsePredicate(Object predicate) { if (predicate instanceof Predicate) { return (Predicate) predicate; } else if (predicate instanceof Junction) { Junction junction = (Junction) predicate; if (!CollectionUtils.isEmpty(junction.getPredicates())) { List<Predicate> predicates = new ArrayList<Predicate>(); for (Object p : junction.getPredicates()) { Predicate result = parsePredicate(p); if (result != null) { predicates.add(result); } } if (!CollectionUtils.isEmpty(predicates)) { if (junction instanceof And) { return cb.and(predicates.toArray(new Predicate[predicates.size()])); } else if (junction instanceof Or) { return cb.or(predicates.toArray(new Predicate[predicates.size()])); } } } } return null; } @Override public T add(Object predicate) { if (!beforeMethodInvoke()) { return (T) this; } this.getCurrent().add(predicate); return (T) this; } protected Junction getCurrent() { return this.junctions.peek(); } @Override public Q criteria() { return criteria; } @Override public CriteriaBuilder criteriaBuilder() { return cb; } @Override public EntityManager entityManager() { return em; } @Override public <E> Subquery<E> getSubquery() { return (Subquery<E>) sq; } @Override public Class<?> domainClass() { return domainClass; } @Override public <E> Root<E> root() { return (Root<E>) root; } }