com.marand.thinkmed.medications.task.impl.MedicationsTasksProviderImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.marand.thinkmed.medications.task.impl.MedicationsTasksProviderImpl.java

Source

/*
 * Copyright (c) 2010-2014 Marand d.o.o. (www.marand.com)
 *
 * This file is part of Think!Med Clinical Medication Management.
 *
 * Think!Med Clinical Medication Management is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Think!Med Clinical Medication Management 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Think!Med Clinical Medication Management.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.marand.thinkmed.medications.task.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import com.marand.maf.core.JsonUtil;
import com.marand.maf.core.Opt;
import com.marand.maf.core.PartialList;
import com.marand.maf.core.StringUtils;
import com.marand.thinkmed.api.externals.data.object.NamedExternalDto;
import com.marand.thinkmed.medications.TaskTypeEnum;
import com.marand.thinkmed.medications.administration.AdministrationTaskConverter;
import com.marand.thinkmed.medications.connector.data.object.PatientDisplayWithLocationDto;
import com.marand.thinkmed.medications.dto.administration.AdministrationPatientTaskDto;
import com.marand.thinkmed.medications.dto.administration.AdministrationTaskDto;
import com.marand.thinkmed.medications.dto.allergies.CheckNewAllergiesTaskDto;
import com.marand.thinkmed.medications.dto.mentalHealth.CheckMentalHealthMedsTaskDto;
import com.marand.thinkmed.medications.dto.task.TherapyTaskSimpleDto;
import com.marand.thinkmed.medications.task.AdministrationTaskDef;
import com.marand.thinkmed.medications.task.CheckMentalHealthMedsTaskDef;
import com.marand.thinkmed.medications.task.CheckNewAllergiesTaskDef;
import com.marand.thinkmed.medications.task.DoctorReviewTaskDef;
import com.marand.thinkmed.medications.task.MedicationsTasksProvider;
import com.marand.thinkmed.medications.task.PerfusionSyringeCompletePreparationTaskDef;
import com.marand.thinkmed.medications.task.PerfusionSyringeDispenseMedicationTaskDef;
import com.marand.thinkmed.medications.task.PerfusionSyringeStartPreparationTaskDef;
import com.marand.thinkmed.medications.task.SupplyReminderTaskDef;
import com.marand.thinkmed.medications.task.SupplyReviewTaskDef;
import com.marand.thinkmed.medications.task.SwitchToOralTaskDef;
import com.marand.thinkmed.medications.task.TherapyTaskDef;
import com.marand.thinkmed.process.dto.AbstractTaskDto;
import com.marand.thinkmed.process.dto.TaskDetailsEnum;
import com.marand.thinkmed.process.dto.TaskDto;
import com.marand.thinkmed.process.service.ProcessService;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.springframework.beans.factory.annotation.Required;

/**
 * @author Mitja Lapajne
 */
public class MedicationsTasksProviderImpl implements MedicationsTasksProvider {
    private ProcessService processService;
    private AdministrationTaskConverter administrationTaskConverter;

    @Required
    public void setProcessService(final ProcessService processService) {
        this.processService = processService;
    }

    @Required
    public void setAdministrationTaskConverter(final AdministrationTaskConverter administrationTaskConverter) {
        this.administrationTaskConverter = administrationTaskConverter;
    }

    @Override
    public List<AdministrationTaskDto> findAdministrationTasks(final String patientId,
            final Collection<String> therapyIds, final Interval searchInterval, final boolean findHistoric) {
        if (therapyIds.isEmpty()) {
            return new ArrayList<>();
        }
        final List<TaskDto> tasks = findAdministrationTasks(
                Collections.singletonList(AdministrationTaskDef.getTaskTypeEnum().buildKey(patientId)), therapyIds,
                searchInterval != null ? searchInterval.getStart() : null,
                searchInterval != null ? searchInterval.getEnd() : null, null, findHistoric);

        return tasks.stream().map(task -> administrationTaskConverter.convertTaskToAdministrationTask(task))
                .collect(Collectors.toList());
    }

    @Override
    public List<TaskDto> findAdministrationTasks(final String patientId, final Collection<String> therapyIds,
            final DateTime taskDueAfter, final DateTime taskDueBefore, final String groupUUId,
            final boolean findHistoric) {
        final List<String> taskKeys = Collections
                .singletonList(AdministrationTaskDef.getTaskTypeEnum().buildKey(patientId));
        return findAdministrationTasks(taskKeys, therapyIds, taskDueAfter, taskDueBefore, groupUUId, findHistoric);
    }

    @Override
    public AdministrationTaskDto getAdministrationTask(@Nonnull final String taskId) {
        return Opt.of(processService.loadTask(taskId, false))
                .map(administrationTaskConverter::convertTaskToAdministrationTask)
                .orElseThrow(() -> new IllegalStateException("task " + taskId + " not found!"));
    }

    @Override
    public List<TaskDto> findAdministrationTasks(final Set<String> patientIds, final DateTime taskDueAfter,
            final DateTime taskDueBefore) {
        final List<String> taskKeys = patientIds.stream()
                .map(patientId -> AdministrationTaskDef.getTaskTypeEnum().buildKey(patientId))
                .collect(Collectors.toList());

        return findAdministrationTasks(taskKeys, null, taskDueAfter, taskDueBefore, null, false);
    }

    private List<TaskDto> findAdministrationTasks(final List<String> taskKeys, final Collection<String> therapyIds,
            final DateTime taskDueAfter, final DateTime taskDueBefore, final String groupUUId,
            final boolean findHistorical) {
        if (taskKeys.isEmpty()) {
            return Collections.emptyList();
        }

        final List<TaskDto> allTasks = processService.findTasks(null, null, null, findHistorical, taskDueAfter,
                taskDueBefore, taskKeys, EnumSet.of(TaskDetailsEnum.VARIABLES));

        return allTasks.stream().filter(task -> !findHistorical || !task.isDeleted())
                .filter(task -> groupUUId == null
                        || groupUUId.equals(task.getVariables().get(AdministrationTaskDef.GROUP_UUID.getName())))
                .filter(task -> therapyIds == null || therapyIds
                        .contains((String) task.getVariables().get(AdministrationTaskDef.THERAPY_ID.getName())))
                .collect(Collectors.toList());
    }

    @Override
    public TaskDto getNextAdministrationTask(final String patientId, final DateTime fromWhen) {
        final List<TaskDto> tasks = findAdministrationTasks(patientId, null, fromWhen, null, null, false);

        TaskDto nextTask = null;
        for (final TaskDto task : tasks) {
            if (task.getDueTime().isAfter(fromWhen)) {
                if (nextTask == null || task.getDueTime().isBefore(nextTask.getDueTime())) {
                    nextTask = task;
                }
            }
        }
        return nextTask;
    }

    @Override
    public Opt<AdministrationTaskDto> findLastAdministrationTaskForTherapy(@Nonnull final String patientId,
            @Nonnull final String therapyId, final Interval searchInterval, final boolean findHistoric) {
        Preconditions.checkNotNull(patientId, "patientId must not be null!");
        Preconditions.checkNotNull(therapyId, "therapyId must not be null!");

        return findLastTaskForTherapy(patientId, therapyId, searchInterval, findHistoric)
                .map(task -> administrationTaskConverter.convertTaskToAdministrationTask(task));
    }

    private Opt<TaskDto> findLastTaskForTherapy(final String patientId, final String therapyId,
            final Interval searchInterval, final boolean findHistoric) {
        final List<TaskDto> tasks = findAdministrationTasks(
                Collections.singletonList(AdministrationTaskDef.getTaskTypeEnum().buildKey(patientId)),
                Collections.singletonList(therapyId), searchInterval != null ? searchInterval.getStart() : null,
                searchInterval != null ? searchInterval.getEnd() : null, null, findHistoric);

        return Opt.from(tasks.stream().max(Comparator.comparing(TaskDto::getDueTime)));
    }

    @Override
    public Opt<DateTime> findLastAdministrationTaskTimeForTherapy(@Nonnull final String patientId,
            @Nonnull final String therapyId, final Interval searchInterval, final boolean findHistoric) {
        Preconditions.checkNotNull(patientId, "patientId must not be null!");
        Preconditions.checkNotNull(therapyId, "therapyId must not be null!");

        return findLastTaskForTherapy(patientId, therapyId, searchInterval, findHistoric)
                .map(AbstractTaskDto::getDueTime);
    }

    @Override
    public Map<String, DateTime> findLastAdministrationTaskTimesForTherapies(final Collection<String> patientIds,
            final DateTime fromTime, final boolean findHistoric) {
        final List<String> taskKeys = patientIds.stream()
                .map(patientId -> AdministrationTaskDef.getTaskTypeEnum().buildKey(patientId))
                .collect(Collectors.toList());

        final List<TaskDto> administrationTasks = findAdministrationTasks(taskKeys, null, fromTime, null, null,
                findHistoric);

        final Map<String, DateTime> therapyLastAdministrationTaskTimestampMap = new HashMap<>();
        //noinspection Convert2streamapi
        for (final TaskDto taskDto : administrationTasks) {
            final String taskTherapyId = (String) taskDto.getVariables()
                    .get(AdministrationTaskDef.THERAPY_ID.getName());
            final DateTime taskDueTime = taskDto.getDueTime();
            if (therapyLastAdministrationTaskTimestampMap.containsKey(taskTherapyId)) {
                if (taskDueTime.isAfter(therapyLastAdministrationTaskTimestampMap.get(taskTherapyId))) {
                    therapyLastAdministrationTaskTimestampMap.put(taskTherapyId, taskDueTime);
                }
            } else {
                therapyLastAdministrationTaskTimestampMap.put(taskTherapyId, taskDueTime);
            }
        }

        return therapyLastAdministrationTaskTimestampMap;
    }

    @Override
    public Map<String, List<TherapyTaskSimpleDto>> findSimpleTasksForTherapies(final String patientId,
            final Collection<String> therapyIds, final DateTime when) {
        final List<String> taskKeys = new ArrayList<>();
        taskKeys.add(DoctorReviewTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));
        taskKeys.add(SwitchToOralTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));
        taskKeys.add(SupplyReviewTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));
        taskKeys.add(SupplyReminderTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));
        taskKeys.add(PerfusionSyringeStartPreparationTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));
        taskKeys.add(
                PerfusionSyringeCompletePreparationTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));
        taskKeys.add(
                PerfusionSyringeDispenseMedicationTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId)));

        final Map<String, TaskDto> doctorReviewTasks = new HashMap<>();
        final Map<String, TaskDto> switchToOralTasks = new HashMap<>();
        final Map<String, TaskDto> supplyReviewTasks = new HashMap<>();
        final Map<String, TaskDto> supplyReminderTasks = new HashMap<>();
        final Map<String, TaskDto> perfusionSyringeTasks = new HashMap<>();

        final PartialList<TaskDto> tasks = processService.findTasks(null, null, null, false, null, null, taskKeys,
                EnumSet.of(TaskDetailsEnum.VARIABLES));

        if (tasks != null) {
            for (final TaskDto task : tasks) {
                final String therapyId = (String) task.getVariables()
                        .get(TherapyTaskDef.ORIGINAL_THERAPY_ID.getName());
                if (task.getTaskExecutionStrategyId().equals(TaskTypeEnum.DOCTOR_REVIEW.getName())) {
                    //don't show future tasks
                    if (!task.getDueTime().withTimeAtStartOfDay().isAfter(when.withTimeAtStartOfDay())) {
                        doctorReviewTasks.put(therapyId, task);
                    }
                } else if (task.getTaskExecutionStrategyId().equals(TaskTypeEnum.SWITCH_TO_ORAL.getName())) {
                    //don't show future tasks
                    if (!task.getDueTime().withTimeAtStartOfDay().isAfter(when.withTimeAtStartOfDay())) {
                        switchToOralTasks.put(therapyId, task);
                    }
                } else if (task.getTaskExecutionStrategyId().equals(TaskTypeEnum.SUPPLY_REVIEW.getName())) {
                    supplyReviewTasks.put(therapyId, task);
                } else if (task.getTaskExecutionStrategyId().equals(TaskTypeEnum.SUPPLY_REMINDER.getName())) {
                    final Boolean isDismissed = (Boolean) task.getVariables()
                            .get(SupplyReminderTaskDef.IS_DISMISSED.getName());
                    if (isDismissed == null || !isDismissed) {
                        supplyReminderTasks.put(therapyId, task);
                    }
                } else if (task.getTaskExecutionStrategyId().equals(TaskTypeEnum.PERFUSION_SYRINGE_START.getName())
                        || task.getTaskExecutionStrategyId()
                                .equals(TaskTypeEnum.PERFUSION_SYRINGE_COMPLETE.getName())
                        || task.getTaskExecutionStrategyId()
                                .equals(TaskTypeEnum.PERFUSION_SYRINGE_DISPENSE.getName())) {
                    perfusionSyringeTasks.put(therapyId, task);
                }
            }
        }

        final Map<String, List<TherapyTaskSimpleDto>> tasksMap = new HashMap<>();
        for (final String therapyId : therapyIds) {
            tasksMap.put(therapyId, new ArrayList<>());

            if (doctorReviewTasks.containsKey(therapyId)) {
                final TherapyTaskSimpleDto doctorReviewTask = buildTherapyTaskSimpleDto(
                        doctorReviewTasks.get(therapyId), TaskTypeEnum.DOCTOR_REVIEW);
                tasksMap.get(therapyId).add(doctorReviewTask);
            }
            if (switchToOralTasks.containsKey(therapyId)) {
                final TherapyTaskSimpleDto switchToOralTask = buildTherapyTaskSimpleDto(
                        switchToOralTasks.get(therapyId), TaskTypeEnum.SWITCH_TO_ORAL);
                tasksMap.get(therapyId).add(switchToOralTask);
            }
            if (supplyReviewTasks.containsKey(therapyId)) {
                final TherapyTaskSimpleDto supplyReviewTask = buildTherapyTaskSimpleDto(
                        supplyReviewTasks.get(therapyId), TaskTypeEnum.SUPPLY_REVIEW);
                tasksMap.get(therapyId).add(supplyReviewTask);
            }
            if (supplyReminderTasks.containsKey(therapyId)) {
                final TherapyTaskSimpleDto supplyReminderTask = buildTherapyTaskSimpleDto(
                        supplyReminderTasks.get(therapyId), TaskTypeEnum.SUPPLY_REMINDER);
                tasksMap.get(therapyId).add(supplyReminderTask);
            }
            if (perfusionSyringeTasks.containsKey(therapyId)) {
                final TaskDto perfusionSyringeTaskDto = perfusionSyringeTasks.get(therapyId);
                final TherapyTaskSimpleDto perfusionSyringeTaskSimple = buildTherapyTaskSimpleDto(
                        perfusionSyringeTasks.get(therapyId),
                        TaskTypeEnum.getByName(perfusionSyringeTaskDto.getTaskExecutionStrategyId()));
                tasksMap.get(therapyId).add(perfusionSyringeTaskSimple);
            }
        }
        return tasksMap;
    }

    private TherapyTaskSimpleDto buildTherapyTaskSimpleDto(final TaskDto taskDto, final TaskTypeEnum taskType) {
        final TherapyTaskSimpleDto simpleTaskDto = new TherapyTaskSimpleDto();
        simpleTaskDto.setId(taskDto.getId());
        simpleTaskDto.setDueTime(taskDto.getDueTime());
        simpleTaskDto.setTaskType(taskType);
        return simpleTaskDto;
    }

    @Override
    public List<AdministrationPatientTaskDto> findAdministrationTasks(
            final Map<String, PatientDisplayWithLocationDto> patientWithLocationMap, final Interval searchInterval,
            final int maxNumberOfTasks, final Locale locale, final DateTime when) {
        final List<TaskDto> tasks = findAdministrationTasks(patientWithLocationMap.keySet(),
                searchInterval.getStart(), searchInterval.getEnd());

        Collections.sort(tasks, (task1, task2) -> task1.getDueTime().compareTo(task2.getDueTime()));

        final List<TaskDto> filteredTasks = tasks.size() > maxNumberOfTasks ? tasks.subList(0, maxNumberOfTasks)
                : tasks;

        final List<AdministrationPatientTaskDto> list = administrationTaskConverter
                .convertTasksToAdministrationPatientTasks(filteredTasks, patientWithLocationMap, locale, when);

        Collections.sort(list, (task1, task2) -> task1.getPlannedTime().compareTo(task2.getPlannedTime()));

        return list;
    }

    @Override
    public List<CheckNewAllergiesTaskDto> findNewAllergiesTasks(@Nonnull final String patientId) {
        StringUtils.checkNotBlank(patientId, "patientId must be defined");

        final PartialList<TaskDto> tasks = processService.findTasks(null, null, null, false, null, null,
                Collections.singletonList(
                        CheckNewAllergiesTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId))),
                EnumSet.of(TaskDetailsEnum.VARIABLES));

        return tasks.stream().map(t -> new CheckNewAllergiesTaskDto(t.getId(), getAllergiesFromTask(t)))
                .collect(Collectors.toList());
    }

    @Override
    public List<CheckMentalHealthMedsTaskDto> findNewCheckMentalHealthMedsTasks(@Nonnull final String patientId) {
        StringUtils.checkNotBlank(patientId, "patientId must be defined");

        final PartialList<TaskDto> tasks = processService.findTasks(null, null, null, false, null, null,
                Collections.singletonList(
                        CheckMentalHealthMedsTaskDef.getTaskTypeEnum().buildKey(String.valueOf(patientId))),
                EnumSet.of(TaskDetailsEnum.VARIABLES));

        return tasks.stream().map(t -> new CheckMentalHealthMedsTaskDto(t.getId())).collect(Collectors.toList());
    }

    private Set<NamedExternalDto> getAllergiesFromTask(final TaskDto task) {
        return Sets.newHashSet(JsonUtil.fromJson(
                (String) task.getVariables().get(CheckNewAllergiesTaskDef.NEW_ALLERGIES.getName()),
                NamedExternalDto[].class));
    }
}