org.medici.bia.dao.titleoccslist.TitleOccsListDAOJpaImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.medici.bia.dao.titleoccslist.TitleOccsListDAOJpaImpl.java

Source

/*
 * TitleOccListDAOJpaImpl.java
 * 
 * Developed by Medici Archive Project (2010-2012).
 * 
 * This file is part of DocSources.
 * 
 * DocSources is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * DocSources is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * As a special exception, if you link this library with other files to
 * produce an executable, this library does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * This exception does not however invalidate any other reasons why the
 * executable file might be covered by the GNU General Public License.
 */
package org.medici.bia.dao.titleoccslist;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.Version;
import org.hibernate.ejb.HibernateEntityManager;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.medici.bia.common.pagination.Page;
import org.medici.bia.common.pagination.PaginationFilter;
import org.medici.bia.common.pagination.PaginationFilter.Order;
import org.medici.bia.common.pagination.PaginationFilter.SortingCriteria;
import org.medici.bia.common.search.SimpleSearchTitleOrOccupation;
import org.medici.bia.common.util.RegExUtils;
import org.medici.bia.dao.JpaDao;
import org.medici.bia.domain.TitleOccsList;
import org.springframework.stereotype.Repository;

/**
 * <b>TitleOccsListDAOJpaImpl</b> is a default implementation of <b>TitleOccsListDAO</b>.
 * 
 * @author Lorenzo Pasquinelli (<a href=mailto:l.pasquinelli@gmail.com>l.pasquinelli@gmail.com</a>)
 * @author Matteo Doni (<a href=mailto:donimatteo@gmail.com>donimatteo@gmail.com</a>)
 */
@Repository
public class TitleOccsListDAOJpaImpl extends JpaDao<Integer, TitleOccsList> implements TitleOccsListDAO {

    /**
     * 
     *  If a serializable class does not explicitly declare a serialVersionUID, 
     *  then the serialization runtime will calculate a default serialVersionUID 
     *  value for that class based on various aspects of the class, as described
     *  in the Java(TM) Object Serialization Specification. However, it is 
     *  strongly recommended that all serializable classes explicitly declare 
     *  serialVersionUID values, since the default serialVersionUID computation 
     *  is highly sensitive to class details that may vary depending on compiler
     *  implementations, and can thus result in unexpected 
     *  InvalidClassExceptions during deserialization. Therefore, to guarantee a
     *   consistent serialVersionUID value across different java compiler 
     *   implementations, a serializable class must declare an explicit 
     *  serialVersionUID value. It is also strongly advised that explicit 
     *  serialVersionUID declarations use the private modifier where possible, 
     *  since such declarations apply only to the immediately declaring 
     *  class--serialVersionUID fields are not useful as inherited members. 
     */
    private static final long serialVersionUID = -947341804163999355L;

    private final Logger logger = Logger.getLogger(this.getClass());

    /**
     * {@inheritDoc}
     */
    @Override
    public TitleOccsList findTitleOcc(String titleOcc) throws PersistenceException {
        Query query = getEntityManager().createQuery("FROM TitleOccsList WHERE titleOcc LIKE :titleOcc");
        query.setParameter("titleOcc", titleOcc);
        query.setMaxResults(1);
        if (query.getResultList().size() != 0) {
            return (TitleOccsList) query.getSingleResult();
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Page searchTitleOrOccupation(org.medici.bia.common.search.Search searchContainer,
            PaginationFilter paginationFilter) throws PersistenceException {
        // We prepare object of return method.
        Page page = new Page(paginationFilter);

        // We obtain hibernate-search session
        FullTextSession fullTextSession = org.hibernate.search.Search
                .getFullTextSession(((HibernateEntityManager) getEntityManager()).getSession());

        org.apache.lucene.search.Query query = searchContainer.toLuceneQuery();
        logger.info("Lucene Query " + query.toString());

        // We execute search
        org.hibernate.search.FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(query,
                TitleOccsList.class);

        // We set size of result.
        if (paginationFilter.getTotal() == null) {
            page.setTotal(new Long(fullTextQuery.getResultSize()));
        }

        // We set pagination  
        fullTextQuery.setFirstResult(paginationFilter.getFirstRecord());
        fullTextQuery.setMaxResults(paginationFilter.getLength());

        // We manage sorting (this manages sorting on multiple fields)
        List<SortingCriteria> sortingCriterias = paginationFilter.getSortingCriterias();
        if (sortingCriterias.size() > 0) {
            SortField[] sortFields = new SortField[sortingCriterias.size()];
            for (int i = 0; i < sortingCriterias.size(); i++) {
                sortFields[i] = new SortField(sortingCriterias.get(i).getColumn(),
                        sortingCriterias.get(i).getColumnType(),
                        (sortingCriterias.get(i).getOrder().equals(Order.ASC) ? true : false));
            }
            fullTextQuery.setSort(new Sort(sortFields));
        }

        // We set search result on return method
        page.setList(fullTextQuery.list());

        return page;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public Page searchTitlesOrOccupations(SimpleSearchTitleOrOccupation simpleSearchTitleOrOccupation,
            PaginationFilter paginationFilter) throws PersistenceException {
        // We prepare object of return method.
        Page page = new Page(paginationFilter);

        // select a.TitleOccID, a.TitleOcc, count(b.personId) from tblTitleOccsList a left outer join tblPoLink b on b.TitleOccID = a.TitleOccID group by a.titleOccID
        StringBuilder stringBuilder = new StringBuilder(
                "select a.titleOccID, a.titleOcc, count(b.personId) from tblTitleOccsList a");
        stringBuilder.append(" left join tblPoLink b on b.titleOccID = a.TitleOccID ");
        if (simpleSearchTitleOrOccupation.getTextSearch() != null) {
            stringBuilder.append(" where a.titleOcc LIKE '%");
            stringBuilder.append(simpleSearchTitleOrOccupation.getTextSearch());
            stringBuilder.append("%' ");
        } else if (simpleSearchTitleOrOccupation.getRoleCatId() != null) {
            stringBuilder.append(" where a.roleCatMinorId=");
            stringBuilder.append(simpleSearchTitleOrOccupation.getRoleCatId());
        }
        stringBuilder.append(" group by a.titleOccID ");

        // We set size of result.
        if (paginationFilter.getTotal() == null) {
            //select  count(*) from ( select count(*) from tblTitleOccsList a left outer join tblPoLink b on b.TitleOccID = a.TitleOccID group by a.titleOccID ) count
            StringBuilder queryCountBuilder = new StringBuilder("");
            queryCountBuilder.append("select count(*) from tblTitleOccsList a ");
            if (simpleSearchTitleOrOccupation.getTextSearch() != null) {
                queryCountBuilder.append(" where a.titleOcc LIKE '%");
                queryCountBuilder.append(simpleSearchTitleOrOccupation.getTextSearch());
                queryCountBuilder.append("%' ");
            } else if (simpleSearchTitleOrOccupation.getRoleCatId() != null) {
                queryCountBuilder.append(" where a.roleCatMinorID=");
                queryCountBuilder.append(simpleSearchTitleOrOccupation.getRoleCatId());
            }

            // In this case we use Native Query!!!
            Query query = getEntityManager().createNativeQuery(queryCountBuilder.toString());

            // Count(*) in native query is mapped as BigInteger, so we need to convert to Long...
            BigInteger result = (BigInteger) query.getSingleResult();
            page.setTotal(NumberUtils.createLong(result.toString()));
        }

        // We invoke native query beacuse we use left outer join with on condition 
        Query query = getEntityManager().createNativeQuery(stringBuilder.toString());
        query.setFirstResult(paginationFilter.getFirstRecord());
        query.setMaxResults(paginationFilter.getLength());

        List<Object> list = (List<Object>) query.getResultList();

        List<Object> result = new ArrayList<Object>(list.size());

        for (int i = 0; i < list.size(); i++) {
            Object[] singleRow = (Object[]) list.get(i);
            List<Object> row = new ArrayList<Object>(0);

            row.add(new TitleOccsList((Integer) singleRow[0], (String) singleRow[1]));
            row.add(NumberUtils.createLong(((BigInteger) singleRow[2]).toString()));
            result.add(row);
        }

        // We set search result on return method
        page.setList(result);

        return page;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<TitleOccsList> searchTitleOrOccupationLinkableToPerson(String searchText)
            throws PersistenceException {
        //String[] outputFields = new String[]{"titleOccId", "titleOcc", "roleCat"};

        FullTextSession fullTextSession = Search
                .getFullTextSession(((HibernateEntityManager) getEntityManager()).getSession());

        QueryParser parserMapNameLf = new QueryParser(Version.LUCENE_30, "titleOcc",
                fullTextSession.getSearchFactory().getAnalyzer("titleOccsListAnalyzer"));

        try {
            org.apache.lucene.search.Query queryTitleOcc = parserMapNameLf.parse(searchText.toLowerCase());
            org.apache.lucene.search.Query queryTitleOccWithWildCard = parserMapNameLf
                    .parse(searchText.toLowerCase() + "*");
            String[] words = RegExUtils.splitPunctuationAndSpaceChars(searchText);

            org.apache.lucene.search.PhraseQuery queryRoleCatMajor = new PhraseQuery();
            for (String singleWord : words) {
                queryRoleCatMajor.add(new Term("roleCat.roleCatMajor", singleWord.toLowerCase() + "*"));
            }
            org.apache.lucene.search.PhraseQuery queryRoleCatMinor = new PhraseQuery();
            for (String singleWord : words) {
                queryRoleCatMinor.add(new Term("roleCat.roleCatMinor", singleWord.toLowerCase() + "*"));
            }

            BooleanQuery booleanQuery = new BooleanQuery();
            booleanQuery.add(new BooleanClause(queryTitleOccWithWildCard, BooleanClause.Occur.MUST));
            booleanQuery.add(new BooleanClause(queryRoleCatMajor, BooleanClause.Occur.SHOULD));
            booleanQuery.add(new BooleanClause(queryRoleCatMinor, BooleanClause.Occur.SHOULD));

            final FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(queryTitleOcc,
                    TitleOccsList.class);
            final FullTextQuery fullTextQueryWithWildCard = fullTextSession.createFullTextQuery(booleanQuery,
                    TitleOccsList.class);

            // Pasquinelli 13/02/2012 Does we need sorting??
            //fullTextQuery.setSort(new Sort(new SortField("titleOcc", SortField.STRING, true)));
            //fullTextQueryWithWildCard.setSort(new Sort(new SortField("titleOcc", SortField.STRING, true)));

            // Projection permits to extract only a subset of domain class, tuning application.
            //fullTextQuery.setProjection(outputFields);
            // Projection returns an array of Objects, using Transformer we can return a list of domain object  
            //fullTextQuery.setResultTransformer(Transformers.aliasToBean(TitleOccsList.class));

            //Matteo it's better to control size before adding to result
            List<TitleOccsList> result = new ArrayList<TitleOccsList>(0);
            List<TitleOccsList> result1 = fullTextQuery.list();
            List<TitleOccsList> result2 = fullTextQueryWithWildCard.list();
            if (result1.size() > 0) {
                result.addAll(result1);
            }
            if (result2.size() > 0) {
                if (result.size() > 0) {
                    result2.removeAll(result);
                }

                if (result2.size() > 0) {
                    result.addAll(result2);
                }
            }

            return result;
        } catch (ParseException parseException) {
            // TODO: handle exception
            return null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Page searchTitleOrOccupationWithAssignedPeople(String alias, Integer roleCatId,
            PaginationFilter paginationFilter) throws PersistenceException {
        // TODO Auto-generated method stub
        return null;
    }
}