I am writing an API that generates Predicates corresponding to Criterion classes I've created.
This is the base criterion class:
public abstract class AbstractCriterion<O extends SearchOperator, V> {
protected O operator;
protected String pathExpression;
protected V value;
protected SearchCriteria<?> searchCriteria;
public AbstractCriterion(SearchCriteria<?> searchCriteria, O operator, String pathExpression, V value) {
...
}
public abstract Predicate getPredicate(CriteriaBuilder criteriaBuilder, Root<?> root);
...
}
Here is the CollectionCriterion class:
public class CollectionCriterion<E> extends AbstractCriterion<CollectionSearchOperator, Object> {
public CollectionCriterion(SearchCriteria<?> searchCriteria, CollectionSearchOperator operator, String pathExpression, Object value) {
...
}
public Predicate getPredicate(CriteriaBuilder criteriaBuilder, Root<?> root) {
...
//here I retrieve the field corresponding to the path expression
//for instance I retrieve the field country corresponding to the
//path "person.address.country"
Field field = JpaUtils.navigateTo(searchCriteria.getManagedClass(), pathExpression);
//here I got to do somme validation and check that the retrieved
//field is a Collection and ideally check if it's a Collection
//containing only E elements (Collection<E>)
if(!Collection.class.isAssignableFrom(field.getType())) {
throw new Exception(...);
}
else {
//if it's a collection check if it contains only
//instances of E
}
...
String[] pathArray = pathExpression.split(".");
//I iterate after splitting the string path expression to get
//the last element's Path object. This is the main reason why
//I am doing validation
Path<Object> tempPath = root.get(pathArray[0]);
for(int i = 1; i < pathArray.length; i++) {
if(i != pathArray.length - 1) {
tempPath = tempPath.get(pathArray[i]);
}
}
Path<Collection<E>> path = tempPath.<Collection<E>> get(pathArray[lastIndex]);
switch(operator) {
...
}
}
1- My first question is about finding a way for checking that the field is a collection of E elements, I am aware of the type erasure at runtime (here from stackoverflow), but I found the following tools that can retrieve generic type parameters: Typetools and Classmate. Is it possible to use those libraries to solve this problem?
2- Is it possible to do this check through a simple cast of the value of the field?
Object instance = field.getDeclaringClass().getConstructor().newInstance();
try {
Collection<E> collection = (Collection<E>) field.getValue(instance);
}
catch(ClassCastException e) {
throw new Exception(...);
}
3- If not possible at all, how does the generic method Path.get() behave when passing an argument type like Collection<E>
? Does it throws an exception if the string argument is not a Collection<E>
?
Path<Collection<E>> path = tempPath.<Collection<E>> get(pathArray[lastIndex]);
Thanks for your time.
Aucun commentaire:
Enregistrer un commentaire