Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
petmongrels authored and 1t5j0y committed Apr 15, 2024
1 parent 73689ec commit dddd2fa
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,6 @@ default Concept findByUuid(String uuid) {
@Query("select c.name from Concept c where c.isVoided = false")
List<String> getAllNames();
List<Concept> getAllConceptByUuidIn(List<String> uuid);
List<Concept> getAllConceptByNameIn(List<String> names);

@Query(value = "SELECT DISTINCT c.uuid, c.name, c.data_type\n" +
" FROM concept c\n" +
" INNER JOIN (\n" +
" SELECT unnest(ARRAY [to_jsonb(key), value]) conecpt_uuid\n" +
" FROM jsonb_each(cast( :observations as jsonb))\n" +
" ) obs ON obs.conecpt_uuid @> to_jsonb(c.uuid)", nativeQuery = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
List<Map<String, String>> getConceptUuidToNameMapList(String observations);

default List<ConceptNameUuidAndDatatype> findAllConceptsInObs(String observations) {
return getConceptUuidToNameMapList(observations)
.stream()
.map(resultMap -> new ConceptNameUuidAndDatatype(resultMap.get("uuid"), resultMap.get("name"), ConceptDataType.valueOf(resultMap.get("data_type"))))
.collect(Collectors.toList());
}

Page<Concept> findAllByUuidIn(String [] uuids, Pageable pageable);
List<Concept> findAllByUuidInAndDataTypeIn(String[] uuids, String[] dataTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
import org.avni.server.web.request.ReferenceDataContract;
import org.avni.server.web.request.application.ConceptUsageContract;
import org.avni.server.web.request.application.FormUsageContract;
import org.avni.server.web.response.ConceptNameUuidAndDatatype;
import org.avni.server.web.response.Response;
import org.avni.server.web.validation.ValidationException;
import org.joda.time.DateTime;
import org.joda.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -114,7 +112,7 @@ private ConceptAnswer fetchOrCreateConceptAnswer(Concept concept, ConceptContrac
return conceptAnswer;
}

private Concept createCodedConcept(Concept concept, ConceptContract conceptRequest) throws AnswerConceptNotFoundException {
private void createCodedConcept(Concept concept, ConceptContract conceptRequest) throws AnswerConceptNotFoundException {
List<ConceptContract> answers = (List<ConceptContract>) O.coalesce(conceptRequest.getAnswers(), new ArrayList<>());
AtomicInteger index = new AtomicInteger(0);
List<ConceptAnswer> conceptAnswers = new ArrayList<>();
Expand All @@ -123,7 +121,6 @@ private Concept createCodedConcept(Concept concept, ConceptContract conceptReque
conceptAnswers.add(conceptAnswer);
}
concept.addAll(conceptAnswers);
return concept;
}

private Concept createNumericConcept(Concept concept, ConceptContract conceptRequest) {
Expand Down Expand Up @@ -155,10 +152,10 @@ private Concept map(@NotNull ConceptContract conceptRequest) throws AnswerConcep
concept.updateAudit();
switch (ConceptDataType.valueOf(impliedDataType)) {
case Coded:
concept = createCodedConcept(concept, conceptRequest);
createCodedConcept(concept, conceptRequest);
break;
case Numeric:
concept = createNumericConcept(concept, conceptRequest);
createNumericConcept(concept, conceptRequest);
break;
}
return concept;
Expand Down Expand Up @@ -251,31 +248,32 @@ public ConceptAnswer getAnswer(String conceptUUID, String conceptAnswerUUID) {
/**
* Important: Not to be used in any Internal API calls
*/
public Object getObservationValue(ConceptNameUuidAndDatatype concept, Map<String, ConceptNameUuidAndDatatype> conceptMap, Object value) {
if (concept.getConceptDataType().equals(ConceptDataType.Date)) {
public Object getObservationValue(Concept questionConcept, Object value) {
if (questionConcept.getDataType().equals(ConceptDataType.Date.toString())) {
return ApiRequestContextHolder.isVersionGreaterThan(1)? DateTimeUtil.toDateString((String) value): value;
}

if (Arrays.asList(ConceptDataType.Audio, ConceptDataType.Id, ConceptDataType.Encounter, ConceptDataType.DateTime,
ConceptDataType.Duration, ConceptDataType.File, ConceptDataType.GroupAffiliation, ConceptDataType.Image,
ConceptDataType.NA, ConceptDataType.Notes, ConceptDataType.Numeric, ConceptDataType.PhoneNumber,
ConceptDataType.Subject, ConceptDataType.Text, ConceptDataType.Time, ConceptDataType.Video)
.contains(concept.getConceptDataType())) {
.contains(ConceptDataType.valueOf(questionConcept.getDataType()))) {
return value;
}

if (value instanceof ArrayList) {
List<Object> elements = (List<Object>) value;
return elements.stream().map(element -> {
if (element != null && element instanceof String) { // Multicoded concept
return getNameWithDefaultValue(matchingConcept(conceptMap, element), element);
} else if (element != null && element instanceof HashMap) { // Repeatable question group
List<Object> answerElements = (List<Object>) value;
return answerElements.stream().map(answersItem -> {
if (answersItem instanceof String) { // Multi coded concept
Concept answerConcept = conceptRepository.findByUuid((String) answersItem);
return getNameWithDefaultValue(answerConcept, answersItem);
} else if (answersItem instanceof HashMap) { // Repeatable question group
LinkedHashMap<String, Object> observationResponse = new LinkedHashMap<>();
Response.mapObservations(conceptRepository, this, observationResponse,
new ObservationCollection((HashMap<String, Object>) element));
new ObservationCollection((HashMap<String, Object>) answersItem));
return observationResponse;
} else {
return getNameWithDefaultValue(matchingConcept(conceptMap, element), element);
return answersItem;
}
}).toArray();
}
Expand All @@ -286,19 +284,21 @@ public Object getObservationValue(ConceptNameUuidAndDatatype concept, Map<String
return observationResponse;
}

if (concept.getConceptDataType().equals(ConceptDataType.Location)) {
if (questionConcept.getDataType().equals(ConceptDataType.Location.toString())) {
return checkAndReturnLocationAddress(value);
}

return getNameWithDefaultValue(matchingConcept(conceptMap, value), value);
}
// Should be used single coded values only. Multi-coded handled above based on value
if (value instanceof String && questionConcept.getDataType().equals(ConceptDataType.Coded.toString())) {
Concept answerConcept = conceptRepository.findByUuid((String) value);
return getNameWithDefaultValue(answerConcept, value);
}

private ConceptNameUuidAndDatatype matchingConcept(Map<String, ConceptNameUuidAndDatatype> conceptMap, Object element) {
return conceptMap.get(element);
return value;
}

private Object getNameWithDefaultValue(ConceptNameUuidAndDatatype value, Object defaultValue) {
return value == null ? defaultValue : value.getName();
private Object getNameWithDefaultValue(Concept answerConcept, Object obsRawValue) {
return answerConcept == null ? obsRawValue : answerConcept.getName();
}

private Object checkAndReturnLocationAddress(Object value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.avni.server.web.response;

import org.avni.server.domain.Concept;
import org.avni.server.domain.ConceptDataType;

public class ConceptNameUuidAndDatatype {
Expand All @@ -13,6 +14,10 @@ public ConceptNameUuidAndDatatype(String uuid, String name, ConceptDataType conc
this.conceptDataType = conceptDataType;
}

public ConceptNameUuidAndDatatype(Concept concept) {
this(concept.getUuid(), concept.getName(), ConceptDataType.valueOf(concept.getDataType()));
}

public String getUuid() {
return uuid;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import org.avni.server.dao.ConceptRepository;
import org.avni.server.domain.CHSBaseEntity;
import org.avni.server.domain.CHSEntity;
import org.avni.server.domain.ObservationCollection;
import org.avni.server.domain.*;
import org.avni.server.service.ConceptService;
import org.avni.server.util.ObjectMapperSingleton;

Expand All @@ -24,15 +22,10 @@ public static void putObservations(ConceptRepository conceptRepository, ConceptS

public static void mapObservations(ConceptRepository conceptRepository, ConceptService conceptService, Map<String, Object> observationsResponse, ObservationCollection observations) {
ObservationCollection obs = Optional.ofNullable(observations).orElse(new ObservationCollection());
String stringObservations;
try {
stringObservations = ObjectMapperSingleton.getObjectMapper().writeValueAsString(obs);
} catch (JsonProcessingException e) {
throw new RuntimeException(String.format("Error while processing observation %s", obs.toString()));
}
List<ConceptNameUuidAndDatatype> conceptMaps = conceptRepository.findAllConceptsInObs(stringObservations);
Map<String, ConceptNameUuidAndDatatype> conceptMap = conceptMaps.stream().collect(Collectors.toMap(s -> s.getUuid(), s -> s));
obs.forEach((key, value) -> observationsResponse.put(conceptMap.get(key).getName(), conceptService.getObservationValue(conceptMap.get(key), conceptMap, value)));
obs.forEach((key, value) -> {
Concept concept = conceptRepository.findByUuid(key);
observationsResponse.put(concept.getName(), conceptService.getObservationValue(concept, value));
});
}

static void putObservations(ConceptRepository conceptRepository, ConceptService conceptService, Map<String, Object> parentMap, LinkedHashMap<String, Object> observationsResponse, ObservationCollection observations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,37 +54,4 @@ public void shouldNotAlterExistingObsWhenPassedEmptyObservations() throws Except
assertThat(observations.size(), is(1));
assertThat(observations.get("First Name"), is("Test"));
}

@Test()
public void shouldAddObservationsWhenPassedObsAreNotEmpty() {
String questionConceptName = "ABC";
String answerValue = "XYZ";
LinkedHashMap<String, Object> parentMap = new LinkedHashMap<>();
LinkedHashMap<String, Object> observationsResponse = new LinkedHashMap<>();
observationsResponse.put("First Name", "Test");
ObservationCollection observations = new ObservationCollection();
String questionConceptUuid = "55f3e0cc-a9bc-45d6-a42c-a4fd3d90465f";
String answerConceptUuid = "a33da2f8-7329-4e2a-8c27-046ee4082524";
Concept questionConcept = new Concept();
questionConcept.setName(questionConceptName);
Concept answerConcept = new Concept();
answerConcept.setUuid(answerConceptUuid);
answerConcept.setName(answerValue);
ConceptAnswer conceptAnswer = new ConceptAnswer();
conceptAnswer.setConcept(answerConcept);
Set<ConceptAnswer> answers = new HashSet<>();
answers.add(conceptAnswer);
questionConcept.setConceptAnswers(answers);
observations.put(questionConceptUuid, answerConceptUuid);
ConceptNameUuidAndDatatype conceptMap1 = new ConceptNameUuidAndDatatype(questionConceptUuid, questionConceptName, ConceptDataType.Coded);
ConceptNameUuidAndDatatype conceptMap2 = new ConceptNameUuidAndDatatype(answerConceptUuid, answerValue, ConceptDataType.NA);
List<ConceptNameUuidAndDatatype> conceptMapList = Arrays.asList(conceptMap1, conceptMap2);
when(conceptRepository.findAllConceptsInObs(anyString())).thenReturn(conceptMapList);
when(conceptService.getObservationValue(any(), anyMap(), anyString())).thenReturn(answerValue);
Response.putObservations(conceptRepository, conceptService, parentMap, observationsResponse, observations);
LinkedHashMap<String, Object> result = (LinkedHashMap<String, Object>) parentMap.get("observations");

assertThat(result.get("First Name"), is("Test"));
assertThat(result.get(questionConceptName), is(answerValue));
}
}
16 changes: 12 additions & 4 deletions makefiles/externalDB.mk
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,15 @@ endif
--exclude-table-data='scheduled_job_run' \
--exclude-table-data='qrtz_*' \
--exclude-table-data='batch_*' \
--exclude-table-data='public.individual_copy' \
--exclude-table-data='public.program_enrolment_copy' \
--exclude-table-data='public.encounter_copy' \
--exclude-table-data='public.program_encounter_copy'
--exclude-table='public.individual_copy' \
--exclude-table='public.program_enrolment_copy' \
--exclude-table='public.encounter_copy' \
--exclude-table='public.program_encounter_copy' \
--exclude-table='public.individual_copy_ck' \
--exclude-table='public.program_enrolment_ck' \
--exclude-table='public.encounter_ck' \
--exclude-table='public.program_encounter_ck' \
--exclude-table='public.individual_copy_ihmp' \
--exclude-table='public.program_enrolment_ihmp' \
--exclude-table-data='public.individual_02_24' \
--exclude-table-data='public.program_enrolment_02_24'

0 comments on commit dddd2fa

Please sign in to comment.