org.rippleosi.patient.details.search.LegacyPatientSearch.java Source code

Java tutorial

Introduction

Here is the source code for org.rippleosi.patient.details.search.LegacyPatientSearch.java

Source

/*
 * Copyright 2015 Ripple OSI
 *
 *    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.
 */
package org.rippleosi.patient.details.search;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.rippleosi.common.types.RepoSourceType;
import org.apache.commons.lang3.time.DateUtils;
import org.rippleosi.common.util.DateFormatter;
import org.rippleosi.patient.details.model.PatientEntity;
import org.rippleosi.patient.details.model.QPatientEntity;
import org.rippleosi.patient.details.repo.PatientRepository;
import org.rippleosi.patient.summary.model.PatientDetails;
import org.rippleosi.patient.summary.model.PatientQueryParams;
import org.rippleosi.patient.summary.model.PatientSummary;
import org.rippleosi.patient.summary.search.PatientSearch;
import org.rippleosi.search.common.model.PageableTableQuery;
import org.rippleosi.search.patient.stats.model.PatientTableQuery;
import org.rippleosi.search.reports.table.model.ReportTableQuery;
import org.rippleosi.search.setting.table.model.SettingTableQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mysema.query.BooleanBuilder;
import com.mysema.util.ArrayUtils;
import org.rippleosi.common.types.RepoSourceTypes;

@Service
@Transactional
public class LegacyPatientSearch implements PatientSearch {

    @Value("${legacy.datasource.priority:900}")
    private int priority;

    @Autowired
    private PatientRepository patientRepository;

    @Autowired
    private PatientEntityToDetailsTransformer patientEntityToDetailsTransformer;

    @Autowired
    private PatientEntityToSummaryTransformer patientEntityToSummaryTransformer;

    @Override
    public RepoSourceType getSource() {
        return RepoSourceTypes.LEGACY;
    }

    @Override
    public int getPriority() {
        return priority;
    }

    @Override
    public List<PatientSummary> findAllPatients() {
        Sort sort = new Sort("nhsNumber");
        Iterable<PatientEntity> patients = patientRepository.findAll(sort);
        return CollectionUtils.collect(patients, patientEntityToSummaryTransformer, new ArrayList<>());
    }

    @Override
    public List<PatientSummary> findAllMatchingPatients(List<String> nhsNumbers, ReportTableQuery tableQuery) {
        if (nhsNumbers.isEmpty()) {
            return null;
        }

        // build the query predicate
        QPatientEntity blueprint = QPatientEntity.patientEntity;
        BooleanBuilder predicate = new BooleanBuilder();

        for (String nhsNumber : nhsNumbers) {
            predicate.or(blueprint.nhsNumber.eq(nhsNumber));
        }

        Iterable<PatientEntity> patients = patientRepository.findAll(predicate, generatePageRequest(tableQuery));
        return CollectionUtils.collect(patients, patientEntityToSummaryTransformer, new ArrayList<>());
    }

    @Override
    public PatientDetails findPatient(String patientId) {
        PatientEntity patient = patientRepository.findByNhsNumber(patientId);
        return patientEntityToDetailsTransformer.transform(patient);
    }

    @Override
    public List<PatientSummary> findPatientsBySearchString(PatientTableQuery tableQuery) {
        BooleanBuilder predicate = generateSearchByPatientReportTablePredicate(tableQuery);

        if (predicate == null) {
            return new ArrayList<>();
        }

        Page<PatientEntity> patients = patientRepository.findAll(predicate, generatePageRequest(tableQuery));
        return CollectionUtils.collect(patients, patientEntityToSummaryTransformer, new ArrayList<>());
    }

    @Override
    public Long countPatientsBySearchString(PatientTableQuery tableQuery) {
        BooleanBuilder predicate = generateSearchByPatientReportTablePredicate(tableQuery);
        return predicate == null ? 0 : patientRepository.count(predicate);
    }

    private BooleanBuilder generateSearchByPatientReportTablePredicate(PatientTableQuery tableQuery) {
        // extract data from search string
        Object[] searchParams = parseSearchParams(tableQuery.getSearchString());
        int totalParams = searchParams.length;

        // build the query predicate
        QPatientEntity blueprint = QPatientEntity.patientEntity;
        BooleanBuilder predicate = new BooleanBuilder();

        // quit processing if no params
        if (totalParams == 0) {
            return null;
        }

        if (totalParams == 1) {
            Object param = searchParams[0];

            // firstly, check whether this param a date
            if (param instanceof Date) {
                predicate.and(blueprint.dateOfBirth.eq((Date) param));
            }
            // if not, it's either the first or last name
            else {
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) param),
                        blueprint.lastName.equalsIgnoreCase((String) param));
            }
        } else if (totalParams == 2) {
            Object firstParam = searchParams[0];
            Object secondParam = searchParams[1];

            // again, start with a date param, then test first and last name
            if (firstParam instanceof Date) {
                predicate.and(blueprint.dateOfBirth.eq((Date) firstParam));
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) secondParam),
                        blueprint.lastName.equalsIgnoreCase((String) secondParam));
            } else if (secondParam instanceof Date) {
                predicate.and(blueprint.dateOfBirth.eq((Date) secondParam));
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) firstParam),
                        blueprint.lastName.equalsIgnoreCase((String) firstParam));
            }
            // if neither are a date, then both are strings
            else {
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) firstParam),
                        blueprint.firstName.equalsIgnoreCase((String) secondParam));
                predicate.andAnyOf(blueprint.lastName.equalsIgnoreCase((String) firstParam),
                        blueprint.lastName.equalsIgnoreCase((String) secondParam));
            }
        } else if (totalParams > 2) {
            Object firstParam = searchParams[0];
            Object secondParam = searchParams[1];
            Object thirdParam = searchParams[2];

            if (firstParam instanceof Date) {
                predicate.and(blueprint.dateOfBirth.eq((Date) firstParam));
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) secondParam),
                        blueprint.firstName.equalsIgnoreCase((String) thirdParam));
                predicate.andAnyOf(blueprint.lastName.equalsIgnoreCase((String) secondParam),
                        blueprint.lastName.equalsIgnoreCase((String) thirdParam));
            } else if (secondParam instanceof Date) {
                predicate.and(blueprint.dateOfBirth.eq((Date) secondParam));
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) firstParam),
                        blueprint.firstName.equalsIgnoreCase((String) thirdParam));
                predicate.andAnyOf(blueprint.lastName.equalsIgnoreCase((String) firstParam),
                        blueprint.lastName.equalsIgnoreCase((String) thirdParam));
            } else if (thirdParam instanceof Date) {
                predicate.and(blueprint.dateOfBirth.eq((Date) thirdParam));
                predicate.andAnyOf(blueprint.firstName.equalsIgnoreCase((String) firstParam),
                        blueprint.firstName.equalsIgnoreCase((String) secondParam));
                predicate.andAnyOf(blueprint.lastName.equalsIgnoreCase((String) firstParam),
                        blueprint.lastName.equalsIgnoreCase((String) secondParam));
            }
            // if none are a date, then there are too many parameters
            else {
                predicate = null;
            }
        }

        return predicate;
    }

    private Object[] parseSearchParams(String searchString) {
        String[] split = StringUtils.split(searchString);
        Object[] searchParams = ArrayUtils.combine(split.length, split);

        for (int i = 0; i < searchParams.length; i++) {
            Date dateParam = DateFormatter.toDate((String) searchParams[i]);

            if (dateParam != null) {
                searchParams[i] = dateParam;
            }
        }

        return searchParams;
    }

    @Override
    public PatientSummary findPatientSummary(String patientId) {
        PatientEntity patient = patientRepository.findByNhsNumber(patientId);
        return patientEntityToSummaryTransformer.transform(patient);
    }

    @Override
    public List<PatientSummary> findAllPatientsByDepartment(SettingTableQuery tableQuery) {
        List<PatientEntity> patients = patientRepository.findPatientsByDepartmentDepartmentIgnoreCase(
                tableQuery.getSearchString(), generatePageRequest(tableQuery));

        return CollectionUtils.collect(patients, patientEntityToSummaryTransformer, new ArrayList<>());
    }

    @Override
    public Long findPatientCountByDepartment(String department) {
        return patientRepository.countByDepartmentDepartmentIgnoreCase(department);
    }

    @Override
    public List<PatientSummary> findPatientsByQueryObject(PatientQueryParams params) {
        BooleanBuilder predicate = generateAdvancedSearchPredicate(params);

        Iterable<PatientEntity> patients = patientRepository.findAll(predicate);
        return CollectionUtils.collect(patients, patientEntityToSummaryTransformer, new ArrayList<>());
    }

    private BooleanBuilder generateAdvancedSearchPredicate(PatientQueryParams params) {
        QPatientEntity blueprint = QPatientEntity.patientEntity;
        BooleanBuilder predicate = new BooleanBuilder();

        String nhsNumber = params.getNhsNumber();

        if (nhsNumber != null) {
            predicate.and(blueprint.nhsNumber.eq(nhsNumber));
        } else {
            String surname = StringUtils.stripToNull(params.getSurname());
            String forename = StringUtils.stripToNull(params.getForename());
            Date dateOfBirth = params.getDateOfBirth();
            String gender = StringUtils.stripToNull(params.getGender());

            if (surname != null) {
                predicate.and(blueprint.lastName.like(surname));
            }
            if (forename != null) {
                predicate.and(blueprint.firstName.like(forename));
            }
            if (dateOfBirth != null) {
                Date truncatedDateOfBirth = DateUtils.truncate(dateOfBirth, Calendar.DATE);

                predicate.and(blueprint.dateOfBirth.eq(truncatedDateOfBirth));
            }
            if (gender != null) {
                predicate.and(blueprint.gender.eq(gender));
            }
        }

        return predicate;
    }

    private PageRequest generatePageRequest(PageableTableQuery tableQuery) {
        // determine page number (zero indexed) and sort direction
        Integer pageNumber = Integer.valueOf(tableQuery.getPageNumber()) - 1;
        Direction sortDirection = Direction.fromString(tableQuery.getOrderType());

        // create the request for a page (sorted by NHS number)
        return new PageRequest(pageNumber, 15, sortDirection, "nhsNumber");
    }
}