Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics variable <T> value

Tags:

java

generics

At the moment I am using the following code to do some filtering in jpa:

if (value.getClass() == Integer.class) {
   return cb.greaterThan(root.<Integer>get(field), (Integer) value);
} else if (value.getClass() == Long.class) {
   return cb.greaterThan(root.<Long>get(field), (Long) value);
} else if (value.getClass() == Float.class) {
   return cb.greaterThan(root.<Float>get(field), (Float) value);
} else if (value.getClass() == Date.class) {
   return cb.greaterThan(root.<Date>get(field), (Date) value);
}

How can i reduce this block to one line like that?

return cb.greaterThan(root.<value.getClass()>get(field), value);

So i need to replace the T value in < T > with my class type. Sadly i am not that good in java generics. Does anybody has an idea? Is it even possible?

root is of the following type: http://docs.oracle.com/javaee/6/api/javax/persistence/criteria/Path.html#get%28java.lang.String%29

edit: here is the full class i want to write:

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

public class FilterExpression {

    public static final Integer BEGINS_WITH = 0;
    public static final Integer ENDS_WITH = 1;
    public static final Integer CONTAINS = 2;
    public static final Integer EQUAL = 3;
    public static final Integer NOT_EQUAL = 4;
    public static final Integer GREATER_THAN = 5;
    public static final Integer GREATER_EQUAL_THAN = 6;
    public static final Integer LESS_THAN = 7;
    public static final Integer LESS_EQUAL_THAN = 8;
    private static final Map<String, Integer> OPERATOR_MAPPING;

    static {
        Map<String, Integer> temp = new HashMap<>();
        temp.put("bw", BEGINS_WITH);
        temp.put("ew", ENDS_WITH);
        temp.put("ct", CONTAINS);
        temp.put("eq", EQUAL);
        temp.put("nq", NOT_EQUAL);
        temp.put("gt", GREATER_THAN);
        temp.put("gq", GREATER_EQUAL_THAN);
        temp.put("lt", LESS_THAN);
        temp.put("lq", LESS_EQUAL_THAN);
        OPERATOR_MAPPING = Collections.unmodifiableMap(temp);
    }

    private String field;
    private Integer operator;
    private Object value;

    public FilterExpression(String field, String operator, String value, Class c) {
        this.field = field;
        setOperator(operator);
        setValue(value, c);
    }

    public Boolean validate() {
        if (StringUtils.isEmpty(field) || operator == null || value == null) {
            return false;
        }
        Class c = value.getClass();

        if (c == String.class) {
            return operator >= BEGINS_WITH && operator <= NOT_EQUAL;
        } else if (c == Integer.class || c == Float.class || c == Double.class) {
            return (EQUAL >= EQUAL && operator <= LESS_EQUAL_THAN);
        } else if (c == Boolean.class) {
            return operator == EQUAL || operator == NOT_EQUAL;
        } else if (c == Identification.Type.class) {
            return operator == EQUAL || operator == NOT_EQUAL;
        }
        return false;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public Integer getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = OPERATOR_MAPPING.get(operator.toLowerCase());
    }

    public Object getValue() {
        return value;
    }

    public void setValue(String s, Class c) {
        try {
            if (Boolean.class == c) {
                this.value = validateBoolean(s);
            } else if (Integer.class == c) {
                this.value = Integer.parseInt(s);
            } else if (Float.class == c) {
                this.value = Float.parseFloat(s);
            } else if (Identification.Type.class == c) {
                this.value = Identification.Type.parse(Integer.parseInt(s));
            } else {
                this.value = s;
            }
        } catch (NumberFormatException ex) {
            this.value = null;
        }
    }

    public <R> Predicate toPredicate(CriteriaBuilder cb, Root<R> root) {
        if (Objects.equals(operator, FilterExpression.EQUAL)) {
            return cb.equal(root.get(field), value);
        } else if (Objects.equals(operator, FilterExpression.NOT_EQUAL)) {
            return cb.notEqual(root.get(field), value);
        } else if (Objects.equals(operator, FilterExpression.CONTAINS)) {
            return cb.like(root.<String>get(field), "%" + value + "%");
        } else if (Objects.equals(operator, FilterExpression.ENDS_WITH)) {
            return cb.like(root.<String>get(field), "%" + value);
        } else if (Objects.equals(operator, FilterExpression.BEGINS_WITH)) {
            return cb.like(root.<String>get(field), value + "%");
        } else if (Objects.equals(operator, FilterExpression.GREATER_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.greaterThan(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.greaterThan(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.greaterThan(root.<Date>get(field), (Date) value);
            }
        } else if (Objects.equals(operator, FilterExpression.GREATER_EQUAL_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.greaterThanOrEqualTo(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.greaterThanOrEqualTo(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.greaterThanOrEqualTo(root.<Date>get(field), (Date) value);
            }
        } else if (Objects.equals(operator, FilterExpression.LESS_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.lessThan(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.lessThan(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.lessThan(root.<Date>get(field), (Date) value);
            }
        } else if (Objects.equals(operator, FilterExpression.LESS_EQUAL_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.lessThanOrEqualTo(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.lessThanOrEqualTo(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.lessThanOrEqualTo(root.<Date>get(field), (Date) value);
            }
        }
        return null;
    }
like image 942
perotom Avatar asked Aug 17 '16 14:08

perotom


2 Answers

I guess you could make the whole class generic.

public class FilterExpression<T extends Comparable<T>> {
    //Make value to be type T instead of Object.
    T value;

    // And you could easily do,
    ...
    return cb.greaterThan(root.<T>get(field), value);
}
like image 106
Codebender Avatar answered Oct 19 '22 14:10

Codebender


As the code of your method is complex since everything is mixed, if you don't intend to refactor your method for me the simplest solution by far is relying on raw types as next:

return cb.greaterThan(root.<Comparable>get(field), (Comparable) value);
like image 27
Nicolas Filotto Avatar answered Oct 19 '22 14:10

Nicolas Filotto