eu.uqasar.service.AbstractService.java Source code

Java tutorial

Introduction

Here is the source code for eu.uqasar.service.AbstractService.java

Source

package eu.uqasar.service;

/*
 * #%L
 * U-QASAR
 * %%
 * Copyright (C) 2012 - 2015 U-QASAR Consortium
 * %%
 * 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.
 * #L%
 */

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;

import lombok.NoArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hibernate.search.query.dsl.TermMatchingContext;
import org.hibernate.search.query.dsl.WildcardContext;
import org.jboss.solder.logging.Logger;

import eu.uqasar.model.AbstractEntity_;
import eu.uqasar.model.Persistable;

@NoArgsConstructor
public abstract class AbstractService<T extends Persistable> implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = -4171879462026403888L;

    private Class<T> clazz;
    private String readableClassName;

    protected static final String LIKE_WILDCARD = "%";

    /**
     *
     * @param clazz
     */
    protected AbstractService(Class<T> clazz) {
        this.clazz = clazz;
        this.readableClassName = getReadableClassName(clazz);
    }

    /**
     *
     * @param clazz
     * @param readableClassName
     */
    protected AbstractService(Class<T> clazz, String readableClassName) {
        this.clazz = clazz;
        this.readableClassName = readableClassName;
    }

    // inject a logger
    @Inject
    protected Logger logger;

    @Inject
    protected EntityManager em;

    /**
     * Detaches entity from persistence context.
     *
     * @param t
     * @return
     */
    public T detach(T t) {
        em.detach(t);
        return t;
    }

    /**
     *
     * @return
     */
    @SuppressWarnings("unused")
    public List<T> getAll() {
        logger.infof("loading all %ss ...", readableClassName);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> criteria = cb.createQuery(clazz);
        Root<T> root = criteria.from(clazz);
        return em.createQuery(criteria).getResultList();
    }

    public List<T> getAllExcept(Collection<T> toExclude) {
        if (toExclude == null || toExclude.isEmpty()) {
            return this.getAll();
        }
        logger.infof("loading all %s except %s ...", readableClassName, toExclude);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> query = cb.createQuery(this.clazz);
        Root<T> root = query.from(this.clazz);
        query.where(cb.not(root.in(toExclude)));
        return em.createQuery(query).getResultList();
    }

    public List<T> getRange(long first, long count) {
        return getRange((int) first, (int) count);
    }

    private List<T> getRange(int first, int count) {
        logger.infof("loading %d %s starting from %d  ...", count, readableClassName, first);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> query = cb.createQuery(this.clazz);
        query.from(this.clazz);
        return em.createQuery(query).setFirstResult(first).setMaxResults(count).getResultList();
    }

    /**
     *
     * @return
     */
    public long countAll() {
        logger.infof("counting all %ss ...", readableClassName);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Long> criteria = cb.createQuery(Long.class);
        Root<T> root = criteria.from(clazz);
        criteria.select(cb.countDistinct(root));
        return em.createQuery(criteria).getSingleResult();
    }

    /**
     *
     * @param id
     * @return
     */
    public T getById(Long id) {
        logger.infof("loading %s with ID %d ...", readableClassName, id);
        return em.find(clazz, id);
    }

    /**
     *
     * @param entity
     * @return
     */
    public T create(T entity) {
        entity = update(entity);
        logger.infof("persisted %s %s ...", readableClassName, entity);
        return entity;
    }

    /**
     *
     * @param entity
     * @return
     */
    public T update(T entity) {
        entity = em.merge(entity);
        logger.infof("updated %s %s ...", readableClassName, entity);
        return entity;
    }

    /**
     *
     * @param entityId
     */
    public void delete(Long entityId) {
        T item = em.find(clazz, entityId);
        delete(item);
    }

    public void delete(Collection<T> entities) {
        for (T entity : entities) {
            delete(entity);
        }
    }

    /**
     *
     * @param entity
     */
    public void delete(T entity) {
        Serializable id = entity.getId();
        entity = em.merge(entity);
        em.remove(entity);
        logger.infof("deleted %s %s with id %s ...", readableClassName, entity, id);
    }

    private <T extends Persistable> String getReadableClassName(Class<T> clazz) {
        return clazz.getSimpleName();
    }

    public <T extends Persistable> long countAll(Class<T> clazz) {
        logger.infof("counting all %ss ...", getReadableClassName(clazz));
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Long> criteria = cb.createQuery(Long.class);
        Root<T> root = criteria.from(clazz);
        criteria.select(cb.countDistinct(root));
        return em.createQuery(criteria).getSingleResult();
    }

    protected <T extends Persistable> T getById(Class<T> clazz, Long id) {
        logger.infof("loading %s with ID %d ...", getReadableClassName(clazz), id);
        return em.find(clazz, id);
    }

    /**
     * Method to get the entity of class by a given name.
     * @param clazz Class
     * @param name attribute name of the searched entity
     * @return T entity
     */
    public <T extends Persistable> T getByName(Class<T> clazz, String name) {
        logger.infof("loading %s with name %d ...", getReadableClassName(clazz), name);
        T entity = null;

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(clazz);
        Root<T> ent = criteriaQuery.from(clazz);
        criteriaQuery.select(ent).where(criteriaBuilder.equal(ent.get("name"), name));

        List<T> entities = em.createQuery(criteriaQuery).getResultList();

        if (entities != null && entities.size() > 0) {
            entity = entities.get(0);
        }
        return entity;
    }

    private <T extends Persistable> List<T> getByIds(Class<T> clazz, Collection<Long> ids) {
        logger.infof("loading %s with IDs %d ...", getReadableClassName(clazz), ids);
        List<T> results = new ArrayList<>();
        for (Long id : ids) {
            results.add(em.find(clazz, id));
        }
        return results;
    }

    public static String[] prepareSearchTerm(String term) {
        return StringUtils.split(term, ' ');
    }

    public <T extends Persistable> List<T> getAll(Class<T> clazz) {
        logger.infof("loading all %ss ...", getReadableClassName(clazz));
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> criteria = cb.createQuery(clazz);
        criteria.from(clazz);
        return em.createQuery(criteria).getResultList();
    }

    public <T extends Persistable> List<T> getAllExcept(Class<T> clazz, Collection<T> toExclude) {
        if (toExclude == null || toExclude.isEmpty()) {
            return getAll(clazz);
        }
        logger.infof("loading all %s except %s ...", getReadableClassName(clazz), toExclude);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> query = cb.createQuery(clazz);
        Root<T> root = query.from(clazz);
        query.where(cb.not(root.in(toExclude)));
        return em.createQuery(query).getResultList();
    }

    public <T extends Persistable> List<T> getRange(Class<T> clazz, long first, long count) {
        return getRange(clazz, (int) first, (int) count);
    }

    private <T extends Persistable> List<T> getRange(Class<T> clazz, int first, int count) {
        logger.infof("loading %d %s starting from %d  ...", count, getReadableClassName(clazz), first);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> query = cb.createQuery(clazz);
        query.from(clazz);
        return em.createQuery(query).setFirstResult(first).setMaxResults(count).getResultList();
    }

    public <P extends T> List<P> fullTextSearch(Class<P> clazz, int first, int count, String... terms) {
        Collection<Long> ids = fullTextSearchForIds(clazz, terms);
        List<P> results = new ArrayList<>();
        if (!ids.isEmpty()) {
            results = getByIds(clazz, ids);
            results = filterFullTextSearchResults(results, clazz);
        }
        return results;
    }

    public <P extends T> List<T> fullTextSearch(int first, int count, String terms) {
        return fullTextSearch(this.clazz, first, count, terms);
    }

    protected Collection<Long> fullTextSearchForIds(String terms) {
        return fullTextSearchForIds(this.clazz, terms);
    }

    private <P extends T> Collection<Long> fullTextSearchForIds(Class<P> clazz, String... terms) {
        FullTextEntityManager ftem = Search.getFullTextEntityManager(em);
        QueryBuilder qb = ftem.getSearchFactory().buildQueryBuilder().forEntity(clazz).get();
        Query luceneQuery;
        WildcardContext wc = qb.keyword().wildcard();
        TermMatchingContext tmc = setFullTextSearchFields(wc, clazz);
        Set<Long> results = new HashSet<>();
        try {
            for (String term : terms) {
                luceneQuery = tmc.ignoreAnalyzer().ignoreFieldBridge().matching(term.toLowerCase()).createQuery();
                FullTextQuery query = ftem.createFullTextQuery(luceneQuery, clazz);
                query.setProjection("id");
                List<Object[]> idList = query.getResultList();
                for (Object[] id : idList) {
                    if (id[0] instanceof Long) {
                        results.add((Long) id[0]);
                    }
                }
            }
        } catch (Exception e) {
            // because of lucene stop words
            logger.warn(e.getMessage(), e);
        }
        return results;
    }

    protected <P extends T> TermMatchingContext setFullTextSearchFields(WildcardContext wc, Class<P> clazz) {
        return wc.onField(AbstractEntity_.id.getName());
    }

    private <P extends T> List<P> filterFullTextSearchResults(List<P> results, Class<P> clazz) {
        return results;
    }

    protected List<T> filterFullTextSearchResults(List<T> results) {
        return results;
    }

    public Long countFullTextResults(String... terms) {
        return countFullTextResults(this.clazz, terms);
    }

    public <P extends T> Long countFullTextResults(Class<P> clazz, String... terms) {
        return (long) fullTextSearchForIds(clazz, terms).size();
    }

    protected List<T> getAllOrdered(Class<T> clazz, Order... orders) {
        logger.infof("loading all %ss ...", getReadableClassName(clazz));
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> criteria = cb.createQuery(clazz);
        criteria.from(clazz);
        if (orders != null && orders.length > 0) {
            criteria.orderBy(orders);
        }
        return em.createQuery(criteria).getResultList();
    }

    protected <T extends Persistable> List<T> getAllOrderedExcept(Class<T> clazz, Collection<T> toExclude,
            Order... orders) {
        if (toExclude == null || toExclude.isEmpty()) {
            return getAll(clazz);
        }
        logger.infof("loading all %s except %s ...", getReadableClassName(clazz), toExclude);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> query = cb.createQuery(clazz);
        Root<T> root = query.from(clazz);
        if (orders != null && orders.length > 0) {
            query.orderBy(orders);
        }
        query.where(cb.not(root.in(toExclude)));
        return em.createQuery(query).getResultList();
    }

    protected <T extends Persistable> List<T> getRangeOrdered(Class<T> clazz, long first, long count,
            Order... orders) {
        return getRangeOrdered(clazz, (int) first, (int) count, orders);
    }

    private <T extends Persistable> List<T> getRangeOrdered(Class<T> clazz, int first, int count, Order... orders) {
        logger.infof("loading %d %s starting from %d  ...", count, getReadableClassName(clazz), first);
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<T> query = cb.createQuery(clazz);
        query.from(clazz);
        if (orders != null && orders.length > 0) {
            query.orderBy(orders);
        }
        return em.createQuery(query).setFirstResult(first).setMaxResults(count).getResultList();
    }

    protected Long performDistinctCountWithEqualPredicate(final Attribute<T, ?> attr, Object value) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Long> query = cb.createQuery(Long.class);
        Root<T> root = query.from(clazz);
        query.where(cb.equal(root.get(attr.getName()), value));
        query.select(cb.countDistinct(root));
        return em.createQuery(query).getSingleResult();
    }

}