/* * Copyright (c) 2014. The Trustees of Indiana University. * * This version of the code is licensed under the MPL 2.0 Open Source license with additional * healthcare disclaimer. If the user is an entity intending to commercialize any application * that uses this code in a for-profit venture, please contact the copyright holder. */ package com.muzima.controller; import com.muzima.api.model.Concept; import com.muzima.api.model.Encounter; import com.muzima.api.model.LastSyncTime; import com.muzima.api.model.Location; import com.muzima.api.model.Observation; import com.muzima.api.model.Person; import com.muzima.api.model.PersonName; import com.muzima.api.service.ConceptService; import com.muzima.api.service.EncounterService; import com.muzima.api.service.LastSyncTimeService; import com.muzima.api.service.ObservationService; import com.muzima.model.observation.Concepts; import com.muzima.model.observation.Encounters; import com.muzima.service.SntpService; import com.muzima.utils.CustomColor; import com.muzima.utils.StringUtils; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import static com.muzima.api.model.APIName.DOWNLOAD_OBSERVATIONS; import static com.muzima.util.Constants.UUID_SEPARATOR; import static com.muzima.util.Constants.UUID_TYPE_SEPARATOR; import static java.util.Arrays.asList; public class ObservationController { private ObservationService observationService; private ConceptService conceptService; private EncounterService encounterService; private LastSyncTimeService lastSyncTimeService; private SntpService sntpService; private Map<String, Integer> conceptColors; public ObservationController(ObservationService observationService, ConceptService conceptService, EncounterService encounterService, LastSyncTimeService lastSyncTimeService, SntpService sntpService) { this.observationService = observationService; this.conceptService = conceptService; this.encounterService = encounterService; this.lastSyncTimeService = lastSyncTimeService; this.sntpService = sntpService; conceptColors = new HashMap<String, Integer>(); } public Concepts getConceptWithObservations(String patientUuid) throws LoadObservationException { try { return groupByConcepts(observationService.getObservationsByPatient(patientUuid)); } catch (IOException e) { throw new LoadObservationException(e); } } public Concepts getConceptWithObservations(String patientUuid, String conceptUuid ) throws LoadObservationException { try { return groupByConcepts(observationService.getObservationsByPatientAndConcept(patientUuid, conceptUuid)); } catch (IOException e) { throw new LoadObservationException(e); } } public int getObservationsCountByPatient(String patientUuid) throws IOException { return observationService.countObservationsByPatient(patientUuid); } private void inflateConcepts(List<Observation> observationsByPatient) throws IOException { Map<String, Concept> conceptCache = new HashMap<String, Concept>(); for (Observation observation : observationsByPatient) { Concept concept = observation.getConcept(); String conceptUuid = concept.getUuid(); if (!conceptCache.containsKey(conceptUuid)) { Concept conceptByUuid = conceptService.getConceptByUuid(conceptUuid); conceptCache.put(conceptUuid, conceptByUuid); } observation.setConcept(conceptCache.get(conceptUuid)); } } private void inflateEncounters(List<Observation> observationsByPatient) throws IOException { Map<String, Encounter> encounterCache = new HashMap<String, Encounter>(); encounterCache.put(null, getEncounterForNullEncounterUuid()); for (Observation observation : observationsByPatient) { Encounter encounter = observation.getEncounter(); String encounterUuid = encounter.getUuid(); if (!encounterCache.containsKey(encounterUuid)) { Encounter fullEncounter = encounterService.getEncounterByUuid(encounterUuid); encounterCache.put(encounterUuid, fullEncounter); } observation.setEncounter(encounterCache.get(encounterUuid)); } } private Encounter getEncounterForNullEncounterUuid() { final Person person = new Person(); person.addName(new PersonName()); final Location location = new Location(); location.setName(""); return new Encounter(){{ setProvider(person); setLocation(location); }}; } public int getConceptColor(String uuid) { if (!conceptColors.containsKey(uuid)) { conceptColors.put(uuid, CustomColor.getOrderedColor(conceptColors.size())); } return conceptColors.get(uuid); } public void replaceObservations(List<Observation> allObservations) throws ReplaceObservationException { try { observationService.updateObservations(allObservations); } catch (IOException e) { throw new ReplaceObservationException(e); } } public Concepts searchObservationsGroupedByConcepts(String term, String patientUuid) throws LoadObservationException { try { return groupByConcepts(observationService.searchObservations(patientUuid, term)); } catch (IOException e) { throw new LoadObservationException(e); } } private Concepts groupByConcepts(List<Observation> observations) throws IOException { inflateConcepts(observations); return new Concepts(observations); } public Encounters getEncountersWithObservations(String patientUuid) throws LoadObservationException { try { return groupByEncounters(observationService.getObservationsByPatient(patientUuid)); } catch (IOException e) { throw new LoadObservationException(e); } } public Encounters getObservationsByEncounterUuid(String encounterUuid) throws LoadObservationException { try { return groupByEncounters(observationService.getObservationsByEncounter(encounterUuid)); } catch (IOException e) { throw new LoadObservationException(e); } } public List<Observation> getObservationsByPatient(String patientUuid) throws LoadObservationException{ try { List<Observation> observations = observationService.getObservationsByPatient(patientUuid); inflateConcepts(observations); return observations; } catch (IOException e) { throw new LoadObservationException(e); } } private Encounters groupByEncounters(List<Observation> observationsByPatient) throws IOException { inflateConcepts(observationsByPatient); inflateEncounters(observationsByPatient); return new Encounters(observationsByPatient); } public Encounters searchObservationsGroupedByEncounter(String term, String patientUuid) throws LoadObservationException { try { return groupByEncounters(observationService.searchObservations(patientUuid, term)); } catch (IOException e) { throw new LoadObservationException(e); } } public List<Observation> downloadObservationsByPatientUuidsAndConceptUuids(List<String> patientUuids, List<String> conceptUuids) throws DownloadObservationException { try { List<String> allConceptsUuids = conceptUuids; List<String> allPatientsUuids = patientUuids; String paramSignature = buildParamSignature(allPatientsUuids, allConceptsUuids); Date lastSyncTime = lastSyncTimeService.getLastSyncTimeFor(DOWNLOAD_OBSERVATIONS, paramSignature); List<Observation> observations = new ArrayList<Observation>(); if (hasExactCallBeenMadeBefore(lastSyncTime)) { observations.addAll(observationService.downloadObservations(patientUuids, conceptUuids, lastSyncTime)); } else { observations.addAll(observationService.downloadObservations(patientUuids, conceptUuids, null)); //ToDo: Revise this while working on Obs Delta download /* LastSyncTime fullLastSyncTimeInfo = lastSyncTimeService.getFullLastSyncTimeInfoFor(DOWNLOAD_OBSERVATIONS); if (isFirstCallToDownloadObservationsEver(fullLastSyncTimeInfo)) { observations.addAll(observationService.downloadObservations(patientUuids, conceptUuids, null)); } else { String[] parameterSplit = fullLastSyncTimeInfo.getParamSignature().split(UUID_TYPE_SEPARATOR, -1); List<String> knownPatientsUuid = asList(parameterSplit[0].split(UUID_SEPARATOR)); List<String> newPatientsUuids = getNewUuids(patientUuids, knownPatientsUuid); List<String> knownConceptsUuid = asList(parameterSplit[1].split(UUID_SEPARATOR)); List<String> newConceptsUuids = getNewUuids(conceptUuids, knownConceptsUuid); allConceptsUuids = getAllUuids(knownConceptsUuid, newConceptsUuids); allPatientsUuids = getAllUuids(knownPatientsUuid, newPatientsUuids); paramSignature = buildParamSignature(allPatientsUuids, allConceptsUuids); if(newPatientsUuids.size()!=0) { observations = observationService.downloadObservations(newPatientsUuids, allConceptsUuids, null); observations.addAll(observationService.downloadObservations(knownPatientsUuid, newConceptsUuids, null)); observations.addAll(observationService.downloadObservations(knownPatientsUuid, knownConceptsUuid, fullLastSyncTimeInfo.getLastSyncDate())); } else{ observations.addAll(observationService.downloadObservations(patientUuids, conceptUuids, null)); } }*/ } LastSyncTime newLastSyncTime = new LastSyncTime(DOWNLOAD_OBSERVATIONS, sntpService.getLocalTime(), paramSignature); lastSyncTimeService.saveLastSyncTime(newLastSyncTime); return observations; } catch (IOException e) { throw new DownloadObservationException(e); } } private ArrayList<String> getAllUuids(List<String> knownUuids, List<String> newUuids) { HashSet<String> allUuids = new HashSet<String>(knownUuids); allUuids.addAll(newUuids); ArrayList<String> sortedUuids = new ArrayList<String>(allUuids); Collections.sort(sortedUuids); return sortedUuids; } private List<String> getNewUuids(List<String> patientUuids, List<String> knownPatientsUuid) { List<String> newPatientsUuids = new ArrayList<String>(); newPatientsUuids.addAll(patientUuids); newPatientsUuids.removeAll(knownPatientsUuid); return newPatientsUuids; } private boolean isFirstCallToDownloadObservationsEver(LastSyncTime fullLastSyncTimeInfo) { return fullLastSyncTimeInfo == null; } private boolean hasExactCallBeenMadeBefore(Date lastSyncTime) { return lastSyncTime != null; } private String buildParamSignature(List<String> patientUuids, List<String> conceptUuids) { String paramSignature = StringUtils.getCommaSeparatedStringFromList(patientUuids); paramSignature += UUID_TYPE_SEPARATOR; paramSignature += StringUtils.getCommaSeparatedStringFromList(conceptUuids); return paramSignature; } public void saveObservations(List<Observation> observations) throws SaveObservationException { try { observationService.saveObservations(observations); } catch (IOException e) { throw new SaveObservationException(e); } } public void deleteObservations(List<Observation> observations) throws DeleteObservationException { try { observationService.deleteObservations(observations); } catch (IOException e) { throw new DeleteObservationException(e); } } public void deleteAllObservations(List<Concept> concepts) throws DeleteObservationException { try { observationService.deleteObservations(getObservations(concepts)); } catch (IOException e) { throw new DeleteObservationException(e); } } public List<Observation> getObservations(List<Concept> concepts) throws IOException { ArrayList<Observation> observations = new ArrayList<Observation>(); for (Concept concept : concepts) { observations.addAll(observationService.getObservations(concept)); } return observations; } public static class LoadObservationException extends Throwable { public LoadObservationException(Throwable e) { super(e); } } public static class ReplaceObservationException extends Throwable { public ReplaceObservationException(Throwable e) { super(e); } } public static class DownloadObservationException extends Throwable { public DownloadObservationException(Throwable e) { super(e); } } public static class SaveObservationException extends Throwable { public SaveObservationException(Throwable e) { super(e); } } public static class DeleteObservationException extends Throwable { public DeleteObservationException(Throwable e) { super(e); } } public static class ParseObservationException extends Throwable { public ParseObservationException(Throwable e) { super(e); } public ParseObservationException(String message) { super(message); } } }