use of de.symeda.sormas.api.contact.MergeContactIndexDto in project SORMAS-Project by hzi-braunschweig.
the class MergeContactsGrid method calculateCompletenessValues.
@Override
@SuppressWarnings("unchecked")
public void calculateCompletenessValues() {
TreeDataProvider<MergeContactIndexDto> dataProvider = (TreeDataProvider<MergeContactIndexDto>) getDataProvider();
TreeData<MergeContactIndexDto> data = dataProvider.getTreeData();
for (MergeContactIndexDto parent : data.getRootItems()) {
FacadeProvider.getContactFacade().updateCompleteness(parent.getUuid());
FacadeProvider.getContactFacade().updateCompleteness(data.getChildren(parent).get(0).getUuid());
}
reload();
}
use of de.symeda.sormas.api.contact.MergeContactIndexDto in project SORMAS-Project by hzi-braunschweig.
the class MergeContactsGrid method buildColumns.
@Override
protected void buildColumns() {
Column<MergeContactIndexDto, String> diseaseColumn = addColumn(contact -> DiseaseHelper.toString(contact.getDisease(), contact.getDiseaseDetails()));
diseaseColumn.setId(COLUMN_DISEASE);
setColumns(COLUMN_UUID, MergeContactIndexDto.CAZE, COLUMN_DISEASE, MergeContactIndexDto.CONTACT_CLASSIFICATION, MergeContactIndexDto.PERSON_FIRST_NAME, MergeContactIndexDto.PERSON_LAST_NAME, MergeContactIndexDto.AGE_AND_BIRTH_DATE, MergeContactIndexDto.SEX, MergeContactIndexDto.DISTRICT_NAME, MergeContactIndexDto.REPORT_DATE_TIME, MergeContactIndexDto.CREATION_DATE, COLUMN_COMPLETENESS, COLUMN_ACTIONS);
getColumn(COLUMN_ACTIONS).setMinimumWidth(280);
Language userLanguage = I18nProperties.getUserLanguage();
((Column<MergeContactIndexDto, Date>) getColumn(MergeContactIndexDto.REPORT_DATE_TIME)).setRenderer(new DateRenderer(DateHelper.getLocalDateTimeFormat(userLanguage)));
((Column<MergeContactIndexDto, Date>) getColumn(MergeContactIndexDto.CREATION_DATE)).setRenderer(new DateRenderer(DateHelper.getLocalDateTimeFormat(userLanguage)));
((Column<MergeContactIndexDto, AgeAndBirthDateDto>) getColumn(MergeContactIndexDto.AGE_AND_BIRTH_DATE)).setRenderer(value -> value == null ? "" : PersonHelper.getAgeAndBirthdateString(value.getAge(), value.getAgeType(), value.getDateOfBirthDD(), value.getDateOfBirthMM(), value.getDateOfBirthYYYY()), new TextRenderer());
}
use of de.symeda.sormas.api.contact.MergeContactIndexDto in project SORMAS-Project by hzi-braunschweig.
the class ContactFacadeEjb method getContactsForDuplicateMerging.
@Override
public List<MergeContactIndexDto[]> getContactsForDuplicateMerging(ContactCriteria criteria, boolean ignoreRegion) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<Contact> root = cq.from(Contact.class);
final ContactQueryContext contactQueryContext = new ContactQueryContext(cb, cq, root);
ContactJoins joins = contactQueryContext.getJoins();
Root<Contact> root2 = cq.from(Contact.class);
Join<Contact, Person> person = joins.getPerson();
Join<Contact, Person> person2 = root2.join(Contact.PERSON, JoinType.LEFT);
Join<Contact, Region> region = joins.getRegion();
Join<Contact, Region> region2 = root2.join(Contact.REGION, JoinType.LEFT);
Join<Contact, Case> sourceCase = joins.getCaze();
Join<Contact, Case> sourceCase2 = root2.join(Contact.CAZE, 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 source case
// * 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)
Predicate sourceCaseFilter = cb.equal(sourceCase, sourceCase2);
Predicate userFilter = service.createUserFilter(contactQueryContext);
Predicate criteriaFilter = criteria != null ? service.buildCriteriaFilter(criteria, contactQueryContext) : 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), configFacade.getNameSimilarityThreshold());
Predicate diseaseFilter = cb.equal(root.get(Contact.DISEASE), root2.get(Contact.DISEASE));
Predicate regionFilter = cb.or(cb.or(cb.isNull(region.get(Region.ID)), cb.isNull(region2.get(Region.ID))), 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(Contact.REPORT_DATE_TIME)), cb.function("date_part", Long.class, cb.parameter(String.class, "date_type"), root2.get(Contact.REPORT_DATE_TIME)))), SECONDS_30_DAYS);
// 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.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))));
Predicate creationDateFilter = cb.or(cb.lessThan(root.get(Contact.CREATION_DATE), root2.get(Contact.CREATION_DATE)), cb.or(cb.lessThanOrEqualTo(root2.get(Contact.CREATION_DATE), DateHelper.getStartOfDay(criteria.getCreationDateFrom())), cb.greaterThanOrEqualTo(root2.get(Contact.CREATION_DATE), DateHelper.getEndOfDay(criteria.getCreationDateTo()))));
Predicate filter = cb.and(service.createDefaultFilter(cb, root), service.createDefaultFilter(cb, root2), sourceCaseFilter);
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, creationDateFilter);
filter = cb.and(filter, cb.notEqual(root.get(Contact.ID), root2.get(Contact.ID)));
cq.where(filter);
cq.multiselect(root.get(Contact.ID), root2.get(Contact.ID), root.get(Contact.CREATION_DATE));
cq.orderBy(cb.desc(root.get(Contact.CREATION_DATE)));
List<Object[]> foundIds = em.createQuery(cq).setParameter("date_type", "epoch").getResultList();
List<MergeContactIndexDto[]> resultList = new ArrayList<>();
if (!foundIds.isEmpty()) {
CriteriaQuery<MergeContactIndexDto> indexContactsCq = cb.createQuery(MergeContactIndexDto.class);
Root<Contact> indexRoot = indexContactsCq.from(Contact.class);
selectMergeIndexDtoFields(cb, indexContactsCq, indexRoot);
indexContactsCq.where(indexRoot.get(Contact.ID).in(foundIds.stream().map(a -> Arrays.copyOf(a, 2)).flatMap(Arrays::stream).collect(Collectors.toSet())));
Map<Long, MergeContactIndexDto> indexContacts = em.createQuery(indexContactsCq).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
MergeContactIndexDto parent = (MergeContactIndexDto) indexContacts.get(idPair[0]).clone();
MergeContactIndexDto child = (MergeContactIndexDto) indexContacts.get(idPair[1]).clone();
if (parent.getCompleteness() == null && child.getCompleteness() == null || parent.getCompleteness() != null && (child.getCompleteness() == null || (parent.getCompleteness() >= child.getCompleteness()))) {
resultList.add(new MergeContactIndexDto[] { parent, child });
} else {
resultList.add(new MergeContactIndexDto[] { child, parent });
}
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
return resultList;
}
Aggregations