Commit 7b7e43c7 authored by luc chatty's avatar luc chatty

PATREG-33 | add identifier value

parent 77b9461d
Pipeline #137189 failed with stages
in 19 minutes and 10 seconds
......@@ -11,7 +11,9 @@ import net.ihe.gazelle.lib.searchmodelapi.business.searchcriterion.option.String
*/
public enum PatientSearchCriterionKey implements SearchCriterionKey {
UUID (String.class, StringSearchCriterionOperator.EXACT, new StringSearchCriterionOptions(true));
UUID (String.class, StringSearchCriterionOperator.EXACT, new StringSearchCriterionOptions(true)),
IDENTIFIER (String.class, StringSearchCriterionOperator.EXACT, new StringSearchCriterionOptions(true)),
DOMAIN (String.class, StringSearchCriterionOperator.EXACT, new StringSearchCriterionOptions(true));
private SearchCriterionOptions defaultOptions;
private SearchCriterionOperator defaultOperator;
......
......@@ -18,4 +18,24 @@ public class PatientSearchCriterionKeyTest {
assertNotNull(key.getDefaultOptions());
assertEquals(StringSearchCriterionOptions.class, key.getDefaultOptions().getClass());
}
@Test
public void test_identifier_key(){
PatientSearchCriterionKey key = PatientSearchCriterionKey.IDENTIFIER;
assertEquals(String.class, key.getValueClass());
assertEquals(StringSearchCriterionOperator.EXACT, key.getDefaultOperator());
assertNotNull(key.getDefaultOptions());
assertEquals(StringSearchCriterionOptions.class, key.getDefaultOptions().getClass());
}
@Test
public void test_domain_key(){
PatientSearchCriterionKey key = PatientSearchCriterionKey.DOMAIN;
assertEquals(String.class, key.getValueClass());
assertEquals(StringSearchCriterionOperator.EXACT, key.getDefaultOperator());
assertNotNull(key.getDefaultOptions());
assertEquals(StringSearchCriterionOptions.class, key.getDefaultOptions().getClass());
}
}
......@@ -35,7 +35,7 @@ public class TestProcessingService implements ProcessingService {
/**
* Setter to the responseToReturn property
* @param responseToReturn
* @param responseToReturn the response to return
*/
public void setResponseToReturn(ResponseTypes responseToReturn){
this.responseToReturn = responseToReturn;
......@@ -225,7 +225,7 @@ public class TestProcessingService implements ProcessingService {
/**
* Returns a {@link ProcessResponse} without any Error thought with status FAILURE.
* @return
* @return ProcessResponse
*/
private ProcessResponse getResponseWithoutErrorInFailureReport(){
ProcessResponse processResponse = new ProcessResponse();
......
......@@ -42,7 +42,7 @@ public class IdentifierConverter {
*/
public static PatientIdentifierDB toPatientIdentifierDB(EntityIdentifier identifier) {
PatientIdentifierDB patientIdentifierDB = new PatientIdentifierDB();
patientIdentifierDB.setIdNumber(identifier.getValue());
patientIdentifierDB.setIdentifier(identifier.getValue());
patientIdentifierDB.setIdentifierTypeCode(identifier.getType());
if(identifier.getSystemIdentifier() != null) {
......@@ -61,7 +61,7 @@ public class IdentifierConverter {
*/
public static EntityIdentifier toPatientIdentifier(PatientIdentifierDB patientIdentifierDB) {
EntityIdentifier returnedPatientIdentifier = new EntityIdentifier();
returnedPatientIdentifier.setValue(patientIdentifierDB.getIdNumber());
returnedPatientIdentifier.setValue(patientIdentifierDB.getIdentifier());
returnedPatientIdentifier.setType(patientIdentifierDB.getIdentifierTypeCode());
if(patientIdentifierDB.getDomain() != null) {
returnedPatientIdentifier.setSystemIdentifier(patientIdentifierDB.getDomain().getUniversalID());
......
......@@ -28,7 +28,7 @@ public class PatientIdentifierDB {
* PID-3-1 (ST) or extension (HL7v3)
*/
@Column(name = "id_number")
private String idNumber;
private String identifier;
/**
* PID-3-4 (HD)
......@@ -83,7 +83,7 @@ public class PatientIdentifierDB {
@PreUpdate
public void setFullPatientIdentifierIfEmpty(){
if (this.fullPatientId == null){
fullPatientId = (this.getIdNumber() != null ?this.getIdNumber(): "");
fullPatientId = (this.getIdentifier() != null ?this.getIdentifier(): "");
if (domain != null){
fullPatientId = fullPatientId.concat("^^^");
if (domain.getNamespaceID() != null) {
......@@ -108,7 +108,7 @@ public class PatientIdentifierDB {
*/
public PatientIdentifierDB(PatientIdentifierDB pid) {
this.fullPatientId = pid.getFullPatientId();
this.idNumber = pid.getIdNumber();
this.identifier = pid.getIdentifier();
this.identifierTypeCode = pid.getIdentifierTypeCode();
this.domain = pid.getDomain();
}
......@@ -191,10 +191,10 @@ public class PatientIdentifierDB {
/**
* <p>Setter for the field <code>idNumber</code>.</p>
*
* @param idNumber a {@link String} object.
* @param identifier a {@link String} object.
*/
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
/**
......@@ -202,8 +202,8 @@ public class PatientIdentifierDB {
*
* @return a {@link String} object.
*/
public String getIdNumber() {
return idNumber;
public String getIdentifier() {
return identifier;
}
/** {@inheritDoc} */
......@@ -221,7 +221,7 @@ public class PatientIdentifierDB {
if (fullPatientId != null ? !fullPatientId.equals(that.fullPatientId) : that.fullPatientId != null) {
return false;
}
if (idNumber != null ? !idNumber.equals(that.idNumber) : that.idNumber != null) {
if (identifier != null ? !identifier.equals(that.identifier) : that.identifier != null) {
return false;
}
return identifierTypeCode != null ? identifierTypeCode.equals(that.identifierTypeCode) : that.identifierTypeCode == null;
......@@ -231,7 +231,7 @@ public class PatientIdentifierDB {
@Override
public int hashCode() {
int result = fullPatientId != null ? fullPatientId.hashCode() : 0;
result = 31 * result + (idNumber != null ? idNumber.hashCode() : 0);
result = 31 * result + (identifier != null ? identifier.hashCode() : 0);
result = 31 * result + (identifierTypeCode != null ? identifierTypeCode.hashCode() : 0);
return result;
}
......
......@@ -3,14 +3,18 @@ package net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.serv
import net.ihe.gazelle.app.patientregistryapi.business.PatientSearchCriterionKey;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.EntityManagerProducer;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientDB;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientIdentifierDB;
import net.ihe.gazelle.lib.searchjpadao.adapter.SearchCriterionJPAMappingService;
import net.ihe.gazelle.lib.searchmodelapi.business.searchcriterion.key.SearchCriterionKey;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
/**
* Concrete {@link SearchCriterionJPAMappingService} for Patients.
......@@ -19,6 +23,8 @@ public class PatientSearchCriterionJPAMappingService implements SearchCriterionJ
private CriteriaBuilder criteriaBuilder;
private EntityManager entityManager;
/**
* Constructor for injection
* @param entityManager {@link EntityManager} to use to build JPA criteria.
......@@ -26,6 +32,7 @@ public class PatientSearchCriterionJPAMappingService implements SearchCriterionJ
@Inject
public PatientSearchCriterionJPAMappingService(@EntityManagerProducer.InjectEntityManager EntityManager entityManager) {
this.criteriaBuilder = entityManager.getCriteriaBuilder();
this.entityManager = entityManager;
}
/**
......@@ -34,8 +41,17 @@ public class PatientSearchCriterionJPAMappingService implements SearchCriterionJ
@Override
public From from(SearchCriterionKey searchCriterionKey, From from) {
PatientSearchCriterionKey patientSearchCriterionKey = castToPatientKey(searchCriterionKey);
if (PatientSearchCriterionKey.UUID.equals(patientSearchCriterionKey)) {;
Metamodel metamodel = entityManager.getMetamodel();
EntityType<PatientDB> entityType = metamodel.entity(PatientDB.class);
if (PatientSearchCriterionKey.UUID.equals(patientSearchCriterionKey)) {
return from;
} else if (PatientSearchCriterionKey.IDENTIFIER.equals(patientSearchCriterionKey)) {
From from2 = (From) from.getJoins().stream()
.filter(p ->
((Join) p).getAttribute().getName().equals("patientIdentifiers") &&
JoinType.LEFT.equals(((Join) p).getJoinType()))
.findAny().orElse(null);
return from2 != null ? from : from.join(entityType.getList("patientIdentifiers", PatientIdentifierDB.class), JoinType.LEFT);
} else {
throw new IllegalArgumentException("Unsupported test key : " + patientSearchCriterionKey);
}
......@@ -49,6 +65,8 @@ public class PatientSearchCriterionJPAMappingService implements SearchCriterionJ
PatientSearchCriterionKey patientSearchCriterionKey = castToPatientKey(searchCriterionKey);
if (PatientSearchCriterionKey.UUID.equals(patientSearchCriterionKey)) {
return "uuid";
} else if (PatientSearchCriterionKey.IDENTIFIER.equals(patientSearchCriterionKey)) {
return "identifier";
} else {
throw new IllegalArgumentException("Unsupported test key : " + patientSearchCriterionKey);
}
......
......@@ -37,7 +37,7 @@ class IdentifierConverterTest {
PatientIdentifierDB identifierDB = IdentifierConverter.toPatientIdentifierDB(identifier,null);
assertEquals(value,identifierDB.getIdNumber(), "value should be mapped to Id number");
assertEquals(value,identifierDB.getIdentifier(), "value should be mapped to Id number");
}
/**
......
......@@ -5,6 +5,7 @@ import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import net.ihe.gazelle.app.patientregistryapi.application.PatientFeedException;
import net.ihe.gazelle.app.patientregistryapi.business.EntityIdentifier;
import net.ihe.gazelle.app.patientregistryapi.business.GenderCode;
import net.ihe.gazelle.app.patientregistryapi.business.Patient;
import net.ihe.gazelle.app.patientregistryapi.business.PatientSearchCriterionKey;
......@@ -83,6 +84,28 @@ public class SearchExecutionStepDefinition {
}
}
/**
* Precondition that will add identifiers to existing patients.
*
* @param patientIdentifierDataList list on information on Identifiers to create
*/
@Given("patients have the following identifiers")
public void patients_have_the_following_identifiers(List<Map<String, String>> patientIdentifierDataList) {
for (Map<String, String> identifierData : patientIdentifierDataList) {
EntityIdentifier identifier = new EntityIdentifier(identifierData.get("systemIdentifier"),
identifierData.get("systemName"), identifierData.get("type"), identifierData.get("value"));
Patient patient = getExistingPatientWithUUID(identifierData.get("tmpuuid"));
if (patient == null) {
throw new IllegalArgumentException(String.format("No patient corresponding to UUID %s !", identifierData.get("tmpuuid")));
} else {
patient.addIdentifier(identifier);
}
}
}
/**
* Feed a patient using tested {@link PatientFeedClient} and {@link PatientProcessingService}
*
......@@ -115,6 +138,9 @@ public class SearchExecutionStepDefinition {
} else if (searchCriteriaName.equals("uuid")) {
this.searchCriteria.addSearchCriterion(createStringSearchCriterion(PatientSearchCriterionKey.UUID,
getStringSearchCriterionOperator(searchCriteriaVerbText), searchCriteriaValue));
} else if (searchCriteriaName.equals("identifier.value")) {
this.searchCriteria.addSearchCriterion(createStringSearchCriterion(PatientSearchCriterionKey.IDENTIFIER,
getStringSearchCriterionOperator(searchCriteriaVerbText), searchCriteriaValue));
} else {
fail(String.format("Unsupported criteria %s", searchCriteriaName));
}
......@@ -183,6 +209,12 @@ public class SearchExecutionStepDefinition {
} else if (parameter.equals("uuid")) {
searchedPatients.forEach((Patient patient) ->
checkStringValueWithOperator(verb, value, patient.getUuid()));
} else if (parameter.equals("identifier.value")) {
searchedPatients.forEach((Patient patient) -> {
List<String> identifierList = new ArrayList<>();
patient.getIdentifiers().forEach(identifier -> identifierList.add(identifier.getValue()));
checkStringListWithOperator(verb, value, identifierList);
});
} else {
fail(String.format("Unsupported criteria %s", parameter));
}
......@@ -192,6 +224,25 @@ public class SearchExecutionStepDefinition {
}
/**
* Check a string value with a specific operator in a list
*
* @param operator name of the operator to use
* @param expected expected value
* @param actual tested value
*/
private void checkStringListWithOperator(String operator, String expected, List<String> actual) {
if (operator != null) {
if (operator.equals("is")) {
assertTrue(actual.contains(expected));
} else {
fail(String.format("Unsupported Operator %s !", operator));
}
} else {
fail("Operator shall not be null !");
}
}
/**
* Check a string value with a specific operator
*
......
......@@ -10,6 +10,7 @@ import io.cucumber.java.en.When;
import net.ihe.gazelle.app.patientregistryapi.application.PatientFeedException;
import net.ihe.gazelle.app.patientregistryapi.application.PatientFeedService;
import net.ihe.gazelle.app.patientregistryapi.application.PatientSearchService;
import net.ihe.gazelle.app.patientregistryapi.business.EntityIdentifier;
import net.ihe.gazelle.app.patientregistryapi.business.GenderCode;
import net.ihe.gazelle.app.patientregistryapi.business.Patient;
import net.ihe.gazelle.app.patientregistryapi.business.PatientSearchCriterionKey;
......@@ -148,6 +149,27 @@ public class SearchExecutionStepDefinition {
}
}
/**
* Precondition that will add identifiers to existing patients.
*
* @param patientIdentifierDataList list on information on Identifiers to create
*/
@Given("patients have the following identifiers")
public void patients_have_the_following_identifiers(List<Map<String, String>> patientIdentifierDataList) {
for (Map<String, String> identifierData : patientIdentifierDataList) {
EntityIdentifier identifier = new EntityIdentifier(identifierData.get("systemIdentifier"),
identifierData.get("systemName"), identifierData.get("type"), identifierData.get("value"));
Patient patient = getExistingPatientWithUUID(identifierData.get("tmpuuid"));
if (patient == null) {
throw new IllegalArgumentException(String.format("No patient corresponding to UUID %s !", identifierData.get("tmpuuid")));
} else {
patient.addIdentifier(identifier);
}
}
}
/**
* Feed a patient using tested {@link PatientFeedClient} and {@link PatientProcessingService}
*
......@@ -180,6 +202,9 @@ public class SearchExecutionStepDefinition {
} else if (searchCriteriaName.equals("uuid")) {
this.searchCriteria.addSearchCriterion(createStringSearchCriterion(PatientSearchCriterionKey.UUID,
getStringSearchCriterionOperator(searchCriteriaVerbText), searchCriteriaValue));
} else if (searchCriteriaName.equals("identifier.value")) {
this.searchCriteria.addSearchCriterion(createStringSearchCriterion(PatientSearchCriterionKey.IDENTIFIER,
getStringSearchCriterionOperator(searchCriteriaVerbText), searchCriteriaValue));
} else {
fail(String.format("Unsupported criteria %s", searchCriteriaName));
}
......@@ -248,6 +273,12 @@ public class SearchExecutionStepDefinition {
} else if (parameter.equals("uuid")) {
searchedPatients.forEach((Patient patient) ->
checkStringValueWithOperator(verb, value, patient.getUuid()));
} else if (parameter.equals("identifier.value")) {
searchedPatients.forEach((Patient patient) -> {
List<String> identifierList = new ArrayList<>();
patient.getIdentifiers().forEach(identifier -> identifierList.add(identifier.getValue()));
checkStringListWithOperator(verb, value, identifierList);
});
} else {
fail(String.format("Unsupported criteria %s", parameter));
}
......@@ -257,6 +288,25 @@ public class SearchExecutionStepDefinition {
}
/**
* Check a string value with a specific operator in a list
*
* @param operator name of the operator to use
* @param expected expected value
* @param actual tested value
*/
private void checkStringListWithOperator(String operator, String expected, List<String> actual) {
if (operator != null) {
if (operator.equals("is")) {
assertTrue(actual.contains(expected));
} else {
fail(String.format("Unsupported Operator %s !", operator));
}
} else {
fail("Operator shall not be null !");
}
}
/**
* Check a string value with a specific operator
*
......
......@@ -5,8 +5,20 @@ Feature: Search Patient information
| tmpuuid | gender | active | dateOfBirth | dateOfDeath | multipleBirthOrder |
| tmpuuid0 | MALE | true | 1984-03-12T17:25:04.017+0100 | 2020-03-12T17:25:04.017+0100 | 134 |
| tmpuuid1 | FEMALE | true | 1984-03-12T17:25:04.017+0100 | 2020-03-12T17:25:04.017+0100 | 134 |
| tmpuuid2 | FEMALE | true | 2019-01-19T17:25:04.017+0100 | 2020-08-28T17:25:04.017+0100 | 134 |
| tmpuuid3 | MALE | false | 1984-09-29T17:25:04.017+0100 | 2020-03-12T17:15:04.017+0100 | 134 |
And patients have the following identifiers
| tmpuuid | systemIdentifier | value | systemName | type |
| tmpuuid0 | urn:oid:1.2.3.4 | identifier0 | system0 | PI |
| tmpuuid0 | urn:oid:5.6.7.8 | identifier0 | system0 | PI |
| tmpuuid1 | urn:oid:1.2.3.4 | identifier1 | system1 | PI |
| tmpuuid2 | urn:oid:1.2.3.4 | identifier2 | system2 | PI |
| tmpuuid3 | urn:oid:1.2.3.4 | identifier3 | system3 | PI |
| tmpuuid3 | urn:oid:9.8.7.6 | identifier0 | system4 | PI |
And patient is fed with provisional uuid "tmpuuid0"
And patient is fed with provisional uuid "tmpuuid1"
And patient is fed with provisional uuid "tmpuuid2"
And patient is fed with provisional uuid "tmpuuid3"
Scenario Outline: Nominal Patient search with one criterion
Given search criterion "<parameter>" "<verb>" "<value>"
......@@ -20,3 +32,4 @@ Feature: Search Patient information
| tmpuuid | is | tmpuuid0 | 1 |
| tmpuuid | is | tmpuuid1 | 1 |
| uuid | is | uuid123 | 0 |
| identifier.value | is | identifier0 | 2 |
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment