/*
* (c) Copyright 2005-2012 JAXIO, www.jaxio.com
* Source code generated by Celerio, a Jaxio product
* Want to use Celerio within your company? email us at info@jaxio.com
* Follow us on twitter: @springfuse
* Template pack-backend-sd:src/main/java/project/repository/support/ByExampleSpecifications.p.vm.java
*/
package com.company.demo.repository.support;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Lists.newArrayList;
import static javax.persistence.metamodel.Attribute.PersistentAttributeType.MANY_TO_ONE;
import static javax.persistence.metamodel.Attribute.PersistentAttributeType.ONE_TO_ONE;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
import java.lang.reflect.Method;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.ReflectionUtils;
import com.google.common.base.Throwables;
/**
* Helper to create find by example query.
*/
public class ByExampleSpecifications {
public static <T> Specification<T> byExample(final EntityManager em, final T example) {
checkNotNull(em, "em must not be null");
checkNotNull(example, "example must not be null");
@SuppressWarnings("unchecked")
final Class<T> type = (Class<T>) example.getClass();
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = newArrayList();
EntityType<T> entity = em.getMetamodel().entity(type);
for (Attribute<T, ?> attr : entity.getDeclaredSingularAttributes()) {
if (attr.getPersistentAttributeType() == MANY_TO_ONE
|| attr.getPersistentAttributeType() == ONE_TO_ONE) {
continue;
}
Object attrValue = getValue(example, attr);
if (attrValue != null) {
if (attr.getJavaType() == String.class) {
if (isNotEmpty((String) attrValue)) {
predicates.add(builder.like(root.get(attribute(entity, attr.getName(), String.class)),
pattern((String) attrValue)));
}
} else {
predicates.add(builder.equal(root.get(attribute(entity, attr.getName(), attrValue
.getClass())), attrValue));
}
}
}
return predicates.isEmpty() ? builder.conjunction() : builder.and(toArray(predicates, Predicate.class));
}
private Object getValue(T example, Attribute<T, ?> attr) {
try {
return ReflectionUtils.invokeMethod((Method) attr.getJavaMember(), example);
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
private <E> SingularAttribute<T, E> attribute(EntityType<T> entity, String fieldName, Class<E> fieldClass) {
return entity.getDeclaredSingularAttribute(fieldName, fieldClass);
}
};
}
/**
* Lookup entities having at least one String attribute matching the passed pattern.
*/
public static <T> Specification<T> byPatternOnStringAttributes(final EntityManager em, final String pattern,
final Class<T> type) {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = newArrayList();
EntityType<T> entity = em.getMetamodel().entity(type);
for (Attribute<T, ?> attr : entity.getDeclaredSingularAttributes()) {
if (attr.getPersistentAttributeType() == MANY_TO_ONE
|| attr.getPersistentAttributeType() == ONE_TO_ONE) {
continue;
}
if (attr.getJavaType() == String.class && isNotEmpty(pattern)) {
predicates.add(builder.like(root.get(attribute(entity, attr)), pattern(pattern)));
}
}
return predicates.isEmpty() ? builder.conjunction() : builder.or(toArray(predicates, Predicate.class));
}
private SingularAttribute<T, String> attribute(EntityType<T> entity, Attribute<T, ?> attr) {
return entity.getDeclaredSingularAttribute(attr.getName(), String.class);
}
};
}
static private String pattern(String str) {
return "%" + str + "%";
}
}