use of de.symeda.sormas.api.caze.CaseIndexDto in project SORMAS-Project by hzi-braunschweig.
the class CaseFacadeEjb method getIndexList.
@Override
public List<CaseIndexDto> getIndexList(CaseCriteria caseCriteria, Integer first, Integer max, List<SortProperty> sortProperties) {
CriteriaQuery<CaseIndexDto> cq = listQueryBuilder.buildIndexCriteria(caseCriteria, sortProperties);
List<CaseIndexDto> cases = QueryHelper.getResultList(em, cq, first, max);
List<Long> caseIds = cases.stream().map(CaseIndexDto::getId).collect(Collectors.toList());
Map<String, ExternalShareInfoCountAndLatestDate> survToolShareCountAndDates = null;
if (externalSurveillanceToolGatewayFacade.isFeatureEnabled()) {
survToolShareCountAndDates = externalShareInfoService.getCaseShareCountAndLatestDate(caseIds).stream().collect(Collectors.toMap(ExternalShareInfoCountAndLatestDate::getAssociatedObjectUuid, Function.identity()));
}
Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight, I18nProperties.getCaption(Captions.inaccessibleValue));
for (CaseIndexDto caze : cases) {
if (survToolShareCountAndDates != null) {
ExternalShareInfoCountAndLatestDate survToolShareCountAndDate = survToolShareCountAndDates.get(caze.getUuid());
if (survToolShareCountAndDate != null) {
caze.setSurveillanceToolShareCount(survToolShareCountAndDate.getCount());
caze.setSurveillanceToolLastShareDate(survToolShareCountAndDate.getLatestDate());
caze.setSurveillanceToolStatus(survToolShareCountAndDate.getLatestStatus());
}
}
Boolean isInJurisdiction = caze.getInJurisdiction();
pseudonymizer.pseudonymizeDto(CaseIndexDto.class, caze, isInJurisdiction, c -> pseudonymizer.pseudonymizeDto(AgeAndBirthDateDto.class, caze.getAgeAndBirthDate(), isInJurisdiction, null));
}
return cases;
}
use of de.symeda.sormas.api.caze.CaseIndexDto in project SORMAS-Project by hzi-braunschweig.
the class CaseService method getCasesForDuplicateMerging.
public List<CaseIndexDto[]> getCasesForDuplicateMerging(CaseCriteria criteria, boolean ignoreRegion, double nameSimilarityThreshold) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<Case> root = cq.from(Case.class);
final CaseQueryContext caseQueryContext = new CaseQueryContext(cb, cq, root);
final CaseJoins<Case> joins = (CaseJoins<Case>) caseQueryContext.getJoins();
Root<Case> root2 = cq.from(Case.class);
Join<Case, Person> person = joins.getPerson();
Join<Case, Person> person2 = root2.join(Case.PERSON, JoinType.LEFT);
Join<Case, Region> responsibleRegion = joins.getResponsibleRegion();
Join<Case, Region> responsibleRegion2 = root2.join(Case.RESPONSIBLE_REGION, JoinType.LEFT);
Join<Case, Region> region = joins.getRegion();
Join<Case, Region> region2 = root2.join(Case.REGION, JoinType.LEFT);
Join<Case, Symptoms> symptoms = joins.getSymptoms();
Join<Case, Symptoms> symptoms2 = root2.join(Case.SYMPTOMS, JoinType.LEFT);
cq.distinct(true);
// similarity:
// * first & last name concatenated with whitespace. Similarity function with default threshold of 0.65D
// uses postgres pg_trgm: https://www.postgresql.org/docs/9.6/pgtrgm.html
// * same disease
// * same region (optional)
// * report date within 30 days of each other
// * same sex or same birth date (when defined)
// * same birth date (when fully defined)
// * onset date within 30 days of each other (when defined)
Predicate userFilter = createUserFilter(cb, cq, root);
Predicate criteriaFilter = criteria != null ? createCriteriaFilter(criteria, caseQueryContext) : null;
Expression<String> nameSimilarityExpr = cb.concat(person.get(Person.FIRST_NAME), " ");
nameSimilarityExpr = cb.concat(nameSimilarityExpr, person.get(Person.LAST_NAME));
Expression<String> nameSimilarityExpr2 = cb.concat(person2.get(Person.FIRST_NAME), " ");
nameSimilarityExpr2 = cb.concat(nameSimilarityExpr2, person2.get(Person.LAST_NAME));
Predicate nameSimilarityFilter = cb.gt(cb.function("similarity", double.class, nameSimilarityExpr, nameSimilarityExpr2), nameSimilarityThreshold);
Predicate diseaseFilter = cb.equal(root.get(Case.DISEASE), root2.get(Case.DISEASE));
Predicate regionFilter = cb.and(cb.equal(responsibleRegion.get(Region.ID), responsibleRegion2.get(Region.ID)), cb.or(cb.and(cb.isNull(region)), cb.equal(region.get(Region.ID), region2.get(Region.ID))));
Predicate reportDateFilter = cb.lessThanOrEqualTo(cb.abs(cb.diff(cb.function("date_part", Long.class, cb.parameter(String.class, "date_type"), root.get(Case.REPORT_DATE)), cb.function("date_part", Long.class, cb.parameter(String.class, "date_type"), root2.get(Case.REPORT_DATE)))), SECONDS_30_DAYS);
// // todo this should use PersonService.buildSimilarityCriteriaFilter
// Sex filter: only when sex is filled in for both cases
Predicate sexFilter = cb.or(cb.or(cb.isNull(person.get(Person.SEX)), cb.isNull(person2.get(Person.SEX))), cb.or(cb.equal(person.get(Person.SEX), Sex.UNKNOWN), cb.equal(person2.get(Person.SEX), Sex.UNKNOWN)), cb.equal(person.get(Person.SEX), person2.get(Person.SEX)));
// Birth date filter: only when birth date is filled in for both cases
Predicate birthDateFilter = cb.or(cb.or(cb.isNull(person.get(Person.BIRTHDATE_DD)), cb.isNull(person.get(Person.BIRTHDATE_MM)), cb.isNull(person.get(Person.BIRTHDATE_YYYY)), cb.isNull(person2.get(Person.BIRTHDATE_DD)), cb.isNull(person2.get(Person.BIRTHDATE_MM)), cb.isNull(person2.get(Person.BIRTHDATE_YYYY))), cb.and(cb.equal(person.get(Person.BIRTHDATE_DD), person2.get(Person.BIRTHDATE_DD)), cb.equal(person.get(Person.BIRTHDATE_MM), person2.get(Person.BIRTHDATE_MM)), cb.equal(person.get(Person.BIRTHDATE_YYYY), person2.get(Person.BIRTHDATE_YYYY))));
// Onset date filter: only when onset date is filled in for both cases
Predicate onsetDateFilter = cb.or(cb.or(cb.isNull(symptoms.get(Symptoms.ONSET_DATE)), cb.isNull(symptoms2.get(Symptoms.ONSET_DATE))), cb.lessThanOrEqualTo(cb.abs(cb.diff(cb.function("date_part", Long.class, cb.parameter(String.class, "date_type"), symptoms.get(Symptoms.ONSET_DATE)), cb.function("date_part", Long.class, cb.parameter(String.class, "date_type"), symptoms2.get(Symptoms.ONSET_DATE)))), SECONDS_30_DAYS));
Predicate creationDateFilter = cb.or(cb.lessThan(root.get(Case.CREATION_DATE), root2.get(Case.CREATION_DATE)), cb.or(cb.lessThanOrEqualTo(root2.get(Case.CREATION_DATE), DateHelper.getStartOfDay(criteria.getCreationDateFrom())), cb.greaterThanOrEqualTo(root2.get(Case.CREATION_DATE), DateHelper.getEndOfDay(criteria.getCreationDateTo()))));
Predicate filter = cb.and(createDefaultFilter(cb, root), createDefaultFilter(cb, root2));
if (userFilter != null) {
filter = cb.and(filter, userFilter);
}
if (filter != null) {
filter = cb.and(filter, criteriaFilter);
} else {
filter = criteriaFilter;
}
if (filter != null) {
filter = cb.and(filter, nameSimilarityFilter);
} else {
filter = nameSimilarityFilter;
}
filter = cb.and(filter, diseaseFilter);
if (!ignoreRegion) {
filter = cb.and(filter, regionFilter);
}
filter = cb.and(filter, reportDateFilter);
filter = cb.and(filter, cb.and(sexFilter, birthDateFilter));
filter = cb.and(filter, onsetDateFilter);
filter = cb.and(filter, creationDateFilter);
filter = cb.and(filter, cb.notEqual(root.get(Case.ID), root2.get(Case.ID)));
cq.where(filter);
cq.multiselect(root.get(Case.ID), root2.get(Case.ID), root.get(Case.CREATION_DATE));
cq.orderBy(cb.desc(root.get(Case.CREATION_DATE)));
List<Object[]> foundIds = em.createQuery(cq).setParameter("date_type", "epoch").getResultList();
List<CaseIndexDto[]> resultList = new ArrayList<>();
if (!foundIds.isEmpty()) {
CriteriaQuery<CaseIndexDto> indexCasesCq = cb.createQuery(CaseIndexDto.class);
Root<Case> indexRoot = indexCasesCq.from(Case.class);
selectIndexDtoFields(new CaseQueryContext(cb, indexCasesCq, indexRoot));
indexCasesCq.where(indexRoot.get(Case.ID).in(foundIds.stream().map(a -> Arrays.copyOf(a, 2)).flatMap(Arrays::stream).collect(Collectors.toSet())));
Map<Long, CaseIndexDto> indexCases = em.createQuery(indexCasesCq).getResultStream().collect(Collectors.toMap(c -> c.getId(), Function.identity()));
for (Object[] idPair : foundIds) {
try {
// Cloning is necessary here to allow us to add the same CaseIndexDto to the grid multiple times
CaseIndexDto parent = (CaseIndexDto) indexCases.get(idPair[0]).clone();
CaseIndexDto child = (CaseIndexDto) indexCases.get(idPair[1]).clone();
if (parent.getCompleteness() == null && child.getCompleteness() == null || parent.getCompleteness() != null && (child.getCompleteness() == null || (parent.getCompleteness() >= child.getCompleteness()))) {
resultList.add(new CaseIndexDto[] { parent, child });
} else {
resultList.add(new CaseIndexDto[] { child, parent });
}
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
return resultList;
}
use of de.symeda.sormas.api.caze.CaseIndexDto in project SORMAS-Project by hzi-braunschweig.
the class CaseFacadeEjbTest method testGetIndexList.
@Test
public void testGetIndexList() {
String districtName = "District";
RDCF rdcf = creator.createRDCF("Region", districtName, "Community", "Facility");
useSurveillanceOfficerLogin(rdcf);
UserDto user = creator.createUser(rdcf.region.getUuid(), rdcf.district.getUuid(), rdcf.facility.getUuid(), "Surv", "Sup", UserRole.SURVEILLANCE_SUPERVISOR);
String lastName = "Person";
PersonDto cazePerson = creator.createPerson("Case", lastName);
creator.createCase(user.toReference(), cazePerson.toReference(), Disease.EVD, CaseClassification.PROBABLE, InvestigationStatus.PENDING, new Date(), rdcf);
creator.createCase(user.toReference(), cazePerson.toReference(), Disease.EVD, CaseClassification.PROBABLE, InvestigationStatus.PENDING, new Date(), rdcf, c -> c.setHealthFacilityDetails("abc"));
creator.createCase(user.toReference(), cazePerson.toReference(), Disease.EVD, CaseClassification.PROBABLE, InvestigationStatus.PENDING, new Date(), rdcf, c -> c.setHealthFacilityDetails("xyz"));
List<CaseIndexDto> results = getCaseFacade().getIndexList(null, 0, 100, Arrays.asList(new SortProperty(CaseIndexDto.DISEASE), new SortProperty(CaseIndexDto.PERSON_FIRST_NAME), new SortProperty(CaseIndexDto.RESPONSIBLE_DISTRICT_NAME), new SortProperty(CaseIndexDto.HEALTH_FACILITY_NAME, false), new SortProperty(CaseIndexDto.SURVEILLANCE_OFFICER_UUID)));
// List should have one entry
assertEquals(3, results.size());
assertEquals(districtName, results.get(0).getResponsibleDistrictName());
assertEquals(lastName, results.get(0).getPersonLastName());
assertEquals("Facility - xyz", results.get(0).getHealthFacilityName());
assertEquals("Facility - abc", results.get(1).getHealthFacilityName());
assertEquals("Facility", results.get(2).getHealthFacilityName());
}
use of de.symeda.sormas.api.caze.CaseIndexDto in project SORMAS-Project by hzi-braunschweig.
the class CaseFacadeEjbTest method testSearchCasesFreetext.
@Test
public void testSearchCasesFreetext() {
RDCF rdcf = creator.createRDCF();
final UserReferenceDto user = creator.createUser(rdcf, UserRole.SURVEILLANCE_OFFICER).toReference();
CaseDataDto caze = creator.createCase(user, creator.createPerson().toReference(), rdcf);
caze.setInternalToken("internalToken");
caze.setExternalToken("externalToken");
caze.setExternalID("externalID");
getCaseFacade().save(caze);
CaseDataDto secondCaze = creator.createCase(user, creator.createPerson().toReference(), rdcf);
secondCaze.setInternalToken("internalToken2");
getCaseFacade().save(secondCaze);
List<CaseIndexDto> indexList = getCaseFacade().getIndexList(new CaseCriteria(), 0, 100, Collections.emptyList());
// test several freetext variations
assertEquals(2, indexList.size());
CaseCriteria caseCriteria = new CaseCriteria();
caseCriteria.setCaseLike("internal");
List<CaseIndexDto> indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertEquals(2, indexListFiltered.size());
caseCriteria.setCaseLike("Token");
indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertEquals(2, indexListFiltered.size());
caseCriteria.setCaseLike("externalToken");
indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertEquals(1, indexListFiltered.size());
assertThat(indexListFiltered.get(0).getUuid(), is(caze.getUuid()));
caseCriteria.setCaseLike("externalID");
indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertEquals(1, indexListFiltered.size());
assertThat(indexListFiltered.get(0).getUuid(), is(caze.getUuid()));
caseCriteria.setCaseLike("unmatchableString");
indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertEquals(0, indexListFiltered.size());
caseCriteria.setCaseLike(caze.getUuid());
indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertEquals(1, indexListFiltered.size());
assertThat(indexListFiltered.get(0).getUuid(), is(caze.getUuid()));
}
use of de.symeda.sormas.api.caze.CaseIndexDto in project SORMAS-Project by hzi-braunschweig.
the class CaseFacadeEjbTest method testSearchCasesWithReducedQuarantine.
@Test
public void testSearchCasesWithReducedQuarantine() {
RDCF rdcf = creator.createRDCF();
CaseDataDto caze = creator.createCase(creator.createUser(rdcf, UserRole.SURVEILLANCE_OFFICER).toReference(), creator.createPerson().toReference(), rdcf);
caze.setQuarantineReduced(true);
getCaseFacade().save(caze);
List<CaseIndexDto> indexList = getCaseFacade().getIndexList(new CaseCriteria(), 0, 100, Collections.emptyList());
assertThat(indexList.get(0).getUuid(), is(caze.getUuid()));
CaseCriteria caseCriteria = new CaseCriteria();
caseCriteria.setWithReducedQuarantine(true);
List<CaseIndexDto> indexListFiltered = getCaseFacade().getIndexList(caseCriteria, 0, 100, Collections.emptyList());
assertThat(indexListFiltered.get(0).getUuid(), is(caze.getUuid()));
}
Aggregations