/**
*
*/
package org.activejpa.entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.activejpa.util.ConvertUtil;
/**
* @author ganeshs
*
*/
public class Condition extends AbstractConstruct {
/**
* @author ganeshs
*
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public enum Operator {
eq("=") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.equal(path, parameter[0]);
}
},
ne("!=") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.notEqual(path, parameter[0]);
}
},
le("<=") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.lessThanOrEqualTo(path, parameter[0]);
}
},
lt("<") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.lessThan(path, parameter[0]);
}
},
ge(">=") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.greaterThanOrEqualTo(path, parameter[0]);
}
},
gt(">") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.greaterThan(path, parameter[0]);
}
},
between("between") {
@Override
public String constructCondition(String name, Object value) {
return name + " between :from" + name + " and :to" + name;
}
@Override
public Predicate constructCondition(CriteriaBuilder builder, Path path, String name) {
name = cleanName(name);
return createPredicate(builder, path, builder.parameter(path.getJavaType(), "from" + name), builder.parameter(path.getJavaType(), "to" + name));
}
@Override
public void setParameters(Query query, String name, Object value, Class<?> paramType) {
name = cleanName(name);
Object[] values = null;
if (value instanceof Object[]) {
values = (Object[]) value;
}
if (values == null || values.length != 2) {
throw new IllegalArgumentException("Value - " + value + " should be an array of size 2");
}
super.setParameters(query, "from" + name, values[0], paramType);
super.setParameters(query, "to" + name, values[1], paramType);
}
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.between(path, parameter[0], parameter[1]);
}
},
in("in") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return path.in(parameter[0]);
}
@Override
public void setParameters(Query query, String name, Object value, Class<?> paramType) {
name = cleanName(name);
if (value instanceof Object[]) {
value = Arrays.asList((Object[]) value);
}
List list = new ArrayList();
for (Object val : (List) value) {
list.add(ConvertUtil.convert(val, paramType));
}
query.setParameter(name, list);
}
@Override
public Predicate constructCondition(CriteriaBuilder builder, Path path, String name) {
name = cleanName(name);
return createPredicate(builder, path, builder.parameter(Collection.class, name));
}
},
like("like") {
@Override
protected Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter) {
return builder.like(path, parameter[0]);
}
};
private String operator;
private Operator(String operator) {
this.operator = operator;
}
public String constructCondition(String name, Object value) {
return name + " " + operator + " :" + name;
}
public void setParameters(Query query, String name, Object value, Class<?> paramType) {
name = cleanName(name);
value = ConvertUtil.convert(value, paramType);
query.setParameter(name, value);
}
public Predicate constructCondition(CriteriaBuilder builder, Path path, String name) {
return createPredicate(builder, path, builder.parameter(path.getJavaType(), cleanName(name)));
}
protected abstract Predicate createPredicate(CriteriaBuilder builder, Path path, Expression... parameter);
/**
* Cleans the name to align with the jpa query language constructs
*
* @param name
* @return
*/
protected String cleanName(String name) {
return name.replace(".", "0_");
}
}
private String name;
private Object value;
private Operator operator;
private Path<?> path;
/**
* Default constructor
*/
public Condition() {
}
/**
* @param name
* @param operator
* @param value
*/
public Condition(String name, Operator operator, Object value) {
this.name = name;
this.value = value;
this.operator = operator;
}
/**
* @param name
* @param value
*/
public Condition(String name, Object value) {
this(name, Operator.eq, value);
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the value
*/
public Object getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(Object value) {
this.value = value;
}
/**
* @return the operator
*/
public Operator getOperator() {
return operator;
}
/**
* @param operator the operator to set
*/
public void setOperator(Operator operator) {
this.operator = operator;
}
public String constructQuery() {
return operator.constructCondition(name, value);
}
public <T extends Model> Predicate constructQuery(CriteriaBuilder builder, Root<T> root) {
path = getPath(root, name);
return operator.constructCondition(builder, path, name);
}
public void setParameters(Query query, Object value) {
operator.setParameters(query, name, value, path.getJavaType());
}
/**
* @return the path
*/
Path<?> getPath() {
return path;
}
/**
* @param path the path to set
*/
void setPath(Path<?> path) {
this.path = path;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((operator == null) ? 0 : operator.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Condition other = (Condition) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (operator != other.operator)
return false;
return true;
}
}