All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eurekaclinical.standardapis.dao.GenericDao Maven / Gradle / Ivy

There is a newer version: 4.1-Alpha-1
Show newest version
package org.eurekaclinical.standardapis.dao;

/*-
 * #%L
 * Eureka! Clinical Standard APIs
 * %%
 * Copyright (C) 2016 Emory University
 * %%
 * 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.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import javax.inject.Provider;
import javax.persistence.NoResultException;
import javax.persistence.criteria.Predicate;

/**
 * Implements the {@link Dao} interface in a generic way.
 *
 * @param  The type of the entity.
 * @param  The type of the unique identifier for the entity.
 * @author hrathod
 */
public class GenericDao implements Dao {

    public enum SqlComparator {

        LESS_THAN_OR_EQUAL_TO,
        LESS_THAN,
        EQUAL_TO,
        NOT_EQUAL_TO,
        GREATER_THAN,
        GREATER_THAN_OR_EQUAL_TO
    }

    /**
     * The type for the entities this DAO instance handles.
     */
    private final Class entityClass;
    /**
     * Provides entity managers on demand.
     */
    private final Provider managerProvider;

    /**
     * Creates a generic DAO that handles the given type of entity. The entity
     * manager provider is used to fetch entity managers to interact with the
     * data store.
     *
     * @param inEntityClass The type of entities to handle.
     * @param inManagerProvider Provides entity managers on demand.
     */
    protected GenericDao(Class inEntityClass,
            Provider inManagerProvider) {
        this.entityClass = inEntityClass;
        this.managerProvider = inManagerProvider;
    }

    @Override
    public T create(T entity) {
        EntityManager entityManager = this.getEntityManager();
        entityManager.persist(entity);
        return entity;
    }

    @Override
    public T retrieve(PK uniqueId) {
        return this.getEntityManager().find(this.entityClass, uniqueId);
    }

    @Override
    public T update(T entity) {
        EntityManager entityManager = this.getEntityManager();
        T result = entityManager.merge(entity);
        return result;
    }

    @Override
    public T remove(T entity) {
        EntityManager entityManager = this.getEntityManager();
        if (entityManager.contains(entity)) {
            entityManager.remove(entity);
        } else {
            entityManager.remove(entityManager.merge(entity));
        }
        return entity;
    }

    @Override
    public T refresh(T entity) {
        this.getEntityManager().refresh(entity);
        return entity;
    }

    @Override
    public List getAll() {
        DatabaseSupport dbSupport
                = new DatabaseSupport(getEntityManager());
        return dbSupport.getAll(this.entityClass);
    }

    protected List getListAsc(SingularAttribute attribute) {
        EntityManager entityManager = this.getEntityManager();
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery criteriaQuery = builder.createQuery(this.entityClass);
        Root root = criteriaQuery.from(this.entityClass);
        criteriaQuery.orderBy(builder.asc(root.get(attribute)));
        return entityManager.createQuery(criteriaQuery).getResultList();
    }

    /**
     * Provides a convenient way for subclasses to implement simple queries that
     * compare an attribute of the entity to a target value.
     *
     * @param attribute The attribute of the entity to compare.
     * @param value The target value of the given attribute.
     * @param  The type of the attribute and target value.
     * @return A single result that matches the given criteria.
     */
    protected  T getUniqueByAttribute(SingularAttribute attribute,
            Y value) {
        try {
            return new DatabaseSupport(getEntityManager())
                    .getUniqueByAttribute(this.entityClass, attribute, value);
        } catch (NoResultException ex) {
            return null;
        }
    }
    
    protected  T getUniqueByAttribute(String attributeName, Y value) {
        try {
            return new DatabaseSupport(getEntityManager())
                    .getUniqueByAttribute(this.entityClass, attributeName, value);
        } catch (NoResultException ex) {
            return null;
        }
    }

    protected  List getListByAttribute(SingularAttribute attribute, Y value) {
        return new DatabaseSupport(getEntityManager())
                .getListByAttribute(this.entityClass, attribute, value);
    }

    protected  List getListByAttribute(
            SingularAttribute attribute,
            SqlComparator comparator,
            Y value) {
        TypedQuery query = this.createTypedQuery(
                attribute, comparator, value);
        return query.getResultList();
    }

    private  TypedQuery createTypedQuery(
            SingularAttribute attribute,
            SqlComparator comparator, Y value) {
        EntityManager entityManager = this.getEntityManager();
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery criteriaQuery = builder.createQuery(this.entityClass);
        Root root = criteriaQuery.from(this.entityClass);
        Path path = root.get(attribute);
        Predicate pred;
        switch (comparator) {
            case LESS_THAN:
                pred = builder.lt(path, value);
                break;
            case LESS_THAN_OR_EQUAL_TO:
                pred = builder.le(path, value);
                break;
            case EQUAL_TO:
                pred = builder.equal(path, value);
                break;
            case NOT_EQUAL_TO:
                pred = builder.notEqual(path, value);
                break;
            case GREATER_THAN_OR_EQUAL_TO:
                pred = builder.ge(path, value);
                break;
            case GREATER_THAN:
                pred = builder.gt(path, value);
                break;
            default:
                throw new AssertionError("Invalid SQLComparator: "
                        + comparator);
        }
        return entityManager.createQuery(criteriaQuery.where(
                builder.equal(path, value)));
    }

    /**
     * Get a list of entities whose path value is the same as the given target
     * value. The path is provided by the QueryPathProvider, and is followed
     * through to get the resulting value. That resulting value is compared to
     * the given target value in the query.
     *
     * @param provider Provides the path from the entity to the target
     * attribute/column.
     * @param value The target value to compare with the resulting attribute
     * value.
     * @param  The type of the target value and resulting attribute/column
     * value.
     * @return A list of entities that match the given criteria.
     */
    protected  List getListByAttribute(QueryPathProvider provider, Y value) {
        EntityManager entityManager = this.getEntityManager();
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery criteriaQuery = builder.createQuery(this.entityClass);
        Root root = criteriaQuery.from(this.entityClass);
        Path path = provider.getPath(root, builder);
        TypedQuery typedQuery = entityManager.createQuery(criteriaQuery.where(
                builder.equal(path, value)));
        return typedQuery.getResultList();
    }

    /**
     * Returns an entity manager instance that can be used to interact with the
     * data source.
     *
     * @return An instance of EntityManager.
     */
    protected final EntityManager getEntityManager() {
        return this.managerProvider.get();
    }
    
    /**
     * Provides an interface for the subclasses to easily perform queries
     * without having to deal with a lot of boiler-plate code. The subclasses
     * can simply provide the path to a value and the target value using this
     * interface, and have this superclass perform the query.
     *
     * @param  The entity type.
     * @param 

The target value and target column type. */ protected static interface QueryPathProvider { /** * Provides a path from the entity to the target attribute. * * @param root The query root, used to build the path. * @param builder The criteria builder for the query. * @return The path from the entity to the target attribute. */ Path

getPath(Root root, CriteriaBuilder builder); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy