uk.org.openeyes.DatabaseFunctions.java Source code

Java tutorial

Introduction

Here is the source code for uk.org.openeyes.DatabaseFunctions.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.org.openeyes;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dcm4che3.util.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.context.internal.ManagedSessionContext;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.ini4j.Wini;
import uk.org.openeyes.models.DicomEyeStatus;
import uk.org.openeyes.models.Episode;
import uk.org.openeyes.models.Event;
import uk.org.openeyes.models.EventType;
import uk.org.openeyes.models.OphinbiometryImportedEvents;
import uk.org.openeyes.models.Patient;
import uk.org.openeyes.models.User;

/**
 *
 * @author VEDELEKT
 */
public class DatabaseFunctions {
    private SessionFactory sessionFactory;

    /**
     *
     */
    protected Patient selectedPatient;

    /**
     *
     */
    protected Episode selectedEpisode;

    /**
     *
     */
    protected Session session;

    /**
     *
     */
    protected Transaction transaction;

    /**
     *
     */
    protected User selectedUser;

    /**
     *
     */
    protected StudyData eventStudy;

    /**
     *
     */
    protected BiometryData eventBiometry;

    /**
     *
     */
    public OphinbiometryImportedEvents importedBiometryEvent;

    /**
     *
     */
    protected boolean isNewEvent = true;

    /**
     *
     */
    protected DICOMLogger dicomLogger;

    /**
     *
     * @param userName
     * @return
     */
    protected User searchStudyUser(String userName) {

        Criteria crit = session.createCriteria(User.class);
        Disjunction or = Restrictions.disjunction();

        User returnUser = null;

        String[] userNameArr = userName.split(" ");
        String lastName = "";

        // we cannot rely on the user name format coming from the dicom file!!!
        if (userNameArr.length == 1) {
            lastName = "";
        } else {
            for (int i = 1; i < userNameArr.length; i++) {
                lastName += userNameArr[i] + " ";
            }
        }
        crit.add(Restrictions.eq("firstName", userNameArr[0]));
        crit.add(Restrictions.eq("lastName", lastName));

        if (crit.list().isEmpty()) {
            // we search for unknown user
            Criteria crit2 = session.createCriteria(User.class);
            crit2.add(Restrictions.eq("firstName", "Unknown"));
            crit2.add(Restrictions.eq("lastName", "IOLMaster"));

            if (crit2.list().isEmpty()) {
                // we create the user
                returnUser = new User();
                returnUser.setUsername("UNKNOWN");
                returnUser.setFirstName("Unknown");
                returnUser.setLastName("IOLMaster");
                returnUser.setEmail("");
                returnUser.setActive(true);
                returnUser.setGlobalFirmRights(false);
                returnUser.setTitle("N/A");
                returnUser.setQualifications("Generated by IOLMaster import");
                returnUser.setRole("Import");
                returnUser.setLastModifiedUserId(new User(1));
                returnUser.setLastModifiedDate(new Date());
                returnUser.setCreatedUserId(new User(1));
                returnUser.setCreatedDate(new Date());
                returnUser.setIsClinical(false);
                returnUser.setIsDoctor(false);
                returnUser.setIsConsultant(false);
                returnUser.setIsSurgeon(false);
                returnUser.setHasSelectedFirms(false);
                session.save(returnUser);
            } else {
                returnUser = (User) crit2.list().get(0);
            }

        } else {
            returnUser = (User) crit.list().get(0);
        }
        return returnUser;
    }

    private Configuration configureHibernate(String iniFile) {
        try {
            Wini ini = new Wini(new File(iniFile));
            Configuration configuration = new Configuration();
            configuration.setProperty("hibernate.connection.url", "jdbc:mysql://" + ini.get("?", "host") + ":"
                    + ini.get("?", "port") + "/" + ini.get("?", "dbname"));
            configuration.setProperty("hibernate.connection.username", "" + ini.get("?", "username"));
            configuration.setProperty("hibernate.connection.password", "" + ini.get("?", "password"));
            configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
            if (ini.get("?", "devmode", int.class) == 1) {
                configuration.setProperty("show_sql", "true");
                configuration.setProperty("hbm2ddl.auto", "validate");
            }
            configuration.addAnnotatedClass(uk.org.openeyes.models.Contact.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.ContactLabel.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.DicomEyeStatus.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.DicomFiles.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.DicomImportLog.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Disorder.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.DoctorGrade.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Episode.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EpisodeStatus.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EthnicGroup.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EtOphinbiometryCalculation.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EtOphinbiometryMeasurement.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EtOphinbiometrySelection.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EtOphinbiometryIolRefValues.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.OphinbiometryImportedEvents.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.OphinbiometryCalculationFormula.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.OphinbiometryLenstypeLens.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.OphinbiometrySurgeon.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Event.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EventGroup.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.EventType.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Eye.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Firm.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Gp.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.ImportSource.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Institution.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Patient.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Practice.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Service.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.ServiceSubspecialtyAssignment.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Site.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Specialty.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.SpecialtyType.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.Subspecialty.class);
            configuration.addAnnotatedClass(uk.org.openeyes.models.User.class);

            return configuration;
        } catch (IOException ex) {
            Logger.getLogger(DatabaseFunctions.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }

    }

    /**
     *
     * @param configFile
     * @param SystemLogger
     */
    public void initSessionFactory(String configFile, DICOMLogger SystemLogger) {
        // A SessionFactory is set up once for an application!
        // if no config specified we should use the default one

        // TODO: need to check for /etc/openeyes/db.conf here!!

        if (this.dicomLogger == null) {
            this.dicomLogger = SystemLogger;
        }

        if (configFile.matches("(?i).*hibernate.cfg.xml") || configFile.equals("")) {
            String defaultConfig = "resources/hibernate.cfg.xml";
            File inputFile = null;
            final StandardServiceRegistry registry;

            if (!configFile.equals("")) {
                inputFile = new File(configFile);
            }

            if (inputFile != null) {
                registry = new StandardServiceRegistryBuilder().configure(inputFile) // configures settings from hibernate.cfg.xml
                        .build();
            } else {
                registry = new StandardServiceRegistryBuilder().configure(defaultConfig) // configures settings from hibernate.cfg.xml
                        .build();
            }

            try {
                sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
                setSession();
                setTransaction();
            } catch (Exception e) {
                // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
                // so destroy it manually.

                // TODO: need to add debug config here!
                e.printStackTrace();
                StandardServiceRegistryBuilder.destroy(registry);
                dicomLogger.systemExitWithLog(5,
                        "Failed to connect to the database, please check your hibernate configuration file!", this);
                //System.exit(5);
            }
        } else {
            // try to open /etc/ database config

            try {
                sessionFactory = configureHibernate(configFile).buildSessionFactory();
                setSession();
                setTransaction();
            } catch (Exception e) {
                dicomLogger.systemExitWithLog(5,
                        "Failed to connect to the database, please check your hibernate configuration file!", this);
            }
        }
    }

    /**
     *
     * @param originalTable
     * @param originalID
     * @return
     */
    public int addVersionTableData(Object originalTable, Integer originalID) {
        // http://www.tutorialspoint.com/hibernate/hibernate_native_sql.htm
        AbstractEntityPersister aep = ((AbstractEntityPersister) session.getSessionFactory()
                .getClassMetadata(originalTable.getClass()));
        String tableName = aep.getTableName();
        String[] properties = aep.getPropertyNames();
        String[] originalColumns = new String[properties.length];

        for (int nameIndex = 0; nameIndex != properties.length; nameIndex++) {
            //System.out.println("Property name: "+properties[nameIndex]);  
            String[] columns = aep.getPropertyColumnNames(nameIndex);
            for (int columnIndex = 0; columnIndex != columns.length; columnIndex++) {
                //System.out.println("Column name: "+columns[columnIndex]);  
                originalColumns[nameIndex] = columns[columnIndex];
            }
        }

        //System.out.println("INSERT INTO "+tableName+"_version (id, "+String.join(",", originalColumns)+",`version_date`,`version_id`) SELECT id, "+String.join(",", originalColumns)+", now(), NULL FROM "+tableName+" WHERE id="+originalID.toString());
        Query query = this.session.createSQLQuery(
                "INSERT INTO " + tableName + "_version (id, " + StringUtils.concat(originalColumns, ',')
                        + ",`version_date`,`version_id`) SELECT id, " + StringUtils.concat(originalColumns, ',')
                        + ", now(), NULL FROM " + tableName + " WHERE id=" + originalID.toString());
        dicomLogger.addToRawOutput("Version audit trail has been added to: " + tableName + "_version");
        return query.executeUpdate();
    }

    /**
     *
     * @return
     */
    public boolean checkConnection() {
        //Session session = sessionFactory.openSession();
        return session.isConnected();
    }

    /**
     *
     */
    public void closeSessionFactory() {
        if (sessionFactory != null) {
            sessionFactory.close();
        }
    }

    /**
     *
     * @return
     */
    public Patient getSelectedPatient() {
        return this.selectedPatient;
    }

    /**
     *
     * @param hosNum
     * @param gender
     * @param birthDate
     */
    public void searchPatient(String hosNum, char gender, Calendar birthDate) {
        Session session = sessionFactory.openSession();
        Criteria crit = session.createCriteria(Patient.class);

        // add leading 0s to the hosNum string
        if (hosNum.length() < 7) {
            hosNum = ("0000000" + hosNum).substring(hosNum.length());
        }

        //crit.add(Restrictions.eq("hosNum",hosNum));
        crit.add(Restrictions.sqlRestriction("lower(hos_num) = '" + hosNum.toLowerCase() + "'"));
        // we should search for M or F only
        if (Character.toString(gender).equals("F") || Character.toString(gender).equals("M")) {
            crit.add(Restrictions.eq("gender", Character.toString(gender)));
        }
        int dateYear = birthDate.get(Calendar.YEAR);
        int dateMonth = birthDate.get(Calendar.MONTH) + 1;
        int dateDay = birthDate.get(Calendar.DAY_OF_MONTH);
        crit.add(Restrictions.sqlRestriction("dob = '" + dateYear + "-" + dateMonth + "-" + dateDay + "'"));
        List patientList = crit.list();

        if (patientList.isEmpty()) {
            // TODO: How to handle this case??
            dicomLogger.addToRawOutput("ERROR: Patient not found for the data specified (hos_num: " + hosNum
                    + ", gender: " + gender + ", dob: " + dateYear + "-" + dateMonth + "-" + dateDay + ")");
        } else if (patientList.size() > 1) {
            // TODO: How to handle this case??
            dicomLogger.addToRawOutput("ERROR: More than 1 record found for patient (hos_num: " + hosNum
                    + ", gender: " + gender + ", dob: " + dateYear + "-" + dateMonth + "-" + dateDay + ")");
        } else {
            // TODO: is everything OK?
            selectedPatient = (Patient) patientList.get(0);
        }
        if (selectedPatient != null) {
            dicomLogger.addToRawOutput("Selected patient: " + selectedPatient);
        }
        session.close();
    }

    /**
     *
     */
    public void selectActiveEpisode() {
        selectedEpisode = null;
        /*
        // New requirement: always follow the manual linking process, so this part has been removed
        if(this.selectedPatient != null){
        Session session = sessionFactory.openSession();
        Criteria episodeCrit = session.createCriteria(Episode.class);
        Criteria patientJoin = episodeCrit.createCriteria("patientId");
            
        patientJoin.add(Restrictions.eq("id", selectedPatient.getId()));
        episodeCrit.add(Restrictions.eq("deleted",0));
        Criteria episodeStatusJoin = episodeCrit.createCriteria("episodeStatusId");
        episodeStatusJoin.add(Restrictions.ne("name", "Discharged"));
        List episodesList = episodeCrit.list();
            
        if(episodesList.isEmpty()){
            //System.out.println("ERROR: No open episodes found!");
            dicomLogger.addToRawOutput("ERROR: No open episodes found!");
        }else if(episodesList.size() != 1){
            //System.out.println("ERROR: More than 1 open episodes found!");
            dicomLogger.addToRawOutput("ERROR: More than 1 open episodes found!");
        }else{
            selectedEpisode = (Episode) episodesList.get(0);
            //System.out.println("Selected episode: "+selectedEpisode.toString());
            dicomLogger.addToRawOutput("Selected episode: "+selectedEpisode.toString());
        }
            
        session.close();
        }
        if(selectedEpisode == null){
        //System.out.println("ERROR: No unique open episode found, will create data without episode!");
        dicomLogger.addToRawOutput("ERROR: No unique open episode found, will create data without episode!");
        }
        */
    }

    /**
     *
     * @return
     */
    public Episode getSelectedEpisode() {
        return this.selectedEpisode;
    }

    /**
    *
    * 
     * @param studyDate
     * @param studyDate
     * @return 
    **/
    public String getStudyYMD(Calendar studyDate) {

        String formattedStudyDate = String.format("%04d-%02d-%02d %02d:%02d:%02d", studyDate.get(Calendar.YEAR),
                studyDate.get(Calendar.MONTH) + 1, studyDate.get(Calendar.DAY_OF_MONTH),
                studyDate.get(Calendar.HOUR_OF_DAY), studyDate.get(Calendar.MINUTE),
                studyDate.get(Calendar.SECOND));
        return formattedStudyDate;
    }

    /**
     *
     * @param inputDate
     * @return
     */
    public String getSQLFormattedDate(Date inputDate) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(inputDate);
    }

    /**
     *
     * @param newEvent
     * @return
     */
    protected OphinbiometryImportedEvents createNewImportedEvent(Event newEvent) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        OphinbiometryImportedEvents importedEvent = new OphinbiometryImportedEvents();

        importedEvent.setDeviceName(eventStudy.getInstituionName());
        importedEvent.setDeviceId(eventStudy.getStationName());
        importedEvent.setDeviceManufacturer(eventStudy.getDeviceManufacturer());
        importedEvent.setDeviceModel(eventStudy.getDeviceModel());
        importedEvent.setDeviceSoftwareVersion(eventStudy.getDeviceSoftwareVersion());
        importedEvent.setStudyId(eventStudy.getStudyInstanceID());
        importedEvent.setSeriesId(eventStudy.getSeriesInstanceID());
        importedEvent.setPatientId(getSelectedPatient());
        importedEvent.setSurgeonName(eventStudy.getSurgeonName());
        importedEvent.setAcquisitionDatetime(eventStudy.getAcquisitionDateTime());
        importedEvent.setDeviceSerialNumber(eventStudy.getDeviceSerial());
        try {
            importedEvent
                    .setContentDateTime(df.parse(getSQLFormattedDate(eventStudy.getContentDateTime().getTime())));
        } catch (ParseException ex) {
            ex.printStackTrace();
        }

        importedEvent.setEventId(newEvent);
        importedEvent.setCreatedDate(new Date());
        importedEvent.setLastModifiedDate(new Date());
        importedEvent.setCreatedUserId(selectedUser);
        importedEvent.setLastModifiedUserId(selectedUser);
        boolean isLinked = false;
        if (getSelectedEpisode() != null) {
            isLinked = true;
        }
        importedEvent.setIsLinked(isLinked);
        importedEvent.setIsMerged(false);
        session.saveOrUpdate(importedEvent);

        return importedEvent;
    }

    /**
     *
     * @return
     */
    protected Event createNewEvent() {
        Event newBiometryEvent = new Event();

        //System.out.println("Starting event...");
        dicomLogger.addToRawOutput("Starting event...");
        if (this.selectedEpisode != null) {
            newBiometryEvent.setEpisodeId(selectedEpisode);
        } else {
            newBiometryEvent.setEpisodeId(null);
        }
        newBiometryEvent.setCreatedUserId(selectedUser);
        // search for event type name "Biometry"
        Criteria eventTypeCrit = session.createCriteria(EventType.class);
        eventTypeCrit.add(Restrictions.eq("name", "Biometry"));
        newBiometryEvent.setEventTypeId((EventType) eventTypeCrit.list().get(0));
        newBiometryEvent.setCreatedDate(new Date());
        newBiometryEvent.setLastModifiedDate(new Date());
        newBiometryEvent.setLastModifiedUserId(selectedUser);

        // TODO: need to check, because it display one month more!!!!
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            newBiometryEvent.setEventDate(df.parse(getStudyYMD(eventStudy.getStudyDateTime())));
        } catch (ParseException ex) {
            Logger.getLogger(DatabaseFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }

        // let's save it!
        // 1. create new event
        session.save(newBiometryEvent);
        //System.out.println("Event saved...");
        dicomLogger.addToRawOutput("Event saved... Event id: " + newBiometryEvent.getId());

        return newBiometryEvent;
    }

    /**
     *
     */
    public void setSession() {
        if (this.session == null || !(this.session.isConnected())) {
            try {
                this.session = sessionFactory.openSession();
            } catch (Exception e) {
                System.exit(5);
            }
            session.setFlushMode(FlushMode.MANUAL);
            ManagedSessionContext.bind(session);
        }
    }

    /**
     *
     * @return
     */
    public Session getSession() {
        setSession();
        return this.session;
    }

    // for unit testing it need to be public

    /**
     *
     */
    public void setTransaction() {
        //if(this.session == null){
        //    this.setSession();
        // }
        this.transaction = this.session.beginTransaction();
    }

    /**
     *
     * @return
     */
    public Transaction getTransaction() {
        return this.transaction;
    }

    // for unit testing it need to be public

    /**
     *
     * @param inputStudy
     */
    public void setEventStudy(StudyData inputStudy) {
        this.eventStudy = inputStudy;
    }

    private StudyData getEventStudy() {
        return this.eventStudy;
    }

    // for unit testing it need to be public

    /**
     *
     * @param inputBiometry
     */
    public void setEventBiometry(BiometryData inputBiometry) {
        this.eventBiometry = inputBiometry;
    }

    private BiometryData getEventBiometry() {
        return this.eventBiometry;
    }

    // for unit testing it need to be public

    /**
     *
     */
    public void setSelectedUser() {
        if (eventStudy != null) {
            String SurgeonName = "";
            if (eventStudy.getSurgeonName() != null) {
                SurgeonName = eventStudy.getSurgeonName();
            }
            this.selectedUser = searchStudyUser(SurgeonName);
        }
    }

    /**
     *  This method can be used with IOLM700 when we extract the string representation of the Eye Status
     * @param EyeStatus
     */
    public Integer getEyeStatusFromSting(String eyeStatus) {
        DicomEyeStatus status;
        Criteria crit = session.createCriteria(DicomEyeStatus.class);
        crit.add(Restrictions.eq("name", eyeStatus));
        List statusList = crit.list();

        System.out.println("Eye status: " + eyeStatus);

        if (statusList.isEmpty()) {
            DetachedCriteria criteria = DetachedCriteria.forClass(DicomEyeStatus.class)
                    .setProjection(Projections.max("id"));
            Integer maxId = (Integer) criteria.getExecutableCriteria(session).list().get(0);
            Integer newId = 0;
            status = new DicomEyeStatus();
            status.setName(eyeStatus);

            if (maxId < 1000) {
                newId = 1000;
            } else {
                newId = maxId + 1;
            }
            status.setId(newId);
            session.save(status);
            session.flush();
        } else {
            status = (DicomEyeStatus) statusList.get(0);
        }

        return status.getId();
    }
}