gov.nih.nci.cabig.caaers.dao.CaaersDao.java Source code

Java tutorial

Introduction

Here is the source code for gov.nih.nci.cabig.caaers.dao.CaaersDao.java

Source

/*******************************************************************************
 * Copyright SemanticBits, Northwestern University and Akaza Research
 * 
 * Distributed under the OSI-approved BSD 3-Clause License.
 * See http://ncip.github.com/caaers/LICENSE.txt for details.
 ******************************************************************************/
package gov.nih.nci.cabig.caaers.dao;

import edu.nwu.bioinformatics.commons.CollectionUtils;
import gov.nih.nci.cabig.caaers.dao.query.AbstractQuery;
import gov.nih.nci.cabig.caaers.dao.query.HQLQuery;
import gov.nih.nci.cabig.caaers.dao.query.NativeSQLQuery;
import gov.nih.nci.cabig.caaers.dao.query.ajax.AbstractAjaxableDomainObjectQuery;
import gov.nih.nci.cabig.caaers.domain.Identifier;
import gov.nih.nci.cabig.caaers.domain.Participant;
import gov.nih.nci.cabig.ctms.dao.AbstractDomainObjectDao;
import gov.nih.nci.cabig.ctms.domain.DomainObject;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.IntegerType;
import org.hibernate.type.Type;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Rhett Sutphin
 */
@Transactional(readOnly = true)
public abstract class CaaersDao<T extends DomainObject> extends AbstractDomainObjectDao<T> {

    protected static final int DEFAULT_MAX_RESULTS_SIZE = 0;

    /**
     * A variation of {@link #findBySubname} that does not allow for extra conditions
     */
    protected List<T> findBySubname(String[] subnames, List<String> substringMatchProperties,
            List<String> exactMatchProperties) {
        return findBySubname(subnames, null, null, substringMatchProperties, exactMatchProperties);
    }

    /**
     * A query builder for use by subclass DAOs. It makes it easy to match a fragment of a name or
     * identifier against multiple properties. This is intended for use in implementing
     * user-friendly dynamic searches; e.g., autocompleters.
     * 
     * @param subnames
     *                the name fragments to search on
     * @param extraConditions
     *                custom HQL conditions with which to constrain the fragment matches
     * @param extraParameters
     *                parameters for the custom conditions
     * @param substringMatchProperties
     *                a list of properties of the implementing object which should be matched as
     *                case-insensitive substrings
     * @param exactMatchProperties
     *                a list of properties which should be matched as case-insensitive full strings
     * @return a list of matching domain object instances
     */
    @SuppressWarnings("unchecked")
    protected List<T> findBySubname(String[] subnames, String extraConditions, List<Object> extraParameters,
            List<String> substringMatchProperties, List<String> exactMatchProperties) {
        if (subnames == null || subnames.length == 0) {
            return Collections.emptyList();
        }

        StringBuilder query = new StringBuilder("from ").append(domainClass().getName()).append(" o where ");
        if (extraConditions != null && extraConditions.length() > 0) {
            query.append(extraConditions).append(" and ");
        }

        List<Object> params = new LinkedList<Object>();
        if (extraParameters != null) {
            params.addAll(extraParameters);
        }

        for (int i = 0; i < subnames.length; i++) {
            buildSubnameQuery(subnames[i], query, params, substringMatchProperties, exactMatchProperties, true);
            if (i < subnames.length - 1) {
                query.append(" and ");
            }
        }

        if (substringMatchProperties != null && !substringMatchProperties.isEmpty()) {
            query.append(" order by o." + substringMatchProperties.get(0));
        }
        getHibernateTemplate().setMaxResults(75);
        log.debug("query::" + query.toString());

        List<T> result = getHibernateTemplate().find(query.toString(), params.toArray());
        getHibernateTemplate().setMaxResults(DEFAULT_MAX_RESULTS_SIZE);

        return result;
    }

    /**
     * Will build the sub name query. 
     * @param subnames   the name fragments to search on
     * @param extraConditions custom HQL conditions with which to constrain the fragment matches
     * @param extraParameters  parameters for the custom conditions
     * @param joins  the join conditions to use
     * @param params the constraints parameters. 
     * @param substringMatchProperties  a list of properties of the implementing object which should be matched as
     *                case-insensitive substrings
     * @param exactMatchProperties  a list of properties which should be matched as case-insensitive full strings
     * @return a String representation of the Query
     */
    protected String buildSubnameQuery(String[] subnames, String extraConditions, List<Object> extraParameters,
            String joins, List<Object> params, List<String> substringMatchProperties,
            List<String> exactMatchProperties) {

        StringBuilder query = new StringBuilder(" select distinct o from ").append(domainClass().getName())
                .append(" o ");
        if (joins != null) {
            query.append(joins).append(" where ");
        }

        if (extraConditions != null) {
            query.append(extraConditions).append(" and ");
        }

        if (extraParameters != null) {
            params.addAll(extraParameters);
        }

        for (int i = 0; i < subnames.length; i++) {
            buildSubnameQuery(subnames[i], query, params, substringMatchProperties, exactMatchProperties, false);
            if (i < subnames.length - 1) {
                query.append(" and ");
            }
        }

        log.debug("query::" + query.toString());
        return query.toString();
    }

    /**
     * Will find the objects, matching the sub names. 
     * @param subnames   the name fragments to search on
     * @param extraConditions custom HQL conditions with which to constrain the fragment matches
     * @param extraParameters  parameters for the custom conditions
     * @param joins  the join conditions to use
     * @param substringMatchProperties  a list of properties of the implementing object which should be matched as
     *                case-insensitive substrings
     * @param exactMatchProperties  a list of properties which should be matched as case-insensitive full strings
     * @return
     */
    @SuppressWarnings("unchecked")
    protected List<T> findBySubname(String[] subnames, String extraConditions, List<Object> extraParameters,
            List<String> substringMatchProperties, List<String> exactMatchProperties, String joins) {
        if (subnames == null || subnames.length == 0) {
            return Collections.emptyList();
        }

        getHibernateTemplate().setMaxResults(75);
        List<Object> params = new LinkedList<Object>();
        List<T> result = getHibernateTemplate().find(buildSubnameQuery(subnames, extraConditions, extraParameters,
                joins, params, substringMatchProperties, exactMatchProperties), params.toArray());
        getHibernateTemplate().setMaxResults(DEFAULT_MAX_RESULTS_SIZE);
        return result;
    }

    /**
     * Will build the sub name query.
     * @param subname   the name fragments to search on
     * @param query the base query to use
     * @param params the constraints parameters.
     * @param substringMatchProperties  a list of properties of the implementing object which should be matched as
     *                case-insensitive substrings
     * @param exactMatchProperties  a list of properties which should be matched as case-insensitive full strings
     * @param includeObjectReference - if true, the referenced objects are prefetched. 
     */
    private void buildSubnameQuery(String subname, StringBuilder query, List<Object> params,
            List<String> substringMatchProperties, List<String> exactMatchProperties,
            boolean includeObjectReference) {
        query.append('(');
        if (hasAny(substringMatchProperties)) {
            for (Iterator<String> it = substringMatchProperties.iterator(); it.hasNext();) {
                String prop = it.next();
                if (includeObjectReference) {
                    query.append("LOWER(o.").append(prop).append(") LIKE ?");
                } else {
                    query.append("LOWER(").append(prop).append(") LIKE ?");
                }

                params.add('%' + subname.toLowerCase() + '%');
                if (it.hasNext()) {
                    query.append(" or ");
                }
            }
            if (hasAny(exactMatchProperties)) {
                query.append(" or ");
            }
        }
        if (hasAny(exactMatchProperties)) {
            for (Iterator<String> it = exactMatchProperties.iterator(); it.hasNext();) {
                String prop = it.next();
                if (includeObjectReference) {
                    query.append("LOWER(o.").append(prop).append(") LIKE ?");
                } else {
                    query.append("LOWER(").append(prop).append(") LIKE ?");
                }
                params.add(subname.toLowerCase());
                if (it.hasNext()) {
                    query.append(" or ");
                }
            }
        }
        query.append(')');
    }

    public List<T> findByIds(List<Integer> ids) {
        HQLQuery query = new HQLQuery("select o from " + domainClass().getName() + " o where id in (:ids)");
        query.setParameterList("ids", ids);
        return (List<T>) search(query);
    }

    /**
     * Will check if the input list is empty or not
     * @param properties - The list to be verified for emptyness
     * @return   true if empty, false otherwise. 
     */
    private boolean hasAny(List<String> properties) {
        return properties != null && properties.size() > 0;
    }

    /**
     * Searches based on an example object. For example, if you want to search for a Participant
     * based on last name:
     * <ul>
     * <li><code>Participant sample = new Participant();</code></li>
     * <li><code>sample.setLastName("last_namee");</code></li>
     * <li><code>participantDao.searchByExample(study)</code></li>
     * </ul>
     * 
     * @return list of matching instances based on your sample object
     */
    @SuppressWarnings("unchecked")
    public List<T> searchByExample(final T sample, final boolean inexactMatches) {
        return (List<T>) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Example example = Example.create(sample).excludeZeroes();
                if (inexactMatches) {
                    example.ignoreCase().enableLike(MatchMode.ANYWHERE);
                }

                return session.createCriteria(domainClass()).add(example).list();
            }
        });
    }

    /**
     * Default search -- case insensitive substring matches
     * 
     * @see #searchByExample(gov.nih.nci.cabig.ctms.domain.DomainObject, boolean)
     */
    public List<T> searchByExample(T example) {
        return searchByExample(example, true);
    }

    /**
     * This method is to enable the case Insensitive matches.   
     * @param sample
     * @param inexactMatches
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> searchByExampleIgnoreCase(final T sample, final boolean inexactMatches) {
        return (List<T>) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Example example = Example.create(sample).ignoreCase().excludeZeroes();
                if (inexactMatches) {
                    example.ignoreCase().enableLike(MatchMode.ANYWHERE);
                }

                return session.createCriteria(domainClass()).add(example).list();
            }
        });
    }

    /**
     * Helper for DAOs which support domain classes with multiple identifiers.
     */
    @SuppressWarnings("unchecked")
    protected T findByIdentifier(final Identifier identifier) {
        return (T) CollectionUtils.firstElement(getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Criteria criteria = session.createCriteria(domainClass()).createCriteria("identifiers");

                if (identifier.getType() != null) {
                    criteria.add(Restrictions.eq("type", identifier.getType()));
                }

                if (identifier.getValue() != null) {
                    criteria.add(Restrictions.eq("value", identifier.getValue()));
                }

                return criteria.list();
            }
        }));
    }

    /**
     * Helper for DAOs which support domain classes with multiple identifiers.
     */
    @SuppressWarnings("unchecked")
    protected T findByIgnoreCaseIdentifier(final Identifier identifier) {
        return (T) CollectionUtils.firstElement(getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Criteria criteria = session.createCriteria(domainClass()).createCriteria("identifiers");

                if (identifier.getType() != null) {
                    criteria.add(Restrictions.eq("type", identifier.getType()));
                }

                if (identifier.getValue() != null) {
                    criteria.add(Restrictions.eq("value", identifier.getValue()).ignoreCase());
                }

                return criteria.list();
            }
        }));
    }

    /**
     * This method will reassociate the domain object to hibernate session. With a lock mode none.
     * 
     * @param o -
     *                the domain object instance that is to be reassociated
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void reassociate(T o) {
        // getHibernateTemplate().lock(o, LockMode.NONE);
        getHibernateTemplate().update(o);
    }

    /**
     * This will merge the changes, and returns a new persistant instance.
     * 
     * @param o -
     *                The domain object to be merged
     * @return a updated persistant instance
     */
    @SuppressWarnings("unchecked")
    @Transactional(readOnly = false)
    public T merge(T o) {
        return (T) getHibernateTemplate().merge(o);
    }

    /**
     * Will flush the hibernate session. 
     */
    @Transactional(readOnly = false)
    public void flush() {
        getHibernateTemplate().flush();
    }

    /**
     * Detaches the passed-in instance (probably a domain object or a collection of domain objects)
     * from the sesison.
     * 
     * @param o
     */
    public void evict(T o) {
        getHibernateTemplate().evict(o);
    }

    /**
     * This will initialize a lazy collection, consisting of domain objects.
     * 
     * @param proxy
     */
    public void initialize(Collection<? extends DomainObject> proxy) {
        getHibernateTemplate().initialize(proxy);
    }

    /**
     * The default implementation will save the domain object
     * @param o
     */
    @Transactional(readOnly = false)
    public void save(T o) {
        getHibernateTemplate().saveOrUpdate(o);
    }

    @Transactional(readOnly = false)
    public void refresh(T o) {
        getHibernateTemplate().refresh(o);
    }

    /**
     * This will lock the object
     * @param o
     */
    @Transactional(readOnly = false)
    public void lock(T o) {
        getHibernateTemplate().lock(o, LockMode.NONE);
    }

    /**
     * 
     * @param date
     * @return
     * @throws ParseException
     */
    public Date stringToDate(String date) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
        return dateFormat.parse(date);
    }

    /**
     * Will clear-off the content in the current Hibernate Session
     * @see org.hibernate.Session
     */
    @Transactional(readOnly = false)
    public void clearSession() {

        Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();

        if (log.isDebugEnabled()) {
            log.debug("Entity Count  before clear() : " + session.getStatistics().getEntityCount());
            log.debug("Collection Count before clear() : " + session.getStatistics().getCollectionCount());
        }

        session.clear();

        if (log.isDebugEnabled()) {
            log.debug("Entity Count  after clear() : " + session.getStatistics().getEntityCount());
            log.debug("Collection Count after clear() : " + session.getStatistics().getCollectionCount());
        }

    }

    /**
     * Will retrive all those domain objects that this DAO is respresenting from the DB. 
     * @param sortCriteria
     * @return
     */
    @SuppressWarnings("unchecked")
    protected List<T> findAll(String sortCriteria) {

        StringBuilder query = new StringBuilder(" select o from ").append(domainClass().getName()).append(" o ");
        if (sortCriteria != null && !org.apache.commons.lang.StringUtils.isEmpty(sortCriteria)) {
            query.append("order by " + sortCriteria);
        }

        log.debug("query::" + query.toString());
        getHibernateTemplate().setMaxResults(0);
        List<T> result = getHibernateTemplate().find(query.toString());
        getHibernateTemplate().setMaxResults(DEFAULT_MAX_RESULTS_SIZE);
        return result;
    }

    /**
     * Will execute the query and return the results. 
     * @param query - An AbstractQuery instance. 
     * @return - List of objects that is fetched by the Query. 
     */
    @SuppressWarnings("unchecked")
    public List<?> search(final AbstractQuery query) {
        return search(query, null, null);
    }

    /**
     * A paginated query. 
     * @param query - The query to be executed. 
     * @param firstResult - The starting index
     * @param maxResults - The number of objects to be returned. 
     * @return - A list of objects returned by the query, matching the pagination criteria. 
     */
    @SuppressWarnings("unchecked")
    public List<?> search(final AbstractQuery query, final Integer firstResult, final Integer maxResults) {
        String queryString = query.getQueryString();
        if (log.isDebugEnabled())
            log.debug("::: " + queryString);
        return (List<?>) getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(final Session session) throws HibernateException, SQLException {
                if (query instanceof NativeSQLQuery) {
                    org.hibernate.SQLQuery nativeQuery = session.createSQLQuery(query.getQueryString());
                    setResultSetBoundaries(nativeQuery, firstResult, maxResults);
                    Map<String, Type> scalarMap = ((NativeSQLQuery) query).getScalarMap();
                    for (String key : scalarMap.keySet()) {
                        nativeQuery.addScalar(key, scalarMap.get(key));
                    }
                    Map<String, Object> queryParameterMap = query.getParameterMap();
                    for (String key : queryParameterMap.keySet()) {
                        Object value = queryParameterMap.get(key);
                        if (value instanceof Collection) {
                            nativeQuery.setParameterList(key, (Collection) value);
                        } else {
                            nativeQuery.setParameter(key, value);
                        }
                    }
                    return nativeQuery.list();
                } else {
                    org.hibernate.Query hibernateQuery = session.createQuery(query.getQueryString());
                    setResultSetBoundaries(hibernateQuery, firstResult, maxResults);
                    Map<String, Object> queryParameterMap = query.getParameterMap();
                    for (String key : queryParameterMap.keySet()) {
                        Object value = queryParameterMap.get(key);
                        if (value instanceof Collection) {
                            hibernateQuery.setParameterList(key, (Collection) value);
                        } else {
                            hibernateQuery.setParameter(key, value);
                        }

                    }
                    return hibernateQuery.list();
                }
            }

        });
    }

    /**
     * @param query
     * @param firstResult
     * @param maxResults
     */
    private void setResultSetBoundaries(org.hibernate.Query query, Integer firstResult, Integer maxResults) {
        if (firstResult != null)
            query.setFirstResult(firstResult);
        if (maxResults != null)
            query.setMaxResults(maxResults);
    }

    /**
     * Will execute the query and return the results.
     * @param query - An AbstractQuery instance.
     * @return - List of objects that is fetched by the Query.
     */
    @SuppressWarnings("unchecked")
    public List<Object[]> search(final AbstractAjaxableDomainObjectQuery query) {
        String queryString = query.getQueryString();
        if (log.isDebugEnabled())
            log.debug("::: " + queryString.toString());
        return (List<Object[]>) getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(final Session session) throws HibernateException, SQLException {
                org.hibernate.Query hibernateQuery = session.createQuery(query.getQueryString());
                Map<String, Object> queryParameterMap = query.getParameterMap();
                for (String key : queryParameterMap.keySet()) {
                    Object value = queryParameterMap.get(key);
                    if (value instanceof Collection) {
                        hibernateQuery.setParameterList(key, (Collection) value);
                    } else {
                        hibernateQuery.setParameter(key, value);
                    }

                }
                return hibernateQuery.list();
            }

        });

    }

}