use of de.symeda.sormas.api.person.PersonCriteria in project SORMAS-Project by hzi-braunschweig.
the class PersonFacadeEjb method getIndexList.
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public List<PersonIndexDto> getIndexList(PersonCriteria criteria, Integer first, Integer max, List<SortProperty> sortProperties) {
long startTime = DateHelper.startTime();
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<PersonIndexDto> cq = cb.createQuery(PersonIndexDto.class);
final Root<Person> person = cq.from(Person.class);
final PersonQueryContext personQueryContext = new PersonQueryContext(cb, cq, person);
final PersonJoins personJoins = (PersonJoins) personQueryContext.getJoins();
personJoins.configure(criteria);
final Join<Person, Location> location = personJoins.getAddress();
final Join<Location, District> district = personJoins.getAddressJoins().getDistrict();
final Subquery<String> phoneSubQuery = cq.subquery(String.class);
final Root<PersonContactDetail> phoneRoot = phoneSubQuery.from(PersonContactDetail.class);
phoneSubQuery.where(cb.and(cb.equal(phoneRoot.get(PersonContactDetail.PERSON), person), cb.isTrue(phoneRoot.get(PersonContactDetail.PRIMARY_CONTACT)), cb.equal(phoneRoot.get(PersonContactDetail.PERSON_CONTACT_DETAIL_TYPE), PersonContactDetailType.PHONE)));
phoneSubQuery.select(phoneRoot.get(PersonContactDetail.CONTACT_INFORMATION));
final Subquery<String> emailSubQuery = cq.subquery(String.class);
final Root<PersonContactDetail> emailRoot = emailSubQuery.from(PersonContactDetail.class);
emailSubQuery.where(cb.and(cb.equal(emailRoot.get(PersonContactDetail.PERSON), person), cb.isTrue(emailRoot.get(PersonContactDetail.PRIMARY_CONTACT)), cb.equal(emailRoot.get(PersonContactDetail.PERSON_CONTACT_DETAIL_TYPE), PersonContactDetailType.EMAIL)));
emailSubQuery.select(emailRoot.get(PersonContactDetail.CONTACT_INFORMATION));
// make sure to check the sorting by the multi-select order if you extend the selections here
cq.multiselect(person.get(Person.UUID), person.get(Person.FIRST_NAME), person.get(Person.LAST_NAME), person.get(Person.APPROXIMATE_AGE), person.get(Person.APPROXIMATE_AGE_TYPE), person.get(Person.BIRTHDATE_DD), person.get(Person.BIRTHDATE_MM), person.get(Person.BIRTHDATE_YYYY), person.get(Person.SEX), district.get(District.NAME), location.get(Location.STREET), location.get(Location.HOUSE_NUMBER), location.get(Location.POSTAL_CODE), location.get(Location.CITY), phoneSubQuery.alias(PersonIndexDto.PHONE), emailSubQuery.alias(PersonIndexDto.EMAIL_ADDRESS), person.get(Person.CHANGE_DATE), JurisdictionHelper.booleanSelector(cb, personService.inJurisdictionOrOwned(personQueryContext)));
Predicate filter = createIndexListFilter(criteria, personQueryContext);
if (filter != null) {
cq.where(filter);
}
cq.distinct(true);
if (sortProperties != null && sortProperties.size() > 0) {
List<Order> order = new ArrayList<Order>(sortProperties.size());
for (SortProperty sortProperty : sortProperties) {
Expression<?> expression;
switch(sortProperty.propertyName) {
case PersonIndexDto.UUID:
case PersonIndexDto.FIRST_NAME:
case PersonIndexDto.LAST_NAME:
case PersonIndexDto.SEX:
expression = person.get(sortProperty.propertyName);
break;
case PersonIndexDto.PHONE:
// order in the multiselect - Postgres limitation - needed to make sure it uses the same expression for ordering
expression = cb.literal(15);
break;
case PersonIndexDto.EMAIL_ADDRESS:
// order in the multiselect - Postgres limitation - needed to make sure it uses the same expression for ordering
expression = cb.literal(16);
break;
case PersonIndexDto.AGE_AND_BIRTH_DATE:
expression = person.get(Person.APPROXIMATE_AGE);
break;
case PersonIndexDto.DISTRICT:
expression = district.get(District.NAME);
break;
case PersonIndexDto.STREET:
case PersonIndexDto.HOUSE_NUMBER:
case PersonIndexDto.POSTAL_CODE:
case PersonIndexDto.CITY:
expression = location.get(sortProperty.propertyName);
break;
default:
throw new IllegalArgumentException(sortProperty.propertyName);
}
order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression));
}
cq.orderBy(order);
} else {
cq.orderBy(cb.desc(person.get(Person.CHANGE_DATE)));
}
List<PersonIndexDto> persons = QueryHelper.getResultList(em, cq, first, max);
Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight, I18nProperties.getCaption(Captions.inaccessibleValue));
pseudonymizer.pseudonymizeDtoCollection(PersonIndexDto.class, persons, p -> p.getInJurisdiction(), (p, isInJurisdiction) -> pseudonymizer.pseudonymizeDto(AgeAndBirthDateDto.class, p.getAgeAndBirthDate(), isInJurisdiction, null));
logger.debug("getIndexList() finished. association={}, count={}, {}ms", Optional.ofNullable(criteria).orElse(new PersonCriteria()).getPersonAssociation().name(), persons.size(), DateHelper.durationMillies(startTime));
return persons;
}
use of de.symeda.sormas.api.person.PersonCriteria in project SORMAS-Project by hzi-braunschweig.
the class PersonFacadeEjb method count.
@Override
public long count(PersonCriteria criteria) {
long startTime = DateHelper.startTime();
final PersonCriteria nullSafeCriteria = Optional.ofNullable(criteria).orElse(new PersonCriteria());
final long count;
if (nullSafeCriteria.getPersonAssociation() == PersonAssociation.ALL) {
// Fetch Person.id per association and find the distinct count.
Set<Long> distinctPersonIds = new HashSet<>();
boolean immunizationModuleReduced = featureConfigurationFacade.isPropertyValueTrue(FeatureType.IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED);
Arrays.stream(PersonAssociation.getSingleAssociations()).filter(e -> !(immunizationModuleReduced && e == PersonAssociation.IMMUNIZATION)).map(e -> getPersonIds(SerializationUtils.clone(nullSafeCriteria).personAssociation(e))).forEach(distinctPersonIds::addAll);
count = distinctPersonIds.size();
} else {
// Directly fetch the count for the only required association
count = getPersonIds(criteria).size();
}
logger.debug("count() finished. association={}, count={}, {}ms", nullSafeCriteria.getPersonAssociation().name(), count, DateHelper.durationMillies(startTime));
return count;
}
use of de.symeda.sormas.api.person.PersonCriteria in project SORMAS-Project by hzi-braunschweig.
the class PersonGrid method setLazyDataProvider.
public void setLazyDataProvider() {
DataProvider<PersonIndexDto, PersonCriteria> dataProvider = DataProvider.fromFilteringCallbacks(query -> FacadeProvider.getPersonFacade().getIndexList(query.getFilter().orElse(null), query.getOffset(), query.getLimit(), query.getSortOrders().stream().map(sortOrder -> new SortProperty(sortOrder.getSorted(), sortOrder.getDirection() == SortDirection.ASCENDING)).collect(Collectors.toList())).stream(), query -> (int) FacadeProvider.getPersonFacade().count(query.getFilter().orElse(null)));
setDataProvider(dataProvider);
setSelectionMode(SelectionMode.NONE);
}
use of de.symeda.sormas.api.person.PersonCriteria in project SORMAS-Project by hzi-braunschweig.
the class PersonFacadeEjbTest method testCountAndGetIndexListWithAssociations.
/**
* Test all {@link PersonAssociation} variants if they work. Also serves to review the generated SQL.
*/
@Test
public void testCountAndGetIndexListWithAssociations() {
PersonFacade cut = getPersonFacade();
Integer offset = null;
Integer limit = null;
List<SortProperty> sortProperties = null;
RDCF rdcf = creator.createRDCF();
UserDto user = creator.createUser(rdcf.region.getUuid(), null, null, null, "Surv", "Sup", UserRole.SURVEILLANCE_SUPERVISOR);
loginWith(user);
// 1a. Test for all available PersonAssociations
for (PersonAssociation pa : PersonAssociation.values()) {
PersonCriteria criteria = new PersonCriteria().personAssociation(pa);
assertThat("Failed for testing association on count: " + pa.name(), cut.count(criteria), equalTo(0L));
assertThat(criteria.getPersonAssociation(), equalTo(pa));
assertThat("Failed for testing association on getIndexList: " + pa.name(), cut.getIndexList(criteria, offset, limit, sortProperties), is(empty()));
assertThat(criteria.getPersonAssociation(), equalTo(pa));
}
// 1b. Test that calling with "null" as criteria also works
assertThat(cut.count(null), equalTo(0L));
assertThat(cut.getIndexList(null, offset, limit, sortProperties), is(empty()));
// 2. Test paging windows
final PersonDto person1 = creator.createPerson("James", "Smith", Sex.MALE, 1920, 1, 1);
final CaseDataDto case1 = creator.createCase(user.toReference(), person1.toReference(), Disease.EVD, CaseClassification.PROBABLE, InvestigationStatus.PENDING, new Date(), rdcf);
final PersonDto person2 = creator.createPerson("Maria", "Garcia", Sex.FEMALE, 1920, 1, 1);
final ContactDto contact2 = creator.createContact(user.toReference(), user.toReference(), person2.toReference(), null, new Date(), new Date(), Disease.EVD, rdcf);
// 2a. count
assertThat(cut.count(new PersonCriteria().personAssociation(PersonAssociation.ALL)), equalTo(2L));
assertThat(cut.count(new PersonCriteria().personAssociation(PersonAssociation.CASE)), equalTo(1L));
assertThat(cut.count(new PersonCriteria().personAssociation(PersonAssociation.CONTACT)), equalTo(1L));
// 2b. getIndexList with all persons in the paging window
assertPersonsFound(case1, contact2, cut, offset, limit, sortProperties);
offset = 0;
limit = 2;
assertPersonsFound(case1, contact2, cut, offset, limit, sortProperties);
offset = 0;
limit = 1;
assertPersonsFound(case1, contact2, cut, offset, limit, sortProperties);
// 2c. getIndexList [PersonAssociation.ALL] with only the contact person in the paging window (default sorting by changeDate)
offset = 1;
limit = 2;
assertPersonsFound(null, null, Arrays.asList(contact2.getPerson()), cut, offset, limit, sortProperties);
}
use of de.symeda.sormas.api.person.PersonCriteria in project SORMAS-Project by hzi-braunschweig.
the class PersonFacadeEjbTest method assertPersonsFound.
private static void assertPersonsFound(CaseDataDto caze, ContactDto contact, List<PersonReferenceDto> allPersons, PersonFacade cut, Integer offset, Integer limit, List<SortProperty> sortProperties) {
List<String> casePersonUuids = caze == null ? Collections.emptyList() : Collections.singletonList(caze.getPerson().getUuid());
List<String> contactPersonUuids = contact == null ? Collections.emptyList() : Collections.singletonList(contact.getPerson().getUuid());
int allCount = Math.min(allPersons.size(), limit != null ? limit : Integer.MAX_VALUE);
// single association
List<PersonIndexDto> caseList = cut.getIndexList(new PersonCriteria().personAssociation(PersonAssociation.CASE), offset, limit, sortProperties);
assertThat(caseList, hasSize(casePersonUuids.size()));
List<PersonIndexDto> contactList = cut.getIndexList(new PersonCriteria().personAssociation(PersonAssociation.CONTACT), offset, limit, sortProperties);
assertThat(contactList, hasSize(contactPersonUuids.size()));
assertThat(cut.getIndexList(new PersonCriteria().personAssociation(PersonAssociation.EVENT_PARTICIPANT), offset, limit, sortProperties), is(empty()));
assertThat(cut.getIndexList(new PersonCriteria().personAssociation(PersonAssociation.IMMUNIZATION), offset, limit, sortProperties), is(empty()));
assertThat(cut.getIndexList(new PersonCriteria().personAssociation(PersonAssociation.TRAVEL_ENTRY), offset, limit, sortProperties), is(empty()));
// ALL
List<PersonIndexDto> allList = cut.getIndexList(new PersonCriteria().personAssociation(PersonAssociation.ALL), offset, limit, sortProperties);
assertThat(allList, hasSize(allCount));
}
Aggregations