org.openmrs.module.idcards.db.hibernate.HibernateIdcardsDAO.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.idcards.db.hibernate.HibernateIdcardsDAO.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.idcards.db.hibernate;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.type.StandardBasicTypes;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifier;
import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.DAOException;
import org.openmrs.module.idcards.GeneratedIdentifier;
import org.openmrs.module.idcards.IdcardsTemplate;
import org.openmrs.module.idcards.db.IdcardsDAO;

/**
 * Hibernate specific Idcards database methods
 */
public class HibernateIdcardsDAO implements IdcardsDAO {

    protected final Log log = LogFactory.getLog(getClass());

    /**
     * Hibernate session factory
     */
    private SessionFactory sessionFactory;

    /**
     * Set session factory
     * 
     * @param sessionFactory
     */
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#saveIdcardsTemplate(org.openmrs.module.idcards.IdcardsTemplate)
     */
    public void saveIdcardsTemplate(IdcardsTemplate idcardsTemplate) throws DAOException {
        sessionFactory.getCurrentSession().saveOrUpdate(idcardsTemplate);
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getIdcardsTemplate(java.lang.Integer)
     */
    public IdcardsTemplate getIdcardsTemplate(Integer templateId) throws DAOException {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(IdcardsTemplate.class, "template")
                .add(Expression.eq("template.templateId", templateId));
        List<IdcardsTemplate> template = criteria.list();
        return template.get(0);
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getAllIdcardsTemplates()
     */
    public List<IdcardsTemplate> getAllIdcardsTemplates() throws DAOException {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(IdcardsTemplate.class, "template");
        return (List<IdcardsTemplate>) criteria.list();
    }

    /**
     * Get all PatientIdentifiers for the patientId.
     * 
     * @param pid The Patient.patientId.
     * @param preferred If true, only return preferred PatientIdentifiers
     * @return
     * @throws org.openmrs.api.db.DAOException
     */
    public List<PatientIdentifier> getPatientIdentifiersByPatientId(Patient pid, boolean preferred)
            throws DAOException {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(PatientIdentifier.class, "identifier")
                .add(Expression.eq("identifier.patient", pid));

        if (preferred) {
            criteria.add(Expression.eq("identifier.preferred", true));
        }

        return criteria.list();

    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getPatientsByIdentifier(java.util.List)
     */
    public List<Patient> getPatientsByIdentifier(List<String> identifiers) throws DAOException {
        String tmp1 = identifiers.toString();
        String tmp2 = tmp1.replaceAll(", ", "\\$|\\^");
        String tmp3 = tmp2.replaceAll(" ", "\\[ ]?");
        String tmp4 = tmp3.replaceAll("\\-", "\\[\\-\\]?");
        String regex = "^" + tmp4.substring(1, tmp4.length() - 1) + "$";
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Patient.class);
        criteria.createAlias("identifiers", "ids");
        criteria.add(Restrictions.sqlRestriction("identifier rlike ?", regex, StandardBasicTypes.STRING));
        log.debug("Patient identifier regex" + regex);
        log.debug("StandardBasicTypes.STRING: " + StandardBasicTypes.STRING.toString());
        return criteria.list();
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getPatientsByPatientId(java.util.List)
     */
    public List<Patient> getPatientsByPatientId(List<Integer> patientIds) throws DAOException {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Patient.class);
        criteria.add(Expression.in("patientId", patientIds));
        return criteria.list();
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#generateIdentifiers(int, int)
     */
    public void generateIdentifiers(int identifierStartValue, int quantityToGenerate) throws DAOException {
        Date generatedDate = new Date();
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(generatedDate);
        Integer currentUserId = Context.getAuthenticatedUser().getUserId();

        Session currentSession = sessionFactory.getCurrentSession();
        currentSession.setCacheMode(CacheMode.IGNORE);

        String insertPrefix = "insert into idcards_generated_identifier (id, generator, date_generated) values ";
        String valuesPrefix = "(";
        String valuesSuffix = ", " + currentUserId + ", '" + date + "')";

        // if we're in mysql, do extended inserts to speed things up
        SessionFactoryImplementor implementor = (SessionFactoryImplementor) sessionFactory;
        Dialect dialect = implementor.getDialect();
        boolean isMySQLDialect = MySQLDialect.class.getName().equals(dialect.getClass().getName());

        if (isMySQLDialect) {
            String sql = null;
            // loop over the list of numbers and get/insert the string identifier
            for (int x = identifierStartValue; x < identifierStartValue + quantityToGenerate; x++) {
                if (sql == null) // if its not the first element, add a comma
                    sql = insertPrefix;
                else
                    sql += ",";

                sql += valuesPrefix + x + valuesSuffix;

                // send to the database every 1001 entries or at the end 
                if (x % 100 == 0 || x == (identifierStartValue + quantityToGenerate - 1)) {
                    try {
                        SQLQuery query = currentSession.createSQLQuery(sql);
                        query.executeUpdate();
                        sql = null; // reset the sql string
                        currentSession.flush();
                    } catch (ConstraintViolationException cve) {
                        log.error("Sql: " + sql);
                        throw new DAOException("Error creating an identifier between " + x + " and " + (x - 1001)
                                + " because it already exists in the system", cve);
                    }
                }
            }

        } else {
            for (int x = identifierStartValue; x < identifierStartValue + quantityToGenerate; x++) {
                String sql = insertPrefix + valuesPrefix + x + valuesSuffix;

                try {
                    SQLQuery query = currentSession.createSQLQuery(sql);
                    query.executeUpdate();
                } catch (ConstraintViolationException cve) {
                    throw new DAOException(
                            "Unable to create identifier: " + x + " because it already exists in the system", cve);
                }

                // control the number of objects in memory
                if (x % 500 == 0 || x == (identifierStartValue + quantityToGenerate - 1)) {
                    currentSession.flush();
                    currentSession.clear();
                }
            }
        }

    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getNumberOfUnprintedGeneratedIdentifiers()
     */
    public Long getNumberOfUnprintedGeneratedIdentifiers() throws DAOException {
        Criteria crit = sessionFactory.getCurrentSession().createCriteria(GeneratedIdentifier.class);
        crit.setProjection(Projections.count("printed"));
        crit.add(Expression.eq("printed", false));

        return (Long) crit.uniqueResult();
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getPrintedIdentifiers()
     */
    public List<GeneratedIdentifier> getPrintedIdentifiers() throws DAOException {
        Criteria crit = sessionFactory.getCurrentSession().createCriteria(GeneratedIdentifier.class);
        crit.add(Expression.eq("printed", true));

        return (List<GeneratedIdentifier>) crit.list();
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#printGeneratedIdentifiers(int,IdcardsTemplate)
     */
    public List<Integer> printGeneratedIdentifiers(int quantityToPrint, IdcardsTemplate template)
            throws DAOException {
        // find the identifiers to return and mark as printed
        String sql = "select id from GeneratedIdentifier where printed = 0 order by RAND()";
        Query query = sessionFactory.getCurrentSession().createQuery(sql);
        query.setMaxResults(quantityToPrint); // this is the "limit = quantityToPrint" for sql

        List<Integer> printedIdentifiers = (List<Integer>) query.list();

        // mark the identifiers as printed
        sql = "update GeneratedIdentifier set printed = 1, printedBy = :printedBy, datePrinted = :date, printedTemplate = :template where id in (:identifiers)";
        query = sessionFactory.getCurrentSession().createQuery(sql);
        query.setParameter("printedBy", Context.getAuthenticatedUser());
        query.setTimestamp("date", new Date());
        query.setParameter("template", template);
        query.setParameterList("identifiers", printedIdentifiers);
        query.executeUpdate();

        return printedIdentifiers;
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getPrintedIdentifiersGrouped()
     */
    public Map<GeneratedIdentifier, Long> getPrintedIdentifiersGrouped() throws DAOException {

        String hql = "select min(id), count(datePrinted) from GeneratedIdentifier where printed = 1 group by datePrinted";

        Query query = sessionFactory.getCurrentSession().createQuery(hql);

        Map<GeneratedIdentifier, Long> returnMap = new LinkedHashMap<GeneratedIdentifier, Long>();

        List<Object[]> rows = (List<Object[]>) query.list();

        for (Object[] row : rows) {
            Integer identifier = (Integer) row[0];
            Long count = (Long) row[1];
            GeneratedIdentifier genId = (GeneratedIdentifier) sessionFactory.getCurrentSession()
                    .createQuery("from GeneratedIdentifier where id = :id").setInteger("id", identifier)
                    .uniqueResult();
            if (genId != null)
                returnMap.put(genId, count);
        }

        return returnMap;
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#getGeneratedIdentifiersGrouped()
     */
    public Map<GeneratedIdentifier, Long> getGeneratedIdentifiersGrouped() throws DAOException {

        String hql = "select min(id), count(dateGenerated) from GeneratedIdentifier group by dateGenerated";

        Query query = sessionFactory.getCurrentSession().createQuery(hql);

        Map<GeneratedIdentifier, Long> returnMap = new LinkedHashMap<GeneratedIdentifier, Long>();

        List<Object[]> rows = (List<Object[]>) query.list();

        for (Object[] row : rows) {
            Integer identifier = (Integer) row[0];
            Long count = (Long) row[1];
            GeneratedIdentifier genId = (GeneratedIdentifier) sessionFactory.getCurrentSession()
                    .createQuery("from GeneratedIdentifier where id = :id").setInteger("id", identifier)
                    .uniqueResult();
            if (genId != null)
                returnMap.put(genId, count);
        }

        return returnMap;
    }

    /**
     * @see org.openmrs.module.idcards.db.IdcardsDAO#generateAndPrintIdentifiers(java.lang.Integer,
     *      java.lang.Integer, java.lang.Integer, org.openmrs.module.idcards.IdcardsTemplate)
     */
    public List<Integer> generateAndPrintIdentifiers(Integer count, Integer min, Integer max,
            IdcardsTemplate template) throws DAOException {

        // make sure there are enough identifiers to generate
        String hql = "select count(id) from GeneratedIdentifier where id >= :min and id < :max";
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        query.setInteger("min", min);
        query.setInteger("max", max);
        Long numIdsAlreadyGeneratedInRange = (Long) query.list().get(0);
        Integer numIdsInRange = max - min;
        Long availableIdentifiers = numIdsInRange - numIdsAlreadyGeneratedInRange;
        if (count > availableIdentifiers)
            throw new DAOException("You can't generate " + count + " identifiers because there are only "
                    + availableIdentifiers + " available identifiers between " + min + " and " + max);

        Session session = sessionFactory.getCurrentSession();

        List<Integer> identifiers = new ArrayList<Integer>(count);

        User user = Context.getAuthenticatedUser();
        Date date = new Date();

        for (int x = 0; x < count; x++) {
            Integer possibleId;
            do { // loop until we have a number that isn't used already
                possibleId = (int) (Math.random() * (max - min)) + min;
            } while (identifiers.contains(possibleId) || isIdentifierGenerated(possibleId));

            identifiers.add(possibleId);
        }

        // insert rows into idcards_generated_identifier
        for (Integer id : identifiers) {
            GeneratedIdentifier generatedIdObject = new GeneratedIdentifier(id, user, date);
            generatedIdObject.setPrinted(true);
            generatedIdObject.setPrintedBy(user);
            generatedIdObject.setDatePrinted(date);
            generatedIdObject.setPrintedTemplate(template);
            session.save(generatedIdObject);
        }

        return identifiers;
    }

    /**
     * Checks the idcards_generated_identifiers table to see if the given string exists in it
     * 
     * @param identifier the identifier to look for
     * @return true if the identifier is in the table
     */
    public boolean isIdentifierGenerated(Integer identifier) {
        String hql = "select id from GeneratedIdentifier where id = :id";

        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        query.setInteger("id", identifier);
        return query.list().size() > 0;

    }

}