name.marcelomorales.siqisiqi.openjpa.impl.OrmFinderImpl.java Source code

Java tutorial

Introduction

Here is the source code for name.marcelomorales.siqisiqi.openjpa.impl.OrmFinderImpl.java

Source

/*
 * Copyright 2013 Marcelo Morales me@marcelomorales.name
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package name.marcelomorales.siqisiqi.openjpa.impl;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import name.marcelomorales.siqisiqi.openjpa.api.OrderBy;
import name.marcelomorales.siqisiqi.openjpa.api.OrmFinder;
import name.marcelomorales.siqisiqi.openjpa.api.OrmFinderSettings;
import name.marcelomorales.siqisiqi.openjpa.api.OrmUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.apache.openjpa.persistence.criteria.ComparisonStyle;
import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.TransactionAttribute;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import javax.persistence.metamodel.Attribute;
import java.io.Serializable;
import java.util.*;

/**
 * Encapsulates OpenJPA-specific behaviour.
 *
 * @author Marcelo Morales
 */
public class OrmFinderImpl<T, PK extends Serializable> implements OrmFinder<T, PK> {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrmFinderImpl.class);

    private final OpenJPAEntityManager entityManager;

    private final Class<T> persistentClass;

    private final OrmFinderSettings<T, PK> settings;

    public OrmFinderImpl(EntityManager entityManager, Class<T> persistentClass, OrmFinderSettings<T, PK> settings) {
        this.settings = settings;
        this.entityManager = OpenJPAPersistence.cast(entityManager);
        this.persistentClass = persistentClass;
    }

    @Override
    @TransactionAttribute
    public T findByPK(final PK id, final String... fg) {
        LOGGER.debug("Searching {} id {}, fg {}", new Object[] { persistentClass, id, fg });

        if (fg != null) {
            entityManager.pushFetchPlan();
            entityManager.getFetchPlan().addFetchGroups(fg);
        }

        T t = entityManager.find(persistentClass, id);

        if (fg != null) {
            entityManager.popFetchPlan();
        }

        return t;
    }

    @Override
    @TransactionAttribute
    public T findCached(final PK id) {
        LOGGER.debug("Searching {} id id {}, cached", persistentClass, id);
        return entityManager.findCached(persistentClass, id);
    }

    @Override
    @TransactionAttribute
    public long countByAttribute(String attributeName, Object attributeValue) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Long> q = cb.createQuery(Long.class);

        Root<T> p = q.from(persistentClass);
        final Expression<Long> count = newCountExpression(cb, p);
        q.select(count);
        q.where(cb.equal(p.get(attributeName), attributeValue));

        try {
            return entityManager.createQuery(q).getSingleResult();
        } catch (NoResultException e) {
            return 0;
        }
    }

    @Override
    @TransactionAttribute
    public List<T> findByAttribute(String attributeName, Object attributeValue, long first, long count,
            String... fg) {
        LOGGER.debug("Searching {} bu attribute {} : {}, fg {}",
                new Object[] { persistentClass, attributeName, attributeValue, fg });

        if (fg != null) {
            entityManager.pushFetchPlan();
            entityManager.getFetchPlan().addFetchGroups(fg);
        }

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> q = cb.createQuery(persistentClass);
        Root<T> p = q.from(persistentClass);
        q.where(cb.equal(p.get(attributeName), attributeValue));

        TypedQuery<T> query = entityManager.createQuery(q);

        OrmUtils.firstCount(query, first, count);
        List<T> resultList = query.getResultList();

        if (fg != null) {
            entityManager.popFetchPlan();
        }

        return resultList;

    }

    @Override
    @TransactionAttribute
    public long countByFullTexts(final String terms) {
        LOGGER.debug("counting by text {} terms {}", persistentClass, terms);
        if (settings.returnsNullIfTermsAreNull() && Strings.isNullOrEmpty(terms)) {
            return 0;
        }

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Long> q = cb.createQuery(Long.class);

        Root<T> p = q.from(persistentClass);
        final Expression<Long> count = newCountExpression(cb, p);
        q.select(count);
        q.where(newFullTextPredicate(cb, p, terms));

        try {
            return entityManager.createQuery(q).getSingleResult();
        } catch (NoResultException e) {
            return 0;
        }
    }

    @Override
    @TransactionAttribute
    public List<T> findByFullTexts(final String terms, final OrderBy<T> orders, final long first, final long count,
            final String... fg) {

        LOGGER.debug("searching by text {} terms {}, fg {}", new Object[] { persistentClass, terms, fg });

        if (settings.returnsNullIfTermsAreNull() && Strings.isNullOrEmpty(terms)) {
            return Collections.emptyList();
        }

        if (fg != null) {
            entityManager.pushFetchPlan();
            entityManager.getFetchPlan().addFetchGroups(fg);
        }

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> q = cb.createQuery(persistentClass);
        Root<T> p = q.from(persistentClass);
        q.where(newFullTextPredicate(cb, p, terms));

        if (orders != null) {
            List<Order> orderList = orders.orders(cb, p);
            if (orderList != null && !orderList.isEmpty()) {
                q.orderBy(orderList);
            }
        }

        TypedQuery<T> query = entityManager.createQuery(q);

        OrmUtils.firstCount(query, first, count);
        List<T> resultList = query.getResultList();

        if (fg != null) {
            entityManager.popFetchPlan();
        }

        return resultList;
    }

    @Override
    @TransactionAttribute
    public long countByExample(final T example, final T example2) {
        OpenJPACriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Long> q = cb.createQuery(Long.class);
        Root<T> from = q.from(persistentClass);
        final Expression<Long> count = newCountExpression(cb, from);
        q.select(count);
        q.where(newQbePredicates(cb, from, example, example2));
        TypedQuery<Long> query = entityManager.createQuery(q);
        try {
            return query.getSingleResult();
        } catch (NoResultException e) {
            return 0;
        }
    }

    @Override
    @TransactionAttribute
    public List<T> findByExample(final T example, final T example2, final OrderBy<T> sortParam, final long first,
            final long count, final String... fg) {
        if (fg != null) {
            entityManager.pushFetchPlan();
            entityManager.getFetchPlan().addFetchGroups(fg);
        }

        OpenJPACriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> q = cb.createQuery(persistentClass);
        Root<T> from = q.from(persistentClass);
        q.where(newQbePredicates(cb, from, example, example2));
        if (sortParam != null) {
            List<Order> orderList = sortParam.orders(cb, from);
            if (orderList != null && !orderList.isEmpty()) {
                q.orderBy(orderList);
            }
        }

        TypedQuery<T> query = entityManager.createQuery(q);
        OrmUtils.firstCount(query, first, count);

        List<T> resultList = query.getResultList();

        if (fg != null) {
            entityManager.popFetchPlan();
        }
        return resultList;
    }

    protected Predicate[] newQBEPredicates(OpenJPACriteriaBuilder cb, Root<T> from, T example, T example2,
            ComparisonStyle style) {

        Attribute<?, ?>[] betweens = settings.betweens(from, persistentClass);

        ArrayList<Predicate> predicates = Lists.newArrayListWithExpectedSize(betweens.length + 1);

        predicates.add(cb.qbe(from, example, style, betweens));

        if (betweens.length > 0) {

            for (Attribute<?, ?> between : betweens) {
                String name = between.getName();
                Path<Comparable> objectPath = from.get(name);
                Comparable propertyValue1 = OrmUtils.get(example, name);
                Comparable propertyValue2 = OrmUtils.get(example2, name);
                predicates.add(cb.between(objectPath, propertyValue1, propertyValue2));
            }
        }

        return predicates.toArray(new Predicate[predicates.size()]);
    }

    protected Expression<Long> newCountExpression(CriteriaBuilder cb, Root<T> from) {
        final Path<PK> countPath = settings.countPath(from, persistentClass);
        if (countPath == null) {
            throw new IllegalStateException("Implements countPath en " + persistentClass);
        }
        return cb.count(countPath);
    }

    protected Predicate newFullTextPredicate(CriteriaBuilder cb, Root<T> p, String terms) {
        LinkedList<Predicate> predicatesOr = Lists.newLinkedList();
        Iterable<Path<String>> fullTexts = settings.getFullTexts(p, persistentClass);
        if (fullTexts != null) {
            for (Path<String> x : fullTexts) {
                StringTokenizer tokenizer = new StringTokenizer(terms, " \t\n\r\f,.;:/");
                LinkedList<Predicate> predicatesAnd = Lists.newLinkedList();
                while (tokenizer.hasMoreTokens()) {
                    String token = "%" + tokenizer.nextToken() + "%";

                    predicatesAnd.add(cb.like(cb.lower(x), StringUtils.lowerCase(token)));
                }
                predicatesOr.add(cb.and(predicatesAnd.toArray(new Predicate[predicatesAnd.size()])));
            }
        }
        final Predicate[] restrictions = predicatesOr.toArray(new Predicate[predicatesOr.size()]);
        return cb.or(restrictions);
    }

    protected Predicate[] newQbePredicates(OpenJPACriteriaBuilder cb, Root<T> from, T example, T example2) {
        if (example == null) {
            return new Predicate[0];
        } else {
            if (example2 == null) {
                final Predicate qbe = cb.qbe(from, example, settings.getComparisonStyle());
                return new Predicate[] { qbe };
            } else {
                return newQBEPredicates(cb, from, example, example2, settings.getComparisonStyle());
            }
        }
    }
}