From 1fc320bd56242fc8631000fe4d548e04e89d982d Mon Sep 17 00:00:00 2001 From: Roeland Luykx Date: Fri, 15 Dec 2023 07:56:32 +0100 Subject: [PATCH 1/3] update dependency to latest husky-api snapshot --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6fa88bb..03f1b22 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 17 17 17 - 2.2.0 + 2.2.1-SNAPSHOT 2.7.13 3.21.0 5.10.1 From 8a3681fe1f86f784f0d408f6a1146a511832e45a Mon Sep 17 00:00:00 2001 From: Roeland Luykx Date: Fri, 2 Feb 2024 10:51:43 +0100 Subject: [PATCH 2/3] add HuskyService integration tests --- pom.xml | 29 +- .../communication/TestApplication.java | 32 ++ .../config/InitializerTestHelper.java | 67 +++ .../config/ServerTestHelper.java | 78 ++++ .../services/hpd/HpdAddFeedTest.java | 230 ++++++++++ .../services/hpd/HpdDeleteFeedTest.java | 141 ++++++ .../services/hpd/HpdSearchRequestTest.java | 346 +++++++++++++++ .../services/pdq/PdqSearchQueryTest.java | 208 +++++++++ .../services/pix/PixAddPatientTest.java | 151 +++++++ .../services/pix/PixMergePatientTest.java | 80 ++++ .../services/pix/PixQueryPatientIDTest.java | 55 +++ .../services/pix/PixUpdatePatientTest.java | 115 +++++ .../services/pix/PixV3QueryTest.java | 408 ++++++++++++++++++ .../services/svs/SvsValueSetManagerTest.java | 243 +++++++++++ .../xds/XdsFindDocumentsLowLevelTest.java | 159 +++++++ .../services/xds/XdsFindDocumentsTest.java | 269 ++++++++++++ .../xds/XdsFindFoldersStoredQueryTest.java | 48 +++ .../xds/XdsRetrieveDocumentSetTest.java | 91 ++++ .../services/xds/XdsSubmitDocumentTest.java | 269 ++++++++++++ .../services/xua/XuaClientTest.java | 252 +++++++++++ .../communication/utils/XdsTestUtils.java | 207 +++++++++ .../resources/application-atna.properties | 1 + src/test/resources/application.properties | 4 +- 23 files changed, 3476 insertions(+), 7 deletions(-) create mode 100644 src/test/java/org/projecthusky/communication/TestApplication.java create mode 100644 src/test/java/org/projecthusky/communication/config/InitializerTestHelper.java create mode 100644 src/test/java/org/projecthusky/communication/config/ServerTestHelper.java create mode 100644 src/test/java/org/projecthusky/communication/services/hpd/HpdAddFeedTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/hpd/HpdDeleteFeedTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/hpd/HpdSearchRequestTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/pdq/PdqSearchQueryTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/pix/PixAddPatientTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/pix/PixMergePatientTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/pix/PixQueryPatientIDTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/pix/PixUpdatePatientTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/pix/PixV3QueryTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/svs/SvsValueSetManagerTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsLowLevelTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/xds/XdsFindFoldersStoredQueryTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/xds/XdsRetrieveDocumentSetTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/xds/XdsSubmitDocumentTest.java create mode 100644 src/test/java/org/projecthusky/communication/services/xua/XuaClientTest.java create mode 100644 src/test/java/org/projecthusky/communication/utils/XdsTestUtils.java diff --git a/pom.xml b/pom.xml index 03f1b22..18ad85b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 org.husky.test.integration husky-integration-tests @@ -12,9 +14,11 @@ 17 17 2.2.1-SNAPSHOT - 2.7.13 + 5.3.31 + 2.7.18 3.21.0 5.10.1 + 4.7.0 3.2.2 @@ -39,9 +43,12 @@ - scm:git:https://github.com/project-husky/husky-integration-tests.git - scm:git:git@github.com:project-husky/husky-integration-tests.git - https://github.com/project-husky/husky-integration-tests/tree/master + + scm:git:https://github.com/project-husky/husky-integration-tests.git + + scm:git:git@github.com:project-husky/husky-integration-tests.git + + https://github.com/project-husky/husky-integration-tests/tree/master HEAD + *
Helping class for client testing with simulated server
+ *
+ *
+ *
+ * + */ +public abstract class ServerTestHelper extends InitializerTestHelper { + + private static Logger logger = LoggerFactory.getLogger(ServerTestHelper.class); + + private static HttpServer server; + + private static int httpPort; + + private static ServerBootstrap bootstrap; + + protected static int getHttpPort() { + return httpPort; + } + + protected static HttpServer getServer() { + return server; + } + + public static HttpRequestHandler registerHandler() { + return null; + } + + @BeforeAll + public static void setUpBefore() throws IOException { + final SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(15000) + .setTcpNoDelay(true).build(); + + bootstrap = ServerBootstrap.bootstrap(); + server = bootstrap.setServerInfo("Test/1.1").setSocketConfig(socketConfig) + .registerHandler("*", new HttpRequestHandler() { + + @Override + public void handle(HttpRequest request, HttpResponse response, + HttpContext context) throws HttpException, IOException { + logger.debug("The request %s", request.getRequestLine()); + response.setStatusCode(500); + response.setEntity(new StringEntity("Hello this is a testserver")); + } + + }).create(); + + server.start(); + httpPort = server.getLocalPort(); + + } + + @AfterAll + public static void tearDownAfter() { + server.stop(); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/hpd/HpdAddFeedTest.java b/src/test/java/org/projecthusky/communication/services/hpd/HpdAddFeedTest.java new file mode 100644 index 0000000..798b482 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/hpd/HpdAddFeedTest.java @@ -0,0 +1,230 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.hpd; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import javax.xml.bind.JAXBException; +import javax.xml.parsers.ParserConfigurationException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.requests.hpd.HpdAddFeed; +import org.projecthusky.communication.requests.hpd.HpdBatchRequest; +import org.projecthusky.communication.requests.hpd.HpdDeleteFeed; +import org.projecthusky.communication.responses.hpd.HpdResponse; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.projecthusky.xua.exceptions.SerializeException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class, + IpfApplicationConfig.class}) +class HpdAddFeedTest { + private static final String PROFESSIONAL_DN = "uid=CommunityC:11100000010,OU=HCProfessional,DC=HPD,O=BAG,C=CH"; + private static final String ORGANIZATION_DN = "uid=CommunityC:22200000010,ou=HCRegulatedOrganization,DC=HPD,O=BAG,C=CH"; + private static final String RELATIONSHIP_DN = "cn=1.1.1:1616607308848Relationship,ou=Relationship,dc=HPD,o=BAG,c=CH"; + private static final String PROFESSIONAL_UID = "CommunityC:11100000010"; + private static final String ORGANIZATION_UID = "CommunityC:22200000010"; + private static final String PROFESSIONAL_IDENTIFIER = "RefData:GLN:7601000000002:ACTIVE"; + private static final String ORGANIZATION_IDENTIFIER = "RefData:OID:1.2.1.999994:ACTIVE"; + private static final String HC_PROFESSIONAL = "HCProfessional"; + private static final String HC_PROFESSION = "BAG:2.16.840.1.113883.6.96:9343006"; + private static final String HC_ORG_PROFESSION = "BAG:2.16.840.1.113883.6.96:9343006"; + private static final String HC_REGISTRATION_STATUS = "Unknown"; + private static final String INET_ORG_PERSON = "inetOrgPerson"; + private static final String HPD_PROVIDER = "HPDProvider"; + private static final String CN = "Gregory House"; + private static final String RELATIONSHIP_CN = "1.1.1:1616607308848Relationship"; + private static final String SN = "House"; + private static final String DISPLAY_NAME = "Dr. House"; + private static final String GIVEN_NAME = "Gregory"; + private static final String ORGANIZATION_REGISTERED_NAME = "Spital Projectathon 2022"; + private static final String GROUP_OF_NAMES = "groupOfNames"; + private static final String TOP = "top"; + private static final String EXPECTED_MESSAGE = "Invalid request: mandatory constraints are not fulfilled!"; + private static final String SUCCESS = "success"; + + @Value(value = "${test.hpd.uri:https://ehealthsuisse.ihe-europe.net/HPDSimulator-ejb/ProviderInformationDirectory_Service/ProviderInformationDirectory_PortType}") + private String webserviceUri; + + @Autowired + private HuskyService huskyService; + + private Destination dest; + + @BeforeEach + void setUp() { + dest = new Destination(); + dest.setUri(URI.create(webserviceUri)); + } + + @Test + void addRequest_professionalProvider_gazelle_returnsCodeZero() throws Exception { + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCProfessional(PROFESSIONAL_DN, PROFESSIONAL_UID, + List.of(PROFESSIONAL_IDENTIFIER), List.of(HC_PROFESSIONAL, INET_ORG_PERSON, HPD_PROVIDER), null, + List.of(CN), SN, GIVEN_NAME, List.of(HC_PROFESSION), DISPLAY_NAME, List.of(HC_REGISTRATION_STATUS)); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + } + + @Test + void addRequest_regulatedOrganizationProvider_gazelle_returnsCodeZero() throws Exception { + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCRegulatedOrganization( + ORGANIZATION_DN, ORGANIZATION_UID, List.of(ORGANIZATION_IDENTIFIER), List.of(HC_PROFESSIONAL, INET_ORG_PERSON, HPD_PROVIDER), null, + List.of(HC_ORG_PROFESSION), List.of(ORGANIZATION_REGISTERED_NAME), List.of(ORGANIZATION_REGISTERED_NAME)); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + } + + @Test + void addRequest_relationshipAttributes_gazelle_returnsCodeZero() throws Exception { + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCRelationshipAttributes(HC_REGISTRATION_STATUS, + RELATIONSHIP_CN, RELATIONSHIP_DN, List.of(GROUP_OF_NAMES, TOP), null); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + assertEquals(SUCCESS, response.getDescription()); + } + + @Test + void addRequest_professionalProvider_mandatoryFieldsNullBlankOrEmptyList_shouldThrowException() { + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCProfessional(null, PROFESSIONAL_UID, + List.of(PROFESSIONAL_IDENTIFIER), List.of(HC_PROFESSIONAL, INET_ORG_PERSON, HPD_PROVIDER), null, + List.of(CN), SN, GIVEN_NAME, Collections.emptyList(), null, List.of(HC_REGISTRATION_STATUS)); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(dest) + .build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> this.huskyService.send(hpdBatchRequest)); + + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(EXPECTED_MESSAGE)); + } + + @Test + void addRequest_regulatedOrganizationProvider_mandatoryFieldsNullOrEmptyList_shouldThrowException() { + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCRegulatedOrganization( + ORGANIZATION_DN, null, List.of(ORGANIZATION_IDENTIFIER), List.of(HC_PROFESSIONAL), null, + List.of(ORGANIZATION_IDENTIFIER), List.of(ORGANIZATION_REGISTERED_NAME), Collections.emptyList()); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(dest) + .build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> this.huskyService.send(hpdBatchRequest)); + + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(EXPECTED_MESSAGE)); + } + + @Test + void addRequest_relationshipAttributes_mandatoryFieldsNullOrBlank_shouldThrowException() { + HpdAddFeed hpdAddRequest = new HpdAddFeed(); + hpdAddRequest.createHCRelationshipAttributes("", RELATIONSHIP_CN, RELATIONSHIP_DN, List.of(GROUP_OF_NAMES), null); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(dest) + .build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> this.huskyService.send(hpdBatchRequest)); + + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(EXPECTED_MESSAGE)); + } + + @Test + void addRequest_relationshipAttributes_destinationURINull_shouldThrowException() { + HpdAddFeed hpdAddRequest = new HpdAddFeed(); + hpdAddRequest.createHCRelationshipAttributes("", ORGANIZATION_UID, ORGANIZATION_DN, List.of(GROUP_OF_NAMES), + null); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest)) + .destination(new Destination()) + .build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> this.huskyService.send(hpdBatchRequest)); + + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(EXPECTED_MESSAGE)); + } + + @Test + void batchRequest_addRequestAndDeleteRequest_shouldReturnResponseCodeZero() + throws SerializeException, JAXBException, ParserConfigurationException, IOException { + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCRelationshipAttributes(HC_REGISTRATION_STATUS, + RELATIONSHIP_CN, RELATIONSHIP_DN, List.of(GROUP_OF_NAMES, TOP), null); + + HpdDeleteFeed hpdDeleteRequest = new HpdDeleteFeed(); + hpdDeleteRequest.setDistinguishedName(RELATIONSHIP_DN); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdAddRequest, hpdDeleteRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + } +} \ No newline at end of file diff --git a/src/test/java/org/projecthusky/communication/services/hpd/HpdDeleteFeedTest.java b/src/test/java/org/projecthusky/communication/services/hpd/HpdDeleteFeedTest.java new file mode 100644 index 0000000..b06a88b --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/hpd/HpdDeleteFeedTest.java @@ -0,0 +1,141 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.hpd; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.net.URI; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.requests.hpd.HpdBatchRequest; +import org.projecthusky.communication.requests.hpd.HpdDeleteFeed; +import org.projecthusky.communication.responses.hpd.HpdResponse; +import org.projecthusky.communication.services.HuskyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class, + org.projecthusky.communication.testhelper.IpfApplicationConfig.class}) +public class HpdDeleteFeedTest { + private static final String PROFESSIONAL_DN = "uid=CommunityC:11100000010,OU=HCProfessional,DC=HPD,O=BAG,C=CH"; + private static final String ORGANIZATION_DN = "uid=CommunityC:22200000010,ou=HCRegulatedOrganization,DC=HPD,O=BAG,C=CH"; + private static final String UNKNOWN_DN = "uid=Unknown,ou=HCRegulatedOrganization,DC=HPD,O=BAG,C=CH"; + private static final String EXCEPTION_MESSAGE = "Invalid request: mandatory constraints are not fulfilled!"; + + @Value(value = "${test.hpd.uri:https://ehealthsuisse.ihe-europe.net/HPDSimulator-ejb/ProviderInformationDirectory_Service/ProviderInformationDirectory_PortType}") + private String webserviceUri; + + @Autowired + private HuskyService huskyService; + + private Destination dest; + + @BeforeEach + void setUp() { + this.dest = new Destination(); + this.dest.setUri(URI.create(webserviceUri)); + } + + @Test + void deleteRequest_professionalProvider_gazelle_returnsCodeZero() throws Exception { + HpdDeleteFeed hpdDeleteRequest = new HpdDeleteFeed(); + hpdDeleteRequest.setDistinguishedName(PROFESSIONAL_DN); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdDeleteRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + } + + @Test + void deleteRequest_regulatedOrganizationProvider_gazelle_returnsCodeZero() throws Exception { + HpdDeleteFeed hpdDeleteRequest = new HpdDeleteFeed(); + hpdDeleteRequest.setDistinguishedName(ORGANIZATION_DN); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdDeleteRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + } + + @Test + void deleteRequest_relationshipAttributes_gazelle_returnsCodeZero() throws Exception { + HpdDeleteFeed hpdDeleteRequest = new HpdDeleteFeed(); + hpdDeleteRequest.setDistinguishedName(UNKNOWN_DN); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdDeleteRequest)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + assertNotNull(response); + assertEquals(0, response.getResponseCode()); + } + + @Test + void deleteRequest_nullDn_shouldThrowException() { + HpdDeleteFeed request = this.huskyService.createHpdDeleteFeed(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + assertThrows(IllegalArgumentException.class, () -> this.huskyService.send(hpdBatchRequest)); + } + + @Test + void deleteRequest_nullDestination_shouldThrowException() { + HpdDeleteFeed request = this.huskyService.createHpdDeleteFeed(); + request.setDistinguishedName(UNKNOWN_DN); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .build(); + + assertThrows(IllegalArgumentException.class, () -> this.huskyService.send(hpdBatchRequest)); + } + + @Test + void deleteRequest_nullDestinationUri_shouldThrowException() { + HpdDeleteFeed hpdDeleteRequest = this.huskyService.createHpdDeleteFeed(); + hpdDeleteRequest.setDistinguishedName(UNKNOWN_DN); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(hpdDeleteRequest)) + .destination(new Destination()) + .build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> this.huskyService.send(hpdBatchRequest)); + + String message = exception.getMessage(); + + assertEquals(EXCEPTION_MESSAGE, message); + } +} \ No newline at end of file diff --git a/src/test/java/org/projecthusky/communication/services/hpd/HpdSearchRequestTest.java b/src/test/java/org/projecthusky/communication/services/hpd/HpdSearchRequestTest.java new file mode 100644 index 0000000..51f1104 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/hpd/HpdSearchRequestTest.java @@ -0,0 +1,346 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.hpd; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.SearchRequest.DerefAliasesType; +import org.openehealth.ipf.commons.ihe.hpd.stub.dsmlv2.SearchRequest.SearchScope; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.requests.hpd.data.HpdFilterOperation; +import org.projecthusky.communication.requests.hpd.data.HpdFilterOperation.OperationType; +import org.projecthusky.communication.requests.hpd.data.HpdOperationParameters; +import org.projecthusky.communication.requests.hpd.data.HpdSimpleParameters; +import org.projecthusky.communication.requests.hpd.data.HpdSubstringParameters; +import org.projecthusky.communication.enums.HpdAttributeName; +import org.projecthusky.communication.requests.hpd.HpdAddFeed; +import org.projecthusky.communication.requests.hpd.HpdBatchRequest; +import org.projecthusky.communication.requests.hpd.HpdSearchQuery; +import org.projecthusky.communication.responses.hpd.HpdResponse; +import org.projecthusky.communication.services.HuskyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class, + org.projecthusky.communication.testhelper.IpfApplicationConfig.class}) +class HpdSearchRequestTest { + private static final String SPITAL_X = "Spital X"; + private static final String KLINIK_HOHEWEG = "Klinik Höheweg"; + private static final String PRAXIS_AM_KREUZWEG = "Praxis am Kreuzweg"; + private static final String IDENTIFIER_VALUE = "RefData:GLN:7601000000002:ACTIVE"; + private static final String DN_ORG = "ou=HCRegulatedOrganization,dc=HPD,o=BAG,c=CH"; + private static final String DN_INDIVIDUAL = "ou=HCProfessional,dc=HPD,o=BAG,c=CH"; + private static final String HOSPITAL = "Hospital"; + private static final String STARTS_WITH = "Klin"; + private static final String ENDS_WITH = "weg"; + private static final String PRACTITIONER_NAME = "Marianne Loser"; + private static final String DR_MED = "Dr. Med."; + private static final String EXCEPTION_MESSAGE = "Invalid request: mandatory constraints are not fulfilled!"; + private static final String HC_REGISTRATION_STATUS = "Unknown"; + private static final String RELATIONSHIP_CN = "1.1.1:1616607308848Relationship"; + private static final String RELATIONSHIP_DN = "cn=1.1.1:1616607308848Relationship,ou=Relationship,dc=HPD,o=BAG,c=CH"; + private static final String GROUP_OF_NAMES = "groupOfNames"; + private static final String TOP = "top"; + + @Value(value = "${test.hpd.uri:https://epdplayground.i4mi.bfh.ch:7443/HPD/services/HPDService}") + private String webserviceUri; + + @Autowired + private HuskyService huskyService; + + private Destination dest; + + @BeforeEach + public void setUp() { + this.dest = new Destination(); + this.dest.setUri(URI.create(webserviceUri)); + } + + @Test + void searchRequest_equalityMatchAndApproxMatchNeg_gazelle_returnsHospitalNameAndDesc() throws Exception { + String gazelleURI = "https://ehealthsuisse.ihe-europe.net/HPDSimulator-ejb/ProviderInformationDirectory_Service/ProviderInformationDirectory_PortType"; + dest = new Destination(); + dest.setUri(URI.create(gazelleURI)); + + HpdSimpleParameters equalityMatchOperation = HpdOperationParameters.createSimpleParameters( + HpdAttributeName.HC_REGISTERED_NAME, SPITAL_X); + + HpdSimpleParameters approxMatchOperation = + HpdOperationParameters.createSimpleParameters(HpdAttributeName.HC_IDENTIFIER, IDENTIFIER_VALUE); + + HpdFilterOperation equality = new HpdFilterOperation(false, equalityMatchOperation, OperationType.EQUALITY_MATCH); + HpdFilterOperation approx = new HpdFilterOperation(false, approxMatchOperation, OperationType.APPROX_MATCH); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .resultAttributeNames(List.of(HpdAttributeName.ORGANIZATION.getName(), HpdAttributeName.DESCRIPTION.getName())) + .isOrRequest(true) + .primitiveFilters(List.of(equality, approx)) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + Set attributeNames = response.getAttributes().keySet(); + Collection> values = response.getAttributes().values(); + + assertNotNull(response); + assertTrue(attributeNames.contains(HpdAttributeName.ORGANIZATION.getName())); + assertTrue(attributeNames.contains(HpdAttributeName.DESCRIPTION.getName())); + assertTrue(values.stream().anyMatch(list -> list.contains(SPITAL_X))); + assertTrue(values.stream().anyMatch(list -> list.contains(HOSPITAL))); + } + + @Test + void searchRequest_andOperationWithSubstringFilter_EPDPlayground_returnsKlinicAttrNameAndValue() + throws Exception { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.HC_REGISTERED_NAME, STARTS_WITH, ENDS_WITH); + + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .resultAttributeNames(List.of(HpdAttributeName.HC_REGISTERED_NAME.getName())) + .isAndRequest(true) + .primitiveFilters(List.of(substring)) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + Set attributeNames = response.getAttributes().keySet(); + Collection> values = response.getAttributes().values(); + + assertNotNull(response); + assertTrue(attributeNames.contains(HpdAttributeName.HC_REGISTERED_NAME.getName())); + assertTrue(values.stream().anyMatch(list -> list.contains(KLINIK_HOHEWEG))); + } + + @Test + void searchRequest_substringAndOperWithEqualityMatchNegated_EPDPlayground_returnsListContainingKlinikName() + throws Exception { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.HC_REGISTERED_NAME, STARTS_WITH, null); + + HpdSimpleParameters equalityMatchOperation = + HpdOperationParameters.createSimpleParameters(HpdAttributeName.HC_REGISTERED_NAME, KLINIK_HOHEWEG); + + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + HpdFilterOperation equality = new HpdFilterOperation(true, equalityMatchOperation, OperationType.EQUALITY_MATCH); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .resultAttributeNames(List.of(HpdAttributeName.HC_REGISTERED_NAME.getName())) + .isAndRequest(true) + .primitiveFilters(List.of(substring, equality)) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + Collection> values = response.getAttributes().values(); + + assertNotNull(response); + assertFalse(values.stream().anyMatch(list -> list.contains(KLINIK_HOHEWEG))); + } + + @Test + void searchRequest_equalityMatchOrganization_EPDPlayground_returnsListContainingAttrNames() throws Exception { + HpdSimpleParameters simpleParameters = HpdOperationParameters.createSimpleParameters( + HpdAttributeName.HC_REGISTERED_NAME, PRAXIS_AM_KREUZWEG); + + HpdFilterOperation filter = new HpdFilterOperation(false, simpleParameters, OperationType.EQUALITY_MATCH); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .resultAttributeNames(List.of(HpdAttributeName.HPD_PROVIDER_LANGUAGE_SUPPORTED.getName(), + HpdAttributeName.HPD_PROVIDER_PRACTICE_ADDRESS.getName())) + .primitiveFilters(List.of(filter)) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + Set attributeNames = response.getAttributes().keySet(); + + assertNotNull(response); + assertTrue(attributeNames.contains(HpdAttributeName.HPD_PROVIDER_PRACTICE_ADDRESS.getName())); + assertTrue(attributeNames.contains(HpdAttributeName.HPD_PROVIDER_LANGUAGE_SUPPORTED.getName())); + } + + @Test + void searchRequest_equalityMatchIndividualProviderSimpleOper_EPDPlayground_returnsPractitionerName() + throws Exception { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.TITLE, DR_MED, null); + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .primitiveFilters(List.of(substring)) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_INDIVIDUAL) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + HpdResponse response = this.huskyService.send(hpdBatchRequest); + + Collection> values = response.getAttributes().values(); + + assertNotNull(response); + assertTrue(values.stream().anyMatch(list -> list.contains(PRACTITIONER_NAME))); + } + + @Test + void searchRequest_mandatoryFieldsNull_shouldThrowException() { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.TITLE, DR_MED, null); + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .isAndRequest(true) + .primitiveFilters(List.of(substring)) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> this.huskyService.send(hpdBatchRequest)); + + String message = exception.getMessage(); + + assertEquals(EXCEPTION_MESSAGE, message); + } + + @Test + void searchRequest_emptyOperationList_shouldThrowException() { + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .isAndRequest(true) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE).build(); + request.setDistinguishedName(DN_ORG); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(dest) + .build(); + + assertThrows(IllegalArgumentException.class, () -> this.huskyService.send(hpdBatchRequest)); + } + + @Test + void searchRequest_nullDestination_shouldThrowException() { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.TITLE, DR_MED, null); + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .primitiveFilters(List.of(substring)) + .isAndRequest(true) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .build(); + + assertThrows(IllegalArgumentException.class, () -> this.huskyService.send(hpdBatchRequest)); + } + + @Test + void searchRequest_nullDestinationUri_shouldThrowException() { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.TITLE, DR_MED, null); + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .primitiveFilters(List.of(substring)) + .isAndRequest(true) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request)) + .destination(new Destination()) + .build(); + + assertThrows(IllegalArgumentException.class, () -> this.huskyService.send(hpdBatchRequest)); + } + + @Test + void batchRequest_searchRequestAndAddRequestTogether_shouldFailValidationAndThrowException() { + HpdSubstringParameters substringOperation = HpdOperationParameters.createSubstringParameters( + HpdAttributeName.TITLE, DR_MED, null); + HpdFilterOperation substring = new HpdFilterOperation(false, substringOperation, OperationType.SUBSTRINGS); + + HpdAddFeed hpdAddRequest = huskyService.createHpdAddFeed(); + hpdAddRequest.createHCRelationshipAttributes(HC_REGISTRATION_STATUS, + RELATIONSHIP_CN, RELATIONSHIP_DN, List.of(GROUP_OF_NAMES, TOP), null); + + HpdSearchQuery request = this.huskyService.createHpdSearchQuery() + .primitiveFilters(List.of(substring)) + .isAndRequest(true) + .derefAliases(DerefAliasesType.NEVER_DEREF_ALIASES) + .scope(SearchScope.WHOLE_SUBTREE) + .distinguishedName(DN_ORG) + .build(); + + HpdBatchRequest hpdBatchRequest = HpdBatchRequest.builder() + .hpdRequests(List.of(request, hpdAddRequest)) + .destination(dest) + .build(); + + assertThrows(IllegalArgumentException.class, () -> this.huskyService.send(hpdBatchRequest)); + } +} \ No newline at end of file diff --git a/src/test/java/org/projecthusky/communication/services/pdq/PdqSearchQueryTest.java b/src/test/java/org/projecthusky/communication/services/pdq/PdqSearchQueryTest.java new file mode 100644 index 0000000..f0a8463 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/pdq/PdqSearchQueryTest.java @@ -0,0 +1,208 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.pdq; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.net.URI; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; + +import javax.xml.bind.DataBindingException; +import javax.xml.bind.JAXBException; +import javax.xml.parsers.ParserConfigurationException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.model.Identificator; +import org.projecthusky.common.model.Name; +import org.projecthusky.common.model.Telecom; +import org.projecthusky.communication.requests.pdq.PdqSearchQuery; +import org.projecthusky.communication.responses.pdq.PdqSearchResults; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.projecthusky.fhir.structures.gen.FhirPatient; +import org.projecthusky.xua.exceptions.SerializeException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class, IpfApplicationConfig.class }) +@ActiveProfiles("atna") +public class PdqSearchQueryTest { + @Value(value = "${test.pdq.uri:https://ehealthsuisse.ihe-europe.net/PAMSimulator-ejb/PDQSupplier_Service/PDQSupplier_PortType}") + private String searchWebServiceUri; + + @Autowired + private HuskyService service; + + private Destination testWSDestination; + + @BeforeEach + public void setUp() { + String senderApplicationOidTestValue = "1.2.3.4"; + this.testWSDestination = new Destination(); + this.testWSDestination.setUri(URI.create(searchWebServiceUri)); + this.testWSDestination.setSenderApplicationOid(senderApplicationOidTestValue); + } + + @Test + public void whenQueryingForCommonPatientName_thenPatientsAreReturned() throws Exception { + Name patientName = new Name(Name.builder().withFamily("Anders").build()); + + PdqSearchQuery patientNameQuery = this.service.createPdqSearchQuery(testWSDestination).patientName(patientName).build(); + PdqSearchResults results = this.service.send(patientNameQuery); + + assertNotNull(results); + assertEquals(9, results.getPatients().size(), "Results have not the expected amount of patients."); + } + + @Test + @Disabled("This test should either return 2 or 11 results, but not 9 as it does. Probably the error is in the paging.") + //TODO: Figure out correct paging mechanism. + public void whenQueryingForCommonPatientName_thatShouldReturnOnly2Results_then2PatientsAreReturned() throws Exception { + Name patientName = new Name(Name.builder().withFamily("Sanders").build()); + + PdqSearchQuery patientNameQuery = this.service.createPdqSearchQuery(testWSDestination).patientName(patientName).build(); + PdqSearchResults results = this.service.send(patientNameQuery); + assertNotNull(results); + assertEquals(2, results.getPatients().size(), "Results have not the expected amount of patients."); + } + + @Test + public void whenQueryingForCommonPatientNameWithFuzzySearch_thenPatientsAreReturned() throws Exception { + Name patientName = new Name(Name.builder().withFamily("Anders").build()); + + PdqSearchQuery patientNameQuery = this.service.createPdqSearchQuery(testWSDestination).patientName(patientName).useFuzzyNameSearch(true).build(); + PdqSearchResults results = this.service.send(patientNameQuery); + + for (FhirPatient patient: results.getPatients()) { + System.out.println(patient); + } + assertNotNull(results); + assertEquals(9, results.getPatients().size(), "Results have not the expected amount of patients."); + } + + @Test + public void whenQueryingForPatientID_thenPatientIsReturned() throws Exception { + Identificator identificator = new Identificator("1.3.6.1.4.1.12559.11.20.1", "27"); + + PdqSearchQuery patientQuery = this.service.createPdqSearchQuery(testWSDestination).identificator(identificator).build(); + PdqSearchResults results = this.service.send(patientQuery); + assertNotNull(results); + assertEquals(1, results.getPatients().size()); + FhirPatient patient = results.getPatients().get(0); + assertNotNull(patient); + assertNull(patient.getId()); + assertEquals("1.3.6.1.4.1.12559.11.20.1", patient.getIdentificators().get(0).getRoot()); + assertEquals("Richard", patient.getName().get(0).getGivenAsSingleString()); + assertEquals("Sanders", patient.getName().get(0).getFamily()); + assertEquals("754-3310", patient.getTelecom().get(0).getValue()); + } + + @Test + public void whenQueryingForPatientBirthday_thenPatientIsReturned() throws DataBindingException, JAXBException, ParserConfigurationException, SerializeException, IOException { + LocalDate birthday = LocalDate.of(1950, 5, 31); + PdqSearchQuery patienQuery = this.service.createPdqSearchQuery(testWSDestination) + .patientDateOfBirth(Date.from(birthday.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())).build(); + PdqSearchResults results = this.service.send(patienQuery); + assertNotNull(results); + assertEquals(1, results.getPatients().size()); + + FhirPatient patient = results.getPatients().get(0); + assertNull(patient.getId()); + assertEquals("1.3.6.1.4.1.12559.11.20.1", patient.getIdentificators().get(0).getRoot()); + assertEquals("35", patient.getIdentificators().get(0).getExtension()); + assertEquals("Sherley", patient.getName().get(0).getGivenAsSingleString()); + assertEquals("Sands", patient.getName().get(0).getFamily()); + assertEquals("754-3015", patient.getTelecom().get(0).getValue()); + assertTrue(patient.getBirthDate().equals(Date.from(birthday.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))); + } + + @Test + public void whenQueryingForPatientByTelecom_thenPatientIsReturned() throws Exception { + Telecom telecomContact = new Telecom(); + telecomContact.setPhone("754-3310"); + + PdqSearchQuery patienQuery = this.service.createPdqSearchQuery(testWSDestination).telecomContact(telecomContact).build(); + PdqSearchResults results = this.service.send(patienQuery); + assertNotNull(results); + assertEquals(1, results.getPatients().size()); + FhirPatient patient = results.getPatients().get(0); + assertNotNull(patient); + assertNull(patient.getId()); + assertEquals("1.3.6.1.4.1.12559.11.20.1", patient.getIdentificators().get(0).getRoot()); + assertEquals("Richard", patient.getName().get(0).getGivenAsSingleString()); + assertEquals("Sanders", patient.getName().get(0).getFamily()); + assertEquals("754-3310", patient.getTelecom().get(0).getValue()); + } + + @Test + public void whenQueryingForPatientIDAndCommonName_thenPatientIsReturned() throws Exception { + Identificator identificator = new Identificator("1.3.6.1.4.1.12559.11.20.1", "27"); + Name patientName = new Name(Name.builder().withFamily("Sanders").build()); + + PdqSearchQuery patientQuery = this.service.createPdqSearchQuery(testWSDestination).identificator(identificator).patientName(patientName).build(); + PdqSearchResults results = this.service.send(patientQuery); + + assertNotNull(results); + assertEquals(1, results.getPatients().size()); + FhirPatient patient = results.getPatients().get(0); + assertNotNull(patient); + assertNull(patient.getId()); + assertEquals("1.3.6.1.4.1.12559.11.20.1", patient.getIdentificators().get(0).getRoot()); + assertEquals("Richard", patient.getName().get(0).getGivenAsSingleString()); + assertEquals("Sanders", patient.getName().get(0).getFamily()); + assertEquals("754-3310", patient.getTelecom().get(0).getValue()); + } + + @Test + @Disabled("This test was designed to figure out whether the search parameters are OR or AND interpreted. Looks like an AND to me.") + public void whenQueryingForMultipleParameters_thenNothingIsFound_asParametersAreInterpretedWithANDLogic() throws Exception { + Identificator identificator = new Identificator("1.3.6.1.4.1.12559.11.20.1", "27"); + Name patientName = new Name(Name.builder().withFamily("Dougon").build()); + Telecom telecomContact = new Telecom(); + telecomContact.setPhone("754-3333"); + + PdqSearchQuery patientQuery = this.service.createPdqSearchQuery(testWSDestination).identificator(identificator).patientName(patientName).telecomContact(telecomContact).build(); + PdqSearchResults results = this.service.send(patientQuery); + + assertNotNull(results); + assertEquals(1, results.getPatients().size()); + FhirPatient patient = results.getPatients().get(0); + assertNotNull(patient); + assertNull(patient.getId()); + assertEquals("1.3.6.1.4.1.12559.11.20.1", patient.getIdentificators().get(0).getRoot()); + assertEquals("Richard", patient.getName().get(0).getGivenAsSingleString()); + assertEquals("Sanders", patient.getName().get(0).getFamily()); + assertEquals("754-3310", patient.getTelecom().get(0).getValue()); + } + + @Test + @Disabled("This test does not find just the one patient with the mother specified, but finds 42. Fix is needed before it works.") + //TODO: FIxing mother's maiden name query is needed for this to work correctly. + public void whenQueryingForMothersMaidenName_thenPatientsAreFound() throws DataBindingException, JAXBException, ParserConfigurationException, SerializeException, IOException { + Name patientName = new Name(Name.builder().withFamily("Ramelet").build()); + PdqSearchQuery patientQuery = this.service.createPdqSearchQuery(testWSDestination).mothersMaidenName(patientName).build(); + PdqSearchResults results = this.service.send(patientQuery); + assertNotNull(results); + assertEquals(1, results.getPatients().size()); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/pix/PixAddPatientTest.java b/src/test/java/org/projecthusky/communication/services/pix/PixAddPatientTest.java new file mode 100644 index 0000000..131decd --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/pix/PixAddPatientTest.java @@ -0,0 +1,151 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.pix; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.net.URI; +import java.text.SimpleDateFormat; + +import javax.xml.bind.JAXBException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.ws.soap.SOAPFaultException; + +import org.hl7.fhir.r4.model.Address; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.ContactPoint; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointUse; +import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.r4.model.HumanName; +import org.hl7.fhir.r4.model.HumanName.NameUse; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.codesystems.V3MaritalStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.enums.CountryCode; +import org.projecthusky.communication.requests.pix.PixAddPatientFeed; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.projecthusky.fhir.structures.gen.FhirCommon; +import org.projecthusky.xua.exceptions.SerializeException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class, IpfApplicationConfig.class }) +@ActiveProfiles("atna") +public class PixAddPatientTest { + @Value(value = "${test.pixq.uri:https://ehealthsuisse.ihe-europe.net/PAMSimulator-ejb/PIXManager_Service/PIXManager_PortType}") + private String searchWebServiceUri; + + @Autowired + private HuskyService service; + + private Destination testWSDestination; + + final private String homeCommunityOid = "1.3.6.1.4.1.12559.11.20.1"; + + final private String spidEprOid = "2.16.756.5.30.1.127.3.10.3"; + + @BeforeEach + public void setUp() { + String senderApplicationOidTestValue = "1.2.3.4"; + String receiverApplicationOid = "1.3.6.1.4.1.12559.11.20.1.10"; + this.testWSDestination = new Destination(); + this.testWSDestination.setUri(URI.create(searchWebServiceUri)); + this.testWSDestination.setSenderApplicationOid(senderApplicationOidTestValue); + this.testWSDestination.setReceiverApplicationOid(receiverApplicationOid); + } + + @Test + public void addPatient() throws Exception { + Organization organization = new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid))); + PixAddPatientFeed query = this.service.createPixAddPatientFeed(testWSDestination, organization) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(spidEprOid)) + .patientName(new HumanName().setFamily("Anders").addGiven("Miriam").addGiven("Maria").addPrefix("Dr.").addSuffix("Msc.").setUse(NameUse.OFFICIAL)) + .birthday(new SimpleDateFormat("dd.MM.yyyy").parse("24.03.1950")) + .gender(AdministrativeGender.OTHER) + .mothersMaidenName(new HumanName().setFamily("Müllers")) + .address(new Address().addLine("Hauptstrasse 11").setPostalCode("3002").setCity("Purkersdorf").setState("Niederösterreich").addLine("Eingang 2, Tür 34").setCountry("AUT")) + .nation(new CodeableConcept().setText(CountryCode.AUSTRIA.getCodeAlpha3())) + .religion(new CodeableConcept().setText("Agnostic")) + .maritalStatus(new CodeableConcept().addCoding(new Coding(null, V3MaritalStatus.S.toCode(), V3MaritalStatus.S.getDisplay()))) + .language(new CodeableConcept().setText("de-AT")) + .language(new CodeableConcept().setText("en")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.HOME).setSystem(ContactPointSystem.PHONE).setValue("+4366793384455")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.WORK).setSystem(ContactPointSystem.PHONE).setValue("+4366793384400")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.MOBILE).setSystem(ContactPointSystem.PHONE).setValue("+4366793384433")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.WORK).setSystem(ContactPointSystem.EMAIL).setValue("sunshine@garten.at")) + .employeeOccupation(new CodeableConcept().setText("Senior Lamp Technicial")) + .build(); + assertTrue(this.service.send(query)); + } + + @Test + public void addMinimalPatient() throws JAXBException, SerializeException, ParserConfigurationException, IOException { + Organization organization = new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid))); + PixAddPatientFeed query = this.service.createPixAddPatientFeed(testWSDestination, organization) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(spidEprOid)) + .patientName(new HumanName().setFamily("Anders").addGiven("Miriam").addGiven("Maria").addPrefix("Dr.").addSuffix("Msc.").setUse(NameUse.OFFICIAL)) + .build(); + assertTrue(this.service.send(query)); + } + + @Test + @Disabled("This test is to prove that adding a patient without a name works (unfortunately).") + public void addSubminimalPatient() throws JAXBException, SerializeException, ParserConfigurationException, IOException { + Organization organization = new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid))); + PixAddPatientFeed query = this.service.createPixAddPatientFeed(testWSDestination, organization) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(spidEprOid)) + .build(); + assertTrue(this.service.send(query)); + } + + @Test + public void addSubminimalPatient_notEvenID() { + RuntimeException exception = assertThrows(RuntimeException.class, () -> { + PixAddPatientFeed query = this.service.createPixAddPatientFeed(testWSDestination, + new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid)))) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .build(); + assertTrue(this.service.send(query)); + }); + assertTrue(exception.getCause() instanceof SOAPFaultException); + assertEquals("javax.xml.ws.soap.SOAPFaultException: A patient must contain exactly 2 patient identifier (1 provided)", exception.getMessage()); + } + + @Test + @Disabled("This is a showcase test: what happens when the scoping organization is missing (SOAPFaultExpetion). Case is prevented by the current builder logic in the query.") + public void addSubminimalPatient_noScopingOrganization() { + RuntimeException exception = assertThrows(RuntimeException.class, () -> { + PixAddPatientFeed query = this.service.createPixAddPatientFeed(testWSDestination, null) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue(String.valueOf(System.currentTimeMillis())).setSystem(spidEprOid)) + .build(); + assertTrue(this.service.send(query)); + }); + assertTrue(exception.getCause() instanceof SOAPFaultException); + assertEquals("javax.xml.ws.soap.SOAPFaultException: providerOrganization is missing", exception.getMessage()); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/pix/PixMergePatientTest.java b/src/test/java/org/projecthusky/communication/services/pix/PixMergePatientTest.java new file mode 100644 index 0000000..d4a1753 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/pix/PixMergePatientTest.java @@ -0,0 +1,80 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.pix; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.text.SimpleDateFormat; + +import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Organization; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.requests.pix.PixMergePatientFeed; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.projecthusky.fhir.structures.gen.FhirCommon; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class, IpfApplicationConfig.class }) +@ActiveProfiles("atna") +public class PixMergePatientTest { + + @Value(value = "${test.pixq.uri:https://ehealthsuisse.ihe-europe.net/PAMSimulator-ejb/PIXManager_Service/PIXManager_PortType}") + private String mergeWebServiceUri; + + @Autowired + private HuskyService service; + + private Destination testWSDestination; + private Organization testScopingOrganization; + + final private String receiverApplicationOid = "1.3.6.1.4.1.12559.11.20.1.10"; + final private String senderApplicationOid = "1.2.3.4"; + + final private String homeCommunityOid = "1.3.6.1.4.1.12559.11.20.1"; + final private String homeCommunityNamespace = "CHPAM2"; + + final private String spidEprOid = "2.16.756.5.30.1.127.3.10.3"; + + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); + + @BeforeEach + public void setUp() { + this.testWSDestination = new Destination(); + this.testWSDestination.setUri(URI.create(mergeWebServiceUri)); + this.testWSDestination.setSenderApplicationOid(senderApplicationOid); + this.testWSDestination.setReceiverApplicationOid(receiverApplicationOid); + + this.testScopingOrganization = new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid))); + } + + @Test + void whenBuildingMergeFeed_andSendingWithService_thenPatientIsMerged() throws Exception { + String obsolatePatientId = "1634721569120"; + PixMergePatientFeed feed = this.service.createPixMergePatientFeed(testWSDestination, testScopingOrganization, + obsolatePatientId, homeCommunityOid, homeCommunityNamespace) + .identifier(new Identifier().setValue("1634641399206").setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue("SPID-1").setSystem(FhirCommon.addUrnOid(spidEprOid))) + .homeCommunityOID(homeCommunityOid).homeCommunityNamespace(homeCommunityNamespace) + .obsolatePatientID("1634721569120") + .birthday(this.dateFormat.parse("19500324")) + .gender(AdministrativeGender.MALE) + .build(); + assertTrue(this.service.send(feed)); + } +} diff --git a/src/test/java/org/projecthusky/communication/services/pix/PixQueryPatientIDTest.java b/src/test/java/org/projecthusky/communication/services/pix/PixQueryPatientIDTest.java new file mode 100644 index 0000000..39614ea --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/pix/PixQueryPatientIDTest.java @@ -0,0 +1,55 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + * + */ +package org.projecthusky.communication.services.pix; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.net.URI; + +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.requests.pix.PixPatientIDQuery; +import org.projecthusky.communication.responses.pix.PixPatientIDResult; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class, + IpfApplicationConfig.class}) +@ActiveProfiles("atna") +public class PixQueryPatientIDTest { + + @Autowired + private HuskyService service; + + @Value(value = "${test.pixq.uri:https://ehealthsuisse.ihe-europe.net/PAMSimulator-ejb/PIXManager_Service/PIXManager_PortType}") + private String pixUri; + + @Test + void test1() throws Exception { + Destination destination = new Destination(); + destination.setUri(URI.create(pixUri)); + destination.setSenderApplicationOid("1.2.3.4"); + destination.setReceiverApplicationOid("1.3.6.1.4.1.12559.11.20.1.10"); + + PixPatientIDQuery query = this.service.createPixPatientIDQuery(destination) + .homeCommunityPatientOid("waldspital-Id-1234").homeCommunityOid("2.16.756.5.30.1.127.3.10.3") + .homeCommunityNamespace("WALDSPITAL") + .build(); + PixPatientIDResult result = this.service.send(query); + assertNotNull(result); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/pix/PixUpdatePatientTest.java b/src/test/java/org/projecthusky/communication/services/pix/PixUpdatePatientTest.java new file mode 100644 index 0000000..1b8d6a0 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/pix/PixUpdatePatientTest.java @@ -0,0 +1,115 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + * + */ +package org.projecthusky.communication.services.pix; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import javax.xml.bind.JAXBException; +import javax.xml.parsers.ParserConfigurationException; + +import org.hl7.fhir.r4.model.Address; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.ContactPoint; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointUse; +import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.r4.model.HumanName; +import org.hl7.fhir.r4.model.HumanName.NameUse; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.codesystems.V3MaritalStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.enums.CountryCode; +import org.projecthusky.communication.requests.pix.PixUpdatePatientFeed; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.fhir.structures.gen.FhirCommon; +import org.projecthusky.xua.exceptions.SerializeException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class }) +@ActiveProfiles("atna") +public class PixUpdatePatientTest { + + @Value(value = "${test.pixq.uri:https://ehealthsuisse.ihe-europe.net/PAMSimulator-ejb/PIXManager_Service/PIXManager_PortType}") + private String searchWebServiceUri; + + @Autowired + private HuskyService service; + + private Destination testWSDestination; + + final private String homeCommunityOid = "1.3.6.1.4.1.12559.11.20.1"; + final private String spidEprOid = "2.16.756.5.30.1.127.3.10.3"; + + @BeforeEach + public void setUp() { + String senderApplicationOidTestValue = "1.2.3.4"; + String receiverApplicationOid = "1.3.6.1.4.1.12559.11.20.1.10"; + this.testWSDestination = new Destination(); + this.testWSDestination.setUri(URI.create(searchWebServiceUri)); + this.testWSDestination.setSenderApplicationOid(senderApplicationOidTestValue); + this.testWSDestination.setReceiverApplicationOid(receiverApplicationOid); + } + + @Test + public void updatePatient() throws ParseException, JAXBException, SerializeException, ParserConfigurationException, IOException { + Organization organization = new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid))); + PixUpdatePatientFeed feed = this.service.createPixUpdatePatientFeed(testWSDestination, organization) + .identifier(new Identifier().setValue("1634793774730").setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue("SPID-101").setSystem(spidEprOid)) + .patientName(new HumanName().setFamily("Anton").addGiven("Bauer-Maier").addPrefix("Dr.").addSuffix("Msc.").setUse(NameUse.OFFICIAL)) + .birthday(new SimpleDateFormat("dd.MM.yyyy").parse("24.04.1955")) + .gender(AdministrativeGender.MALE) + .mothersMaidenName(new HumanName().setFamily("Müllers")) + .address(new Address().addLine("Testgasse 88").setPostalCode("1020").setCity("Wien").setState("Wien").addLine("Eingang 2, Tür 34").setCountry("AUT")) + .nation(new CodeableConcept().setText(CountryCode.AUSTRIA.getCodeAlpha3())) + .religion(new CodeableConcept().setText("Agnostic")) + .maritalStatus(new CodeableConcept().addCoding(new Coding(null, V3MaritalStatus.M.toCode(), V3MaritalStatus.M.getDisplay()))) + .language(new CodeableConcept().setText("de-AT")) + .language(new CodeableConcept().setText("en")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.HOME).setSystem(ContactPointSystem.PHONE).setValue("+4366793385111")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.WORK).setSystem(ContactPointSystem.PHONE).setValue("+4366793385222")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.MOBILE).setSystem(ContactPointSystem.PHONE).setValue("+4366793384433")) + .telecomContact(new ContactPoint().setUse(ContactPointUse.WORK).setSystem(ContactPointSystem.EMAIL).setValue("anton.chiguhr@texasstate.us")) + .employeeOccupation(new CodeableConcept().setText("Chief Solver")) + .build(); + assertTrue(this.service.send(feed)); + } + + /** + * WARNING!
+ * As stated in the documentation, this will remove all other infos about a patient than the IDs and the organization providing it. Use like this only for testing purposes! + */ + @Test + @Disabled("This test is disabled because how the webservice works (replace vs. update, see query documentation), but is fully working if enabled.") + public void updatePatientWithAbsoluteMinimalInformation() throws JAXBException, SerializeException, ParserConfigurationException, IOException { + Organization organization = new Organization().addIdentifier(new Identifier().setValue("Husky").setSystem(FhirCommon.addUrnOid(homeCommunityOid))); + PixUpdatePatientFeed feed = this.service.createPixUpdatePatientFeed(testWSDestination, organization) + .identifier(new Identifier().setValue("1634793774730").setSystem(FhirCommon.addUrnOid(homeCommunityOid))) + .identifier(new Identifier().setValue("SPID-101").setSystem(spidEprOid)) + .build(); + assertTrue(this.service.send(feed)); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/pix/PixV3QueryTest.java b/src/test/java/org/projecthusky/communication/services/pix/PixV3QueryTest.java new file mode 100644 index 0000000..45d5dde --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/pix/PixV3QueryTest.java @@ -0,0 +1,408 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + * + */ +package org.projecthusky.communication.services.pix; + + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import org.hl7.fhir.dstu2016may.model.codesystems.V3MaritalStatus; +import org.hl7.fhir.r4.model.Address; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.ContactPoint; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointUse; +import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.r4.model.HumanName; +import org.hl7.fhir.r4.model.HumanName.NameUse; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Patient.PatientCommunicationComponent; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.openehealth.ipf.commons.audit.AuditContext; +import org.projecthusky.common.communication.AffinityDomain; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.enums.CountryCode; +import org.projecthusky.communication.ConvenienceMasterPatientIndexV3; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.mpi.impl.PixV3Query; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.projecthusky.fhir.structures.gen.FhirCommon; +import org.projecthusky.fhir.structures.gen.FhirPatient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * See https://pixpdqtests.nist.gov/pixpdqtool/ IHE PIX and PDQ Pre-Connectathon + * Test Tool + * + * Configuration for 2015 Europe + * + * Application Name: provided by test tool Facility Name: provided by test tool + * IP Address: provided by test tool Port Number: V3 Message (Non Secure: 9090 ) + * + * ATTENTION: You need to start the testtool and need to get the parameters from + * webpage otherwise the test will not run through, you need also to remove + * the @Ignore to perform the tests directly + */ +@ExtendWith(value = SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class, IpfApplicationConfig.class }) +class PixV3QueryTest { + + /** The SLF4J logger instance. */ + protected static Logger log = LoggerFactory.getLogger(PixV3QueryTest.class); + + @Autowired + private ConvenienceMasterPatientIndexV3 convenienceMasterPatientIndexV3Client; + + @Autowired + protected AuditContext auditContext; + + // note: fill below in from test tool before running test and remove @Ignore + // Annotation above to run the tests manual + @Value(value = "${test.pixq.uri:https://ehealthsuisse.ihe-europe.net/PAMSimulator-ejb/PIXManager_Service/PIXManager_PortType}") + private String pixUri; + + final private String facilityName = null; // "2.16.840.1.113883.3.72.6.1"; + + final private String receiverApplicationOid = "1.3.6.1.4.1.12559.11.20.1.10"; + final private String senderApplicationOid = "1.2.3.4"; + + final private String homeCommunityOid = "1.3.6.1.4.1.12559.11.20.1"; + final private String homeCommunityNamespace = "CHPAM2"; + + final private String spidEprOid = "2.16.756.5.30.1.127.3.10.3"; + final private String spidEprNamespace = "SPID"; + + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); + + private Organization getScopingOrganization() { + final Organization org = new Organization(); + final Identifier identifier = new Identifier(); + identifier.setValue("Husky"); + identifier.setSystem(FhirCommon.addUrnOid(homeCommunityOid)); + org.getIdentifier().add(identifier); + return org; + } + + /** + * Method implementing + * + * @throws java.lang.Exception + */ + @BeforeEach + public void setUp() throws Exception { + var app = new SpringApplication(TestApplication.class); + app.setWebApplicationType(WebApplicationType.NONE); + app.run(); + } + + @Test + void contextLoads() { + assertNotNull(convenienceMasterPatientIndexV3Client); + assertNotNull(convenienceMasterPatientIndexV3Client.getContext()); + assertNotNull(auditContext); + } + + /** + * The purpose of this test is to check that your PIX Source can send a valid + * feed message (Patient Registry Record Added : PRPA_IN201301UV02). Your PIX + * Source is required to register a patient in domain 1.3.6.1.4.1.12559.11.20.1 + * (CHPAM2). + * + * Send a valid feed message (PRPA_IN201301UV02) to the PIX Manager. The message + * shall contain a patient in domain CHPAM2 with all possible optional data provided + * The NIST PIX Manager sends back an acknowledgement + * (MCCI_IN000002UV01) back to your PIX Source. + */ + + @Test + void ITI44SourceFeedTest() { + + log.debug("ITI44SourceFeedTest with target " + pixUri); + + final AffinityDomain affinityDomain = new AffinityDomain(); + final Destination dest = new Destination(); + + dest.setUri(URI.create(pixUri)); + dest.setSenderApplicationOid(senderApplicationOid); + dest.setReceiverApplicationOid(receiverApplicationOid); + dest.setReceiverFacilityOid(facilityName); + affinityDomain.setPdqDestination(dest); + affinityDomain.setPixDestination(dest); + + PixV3Query pixV3Query = new PixV3Query(affinityDomain, homeCommunityOid, homeCommunityNamespace, spidEprOid, spidEprNamespace, + convenienceMasterPatientIndexV3Client.getContext(), + convenienceMasterPatientIndexV3Client.getAuditContext()); + + final FhirPatient patient = new FhirPatient(); + + final Identifier identifier = new Identifier(); + identifier.setValue(String.valueOf(System.currentTimeMillis())); + identifier.setSystem(FhirCommon.addUrnOid(homeCommunityOid)); + patient.getIdentifier().add(identifier); + + + final Identifier identifier2 = new Identifier(); + identifier2.setValue(String.valueOf(System.currentTimeMillis())); + identifier2.setSystem(spidEprOid); + patient.getIdentifier().add(identifier2); + + + final HumanName humanName = new HumanName().setFamily("Anders").addGiven("Miriam").addGiven("Maria").addPrefix("Dr.").addSuffix("Msc.").setUse( + NameUse.OFFICIAL); + patient.getName().add(humanName); + + try { + patient.setBirthDate(new SimpleDateFormat("dd.MM.yyyy").parse("24.03.1950")); + } catch (ParseException e) { + e.printStackTrace(); + } + System.out.println("Patient birthday:" + patient.getBirthDateElement().getValueAsString() + " and " + patient.getBirthDateElement().getValueAsString().replace("-", "")); + + patient.setGender(AdministrativeGender.OTHER); + + final HumanName mothersMaidenName = new HumanName(); + mothersMaidenName.setFamily("Müller"); + patient.setMothersMaidenName(mothersMaidenName); + + + final Address address = new Address() + .addLine("Testgasse 1").setPostalCode("8010").setCity("Graz").setState("Steiermark").addLine("Eingang 2, Tür 34"); + address.setCountry("AUT"); + patient.getAddress().add(address); + + final CodeableConcept nation = new CodeableConcept(); + nation.setText(CountryCode.AUSTRIA.getCodeAlpha3()); + patient.setNation(nation); + + final CodeableConcept religion = new CodeableConcept(); + religion.setText("Agnostic"); + patient.setReligiousAffiliation(religion); + + + final CodeableConcept maritalStatus = new CodeableConcept(); + maritalStatus.addCoding(new Coding(null, V3MaritalStatus.S.toCode(), V3MaritalStatus.S.getDisplay()));// single + patient.setMaritalStatus(maritalStatus); + + final CodeableConcept deAT = new CodeableConcept(); + deAT.setText("de-AT"); + final CodeableConcept en = new CodeableConcept(); + en.setText("en"); + + patient.getCommunication().add(new PatientCommunicationComponent().setLanguage(deAT)); + patient.getCommunication().add(new PatientCommunicationComponent().setLanguage(en)); + + final ContactPoint telHome = new ContactPoint(); + telHome.setUse(ContactPointUse.HOME); + telHome.setSystem(ContactPointSystem.PHONE); + telHome.setValue("+431000000000"); + + final ContactPoint telWork = new ContactPoint(); + telWork.setUse(ContactPointUse.WORK); + telWork.setSystem(ContactPointSystem.PHONE); + telWork.setValue("+431000000000"); + + final ContactPoint telMobile = new ContactPoint(); + telMobile.setUse(ContactPointUse.MOBILE); + telMobile.setSystem(ContactPointSystem.PHONE); + telMobile.setValue("+4366400000000"); + + final ContactPoint eMail = new ContactPoint(); + eMail.setUse(ContactPointUse.WORK); + eMail.setSystem(ContactPointSystem.EMAIL); + eMail.setValue("xyz@abc.at"); + + patient.getTelecom().add(telHome); + patient.getTelecom().add(telWork); + patient.getTelecom().add(telMobile); + patient.getTelecom().add(eMail); + + final CodeableConcept employeeOccupationCode = new CodeableConcept(); + employeeOccupationCode.setText("employeeOccupationCode"); + patient.setEmployeeOccupation(employeeOccupationCode); + + patient.getManagingOrganization().setResource(getScopingOrganization()); + + + final FhirContext ctx = new FhirContext(FhirVersionEnum.R4); + final String encoded = ctx.newXmlParser().encodeResourceToString(patient); + log.debug(encoded); + + assertTrue(pixV3Query.addPatient(patient, null, null)); +// pixV3Query.mergePatient(patient, encoded, null, encoded); + + } + + + /** + * The purpose of this test is to check that your PIX Source can send an merge + * message (Patient Registry Duplicates Resolved : PRPA_IN201304UV02). + * + * Send a valid merge message (PRPA_IN201304UV02) to the PIX Manager. The + * message shall contain patient Maier Hubert in domain CHPAM2 replacement + * of ID 1634721569120 (Maier Hubertus) in domain CHPAM2. The PIX Manager sends an + * acknowledgement (MCCI_IN000002UV01) back to your PIX Source. + * @throws ParseException + */ + + @Test + void ITI44SourceMergeTest() throws ParseException { + log.debug("ITI44SourceMergeTest with target {}", pixUri); + + final AffinityDomain affinityDomain = new AffinityDomain(); + final Destination dest = new Destination(); + + dest.setUri(URI.create(pixUri)); + dest.setSenderApplicationOid(senderApplicationOid); + dest.setReceiverApplicationOid(receiverApplicationOid); + dest.setReceiverFacilityOid(facilityName); + affinityDomain.setPdqDestination(dest); + affinityDomain.setPixDestination(dest); + + PixV3Query pixV3Query = new PixV3Query(affinityDomain, homeCommunityOid, homeCommunityNamespace, null, null, + convenienceMasterPatientIndexV3Client.getContext(), + convenienceMasterPatientIndexV3Client.getAuditContext()); + + final FhirPatient patient = new FhirPatient(); + final HumanName humanName = new HumanName().setFamily("Maier").addGiven("Hubert"); + patient.getName().add(humanName); + + final Identifier identifier = new Identifier(); + identifier.setValue("1634641399206"); + identifier.setSystem(FhirCommon.addUrnOid(homeCommunityOid)); + patient.getIdentifier().add(identifier); + + final Identifier identifier2 = new Identifier(); + identifier2.setValue("SPID-1"); + identifier2.setSystem(spidEprOid); + patient.getIdentifier().add(identifier2); + + patient.setBirthDate(this.dateFormat.parse("19500324")); + patient.setGender(AdministrativeGender.MALE); + patient.getManagingOrganization().setResource(getScopingOrganization()); + + final FhirContext ctx = new FhirContext(FhirVersionEnum.R4); + final String encoded = ctx.newXmlParser().encodeResourceToString(patient); + log.debug(encoded); + + assertTrue(pixV3Query.mergePatient(patient, "1634721569120", null, null)); + } + + /** + * The purpose of this test is to update family name, address of patient, gender and birthdate + * of patient identified by id 1634793774730 + * + * ids of patient in patient manager + * 761337610436974489^^^&1.3.6.1.4.1.21367.2017.2.5.10& + * CHPAM4489^^^&1.3.6.1.4.1.12559.11.20.1& + * @throws ParseException + */ + + @Test + void ITI44SourceUpdateTest() throws ParseException { + final AffinityDomain affinityDomain = new AffinityDomain(); + final Destination dest = new Destination(); + + dest.setUri(URI.create(pixUri)); + dest.setSenderApplicationOid(senderApplicationOid); + dest.setReceiverApplicationOid(receiverApplicationOid); + dest.setReceiverFacilityOid(facilityName); + affinityDomain.setPdqDestination(dest); + affinityDomain.setPixDestination(dest); + + PixV3Query pixV3Query = new PixV3Query(affinityDomain, homeCommunityOid, homeCommunityNamespace, null, null, + convenienceMasterPatientIndexV3Client.getContext(), + convenienceMasterPatientIndexV3Client.getAuditContext()); + + + final FhirPatient patient = new FhirPatient(); + final HumanName humanName = new HumanName().setFamily("Bauer-Maier").addGiven("Anton"); + patient.getName().add(humanName); + final org.hl7.fhir.r4.model.Address address = new org.hl7.fhir.r4.model.Address() + .addLine("Testgasse 18").setPostalCode("1020").setCity("Wien").setState("AUT"); + final Identifier identifier = new Identifier(); + identifier.setValue("1634793774730"); + identifier.setSystem(FhirCommon.addUrnOid(homeCommunityOid)); + patient.getIdentifier().add(identifier); + + final Identifier identifier2 = new Identifier(); + identifier2.setValue("SPID-101"); + identifier2.setSystem(spidEprOid); + patient.getIdentifier().add(identifier2); + + patient.setBirthDate(this.dateFormat.parse("19500324")); + patient.getAddress().add(address); + patient.setGender(AdministrativeGender.MALE); + patient.getManagingOrganization().setResource(getScopingOrganization()); + + final FhirContext ctx = new FhirContext(FhirVersionEnum.R4); + final String encoded = ctx.newXmlParser().encodeResourceToString(patient); + log.debug(encoded); + + assertTrue(pixV3Query.updatePatient(patient, null, null)); + } + + + /** + * The purpose of this test is to cross reference id of patient Léo Gerard + * retrieve SPID of patient using home community ID CHPAM4489 + * + * ids of patient in patient manager + * 761337610436974489^^^&1.3.6.1.4.1.21367.2017.2.5.10& + * CHPAM4489^^^&1.3.6.1.4.1.12559.11.20.1& + */ + @Test + void ITI45ConsumerTest() { + + log.debug("ITI45ConsumerTest with target " + pixUri); + final AffinityDomain affinityDomain = new AffinityDomain(); + final Destination dest = new Destination(); + + dest.setUri(URI.create(pixUri)); + dest.setSenderApplicationOid(senderApplicationOid); + dest.setReceiverApplicationOid(receiverApplicationOid); + dest.setReceiverFacilityOid(facilityName); + affinityDomain.setPdqDestination(dest); + affinityDomain.setPixDestination(dest); + + PixV3Query pixV3Query = new PixV3Query(affinityDomain, homeCommunityOid, homeCommunityNamespace, + spidEprOid, spidEprNamespace, + convenienceMasterPatientIndexV3Client.getContext(), + convenienceMasterPatientIndexV3Client.getAuditContext()); + + final FhirPatient patient = new FhirPatient(); + final Identifier identifier = new Identifier(); + identifier.setValue("CHPAM4489"); + identifier.setSystem(FhirCommon.addUrnOid(homeCommunityOid)); + patient.getIdentifier().add(identifier); + + String patId = pixV3Query.queryPatientId(patient, null, null); + + assertEquals("761337610436974489", patId); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/svs/SvsValueSetManagerTest.java b/src/test/java/org/projecthusky/communication/services/svs/SvsValueSetManagerTest.java new file mode 100644 index 0000000..5309b92 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/svs/SvsValueSetManagerTest.java @@ -0,0 +1,243 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + * + */ +package org.projecthusky.communication.services.svs; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import javax.xml.parsers.ParserConfigurationException; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; +import org.projecthusky.common.basetypes.IdentificatorBaseType; +import org.projecthusky.common.utils.LangText; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.requests.svs.SvsValueSetRequest; +import org.projecthusky.communication.responses.svs.SvsValueSetResponse; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.valueset.api.ValueSetManager; +import org.projecthusky.valueset.config.ValueSetConfig; +import org.projecthusky.valueset.enums.SourceFormatType; +import org.projecthusky.valueset.enums.SourceSystemType; +import org.projecthusky.valueset.exceptions.InitializationException; +import org.projecthusky.valueset.model.ValueSet; +import org.projecthusky.valueset.model.ValueSetEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.xml.sax.SAXException; + +/** + * The Test Class for ValueSetManager with downloading value sets from ART-DECOR. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { + TestApplication.class}) +@EnableAutoConfiguration +class SvsValueSetManagerTest { + + @Autowired + private HuskyService huskyService; + + /** + * This test checks the behavior of the {@link ValueSetManager#downloadValueSetRaw(ValueSetConfig)} when downloading + * value sets as a byte array. As an example the possible values for EprAuthorRole (2.16.756.5.30.1.127.3.10.1) are + * downloaded. + * + * @throws MalformedURLException + * @throws IOException + */ + @Test + void downloadRawTest() + throws MalformedURLException, IOException, ParserConfigurationException, InitializationException, SAXException { + String testUrl = "https://art-decor.org/decor/services/RetrieveValueSet?prefix=ch-epr-&format=json&id=2.16.756.5.30.1.127.3.10.1"; + + // download expected values from fixed URL + String downloadedString = IOUtils.toString(new URL(testUrl), StandardCharsets.UTF_8); + + // configure URL and the source system type for downloading value sets + SvsValueSetRequest valueSetRequest = this.huskyService.createValueSetRequest() + .sourceSystemType(SourceSystemType.ARTDECOR_FHIR) + .sourceUrl(testUrl) + .build(); + + // download value sets + SvsValueSetResponse downloadedByteArray = this.huskyService.send(valueSetRequest, true); + String byteArrayString = new String(downloadedByteArray.getValueSetRaw(), + StandardCharsets.UTF_8); + assertEquals(downloadedString, byteArrayString); + } + + /** + * This test checks the behavior of the {@link ValueSetManager#downloadValueSetRaw(ValueSetConfig)} when downloading + * value sets with an ID, which doesn't exist. As an example the possible values for EprAuthorRole + * (2.16.756.5.30.1.127.3.10.1) are downloaded. + * + * @throws IOException + */ + @Test + void downloadRawUnknownIdTest() + throws IOException, ParserConfigurationException, InitializationException, SAXException { + // id in URL doesn't exists + String testUrl = "https://art-decor.org/decor/services/RetrieveValueSet?prefix=ch-epr-&format=json&id=1.2.3.4.5"; + + // configure URL and the source system type for downloading value sets + SvsValueSetRequest valueSetRequest = this.huskyService.createValueSetRequest() + .sourceSystemType(SourceSystemType.ARTDECOR_FHIR) + .sourceUrl(testUrl) + .build(); + + // download value sets + SvsValueSetResponse downloadedByteArray = this.huskyService.send(valueSetRequest, true); + String byteArrayString = new String(downloadedByteArray.getValueSetRaw(), + StandardCharsets.UTF_8); + assertEquals("null", byteArrayString); + } + + /** + * This test checks the behavior of the {@link ValueSetManager#downloadValueSet(ValueSetConfig)} when downloading + * value sets as {@link ValueSet} in JSON, XML or IHE SVS format. As an example the possible values for + * DocumentEntry.author.authorRole (2.16.756.5.30.1.127.3.10.1.1.3) are downloaded. + * + * @throws IOException + * @throws ParserConfigurationException + * @throws SAXException + * @throws InitializationException + */ + @Test + void downloadValueSetTest() + throws IOException, ParserConfigurationException, InitializationException, SAXException { + String baseUrlJson = "https://art-decor.org/decor/services/RetrieveValueSet?prefix=ch-epr-&format=json"; + String baseUrlIheSvs = "https://art-decor.org/decor/services/RetrieveValueSet?prefix=ch-epr-&format=svs"; + String baseUrlXml = "https://art-decor.org/decor/services/RetrieveValueSet?prefix=ch-epr-&format=xml"; + + String projectFolder = "../../common/husky-common-ch/src/main/java/org/husky/common/ch/enums"; + SourceSystemType sourceSystemType = SourceSystemType.ARTDECOR_FHIR; + + String className1 = "AuthorRole"; + IdentificatorBaseType authorRoleId = IdentificatorBaseType.builder() + .withRoot("2.16.756.5.30.1.127.3.10.1.1.3").build(); + Date authorRoleTimeStamp = new GregorianCalendar(2018, Calendar.JUNE, 13, 7, 40, 11).getTime(); + URL authorRoleSourceUrlJson; + String authorRoleSourceUrlJsonString = ""; + + authorRoleSourceUrlJson = ValueSetManager.buildValueSetArtDecorUrl(baseUrlJson, + authorRoleId, authorRoleTimeStamp); + authorRoleSourceUrlJsonString = authorRoleSourceUrlJson.toString(); + + // configuring the download of value sets in JSON format + // sets the URL for downloading and specifies the class name and the folder + // where the values should be saved + SvsValueSetRequest valueSetRequestJson = this.huskyService.createValueSetRequest() + .className(className1) + .projectFolder(projectFolder).sourceFormatType(SourceFormatType.JSON) + .sourceSystemType(sourceSystemType).sourceUrl(authorRoleSourceUrlJsonString) + .build(); + + URL authorRoleSourceUrlIheSvs; + String authorRoleSourceUrlIheSvsString = ""; + authorRoleSourceUrlIheSvs = ValueSetManager.buildValueSetArtDecorUrl(baseUrlIheSvs, + authorRoleId, authorRoleTimeStamp); + authorRoleSourceUrlIheSvsString = authorRoleSourceUrlIheSvs.toString(); + + // configuring the download of value sets in IHE SVS XML format + // sets the URL for downloading and specifies the class name and the folder + // where the values should be saved + SvsValueSetRequest valueSetRequestIheSvs = this.huskyService.createValueSetRequest() + .className(className1) + .projectFolder(projectFolder).sourceFormatType(SourceFormatType.IHESVS) + .sourceSystemType(sourceSystemType) + .sourceUrl(authorRoleSourceUrlIheSvsString).build(); + + URL authorRoleSourceUrlXml; + String authorRoleSourceUrlXmlString = ""; + authorRoleSourceUrlXml = ValueSetManager.buildValueSetArtDecorUrl(baseUrlXml, authorRoleId, + authorRoleTimeStamp); + authorRoleSourceUrlXmlString = authorRoleSourceUrlXml.toString(); + + // configuring the download of value sets in XML format + // sets the URL for downloading and specifies the class name and the folder + // where the values should be saved + SvsValueSetRequest valueSetRequestXml = this.huskyService.createValueSetRequest() + .className(className1) + .projectFolder(projectFolder).sourceFormatType(SourceFormatType.XML) + .sourceSystemType(sourceSystemType).sourceUrl(authorRoleSourceUrlXmlString) + .build(); + + // download value sets in different formats + SvsValueSetResponse valueSetJson = this.huskyService.send(valueSetRequestJson, false); + SvsValueSetResponse valueSetIheSvs = this.huskyService.send(valueSetRequestIheSvs, false); + SvsValueSetResponse valueSetXml = this.huskyService.send(valueSetRequestXml, false); + + // 1. Compare Json and IHE SVS + assertEquals(valueSetJson.getValueSet().getIdentificator(), + valueSetIheSvs.getValueSet().getIdentificator()); + assertEquals(valueSetJson.getValueSet().getDisplayName(), + valueSetIheSvs.getValueSet().getDisplayName()); + // cannot be tested, as this information is not available in the + // IHE SVS format: + // assertEquals(valueSetJson.getName(), valueSetIheSvs.getName()); + assertEquals(valueSetJson.getValueSet().getStatus(), valueSetIheSvs.getValueSet().getStatus()); + assertEquals(valueSetJson.getValueSet().getVersion(), + valueSetIheSvs.getValueSet().getVersion()); + + // IHE SVS does only provide Purpose (which is loaded as English + // description). It couldn't be tested because different namespaces are used + /* + * assertEquals(valueSetJson.getDescription(LanguageCode.ENGLISH), + * valueSetIheSvs.getDescription(LanguageCode.ENGLISH)); + */ + + for (ValueSetEntry vse : valueSetJson.getValueSet().getValueSetEntryList()) { + ValueSetEntry obj = valueSetIheSvs.getValueSet() + .getValueSetEntryByCode(vse.getCodeBaseType()); + // cannot be tested, as this information is not available in the + // IHE SVS format: + // assertEquals(vse.getDesignationList().size(), + // obj.getDesignationList().size()); + assertEquals(vse.getLevel(), obj.getLevel()); + // cannot be tested, as this information is not available in the + // IHE SVS format: + // assertEquals(vse.getValueSetEntryType(), + // obj.getValueSetEntryType()); + } + + // 2. Compare Json and XML + assertEquals(valueSetJson.getValueSet().getIdentificator(), + valueSetXml.getValueSet().getIdentificator()); + assertEquals(valueSetJson.getValueSet().getDisplayName(), + valueSetXml.getValueSet().getDisplayName()); + // cannot be tested, as this information is not available in the + // XML format: + assertEquals(valueSetJson.getValueSet().getName(), valueSetXml.getValueSet().getName()); + assertEquals(valueSetJson.getValueSet().getStatus(), valueSetXml.getValueSet().getStatus()); + assertEquals(valueSetJson.getValueSet().getVersion(), valueSetXml.getValueSet().getVersion()); + + for (LangText jsonDesc : valueSetJson.getValueSet().getDescriptionList()) { + String xmlDesc = valueSetXml.getValueSet().getDescription(jsonDesc.getLangCode()); + assertNotNull(xmlDesc); + } + + for (ValueSetEntry vse : valueSetJson.getValueSet().getValueSetEntryList()) { + ValueSetEntry obj = valueSetXml.getValueSet().getValueSetEntryByCode(vse.getCodeBaseType()); + assertEquals(vse.getDesignationList().size(), obj.getDesignationList().size()); + assertEquals(vse.getLevel(), obj.getLevel()); + // cannot be tested, as this information is not available in the + // XML format: + assertEquals(vse.getValueSetEntryType(), obj.getValueSetEntryType()); + } + } +} diff --git a/src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsLowLevelTest.java b/src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsLowLevelTest.java new file mode 100644 index 0000000..d7538d8 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsLowLevelTest.java @@ -0,0 +1,159 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.xds; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AvailabilityStatus; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.DocumentEntry; +import org.openehealth.ipf.commons.ihe.xds.core.requests.query.QueryReturnType; +import org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse; +import org.openehealth.ipf.commons.ihe.xds.core.responses.Status; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.model.Identificator; +import org.projecthusky.communication.requests.xds.XdsRegistryStoredFindDocumentsQuery; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyWebServiceClient; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class, IpfApplicationConfig.class }) +@ActiveProfiles("atna") +public class XdsFindDocumentsLowLevelTest { + + @Value(value = "${test.xds.xcq.uri:http://ehealthsuisse.ihe-europe.net:8280/xdstools7/sim/epr-testing__for_init_gw_testing/rep/xcq}") + private String webserviceUri; + + @Autowired + private HuskyWebServiceClient wsClient; + + private Destination dest; + + @BeforeEach + public void setUp() { + this.dest = new Destination(); + dest.setUri(URI.create(webserviceUri)); + dest.setSenderApplicationOid("1.2.3.4"); + } + + @Test + public void whenPatientQueriedByName_thenPatientIsReturned() throws Exception { + Identificator identificator = new Identificator("1.3.6.1.4.1.12559.11.20.1", "4711"); + + XdsRegistryStoredFindDocumentsQuery query = XdsRegistryStoredFindDocumentsQuery.builder().destination(dest) + .patientID(identificator).availabilityStatus(AvailabilityStatus.APPROVED).build(); + QueryResponse queryResponse = this.wsClient.sendRegistryStoredFindDocumentsQuery(query, null, query.getDestination().getUri(), QueryReturnType.LEAF_CLASS, null); + assertNotNull(queryResponse); + assertTrue(queryResponse.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, queryResponse.getStatus()); + assertEquals(0, queryResponse.getReferences().size()); + } + + @Test + void queryFindDocumentsMetadataOfPdf() throws Exception { + Identificator patientId = new Identificator("1.3.6.1.4.1.21367.13.20.1000", "IHERED-1024"); + + XdsRegistryStoredFindDocumentsQuery query = XdsRegistryStoredFindDocumentsQuery.builder().destination(dest) + .patientID(patientId).availabilityStatus(AvailabilityStatus.APPROVED).build(); + final QueryResponse response = this.wsClient.sendRegistryStoredFindDocumentsQuery(query, null, query.getDestination().getUri(), QueryReturnType.LEAF_CLASS, null); + + // check if query was successful + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + assertFalse(response.getDocumentEntries().isEmpty()); + //assertEquals(221, response.getDocumentEntries().size()); + + DocumentEntry documentEntry = response.getDocumentEntries().get(0); + + // check if identifiers (unique ID, repository ID and home community ID) are + // equal + assertEquals("1.2.820.99999.15031207481211484821638086641062503555190193702785", documentEntry.getUniqueId()); + assertEquals("1.1.4567332.1.75", documentEntry.getRepositoryUniqueId()); + assertEquals("urn:oid:1.1.4567334.1.6", documentEntry.getHomeCommunityId()); + assertEquals("urn:uuid:b8f37101-8842-4e2c-b1e7-bc421d0dc01f", documentEntry.getEntryUuid()); + + assertEquals(AvailabilityStatus.APPROVED, documentEntry.getAvailabilityStatus()); + assertEquals("application/pdf", documentEntry.getMimeType()); + + assertNull(documentEntry.getComments()); + assertNull(documentEntry.getDocumentAvailability()); + + assertEquals("Informed Consent", documentEntry.getTitle().getValue()); + assertEquals("20211012082534", documentEntry.getCreationTime().toHL7()); + + // check different codes + assertEquals("de-CH", documentEntry.getLanguageCode()); + + assertNotNull(documentEntry.getClassCode()); + assertEquals("422735006", documentEntry.getClassCode().getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getClassCode().getSchemeName()); + assertEquals("Summary clinical document (record artifact)", documentEntry.getClassCode().getDisplayName().getValue()); + + assertNotNull(documentEntry.getConfidentialityCodes().get(0)); + assertEquals("17621005", documentEntry.getConfidentialityCodes().get(0).getCode()); + assertEquals("Normal (qualifier value)", documentEntry.getConfidentialityCodes().get(0).getDisplayName().getValue()); + + assertTrue(documentEntry.getEventCodeList().isEmpty()); + + assertEquals("urn:ihe:iti:xds-sd:pdf:2008", documentEntry.getFormatCode().getCode()); + assertEquals("1.3.6.1.4.1.19376.1.2.3", documentEntry.getFormatCode().getSchemeName()); + assertEquals("1.3.6.1.4.1.19376.1.2.20 (Scanned Document)", documentEntry.getFormatCode().getDisplayName().getValue()); + + assertEquals("394747008", documentEntry.getHealthcareFacilityTypeCode().getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getHealthcareFacilityTypeCode().getSchemeName()); + assertEquals("Health Authority", documentEntry.getHealthcareFacilityTypeCode().getDisplayName().getValue()); + + assertEquals("394810000", documentEntry.getPracticeSettingCode().getCode()); + assertEquals("Rheumatology (qualifier value)", documentEntry.getPracticeSettingCode().getDisplayName().getValue()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getPracticeSettingCode().getSchemeName()); + + assertEquals("371535009", documentEntry.getTypeCode().getCode()); + assertEquals("Transfer summary report (record artifact)", documentEntry.getTypeCode().getDisplayName().getValue()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getTypeCode().getSchemeName()); + + // check patient details + assertEquals("IHERED-1024", documentEntry.getPatientId().getId()); + assertEquals("1.3.6.1.4.1.21367.13.20.1000", documentEntry.getPatientId().getAssigningAuthority().getUniversalId()); + + assertEquals("2342134localid", documentEntry.getSourcePatientId().getId()); + assertEquals("1.2.3.4", documentEntry.getSourcePatientId().getAssigningAuthority().getUniversalId()); + + // check author details + assertFalse(documentEntry.getAuthors().isEmpty()); + assertNotNull(documentEntry.getAuthors().get(0)); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorPerson()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorPerson().getName()); + assertEquals("Bereit", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getFamilyName()); + assertEquals("Allzeit", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getGivenName()); + assertEquals("Dr.", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getPrefix()); + + assertNotNull(documentEntry.getAuthors().get(0).getAuthorRole()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorRole().get(0)); + assertEquals("221", documentEntry.getAuthors().get(0).getAuthorRole().get(0).getId()); + assertEquals("2.16.840.1.113883.2.9.6.2.7", + documentEntry.getAuthors().get(0).getAuthorRole().get(0).getAssigningAuthority().getUniversalId()); + + assertNotNull(documentEntry.getAuthors().get(0).getAuthorSpecialty()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0)); + assertNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0).getId()); + assertNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0).getAssigningAuthority().getUniversalId()); + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsTest.java b/src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsTest.java new file mode 100644 index 0000000..918a59a --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/xds/XdsFindDocumentsTest.java @@ -0,0 +1,269 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + */ +package org.projecthusky.communication.services.xds; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AvailabilityStatus; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.DocumentEntry; +import org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse; +import org.openehealth.ipf.commons.ihe.xds.core.responses.Status; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.model.Code; +import org.projecthusky.common.model.Identificator; +import org.projecthusky.communication.requests.xds.XdsFindFoldersStoredQuery; +import org.projecthusky.communication.requests.xds.XdsRegistryStoredFindDocumentsQuery; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class, + IpfApplicationConfig.class}) +@ActiveProfiles("atna") +public class XdsFindDocumentsTest { + + @Value(value = "${test.xds.xcq.uri:http://ehealthsuisse.ihe-europe.net:8280/xdstools7/sim/epr-testing__for_init_gw_testing/rep/xcq}") + private String webserviceUri; + + @Autowired + private HuskyService service; + + private Destination dest; + + @BeforeEach + public void setUp() { + this.dest = new Destination(); + dest.setUri(URI.create(webserviceUri)); + dest.setSenderApplicationOid("1.2.3.4"); + } + + @Test + public void whenDocumentQueriedByPatientIdenificator_thenDocumentIsFound() throws Exception { + Identificator identificator = new Identificator("1.3.6.1.4.1.21367.13.20.1000", "IHERED-1024"); + + XdsRegistryStoredFindDocumentsQuery query = this.service.createRegistryStoredFindDocumentsQuery(dest, identificator) + .availabilityStatus(AvailabilityStatus.APPROVED).build(); + QueryResponse response = this.service.send(query); + + // check if query was successful + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + assertFalse(response.getDocumentEntries().isEmpty()); + + DocumentEntry documentEntry = response.getDocumentEntries().get(0); + + // check if identifiers (unique ID, repository ID and home community ID) are + // equal + assertEquals("1.2.820.99999.15031207481211484821638086641062503555190193702785", documentEntry.getUniqueId()); + assertEquals("1.1.4567332.1.75", documentEntry.getRepositoryUniqueId()); + assertEquals("urn:oid:1.1.4567334.1.6", documentEntry.getHomeCommunityId()); + assertEquals("urn:uuid:b8f37101-8842-4e2c-b1e7-bc421d0dc01f", documentEntry.getEntryUuid()); + + assertEquals(AvailabilityStatus.APPROVED, documentEntry.getAvailabilityStatus()); + assertEquals("application/pdf", documentEntry.getMimeType()); + + assertNull(documentEntry.getComments()); + assertNull(documentEntry.getDocumentAvailability()); + + assertEquals("Informed Consent", documentEntry.getTitle().getValue()); + assertEquals("20211012082534", documentEntry.getCreationTime().toHL7()); + + // check different codes + assertEquals("de-CH", documentEntry.getLanguageCode()); + + assertNotNull(documentEntry.getClassCode()); + assertEquals("422735006", documentEntry.getClassCode().getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getClassCode().getSchemeName()); + assertEquals("Summary clinical document (record artifact)", + documentEntry.getClassCode().getDisplayName().getValue()); + + assertNotNull(documentEntry.getConfidentialityCodes().get(0)); + assertEquals("17621005", documentEntry.getConfidentialityCodes().get(0).getCode()); + assertEquals("Normal (qualifier value)", + documentEntry.getConfidentialityCodes().get(0).getDisplayName().getValue()); + + assertTrue(documentEntry.getEventCodeList().isEmpty()); + + assertEquals("urn:ihe:iti:xds-sd:pdf:2008", documentEntry.getFormatCode().getCode()); + assertEquals("1.3.6.1.4.1.19376.1.2.3", documentEntry.getFormatCode().getSchemeName()); + assertEquals("1.3.6.1.4.1.19376.1.2.20 (Scanned Document)", + documentEntry.getFormatCode().getDisplayName().getValue()); + + assertEquals("394747008", documentEntry.getHealthcareFacilityTypeCode().getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getHealthcareFacilityTypeCode().getSchemeName()); + assertEquals("Health Authority", documentEntry.getHealthcareFacilityTypeCode().getDisplayName().getValue()); + + assertEquals("394810000", documentEntry.getPracticeSettingCode().getCode()); + assertEquals("Rheumatology (qualifier value)", documentEntry.getPracticeSettingCode().getDisplayName().getValue()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getPracticeSettingCode().getSchemeName()); + + assertEquals("371535009", documentEntry.getTypeCode().getCode()); + assertEquals("Transfer summary report (record artifact)", documentEntry.getTypeCode().getDisplayName().getValue()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getTypeCode().getSchemeName()); + + // check patient details + assertEquals("IHERED-1024", documentEntry.getPatientId().getId()); + assertEquals("1.3.6.1.4.1.21367.13.20.1000", documentEntry.getPatientId().getAssigningAuthority().getUniversalId()); + + assertEquals("2342134localid", documentEntry.getSourcePatientId().getId()); + assertEquals("1.2.3.4", documentEntry.getSourcePatientId().getAssigningAuthority().getUniversalId()); + + // check author details + assertFalse(documentEntry.getAuthors().isEmpty()); + assertNotNull(documentEntry.getAuthors().get(0)); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorPerson()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorPerson().getName()); + assertEquals("Bereit", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getFamilyName()); + assertEquals("Allzeit", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getGivenName()); + assertEquals("Dr.", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getPrefix()); + + assertNotNull(documentEntry.getAuthors().get(0).getAuthorRole()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorRole().get(0)); + assertEquals("221", documentEntry.getAuthors().get(0).getAuthorRole().get(0).getId()); + assertEquals("2.16.840.1.113883.2.9.6.2.7", + documentEntry.getAuthors().get(0).getAuthorRole().get(0).getAssigningAuthority().getUniversalId()); + + assertNotNull(documentEntry.getAuthors().get(0).getAuthorSpecialty()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0)); + assertNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0).getId()); + assertNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0).getAssigningAuthority().getUniversalId()); + } + + @Test + public void whenAllPossibleParametersSetInQuery_thenDocumentIsReturned() throws Exception { + Identificator identificator = new Identificator("1.3.6.1.4.1.21367.13.20.1000", "IHERED-1024"); + + XdsRegistryStoredFindDocumentsQuery query = this.service.createRegistryStoredFindDocumentsQuery(dest, identificator) + .availabilityStatus(AvailabilityStatus.APPROVED) + .classCode(new Code(Code.builder().withCode("422735006").withCodeSystem("2.16.840.1.113883.6.96") + .withDisplayName("Summary clinical document (record artifact)").build())) + .confidentialityCode(new Code(Code.builder().withCode("17621005").withCodeSystem("2.16.840.1.113883.6.96") + .withDisplayName("Normal (qualifier value)").build())) + .formatCode(new Code( + Code.builder().withCode("urn:ihe:iti:xds-sd:pdf:2008").withCodeSystem("1.3.6.1.4.1.19376.1.2.3") + .withDisplayName("1.3.6.1.4.1.19376.1.2.20 (Scanned Document)").build())) + .healthCareFacilityCode(new Code(Code.builder().withCode("394747008").withCodeSystem("2.16.840.1.113883.6.96") + .withDisplayName("Health Authority").build())) + .practiceSettingCode(new Code(Code.builder().withCode("394810000").withCodeSystem("2.16.840.1.113883.6.96") + .withDisplayName("Rheumatology (qualifier value)").build())) + .build(); + QueryResponse response = this.service.send(query); + + // check if query was successful + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + assertFalse(response.getDocumentEntries().isEmpty()); + + DocumentEntry documentEntry = response.getDocumentEntries().get(0); + + // check if identifiers (unique ID, repository ID and home community ID) are + // equal + assertEquals("1.2.820.99999.15031207481211484821638086641062503555190193702785", documentEntry.getUniqueId()); + assertEquals("1.1.4567332.1.75", documentEntry.getRepositoryUniqueId()); + assertEquals("urn:oid:1.1.4567334.1.6", documentEntry.getHomeCommunityId()); + assertEquals("urn:uuid:b8f37101-8842-4e2c-b1e7-bc421d0dc01f", documentEntry.getEntryUuid()); + + assertEquals(AvailabilityStatus.APPROVED, documentEntry.getAvailabilityStatus()); + assertEquals("application/pdf", documentEntry.getMimeType()); + + assertNull(documentEntry.getComments()); + assertNull(documentEntry.getDocumentAvailability()); + + assertEquals("Informed Consent", documentEntry.getTitle().getValue()); + assertEquals("20211012082534", documentEntry.getCreationTime().toHL7()); + + // check different codes + assertEquals("de-CH", documentEntry.getLanguageCode()); + + assertNotNull(documentEntry.getClassCode()); + assertEquals("422735006", documentEntry.getClassCode().getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getClassCode().getSchemeName()); + assertEquals("Summary clinical document (record artifact)", + documentEntry.getClassCode().getDisplayName().getValue()); + + assertNotNull(documentEntry.getConfidentialityCodes().get(0)); + assertEquals("17621005", documentEntry.getConfidentialityCodes().get(0).getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getConfidentialityCodes().get(0).getSchemeName()); + assertEquals("Normal (qualifier value)", + documentEntry.getConfidentialityCodes().get(0).getDisplayName().getValue()); + + assertTrue(documentEntry.getEventCodeList().isEmpty()); + + assertEquals("urn:ihe:iti:xds-sd:pdf:2008", documentEntry.getFormatCode().getCode()); + assertEquals("1.3.6.1.4.1.19376.1.2.3", documentEntry.getFormatCode().getSchemeName()); + assertEquals("1.3.6.1.4.1.19376.1.2.20 (Scanned Document)", + documentEntry.getFormatCode().getDisplayName().getValue()); + + assertEquals("394747008", documentEntry.getHealthcareFacilityTypeCode().getCode()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getHealthcareFacilityTypeCode().getSchemeName()); + assertEquals("Health Authority", documentEntry.getHealthcareFacilityTypeCode().getDisplayName().getValue()); + + assertEquals("394810000", documentEntry.getPracticeSettingCode().getCode()); + assertEquals("Rheumatology (qualifier value)", documentEntry.getPracticeSettingCode().getDisplayName().getValue()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getPracticeSettingCode().getSchemeName()); + + assertEquals("371535009", documentEntry.getTypeCode().getCode()); + assertEquals("Transfer summary report (record artifact)", documentEntry.getTypeCode().getDisplayName().getValue()); + assertEquals("2.16.840.1.113883.6.96", documentEntry.getTypeCode().getSchemeName()); + + // check patient details + assertEquals("IHERED-1024", documentEntry.getPatientId().getId()); + assertEquals("1.3.6.1.4.1.21367.13.20.1000", documentEntry.getPatientId().getAssigningAuthority().getUniversalId()); + + assertEquals("2342134localid", documentEntry.getSourcePatientId().getId()); + assertEquals("1.2.3.4", documentEntry.getSourcePatientId().getAssigningAuthority().getUniversalId()); + + // check author details + assertFalse(documentEntry.getAuthors().isEmpty()); + assertNotNull(documentEntry.getAuthors().get(0)); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorPerson()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorPerson().getName()); + assertEquals("Bereit", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getFamilyName()); + assertEquals("Allzeit", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getGivenName()); + assertEquals("Dr.", documentEntry.getAuthors().get(0).getAuthorPerson().getName().getPrefix()); + + assertNotNull(documentEntry.getAuthors().get(0).getAuthorRole()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorRole().get(0)); + assertEquals("221", documentEntry.getAuthors().get(0).getAuthorRole().get(0).getId()); + assertEquals("2.16.840.1.113883.2.9.6.2.7", + documentEntry.getAuthors().get(0).getAuthorRole().get(0).getAssigningAuthority().getUniversalId()); + + assertNotNull(documentEntry.getAuthors().get(0).getAuthorSpecialty()); + assertNotNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0)); + assertNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0).getId()); + assertNull(documentEntry.getAuthors().get(0).getAuthorSpecialty().get(0).getAssigningAuthority().getUniversalId()); + } + + @Test + public void whenFoldersAreQueriedByPatientIdentificator_success() throws Exception { + Identificator patientID = new Identificator("1.3.6.1.4.1.21367.13.20.1000", "IHERED-1024"); + + XdsFindFoldersStoredQuery query = this.service.createFindFoldersStoredQuery().destination(dest) + .patientID(patientID).availabilityStatus(AvailabilityStatus.APPROVED).build(); + + QueryResponse response = this.service.send(query); + + // check if query was successful + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + } +} diff --git a/src/test/java/org/projecthusky/communication/services/xds/XdsFindFoldersStoredQueryTest.java b/src/test/java/org/projecthusky/communication/services/xds/XdsFindFoldersStoredQueryTest.java new file mode 100644 index 0000000..7206854 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/xds/XdsFindFoldersStoredQueryTest.java @@ -0,0 +1,48 @@ +package org.projecthusky.communication.services.xds; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AvailabilityStatus; +import org.openehealth.ipf.commons.ihe.xds.core.requests.query.FindFoldersQuery; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.requests.xds.XdsFindFoldersStoredQuery; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.projecthusky.communication.utils.XdsTestUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class, + IpfApplicationConfig.class}) +public class XdsFindFoldersStoredQueryTest extends XdsTestUtils { + @Value(value = "${test.xds.xcq.uri:http://ehealthsuisse.ihe-europe.net:8280/xdstools7/sim/epr-testing__for_init_gw_testing/rep/xcq}") + private String webserviceUri; + + @Autowired + private HuskyService service; + + @Test + void testFindFoldersStoredQuery() { + Destination dest = new Destination(); + dest.setUri(URI.create(webserviceUri)); + dest.setSenderApplicationOid("1.2.3.4"); + + XdsFindFoldersStoredQuery query = this.service.createFindFoldersStoredQuery().destination(dest).patientID(patientId) + .availabilityStatus(List.of(AvailabilityStatus.SUBMITTED)).build(); + + assertTrue(query.getIpfQuery() instanceof FindFoldersQuery); + + FindFoldersQuery sqpl = (FindFoldersQuery) query.getIpfQuery(); + + assertEquals(patientId.getRoot(), sqpl.getPatientId().getAssigningAuthority().getUniversalId()); + assertEquals(patientId.getExtension(), sqpl.getPatientId().getId()); + + assertEquals(availabilityStatus.getQueryOpcode(), sqpl.getStatus().get(0).getQueryOpcode()); + } +} diff --git a/src/test/java/org/projecthusky/communication/services/xds/XdsRetrieveDocumentSetTest.java b/src/test/java/org/projecthusky/communication/services/xds/XdsRetrieveDocumentSetTest.java new file mode 100644 index 0000000..f90b44b --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/xds/XdsRetrieveDocumentSetTest.java @@ -0,0 +1,91 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + * + */ +package org.projecthusky.communication.services.xds; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; + +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.xds.core.responses.RetrievedDocument; +import org.openehealth.ipf.commons.ihe.xds.core.responses.RetrievedDocumentSet; +import org.openehealth.ipf.commons.ihe.xds.core.responses.Status; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.communication.DocumentRequest; +import org.projecthusky.communication.requests.xds.XdsDocumentSetRequest; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.testhelper.IpfApplicationConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class, IpfApplicationConfig.class }) +@ActiveProfiles("atna") +public class XdsRetrieveDocumentSetTest { + + @Autowired + private HuskyService service; + + @Value(value = "${test.epdpg.xds.ret.uri:https://epdplayground.i4mi.bfh.ch:6443/Repository/services/RepositoryService}") + private String repositoryURL; + + @Test + void retrieveDocuments() throws Exception { + String applicationOid = "2.16.840.1.113883.3.72.6.5.100.1399"; + String facilityOid = "Waldpsital Bern"; + String senderApplicationOid = "1.2.3.4"; + + final String documentId_1 = "2.25.90799173491713586491471839779315544798"; + final String repositoryId_1 = "1.1.1.2.31"; + final String homeCommunityId_1 = "urn:oid:1.1.1"; + + final String documentId_2 = "2.25.253445961889251413523507992196901058285"; + final String repositoryId_2 = "1.1.1.2.31"; + final String homeCommunityId_2 = "urn:oid:1.1.1"; + + Destination dest = new Destination(); + dest.setUri(URI.create(repositoryURL)); + dest.setSenderApplicationOid(senderApplicationOid); + dest.setReceiverApplicationOid(applicationOid); + dest.setReceiverFacilityOid(facilityOid); + + XdsDocumentSetRequest request = XdsDocumentSetRequest.builder().destination(dest) + .documentRequest(new DocumentRequest(repositoryId_1, null, documentId_1, homeCommunityId_1)) + .documentRequest(new DocumentRequest(repositoryId_2, null, documentId_2, homeCommunityId_2)) + .build(); + + RetrievedDocumentSet set = this.service.send(request); + assertEquals(Status.SUCCESS, set.getStatus()); + assertTrue(set.getErrors().isEmpty()); + + // check if document is returned + assertFalse(set.getDocuments().isEmpty()); + assertEquals(2, set.getDocuments().size()); + + for (RetrievedDocument retrievedDocument : set.getDocuments()) { + + // check mime type + assertEquals("application/fhir+json", retrievedDocument.getMimeType()); + + // check for content + try (var is = retrievedDocument.getDataHandler().getInputStream()) { + byte[] bytesOfDocument = is.readAllBytes(); + assertNotNull(bytesOfDocument); + } + } + } + +} diff --git a/src/test/java/org/projecthusky/communication/services/xds/XdsSubmitDocumentTest.java b/src/test/java/org/projecthusky/communication/services/xds/XdsSubmitDocumentTest.java new file mode 100644 index 0000000..3f0bd90 --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/xds/XdsSubmitDocumentTest.java @@ -0,0 +1,269 @@ +package org.projecthusky.communication.services.xds; + + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Association; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AssociationType; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AvailabilityStatus; +import org.openehealth.ipf.commons.ihe.xds.core.responses.ErrorCode; +import org.openehealth.ipf.commons.ihe.xds.core.responses.ErrorInfo; +import org.openehealth.ipf.commons.ihe.xds.core.responses.Response; +import org.openehealth.ipf.commons.ihe.xds.core.responses.Severity; +import org.openehealth.ipf.commons.ihe.xds.core.responses.Status; +import org.projecthusky.common.communication.Destination; +import org.projecthusky.common.communication.DocumentMetadata; +import org.projecthusky.common.communication.SubmissionSetMetadata; +import org.projecthusky.common.enums.DocumentDescriptor; +import org.projecthusky.common.model.Code; +import org.projecthusky.common.model.Identificator; +import org.projecthusky.communication.ConvenienceCommunication; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.requests.xds.XdsDocumentWithMetadata; +import org.projecthusky.communication.requests.xds.XdsProvideAndRetrieveDocumentSetQuery; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.communication.utils.XdsTestUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * The purpose of this test class is to check whether the submission of documents (XDS ITI-41) works. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestApplication.class}) +@EnableAutoConfiguration +class XdsSubmitDocumentTest extends XdsTestUtils { + @Autowired + private HuskyService huskyService; + + @Value(value = "${test.xds.pnr.uri:http://ehealthsuisse.ihe-europe.net:8280/xdstools7/sim/epr-testing__for_init_gw_testing/rep/prb}") + private String pnrUri; + + final private String applicationName = "2.16.840.1.113883.3.72.6.5.100.1399"; + final private String facilityName = null; + + final private String senderApplicationOid = "1.2.3.4"; + + + /** + * This method creates and start spring test application. Moreover, it sets the endpoint of XDS service for submitting + * documents. + * + * @throws java.lang.Exception + */ + @BeforeEach + public void setUp() throws Exception { + // create and start spring test application + var app = new SpringApplication(TestApplication.class); + app.setWebApplicationType(WebApplicationType.NONE); + app.run(); + } + + /** + * This method checks if initialization of {@link ConvenienceCommunication} was correct. + */ + @Test + void contextLoads() { + assertNotNull(huskyService); + } + + /** + * This test checks the behavior of the + * {@link ConvenienceCommunication#submit(SubmissionSetMetadata, org.projecthusky.xua.core.SecurityHeaderElement, + * String)} when a PDF document is submitted with separate submission set metadata. + * + * @throws Exception + */ + @Test + void submitPdfDocTest() throws Exception { + DocumentMetadata documentMetadata = new DocumentMetadata(); + Identificator patientId = new Identificator("1.3.6.1.4.1.21367.13.20.1000", "IHERED-1024"); + setMetadataForPdf(documentMetadata, patientId); + + XdsDocumentWithMetadata.XdsDocumentWithMetadataBuilder builder = this.huskyService.createDocumentWithMetadata(); + XdsDocumentWithMetadata documentWithMetadata = builder.documentMetadata(documentMetadata).dataStream(getDocPdf()) + .documentDescriptor(DocumentDescriptor.PDF) + .build(); + + SubmissionSetMetadata subSet = new SubmissionSetMetadata(); + setSubmissionMetadata(subSet, patientId); + + XdsProvideAndRetrieveDocumentSetQuery.XdsProvideAndRetrieveDocumentSetQueryBuilder documentSetQueryBuilder = + this.huskyService.createProvideAndRetrieveDocumentSetQuery(); + XdsProvideAndRetrieveDocumentSetQuery provideAndRetrieveDocumentSetQuery = + documentSetQueryBuilder.documentWithMetadata(List.of(documentWithMetadata)).destination(createDestination()) + .submissionSetMetadata(subSet).build(); + + // submit added documents + Response response = huskyService.send(provideAndRetrieveDocumentSetQuery); + + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + } + + /** + * This test checks the behavior of the + * {@link ConvenienceCommunication#submit(SubmissionSetMetadata, org.projecthusky.xua.core.SecurityHeaderElement, + * String)} when a CDA document is submitted with separate submission set metadata. + * + * @throws Exception + */ + @Test + void submitCdaDocTest() throws Exception { + DocumentMetadata documentMetadata = new DocumentMetadata(); + Identificator patientId = new Identificator("1.3.6.1.4.1.21367.13.20.3000", "IHEBLUE-2599"); + setMetadataForCda(documentMetadata, patientId); + + XdsDocumentWithMetadata documentWithMetadata = this.huskyService.createDocumentWithMetadata().documentMetadata(documentMetadata) + .dataStream(getDocCda()).documentDescriptor(DocumentDescriptor.CDA_R2).build(); + + SubmissionSetMetadata subSet = new SubmissionSetMetadata(); + setSubmissionMetadata(subSet, patientId); + + XdsProvideAndRetrieveDocumentSetQuery provideAndRetrieveDocumentSetQuery = + this.huskyService.createProvideAndRetrieveDocumentSetQuery().documentWithMetadata(List.of(documentWithMetadata)) + .submissionSetMetadata(subSet).destination(createDestination()).build(); + + // submit added documents + Response response = huskyService.send(provideAndRetrieveDocumentSetQuery); + + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + } + + /** + * This test checks the behavior of the + * {@link ConvenienceCommunication#submit(SubmissionSetMetadata, org.projecthusky.xua.core.SecurityHeaderElement, + * String)} when a CDA document is submitted with invalid metadata. + * + * @throws Exception + */ + @Test + void submitDocumentWrongMetadataTest() throws Exception { + DocumentMetadata documentMetadata = new DocumentMetadata(); + Identificator patientId = new Identificator("1.3.6.1.4.1.21367.13.20.3000", "IHEBLUE-2599"); + // The metadata is set explicitly here. In this test case an incorrect class + // code is set. + setMetadataForCda(documentMetadata, patientId); + documentMetadata.setClassCode(new Code("1", "1.2.3.4.5", "display")); + + XdsDocumentWithMetadata documentWithMetadata = this.huskyService.createDocumentWithMetadata().documentMetadata(documentMetadata) + .dataStream(getDocCda()).documentDescriptor(DocumentDescriptor.CDA_R2).build(); + + SubmissionSetMetadata subSet = new SubmissionSetMetadata(); + setSubmissionMetadata(subSet, patientId); + + XdsProvideAndRetrieveDocumentSetQuery provideAndRetrieveDocumentSetQuery = + this.huskyService.createProvideAndRetrieveDocumentSetQuery().documentWithMetadata(List.of(documentWithMetadata)) + .submissionSetMetadata(subSet).destination(createDestination()).build(); + + // submit added documents + Response response = huskyService.send(provideAndRetrieveDocumentSetQuery); + + // checks whether the submission of the document failed + assertEquals(Status.FAILURE, response.getStatus()); + assertFalse(response.getErrors().isEmpty()); + + // checks if XDSRegistryMetadataError is returned + ErrorInfo error = response.getErrors().get(0); + assertEquals(ErrorCode.REGISTRY_METADATA_ERROR, error.getErrorCode()); + assertEquals("CodeValidation", error.getLocation()); + assertEquals(Severity.ERROR, error.getSeverity()); + } + + /** + * This test checks the behavior of the + * {@link ConvenienceCommunication#submitReplacement(SubmissionSetMetadata, String, + * org.projecthusky.xua.core.SecurityHeaderElement, String)} when an existing CDA document is to be replaced by a new + * one. + * + * @throws Exception + */ + @Test + void replaceCdaDocTest() throws Exception { + // Here the version 1 of the CDA document is transmitted, which should be replaced afterwards + DocumentMetadata documentMetadata = new DocumentMetadata(); + Identificator patientId = new Identificator("1.3.6.1.4.1.21367.13.20.3000", "IHEBLUE-1043"); + setMetadataForCda(documentMetadata, patientId); + + XdsDocumentWithMetadata documentWithMetadata = this.huskyService.createDocumentWithMetadata().documentMetadata(documentMetadata) + .dataStream(getDocCda()).documentDescriptor(DocumentDescriptor.CDA_R2).build(); + + SubmissionSetMetadata subSet = new SubmissionSetMetadata(); + setSubmissionMetadata(subSet, patientId); + + XdsProvideAndRetrieveDocumentSetQuery provideAndRetrieveDocumentSetQuery = + this.huskyService.createProvideAndRetrieveDocumentSetQuery().documentWithMetadata(List.of(documentWithMetadata)) + .submissionSetMetadata(subSet).destination(createDestination()).build(); + + // submit added documents + Response response = huskyService.send(provideAndRetrieveDocumentSetQuery); + + // checks whether the document has been successfully submitted + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + + // The entry UUID of the first submitted document is stored here, since it is + // needed when replacing the document. + String entryUuid = provideAndRetrieveDocumentSetQuery.getDocumentWithMetadata().get(0).getDocumentMetadata() + .getDocumentEntry().getEntryUuid(); + + // Here the version 2 of the CDA document is transmitted, which should replace + // the first CDA document + documentMetadata = new DocumentMetadata(); + patientId = new Identificator("1.3.6.1.4.1.21367.13.20.3000", "IHEBLUE-1043"); + setMetadataForCda(documentMetadata, patientId); + + documentWithMetadata = this.huskyService.createDocumentWithMetadata().documentMetadata(documentMetadata) + .dataStream(getDocCdaV2()).documentDescriptor(DocumentDescriptor.CDA_R2).build(); + + subSet = new SubmissionSetMetadata(); + setSubmissionMetadata(subSet, patientId); + + provideAndRetrieveDocumentSetQuery = + this.huskyService.createProvideAndRetrieveDocumentSetQuery().documentWithMetadata(List.of(documentWithMetadata)) + .submissionSetMetadata(subSet).destination(createDestination()).association(createAssociation(entryUuid)).build(); + + // method to replace existing document with passed entry UUID is called. All + // added documents are submitted + response = huskyService.send(provideAndRetrieveDocumentSetQuery); + + // checks whether the document has been successfully replaced + assertTrue(response.getErrors().isEmpty()); + assertEquals(Status.SUCCESS, response.getStatus()); + } + + private Association createAssociation(String entryUuid) { + Association association = new Association(); + association.setAssociationType(AssociationType.REPLACE); + association.setAvailabilityStatus(AvailabilityStatus.APPROVED); + association.setTargetUuid(entryUuid); + association.assignEntryUuid(); + return association; + } + + private Destination createDestination() { + final Destination dest = new Destination(); + + try { + dest.setUri(new URI(pnrUri)); + } catch (final URISyntaxException e) { + e.printStackTrace(); + } + dest.setSenderApplicationOid(senderApplicationOid); + dest.setReceiverApplicationOid(applicationName); + dest.setReceiverFacilityOid(facilityName); + return dest; + } +} diff --git a/src/test/java/org/projecthusky/communication/services/xua/XuaClientTest.java b/src/test/java/org/projecthusky/communication/services/xua/XuaClientTest.java new file mode 100644 index 0000000..fbe5e4f --- /dev/null +++ b/src/test/java/org/projecthusky/communication/services/xua/XuaClientTest.java @@ -0,0 +1,252 @@ +package org.projecthusky.communication.services.xua; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; +import org.openehealth.ipf.commons.ihe.xacml20.stub.saml20.assertion.AttributeStatementType; +import org.openehealth.ipf.commons.ihe.xacml20.stub.saml20.assertion.AttributeType; +import org.openehealth.ipf.commons.ihe.xacml20.stub.saml20.assertion.StatementAbstractType; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.impl.AttributeValueImpl; +import org.projecthusky.communication.TestApplication; +import org.projecthusky.communication.config.ServerTestHelper; +import org.projecthusky.communication.requests.xua.XuaRequest; +import org.projecthusky.communication.responses.xua.XuaResponse; +import org.projecthusky.communication.services.HuskyService; +import org.projecthusky.xua.communication.clients.XuaClient; +import org.projecthusky.xua.communication.xua.AppliesTo; +import org.projecthusky.xua.communication.xua.RequestType; +import org.projecthusky.xua.communication.xua.TokenType; +import org.projecthusky.xua.communication.xua.XUserAssertionResponse; +import org.projecthusky.xua.communication.xua.impl.AppliesToBuilderImpl; +import org.projecthusky.xua.core.SecurityHeaderElement; +import org.projecthusky.xua.deserialization.impl.AssertionDeserializerImpl; +import org.projecthusky.xua.exceptions.ClientSendException; +import org.projecthusky.xua.exceptions.DeserializeException; +import org.projecthusky.xua.exceptions.SerializeException; +import org.projecthusky.xua.exceptions.SoapException; +import org.projecthusky.xua.hl7v3.PurposeOfUse; +import org.projecthusky.xua.hl7v3.Role; +import org.projecthusky.xua.hl7v3.impl.CodedWithEquivalentsBuilder; +import org.projecthusky.xua.saml2.impl.AttributeImpl; +import org.projecthusky.xua.serialization.impl.XUserAssertionResponseSerializerImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * The purpose of this test class is to check if the assertion query works for a + * user. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = { TestApplication.class }) +@EnableAutoConfiguration +class XuaClientTest extends ServerTestHelper { + + private final Logger logger = LoggerFactory.getLogger(XuaClientTest.class); + + @Value(value = "${test.xua.uri:https://ehealthsuisse.ihe-europe.net:10443/STS}") + private String urlToXua; + + @Value(value = "${test.xua.keystore.file:src/test/resources/project-husky.p12}") + private String clientKeyStore; + @Value(value = "${test.xua.keystore.password:husky2023}") + private String clientKeyStorePass; + @Value(value = "${test.xua.keystore.type:pkcs12}") + private String clientKeyStoreType; + @Value(value = "${test.xua.assertion.file:src/test/resources/Assertion.xml}") + private String xuaAssertionFile; + + @Autowired + private HuskyService huskyService; + + /** + * This test checks the behavior of the + * {@link XuaClient#send(SecurityHeaderElement, org.projecthusky.xua.communication.xua.XUserAssertionRequest) + * when querying a XUA assertion for a registered healthcare professional + * + * @throws Exception + */ + @Test + void testGetAssertionForHcp() + throws ClientSendException, DeserializeException, IOException { + try (InputStream is = new FileInputStream(xuaAssertionFile)) { + + var idpAssertion = new AssertionDeserializerImpl().fromXmlByteArray(IOUtils.toByteArray(is)); + + // set role of subject + var role = new CodedWithEquivalentsBuilder().code("HCP").codeSystem("2.16.756.5.30.1.127.3.10.6") + .displayName("Behandelnde(r)") + .buildObject(Role.DEFAULT_NS_URI, Role.DEFAULT_ELEMENT_LOCAL_NAME, Role.DEFAULT_PREFIX); + + // set the purpose of use + var purposeOfUse = new CodedWithEquivalentsBuilder().code("NORM").codeSystem("2.16.756.5.30.1.127.3.10.6") + .displayName("Normal Access").buildObject(PurposeOfUse.DEFAULT_NS_URI, + PurposeOfUse.DEFAULT_ELEMENT_LOCAL_NAME, PurposeOfUse.DEFAULT_PREFIX); + + // set ID of patient with namespace EPR_SPID + String resourceId = "761337610411265304^^^SPID&2.16.756.5.30.1.127.3.10.3&ISO"; + + AppliesTo appliesTo = new AppliesToBuilderImpl().address("https://localhost:17001/services/iti18").create(); + + XuaRequest xuaRequest = this.huskyService.createXuaRequest().appliesTo(appliesTo).purposeOfUse(purposeOfUse) + .subjectRole(role).resourceId(resourceId).requestType(RequestType.WST_ISSUE) + .tokenType(TokenType.OASIS_WSS_SAML_PROFILE_11_SAMLV20).idpAssertion(idpAssertion) + .repositoryUri(urlToXua).clientKeyStoreType(clientKeyStoreType).clientKeyStore(clientKeyStore) + .clientKeyStorePass(clientKeyStorePass).build(); + + // query XUA assertion + XuaResponse response = huskyService.send(xuaRequest); + + // check if assertion is returned + assertNotNull(response); + + //printOutresponse(response); + + assertNotNull(response.getAssertion()); + assertNotNull(((Assertion) response.getAssertion().getWrappedObject()).getIssuer()); + // check if correct issuer is included in assertion + assertEquals("https://ehealthsuisse.ihe-europe.net/STS", + ((Assertion) response.getAssertion().getWrappedObject()).getIssuer().getValue()); + + String actualRole = null; + String actualPurposeOfUse = null; + String actualSubjectId = null; + String actualResourceId = null; + + for (StatementAbstractType statement : response.getAssertion() + .getStatementOrAuthnStatementOrAuthzDecisionStatement()) { + if (statement instanceof AttributeStatementType) { + AttributeStatementType attributeStatementType = (AttributeStatementType) statement; + + for (Object obj : attributeStatementType.getAttributeOrEncryptedAttribute()) { + if (obj instanceof AttributeType) { + AttributeImpl attribute = (AttributeImpl) obj; + + if (attribute.isValueARole()) { + actualRole = attribute.getValueAsRole().getCode(); + } + + if (attribute.isValueAPurposeOfUse()) { + actualPurposeOfUse = attribute.getValueAsPurposeOfUse().getCode(); + } + + if (attribute.getName() + .equalsIgnoreCase("urn:oasis:names:tc:xspa:1.0:subject:subject-id")) { + actualSubjectId = ((AttributeValueImpl) attribute.getWrappedObject() + .getAttributeValues().get(0)).getTextContent(); + } + + if (attribute.getName() + .equalsIgnoreCase("urn:oasis:names:tc:xacml:2.0:resource:resource-id")) { + actualResourceId = (((AttributeValueImpl) attribute.getWrappedObject() + .getAttributeValues().get(0))).getTextContent(); + } + + } + } + } + } + + // check attribute parameter of returned assertion + assertEquals(role.getCode(), actualRole); + assertEquals(purposeOfUse.getCode(), actualPurposeOfUse); + assertEquals("Ann Andrews", actualSubjectId); + assertEquals(resourceId, actualResourceId); + } + } + + private void printOutresponse(List responses) { + responses.forEach(response -> { + try { + String xmlString = new XUserAssertionResponseSerializerImpl().toXmlString(response); + logger.info(xmlString); + } catch (SerializeException e) { + + } + }); + + } + + /** + * This test checks the behavior of the + * {@link XuaClient#send(SecurityHeaderElement, org.projecthusky.xua.communication.xua.XUserAssertionRequest) + * when querying a XUA assertion for registered user with a wrong role. + * + * @throws Exception + */ + @Test + void testWrongAssertionDetailsForHcp() + throws DeserializeException, IOException { + try (InputStream is = new FileInputStream(xuaAssertionFile)) { + + var idpAssertion = new AssertionDeserializerImpl().fromXmlByteArray(IOUtils.toByteArray(is)); + + var role = new CodedWithEquivalentsBuilder().code("AKT").codeSystem("1.2.3.4.5") + .displayName("Behandelnde(r)") + .buildObject(Role.DEFAULT_NS_URI, Role.DEFAULT_ELEMENT_LOCAL_NAME, Role.DEFAULT_PREFIX); + var purposeOfUse = new CodedWithEquivalentsBuilder().code("NORM").codeSystem("2.16.756.5.30.1.127.3.10.6") + .displayName("Normal Access").buildObject(PurposeOfUse.DEFAULT_NS_URI, + PurposeOfUse.DEFAULT_ELEMENT_LOCAL_NAME, PurposeOfUse.DEFAULT_PREFIX); + String resourceId = "761337610411265304^^^SPID&2.16.756.5.30.1.127.3.10.3&ISO"; + + AppliesTo appliesTo = new AppliesToBuilderImpl().address("https://localhost:17001/services/iti18").create(); + + XuaRequest xuaRequest = this.huskyService.createXuaRequest().appliesTo(appliesTo).purposeOfUse(purposeOfUse) + .subjectRole(role).resourceId(resourceId).requestType(RequestType.WST_ISSUE) + .tokenType(TokenType.OASIS_WSS_SAML_PROFILE_11_SAMLV20).idpAssertion(idpAssertion) + .repositoryUri(urlToXua).clientKeyStoreType(clientKeyStoreType).clientKeyStore(clientKeyStore) + .clientKeyStorePass(clientKeyStorePass).build(); + + // query XUA assertion and expecting SoapException due to wrong role code + assertThrows(SoapException.class, () -> huskyService.send(xuaRequest)); + } + } + + /** + * This test checks the behavior of the + * {@link XuaClient#send(SecurityHeaderElement, org.projecthusky.xua.communication.xua.XUserAssertionRequest) + * when querying a XUA assertion for registered user with a wrong role, a wrong + * patient ID and a wrong purpose of use. + * + * @throws Exception + */ + @Test + void testInvalidXmlAssertionForHcp() + throws DeserializeException, IOException { + try (InputStream is = new FileInputStream(xuaAssertionFile)) { + + var idpAssertion = new AssertionDeserializerImpl().fromXmlByteArray(IOUtils.toByteArray(is)); + + var role = new CodedWithEquivalentsBuilder().code("AKT").codeSystem("1.2.3.4.5") + .displayName("Behandelnde(r)") + .buildObject(Role.DEFAULT_NS_URI, Role.DEFAULT_ELEMENT_LOCAL_NAME, Role.DEFAULT_PREFIX); + var purposeOfUse = new CodedWithEquivalentsBuilder().code("1234").codeSystem("1.2.3.4.5.6.7") + .displayName("Normal Access").buildObject(PurposeOfUse.DEFAULT_NS_URI, + PurposeOfUse.DEFAULT_ELEMENT_LOCAL_NAME, PurposeOfUse.DEFAULT_PREFIX); + String resourceId = "1234^^^SPID&2.16.756.5.30.1.127.3.10.3&ISO"; + + AppliesTo appliesTo = new AppliesToBuilderImpl().address("https://localhost:17001/services/iti18").create(); + + XuaRequest xuaRequest = this.huskyService.createXuaRequest().appliesTo(appliesTo).purposeOfUse(purposeOfUse) + .subjectRole(role).resourceId(resourceId).requestType(RequestType.WST_ISSUE) + .tokenType(TokenType.OASIS_WSS_SAML_PROFILE_11_SAMLV20).idpAssertion(idpAssertion) + .repositoryUri(urlToXua).clientKeyStoreType(clientKeyStoreType).clientKeyStore(clientKeyStore) + .clientKeyStorePass(clientKeyStorePass).build(); + + // query XUA assertion and expecting ClientSendException due to invalid + // assertion + assertThrows(ClientSendException.class, () -> huskyService.send(xuaRequest)); + } + } +} + diff --git a/src/test/java/org/projecthusky/communication/utils/XdsTestUtils.java b/src/test/java/org/projecthusky/communication/utils/XdsTestUtils.java new file mode 100644 index 0000000..b2fac5a --- /dev/null +++ b/src/test/java/org/projecthusky/communication/utils/XdsTestUtils.java @@ -0,0 +1,207 @@ +/* + * This code is made available under the terms of the Eclipse Public License v1.0 + * in the github project https://github.com/project-husky/husky there you also + * find a list of the contributors and the license information. + * + * This project has been developed further and modified by the joined working group Husky + * on the basis of the eHealth Connector opensource project from June 28, 2021, + * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. + * + */ +package org.projecthusky.communication.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.openehealth.ipf.commons.core.OidGenerator; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AssociationType; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.AvailabilityStatus; +import org.projecthusky.common.basetypes.NameBaseType; +import org.projecthusky.common.communication.DocumentMetadata; +import org.projecthusky.common.communication.SubmissionSetMetadata; +import org.projecthusky.common.enums.DateTimeRangeAttributes; +import org.projecthusky.common.enums.EhcVersions; +import org.projecthusky.common.enums.LanguageCode; +import org.projecthusky.common.model.Author; +import org.projecthusky.common.model.Code; +import org.projecthusky.common.model.Identificator; +import org.projecthusky.common.model.Name; +import org.projecthusky.communication.xd.storedquery.DateTimeRange; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class XdsTestUtils { + + // Initialize PatientId + public static Identificator patientId = new Identificator("1.3.6.1.4.1.21367.13.20.2005.1000", + "IHERED-1644"); + + // Initialize AuthorPerson + public static Author authorPerson; + + public static List formatCodes = List + .of(new Code("urn:ihe:rad:1.2.840.10008.5.1.4.1.1.88.59", "KOS Dokument", null)); + + public static List confidentialityCodes = List.of(new Code("30001", "administrative Daten", null)); + + public static List docIds = List.of("123455.235234", "1.2.3.4.5.6.7.8"); + + public static List parentRelation = List.of(AssociationType.APPEND, AssociationType.REPLACE); + + // Date Time Ranges + public static DateTimeRange dateTimeRange1; + + public static DateTimeRange dateTimeRange2; + + public static DateTimeRange[] dateTimeRanges; + + public static DateTimeRange eDateTimeRange1; + public static DateTimeRange eDateTimeRange2; + + public static DateTimeRange eDateTimeRanges[]; + public static ZonedDateTime d1; + public static ZonedDateTime d2; + /** The SLF4J logger instance. */ + protected final Logger log = LoggerFactory.getLogger(getClass()); + + public AvailabilityStatus availabilityStatus; + + public XdsTestUtils() { + // Initalize DateTimeRanges + dateTimeRange1 = new DateTimeRange(DateTimeRangeAttributes.CREATION_TIME, + LocalDateTime.parse("201401012300", DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + .atZone(ZoneId.systemDefault()), + LocalDateTime.parse("201412310400", DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + .atZone(ZoneId.systemDefault())); + dateTimeRange2 = new DateTimeRange(DateTimeRangeAttributes.CREATION_TIME, + LocalDateTime.parse("201501012300", DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + .atZone(ZoneId.systemDefault()), + LocalDateTime.parse("201502010400", DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + .atZone(ZoneId.systemDefault())); + dateTimeRanges = new DateTimeRange[] { dateTimeRange1, dateTimeRange2 }; + + d1 = LocalDateTime.parse("19800521022211", DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + .atZone(ZoneId.systemDefault()); + d2 = LocalDateTime.parse("20150521133459", DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + .atZone(ZoneId.systemDefault()); + eDateTimeRange1 = new DateTimeRange( + DateTimeRangeAttributes.CREATION_TIME, d1, d2); + eDateTimeRange2 = new DateTimeRange( + DateTimeRangeAttributes.SERVICE_START_TIME, d1, d2); + eDateTimeRanges = new DateTimeRange[] { + eDateTimeRange1, eDateTimeRange2 }; + + availabilityStatus = AvailabilityStatus.SUBMITTED; + + // Initialize AuthorPerson + authorPerson = new Author(); + var name = new Name(); + name.setFamily("Bereit"); + name.setGiven("Allzeit"); + name.setPrefix("Dr."); + authorPerson.addName(name); + + authorPerson.getIds().add(new Identificator(null, "123456789")); + } + + public String extractByRegex(String aRegEx, List> aInput) { + final Pattern p = Pattern.compile(aRegEx); + + for (List item : aInput) { + for (String itemStr : item) { + final Matcher m = p.matcher(itemStr); + if (m.find()) { + return m.group(1); + } + } + } + + return ""; + } + + protected InputStream getDocPdf() throws FileNotFoundException { + File file = new File("src/test/resources/docConsumer/patientconsent.pdf"); + return new FileInputStream(file); + } + + protected InputStream getDocCda() throws FileNotFoundException { + File file = new File("src/test/resources/docConsumer/CDA-CH-VACD_Impfausweis.xml"); + return new FileInputStream(file); + } + + protected InputStream getDocCdaV2() throws FileNotFoundException { + File file = new File("src/test/resources/docConsumer/CDA-CH-VACD_Impfausweis_V2.xml"); + return new FileInputStream(file); + } + + protected void setMetadataForCda(DocumentMetadata metaData, Identificator patientId) { + Name name = new Name(new NameBaseType()); + name.setGiven("Gerald"); + name.setFamily("Smitty"); + + Author author = new Author(); + author.addName(name); + + author.setRoleFunction(new Code("HCP", "2.16.756.5.30.1.127.3.10.1.1.3", "Healthcare professional")); + + metaData.addAuthor(author); + metaData.setDestinationPatientId(patientId); + metaData.setSourcePatientId(new Identificator("1.2.3.4", "2342134localid")); + metaData.setCodedLanguage(LanguageCode.FRENCH_CODE); + + metaData.setTypeCode( + new Code("41000179103", "2.16.840.1.113883.6.96", "Immunization record (record artifact)")); + metaData.setFormatCode(new Code("urn:ihe:iti:xds-sd:pdf:2008", "1.3.6.1.4.1.19376.1.2.3", + "1.3.6.1.4.1.19376.1.2.20 (Scanned Document)")); + metaData.setClassCode( + new Code("419891008", "2.16.840.1.113883.6.96", "Record artifact (record artifact)")); + metaData.setHealthcareFacilityTypeCode(new Code("394747008", "2.16.840.1.113883.6.96", "Health Authority")); + metaData.setPracticeSettingCode( + new Code("394802001", "2.16.840.1.113883.6.96", "General medicine (qualifier value)")); + metaData.addConfidentialityCode(new Code("17621005", "2.16.840.1.113883.6.96", "Normal (qualifier value)")); + } + + protected void setMetadataForPdf(DocumentMetadata metaData, Identificator patientId) { + Name name = new Name(new NameBaseType()); + name.setGiven("Gerald"); + name.setFamily("Smitty"); + + Author author = new Author(); + author.addName(name); + + author.setRoleFunction(new Code("HCP", "2.16.756.5.30.1.127.3.10.1.1.3", "Healthcare professional")); + + metaData.addAuthor(author); + metaData.setDestinationPatientId(patientId); + metaData.setSourcePatientId(new Identificator("1.2.3.4", "2342134localid")); + metaData.setCodedLanguage(LanguageCode.GERMAN_CODE); + metaData.setTypeCode(new Code("419891008", "2.16.840.1.113883.6.96", "Record artifact (record artifact)")); + metaData.setFormatCode(new Code("urn:ihe:iti:xds-sd:pdf:2008", "1.3.6.1.4.1.19376.1.2.3", + "1.3.6.1.4.1.19376.1.2.20 (Scanned Document)")); + metaData.setClassCode(new Code("184216000", "2.16.840.1.113883.6.96", "Patient record type (record artifact)")); + metaData.setHealthcareFacilityTypeCode(new Code("394747008", "2.16.840.1.113883.6.96", "Health Authority")); + metaData.setPracticeSettingCode( + new Code("394802001", "2.16.840.1.113883.6.96", "General medicine (qualifier value)")); + metaData.addConfidentialityCode(new Code("17621005", "2.16.840.1.113883.6.96", "Normal (qualifier value)")); + metaData.setTitle("Informed Consent"); + } + + protected void setSubmissionMetadata(SubmissionSetMetadata metadata, Identificator patientId) { + metadata.getAuthor().add(authorPerson); + metadata.setUniqueId(OidGenerator.uniqueOid().toString()); + metadata.setSourceId(EhcVersions.getCurrentVersion().getOid()); + metadata.setEntryUUID(UUID.randomUUID().toString()); + metadata.setDestinationPatientId(patientId); + metadata.setContentTypeCode(new Code("71388002", "2.16.840.1.113883.6.96", "Procedure (procedure)")); + } + +} diff --git a/src/test/resources/application-atna.properties b/src/test/resources/application-atna.properties index 6816f14..5f2b76d 100644 --- a/src/test/resources/application-atna.properties +++ b/src/test/resources/application-atna.properties @@ -1,4 +1,5 @@ spring.application.name = Husky Test + camel.dataformat.mime-multipart.multipartWithoutAttachment = true ipf.atna.audit-enabled = true diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 31f1a66..73448fc 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,7 +1,7 @@ -spring.application.name= Husky Test +spring.application.name = Husky Test application.title = Husky Test -application.version= 1.0.0 +application.version = 1.0.0 camel.dataformat.mime-multipart.multipartWithoutAttachment = true From e18518044e1278751b3f175f6566c04972986de8 Mon Sep 17 00:00:00 2001 From: Roeland Luykx <75606442+ralych@users.noreply.github.com> Date: Thu, 8 Feb 2024 06:25:51 +0100 Subject: [PATCH 3/3] Update java_ci.yml enable also develop branch --- .github/workflows/java_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/java_ci.yml b/.github/workflows/java_ci.yml index 0d1f84e..8600b6e 100644 --- a/.github/workflows/java_ci.yml +++ b/.github/workflows/java_ci.yml @@ -5,9 +5,9 @@ name: Java CI with Maven and CodeQL on: push: - branches: [ master ] + branches: [ master, develop ] pull_request: - branches: [ master ] + branches: [ master, develop ] jobs: build: