Commit 71ffa595 authored by luc chatty's avatar luc chatty

Merge branch 'feature/patreg-33' into 'develop'

Feature/patreg 33

See merge request !5
parents 72bc8918 87f7e9d3
Pipeline #138814 passed with stages
in 6 minutes and 58 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();
......
......@@ -44,6 +44,7 @@
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>patient-registry-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
......@@ -166,7 +167,7 @@
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
......@@ -200,7 +201,7 @@
<execution>
<id>drop-db-before-test-if-any</id>
<phase>generate-test-resources</phase>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
......@@ -216,7 +217,7 @@
<execution>
<id>create-db-before-test</id>
<phase>generate-test-resources</phase>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
......@@ -232,7 +233,7 @@
<execution>
<id>create-user-before-test</id>
<phase>generate-test-resources</phase>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
......@@ -240,7 +241,23 @@
<!-- need another database to drop the targeted one -->
<url>jdbc:postgresql://${postgresql.host}:${postgresql.port}/${postgresql.gazelle.name}</url>
<autocommit>true</autocommit>
<sqlCommand>create user gazelle with password '${postgresql.gazelle.password}'</sqlCommand>
<sqlCommand>create user ${postgresql.gazelle.login} with password '${postgresql.gazelle.password}'</sqlCommand>
<!-- ignore error when database is not avaiable -->
<onError>continue</onError>
</configuration>
</execution>
<execution>
<id>change-user-before-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<!-- need another database to drop the targeted one -->
<url>jdbc:postgresql://${postgresql.host}:${postgresql.port}/${postgresql.root.login}</url>
<autocommit>true</autocommit>
<sqlCommand>ALTER DATABASE "${postgresql.gazelle.name}" OWNER TO ${postgresql.gazelle.login}</sqlCommand>
<!-- ignore error when database is not avaiable -->
<onError>continue</onError>
</configuration>
......@@ -248,7 +265,7 @@
<execution>
<id>create-schema</id>
<phase>generate-test-resources</phase>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
......@@ -267,7 +284,8 @@
<artifactId>wildfly-maven-plugin</artifactId>
<version>2.1.0.Beta1</version>
<configuration>
<jboss-home>${env.JBOSS_HOME}</jboss-home>
<jboss-home>${env.JBOSS_HOME}</jboss-home>
<startupTimeout>300</startupTimeout>
</configuration>
<executions>
<execution>
......@@ -307,7 +325,7 @@
<goal>deploy</goal>
</goals>
<configuration>
<filename>patient-registry-${project.version}-jar-with-dependencies.jar</filename>
<filename>patient-registry-${project.version}.jar</filename>
<runtimeName>patient-registry.jar</runtimeName>
</configuration>
</execution>
......
package net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.converter;
import net.ihe.gazelle.app.patientregistryapi.business.EntityIdentifier;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.DesignatorTypeDB;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.HierarchicDesignatorDB;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientDB;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientIdentifierDB;
......@@ -42,13 +43,14 @@ 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) {
HierarchicDesignatorDB designator = new HierarchicDesignatorDB();
designator.setUniversalID(identifier.getSystemIdentifier());
designator.setNamespaceID(identifier.getSystemName());
designator.setUsage(DesignatorTypeDB.PATIENT_ID);
patientIdentifierDB.setDomain(designator);
}
return patientIdentifierDB;
......@@ -61,7 +63,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;
}
......
......@@ -9,7 +9,8 @@ public interface DomainDAO {
/**
* Retrieve a Hierarchic Designator from database.
* @param domainIdentifier Identifier of the domain to retrieve
*
* @param domainIdentifier Identifier of the domain to retrieve
* @return the domain from database that corresponds to the requested identifier
*/
HierarchicDesignatorDB retrieve(String domainIdentifier);
......
......@@ -2,6 +2,7 @@ package net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.serv
import net.ihe.gazelle.app.patientregistryapi.application.DomainService;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.EntityManagerProducer;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.DesignatorTypeDB;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.HierarchicDesignatorDB;
import javax.inject.Inject;
......@@ -26,7 +27,8 @@ public class DomainDAOImpl implements DomainDAO, DomainService {
/**
* Constructor for the class. Takes an EntityManager as argument. It will be used to perform actions on Database.
* @param entityManager {@link EntityManager} to perform actions on Database.
*
* @param entityManager {@link EntityManager} to perform actions on Database.
*/
@Inject
public DomainDAOImpl(@EntityManagerProducer.InjectEntityManager EntityManager entityManager) {
......@@ -38,7 +40,8 @@ public class DomainDAOImpl implements DomainDAO, DomainService {
/**
* Delete a domain from Database.
* @param domainIdentifier identifier of the domain to delete.
*
* @param domainIdentifier identifier of the domain to delete.
*/
public void delete(String domainIdentifier) {
HierarchicDesignatorDB domain = retrieve(domainIdentifier);
......@@ -55,11 +58,13 @@ public class DomainDAOImpl implements DomainDAO, DomainService {
/**
* Retrieve a Domain by its Identifier
* @param domainIdentifier identifier of the Domain to retrieve.
*
* @param domainIdentifier identifier of the Domain to retrieve.
* @return retrieved Domain if exists, or null.
*/
public HierarchicDesignatorDB retrieve(String domainIdentifier) {
TypedQuery<HierarchicDesignatorDB> query = entityManager.createNamedQuery("HierarchicDesignatorDB.findByUniversalID", HierarchicDesignatorDB.class);
TypedQuery<HierarchicDesignatorDB> query = entityManager.createNamedQuery("HierarchicDesignatorDB.findByUniversalID",
HierarchicDesignatorDB.class);
query.setParameter("universalID", domainIdentifier);
HierarchicDesignatorDB domain;
try {
......@@ -77,6 +82,7 @@ public class DomainDAOImpl implements DomainDAO, DomainService {
@Override
public void createDomain(String domainIdentifier, String domainName) {
HierarchicDesignatorDB domain = new HierarchicDesignatorDB(domainName, domainIdentifier, "ISO", null);
domain.setUsage(DesignatorTypeDB.PATIENT_ID);
entityManager.persist(domain);
entityManager.flush();
}
......
package net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.service;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientIdentifierDB;
/**
* API for the Identifier DAO
*/
public interface IdentifierDAO {
/**
* Retrieve a {@link net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientIdentifierDB} from database.
*
* @param fullPatientIdentifier Full Patient identifier
* @param identifierTypeCode Type Code for the identifier
* @return the domain from database that corresponds to the requested identifier
*/
PatientIdentifierDB retrieve(String fullPatientIdentifier, String identifierTypeCode);
}
package net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.service;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.EntityManagerProducer;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.model.patient.PatientIdentifierDB;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;
/**
* DAO for Identifier Objects.
*/
public class IdentifierDAOImpl implements IdentifierDAO {
private EntityManager entityManager;
/**
* Private constructor to hide the implicit one.
*/
private IdentifierDAOImpl() {
}
/**
* Constructor for the class. Takes an EntityManager as argument. It will be used to perform actions on Database.
*
* @param entityManager {@link EntityManager} to perform actions on Database.
*/
@Inject
public IdentifierDAOImpl(@EntityManagerProducer.InjectEntityManager EntityManager entityManager) {
if (entityManager == null) {
throw new IllegalArgumentException("EntityManager cannot be null");
}
this.entityManager = entityManager;
}
/**
* {@inheritDoc}
*/
@Override
public PatientIdentifierDB retrieve(String fullPatientIdentifier, String identifierTypeCode) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(PatientIdentifierDB.class);
From from = criteriaQuery.from(PatientIdentifierDB.class);
Path<String> fullPatientIdPath = from.get("fullPatientId");
Path<String> identifierTypeCodePath = from.get("identifierTypeCode");
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(fullPatientIdPath, fullPatientIdentifier));
predicates.add(criteriaBuilder.equal(identifierTypeCodePath, identifierTypeCode));
Predicate finalPredicate = criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
TypedQuery<PatientIdentifierDB> query = entityManager.createQuery(criteriaQuery.select(from).where(finalPredicate).distinct(true));
try {
return query.getSingleResult();
} catch (NoResultException e) {
return null;
}
}
}
......@@ -4,7 +4,9 @@ import net.ihe.gazelle.app.patientregistryapi.business.Patient;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.EntityManagerProducer;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.converter.PatientConverter;
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.app.patientregistryservice.adapter.dao.pamsimulator.service.DomainDAO;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.service.IdentifierDAO;
import net.ihe.gazelle.app.patientregistryservice.adapter.dao.pamsimulator.service.patient.search.PatientSearchDAO;
import net.ihe.gazelle.app.patientregistryservice.application.*;
import net.ihe.gazelle.framework.loggerservice.application.GazelleLogger;
......@@ -15,6 +17,8 @@ import net.ihe.gazelle.lib.searchmodelapi.business.exception.SearchException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
......@@ -26,6 +30,7 @@ public class PatientDAOImpl implements PatientDAO {
private static final GazelleLogger log = GazelleLoggerFactory.getInstance().getLogger(PatientDAOImpl.class);
private EntityManager entityManager;
private DomainDAO domainDAO;
private IdentifierDAO identifierDAO;
private PatientSearchDAO patientSearchDAO;
/**
......@@ -39,12 +44,16 @@ public class PatientDAOImpl implements PatientDAO {
* @param entityManager {@link EntityManager} to use by DAO.
* @param patientSearchDAO {@link PatientSearchDAO} concrete SearchDAO for Patients.
* @param domainDAO {@link DomainDAO} to retrieve Domains from database.
* @param identifierDAO {@link IdentifierDAO} to retrieve Identifiers from database.
*/
@Inject
public PatientDAOImpl(@EntityManagerProducer.InjectEntityManager EntityManager entityManager, PatientSearchDAO patientSearchDAO, DomainDAO domainDAO){
public PatientDAOImpl(@EntityManagerProducer.InjectEntityManager EntityManager entityManager, PatientSearchDAO patientSearchDAO,
DomainDAO domainDAO
, IdentifierDAO identifierDAO) {
this.entityManager = entityManager;
this.patientSearchDAO = patientSearchDAO;
this.domainDAO = domainDAO;
this.identifierDAO = identifierDAO;
}
/**
......@@ -76,11 +85,22 @@ public class PatientDAOImpl implements PatientDAO {
patientDB = PatientConverter.toPatientDB(patient);
patientDB.getPatientIdentifiers().forEach(patientIdentifierDB -> {
if(patientIdentifierDB.getDomain() != null) {
Iterator<PatientIdentifierDB> iterator = patientDB.getPatientIdentifiers().iterator();
List<PatientIdentifierDB> identifiersFromDB = new ArrayList<>();
while (iterator.hasNext()) {
PatientIdentifierDB patientIdentifierDB = iterator.next();
patientIdentifierDB.setFullPatientIdentifierIfEmpty();
PatientIdentifierDB patientIdentifierFromDB = identifierDAO.retrieve(patientIdentifierDB.getFullPatientId(),
patientIdentifierDB.getIdentifierTypeCode());
if (patientIdentifierFromDB != null) {
iterator.remove();
identifiersFromDB.add(patientIdentifierFromDB);
} else if (patientIdentifierDB.getDomain() != null) {
patientIdentifierDB.setDomain(domainDAO.retrieve(patientIdentifierDB.getDomain().getUniversalID()));
}
});
}
patientDB.getPatientIdentifiers().addAll(identifiersFromDB);
try {
entityManager.persist(patientDB);
entityManager.flush();
......@@ -122,6 +142,12 @@ public class PatientDAOImpl implements PatientDAO {
}
}
/**
* Read a {@link PatientDB} from database based on its UUID
*
* @param uuid value of the Patient's UUID
* @return the {@link PatientDB}
*/
private PatientDB readPatientDB(String uuid) {
TypedQuery<PatientDB> query = entityManager.createNamedQuery("PatientDB.findByUuid", PatientDB.class);
query.setParameter("uuid", uuid);
......
......@@ -2,22 +2,29 @@ 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.HierarchicDesignatorDB;
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.
*/
public class PatientSearchCriterionJPAMappingService implements SearchCriterionJPAMappingService {
private CriteriaBuilder criteriaBuilder;
private static final String PATIENT_IDENTIFIER_ATTRIBUTE = "patientIdentifiers";
private static final String DOMAIN_ATTRIBUTE = "domain";
private EntityManager entityManager;
/**
* Constructor for injection
......@@ -25,18 +32,41 @@ public class PatientSearchCriterionJPAMappingService implements SearchCriterionJ
*/
@Inject
public PatientSearchCriterionJPAMappingService(@EntityManagerProducer.InjectEntityManager EntityManager entityManager) {
this.criteriaBuilder = entityManager.getCriteriaBuilder();
this.entityManager = entityManager;
}
/**
* {@inheritDoc}
*/
@Override
public From from(SearchCriterionKey searchCriterionKey) {
public From from(SearchCriterionKey searchCriterionKey, From from) {
PatientSearchCriterionKey patientSearchCriterionKey = castToPatientKey(searchCriterionKey);
Metamodel metamodel = entityManager.getMetamodel();
EntityType<PatientDB> entityType = metamodel.entity(PatientDB.class);
EntityType<PatientIdentifierDB> entityTypeIdentifier = metamodel.entity(PatientIdentifierDB.class);
if (PatientSearchCriterionKey.UUID.equals(patientSearchCriterionKey)) {