org.primefaces.model.JPALazyDataModel Maven / Gradle / Ivy
/*
* The MIT License
*
* Copyright (c) 2009-2024 PrimeTek Informatics
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.primefaces.model;
import org.primefaces.context.PrimeApplicationContext;
import org.primefaces.util.BeanUtils;
import org.primefaces.util.Callbacks;
import org.primefaces.util.ComponentUtils;
import org.primefaces.util.Constants;
import org.primefaces.util.LocaleUtils;
import org.primefaces.util.PropertyDescriptorResolver;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.Type;
/**
* Basic {@link LazyDataModel} implementation with JPA and Criteria API.
*
* @param The model class.
*/
public class JPALazyDataModel extends LazyDataModel implements Serializable {
private static final Logger LOGGER = Logger.getLogger(JPALazyDataModel.class.getName());
protected Class entityClass;
protected String rowKeyField;
protected boolean caseSensitive = true;
protected boolean wildcardSupport = false;
protected Class> rowKeyType;
protected QueryEnricher queryEnricher;
protected FilterEnricher filterEnricher;
protected AdditionalFilterMeta additionalFilterMeta;
protected SortEnricher sortEnricher;
protected Callbacks.SerializableSupplier entityManager;
protected Callbacks.SerializableFunction rowKeyProvider;
protected Callbacks.SerializableConsumer> resultEnricher;
/**
* For serialization only
*/
public JPALazyDataModel() {
// NOOP
}
@Override
public int count(Map filterBy) {
EntityManager em = entityManager.get();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(Long.class);
Root root = cq.from(entityClass);
cq = cq.select(cb.count(root));
applyFilters(cb, cq, root, filterBy);
TypedQuery query = em.createQuery(cq);
return query.getSingleResult().intValue();
}
@Override
public List load(int first, int pageSize, Map sortBy, Map filterBy) {
EntityManager em = entityManager.get();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(entityClass);
Root root = cq.from(entityClass);
cq = cq.select(root);
applyFilters(cb, cq, root, filterBy);
applySort(cb, cq, root, sortBy);
TypedQuery query = em.createQuery(cq);
query.setFirstResult(first);
query.setMaxResults(pageSize);
if (queryEnricher != null) {
queryEnricher.enrich(query);
}
List result = query.getResultList();
if (resultEnricher != null) {
resultEnricher.accept(result);
}
return result;
}
protected void applyFilters(CriteriaBuilder cb,
CriteriaQuery> cq,
Root root,
Map filterBy) {
List predicates = new ArrayList<>();
applyFiltersFromFilterMeta(entityClass, filterBy.values(), cb, cq, root, predicates);
if (filterEnricher != null) {
filterEnricher.enrich(filterBy, cb, cq, root, predicates);
}
if (additionalFilterMeta != null) {
applyFiltersFromFilterMeta(entityClass, additionalFilterMeta.process(), cb, cq, root, predicates);
}
if (!predicates.isEmpty()) {
cq.where(
cb.and(predicates.toArray(new Predicate[0])));
}
}
protected void applyFiltersFromFilterMeta(Class entityClass, Collection filterBy, CriteriaBuilder cb,
CriteriaQuery> cq,
Root root, List predicates) {
if (filterBy != null) {
FacesContext context = FacesContext.getCurrentInstance();
Locale locale = LocaleUtils.getCurrentLocale(context);
PropertyDescriptorResolver propResolver = PrimeApplicationContext.getCurrentInstance(context).getPropertyDescriptorResolver();
for (FilterMeta filter : filterBy) {
if (filter.getField() == null || filter.getFilterValue() == null || filter.isGlobalFilter()) {
continue;
}
PropertyDescriptor pd = propResolver.get(entityClass, filter.getField());
Object filterValue = filter.getFilterValue();
Object convertedFilterValue;
Class> filterValueClass = filterValue.getClass();
if (filterValueClass.isArray() || Collection.class.isAssignableFrom(filterValueClass)) {
convertedFilterValue = filterValue;
}
else {
convertedFilterValue = ComponentUtils.convertToType(filterValue, pd.getPropertyType(), LOGGER);
}
Expression fieldExpression = resolveFieldExpression(cb, cq, root, filter.getField());
Predicate predicate = createPredicate(filter, pd, root, cb, fieldExpression, convertedFilterValue, locale);
predicates.add(predicate);
}
}
}
/**
* @deprecated use the builder and filterEnricher instead
*/
@Deprecated
protected void applyGlobalFilters(Map filterBy, CriteriaBuilder cb, CriteriaQuery> cq,
Root root, List predicates) {
}
protected Predicate createPredicate(FilterMeta filter,
PropertyDescriptor pd,
Root root,
CriteriaBuilder cb,
Expression fieldExpression,
Object filterValue,
Locale locale) {
boolean isCaseSensitive = caseSensitive || !(CharSequence.class.isAssignableFrom(pd.getPropertyType()) || pd.getPropertyType() == char.class);
Supplier> fieldExpressionAsString = () -> isCaseSensitive
? fieldExpression.as(String.class)
: cb.upper(fieldExpression.as(String.class));
Supplier> filterValueAsCollection = () -> filterValue.getClass().isArray()
? Arrays.asList((Object[]) filterValue)
: (Collection
© 2015 - 2024 Weber Informatics LLC | Privacy Policy