List<QueryRule> rules = Arrays.asList(rul);
Predicate whereClause = null;
List<Order> orders = new ArrayList<Order>();
QueryRule prevRule = null;
forLoop: for (int i = 0; i < rules.size(); ++i)
{
QueryRule rule = rules.get(i);
if (mapper != null)
{
rule.setField(mapper.getTableFieldName(rule.getField()));
Operator operator = rule.getOperator();
if (operator == Operator.SORTASC || operator == Operator.SORTDESC)
{
rule.setField(mapper.getTableFieldName(rule.getValue().toString()));
}
String attributeName = rule.getJpaAttribute();
Predicate predicate = null;
Expression<?> expression = _addJoin(rule, root, joinHash);
Expression<?> lhs = null;
if (expression != null)
{
lhs = expression;
}
else if (attributeName != null)
{
lhs = root.get(attributeName);
}
Object rhs = rule.getValue();
switch (operator)
{
case LAST:
throw new UnsupportedOperationException("Not supported yet.");
case SORTASC:
orders.add(cb.asc(lhs));
break;
case SORTDESC:
orders.add(cb.desc(lhs));
break;
case LIMIT:
limitOffset[0] = (Integer) rule.getValue();
break;
case OFFSET:
limitOffset[1] = (Integer) rule.getValue();
break;
default:
switch (operator)
{
case EQUALS:
if (rhs instanceof Entity)
{
try
{
predicate = cb.equal(root.get(attributeName), rule.getValue());
}
catch (Exception ex)
{
LogFactory.getLog(JPAQueryGeneratorUtil.class.getName()).error(ex);
}
}
else
{
try
{
// it's a xref attribute which is joined
// to root
if (attributeName.contains(".")
|| root.get(attributeName).getJavaType().getName()
.equals("java.util.List")
|| root.get(attributeName).getJavaType().newInstance() instanceof Entity)
{
predicate = cb.equal(lhs, rhs);
}
else
{ // normal attribute
predicate = cb.equal(lhs, rhs);
}
}
catch (InstantiationException ex)
{
// this is a hack, newInstance can not
// be called on inmutable object
// like Integer
predicate = cb.equal(lhs, rhs);
}
catch (IllegalAccessException ex)
{
LogFactory.getLog(JPAQueryGeneratorUtil.class.getName()).error(ex);
throw new DatabaseException(ex);
}
}
break;
case NOT:
predicate = cb.notEqual(lhs, rhs);
break;
case LIKE:
if (lhs.getJavaType().getSimpleName().equals("String"))
{
predicate = cb.like(lhs.as(String.class), (String) rhs);
}
else
{
// TODO: What to do here?
}
break;
case LESS:
predicate = cb.lessThan((Expression) lhs, (Comparable<Object>) rhs);
break;
case GREATER:
predicate = cb.greaterThan((Expression) lhs, (Comparable<Object>) rhs);
break;
case LESS_EQUAL:
predicate = cb.lessThanOrEqualTo((Expression) lhs, (Comparable<Object>) rhs);
break;
case GREATER_EQUAL:
predicate = cb.greaterThanOrEqualTo((Expression) lhs, (Comparable<Object>) rhs);
break;
case NESTED:
QueryRule[] nestedrules = rule.getNestedRules();
predicate = _createWhere(db, mapper, em, root, cq, cb, new int[2], joinHash,
nestedrules);
break;
case SUBQUERY:
SubQueryRule sqr = (SubQueryRule) rule;
Subquery sq = cq.subquery(sqr.getSubQueryResultClass());
Root<IN> sqFrom = sq.from(sqr.getSubQueryFromClass());
Mapper<IN> sqMapper = db.getMapper(sqr.getSubQueryFromClass().getName());
Predicate where = _createWhere(db, sqMapper, em, sqFrom, cq, cb, new int[2], joinHash,
(QueryRule[]) sqr.getValue());
sq.select(sqFrom.get(sqr.getSubQueryAttributeJpa())).where(where);
// the operator of subquery should be handled in
// the right way such that no code duplication
// should occure
// for the moment only in will work (more to
// come)
String fieldForSubQuery = sqr.getJpaAttribute();
if (sqr.getSubQueryOperator().equals(Operator.IN))
{
predicate = cb.in(root.get(fieldForSubQuery)).value(sq);
}
else
{
throw new UnsupportedOperationException();
}
break;
case IN: // not a query but a list for example
// SELECT * FROM
// x WHERE x.a1 IN (v1, v2, v3)
Object[] values = new Object[0];
if (rule.getValue() instanceof List)
{
values = ((List<?>) rule.getValue()).toArray();
}
else
{
values = (Object[]) rule.getValue();
}
Class<?> attrClass = null;
if (attributeName.contains("."))
{
attrClass = lhs.getJavaType();