Skip to content

Commit 14eceda

Browse files
committed
Merge branch 'feature/cetp-implementation' into feature/EPA-282-ws-client
# Conflicts: # src/main/java/health/ere/ps/service/gematik/PharmacyService.java
2 parents 43dfd64 + b2d2efc commit 14eceda

File tree

4 files changed

+144
-47
lines changed

4 files changed

+144
-47
lines changed

src/main/java/health/ere/ps/service/gematik/PharmacyService.java

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
import com.fasterxml.jackson.databind.DeserializationFeature;
66
import com.fasterxml.jackson.databind.MapperFeature;
77
import com.fasterxml.jackson.databind.ObjectMapper;
8+
9+
import ca.uhn.fhir.context.FhirContext;
810
import de.gematik.ws.conn.cardservicecommon.v2.CardTypeType;
911
import de.gematik.ws.conn.connectorcontext.v2.ContextType;
1012
import de.gematik.ws.conn.eventservice.wsdl.v7.EventServicePortType;
1113
import de.gematik.ws.conn.vsds.vsdservice.v5.FaultMessage;
1214
import de.gematik.ws.conn.vsds.vsdservice.v5.VSDServicePortType;
1315
import de.gematik.ws.conn.vsds.vsdservice.v5.VSDStatusType;
16+
import de.gematik.ws.fa.vsdm.vsd.v5.UCAllgemeineVersicherungsdatenXML;
17+
import de.gematik.ws.fa.vsdm.vsd.v5.UCGeschuetzteVersichertendatenXML;
18+
import de.gematik.ws.fa.vsdm.vsd.v5.UCPersoenlicheVersichertendatenXML;
1419
import de.health.service.cetp.IKonnektorClient;
1520
import de.health.service.cetp.domain.eventservice.Subscription;
1621
import health.ere.ps.config.AppConfig;
@@ -27,6 +32,9 @@
2732
import jakarta.ws.rs.client.Client;
2833
import jakarta.ws.rs.client.Entity;
2934
import jakarta.ws.rs.core.Response;
35+
import jakarta.xml.bind.DatatypeConverter;
36+
import jakarta.xml.bind.JAXBContext;
37+
import jakarta.xml.bind.JAXBException;
3038
import jakarta.xml.ws.Holder;
3139
import org.apache.commons.lang3.StringUtils;
3240
import org.apache.commons.lang3.tuple.Pair;
@@ -111,9 +119,32 @@ public class PharmacyService implements AutoCloseable {
111119

112120
Client client;
113121

114-
private final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
122+
static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
115123
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
116124

125+
static DocumentBuilder builder;
126+
127+
static {
128+
try {
129+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
130+
builder = factory.newDocumentBuilder();
131+
} catch (ParserConfigurationException e) {
132+
log.log(Level.SEVERE, "Could create parser", e);
133+
}
134+
}
135+
136+
static final JAXBContext jaxbContext = createJaxbContext();
137+
138+
static JAXBContext createJaxbContext() {
139+
try {
140+
return JAXBContext.newInstance(UCPersoenlicheVersichertendatenXML.class,
141+
UCAllgemeineVersicherungsdatenXML.class, UCGeschuetzteVersichertendatenXML.class);
142+
} catch (JAXBException e) {
143+
log.log(Level.SEVERE, "Could not init jaxb context", e);
144+
return null;
145+
}
146+
}
147+
117148
@PostConstruct
118149
public void init() {
119150
client = ERezeptWorkflowService.initClientWithVAU(appConfig);
@@ -141,9 +172,11 @@ public Pair<Bundle, String> getEPrescriptionsForCardHandle(
141172
runtimeConfig = new RuntimeConfig();
142173
}
143174
runtimeConfig.setSMCBHandle(smcbHandle);
144-
Holder<byte[]> pruefungsnachweis = readVSD(correlationId, egkHandle, smcbHandle, runtimeConfig);
175+
ReadVSDResult readVSD = readVSD(correlationId, egkHandle, smcbHandle, runtimeConfig);
176+
Holder<byte[]> pruefungsnachweis = readVSD.pruefungsnachweis;
145177
String pnw = Base64.getEncoder().encodeToString(pruefungsnachweis.value);
146178
try (Response response = client.target(appConfig.getPrescriptionServiceURL()).path("/Task")
179+
.queryParam("kvnr", extractKVNR(readVSD))
147180
.queryParam("pnw", pnw).request()
148181
.header("Content-Type", "application/fhir+xml")
149182
.header("User-Agent", appConfig.getUserAgent())
@@ -166,7 +199,35 @@ public Pair<Bundle, String> getEPrescriptionsForCardHandle(
166199
}
167200
}
168201

169-
public Holder<byte[]> readVSD(
202+
static synchronized String extractKVNR(ReadVSDResult readVSDResult) {
203+
try {
204+
Holder<byte[]> pnw = readVSDResult.pruefungsnachweis;
205+
String decodedXMLFromPNW = new String(new GZIPInputStream(new ByteArrayInputStream(pnw.value)).readAllBytes());
206+
Document doc = builder.parse(new ByteArrayInputStream(decodedXMLFromPNW.getBytes()));
207+
String e = doc.getElementsByTagName("E").item(0).getTextContent();
208+
if (e.equals("3")) {
209+
InputStream isPersoenlicheVersichertendaten = new GZIPInputStream(
210+
new ByteArrayInputStream(readVSDResult.persoenlicheVersichertendaten.value));
211+
UCPersoenlicheVersichertendatenXML patient = (UCPersoenlicheVersichertendatenXML) jaxbContext
212+
.createUnmarshaller().unmarshal(isPersoenlicheVersichertendaten);
213+
214+
String versichertenID = patient.getVersicherter().getVersichertenID();
215+
log.fine("VSDM result: "+e+" VersichertenID: " + versichertenID);
216+
return versichertenID;
217+
} else {
218+
String pn = doc.getElementsByTagName("PZ").item(0).getTextContent();
219+
String base64PN = new String(DatatypeConverter.parseBase64Binary(pn));
220+
String kvnrFromPn = base64PN.substring(0, 10);
221+
return kvnrFromPn;
222+
}
223+
} catch (SAXException | IOException | NullPointerException | JAXBException e) {
224+
String msg = "Could not parse PNW message";
225+
log.log(Level.WARNING, msg, e);
226+
return "";
227+
}
228+
}
229+
230+
public ReadVSDResult readVSD(
170231
String correlationId,
171232
String egkHandle,
172233
String smcbHandle,
@@ -221,7 +282,21 @@ public Holder<byte[]> readVSD(
221282
readEPrescriptionsMXBean.increaseVSDFailed();
222283
throw t;
223284
}
224-
return pruefungsnachweis;
285+
ReadVSDResult readVSDResult = new ReadVSDResult();
286+
readVSDResult.persoenlicheVersichertendaten = persoenlicheVersichertendaten;
287+
readVSDResult.allgemeineVersicherungsdaten = allgemeineVersicherungsdaten;
288+
readVSDResult.geschuetzteVersichertendaten = geschuetzteVersichertendaten;
289+
readVSDResult.vSD_Status = vSD_Status;
290+
readVSDResult.pruefungsnachweis = pruefungsnachweis;
291+
return readVSDResult;
292+
}
293+
294+
public class ReadVSDResult {
295+
Holder<byte[]> persoenlicheVersichertendaten;
296+
Holder<byte[]> allgemeineVersicherungsdaten;
297+
Holder<byte[]> geschuetzteVersichertendaten;
298+
Holder<VSDStatusType> vSD_Status;
299+
Holder<byte[]> pruefungsnachweis;
225300
}
226301

227302
private String getEvent(DocumentBuilder builder, byte[] pruefnachweisBytes) throws IOException, SAXException {

src/test/java/health/ere/ps/service/gematik/CardInsertedTest.java

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
package health.ere.ps.service.gematik;
22

3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNotNull;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
import static org.mockito.ArgumentMatchers.any;
7+
import static org.mockito.ArgumentMatchers.anyString;
8+
import static org.mockito.ArgumentMatchers.eq;
9+
import static org.mockito.Mockito.doReturn;
10+
import static org.mockito.Mockito.doThrow;
11+
import static org.mockito.Mockito.mock;
12+
import static org.mockito.Mockito.never;
13+
import static org.mockito.Mockito.spy;
14+
import static org.mockito.Mockito.times;
15+
import static org.mockito.Mockito.verify;
16+
import static org.mockito.Mockito.when;
17+
18+
import java.io.InputStream;
19+
import java.math.BigInteger;
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
import org.apache.commons.lang3.tuple.Pair;
24+
import org.junit.jupiter.api.Test;
25+
import org.mockito.ArgumentCaptor;
26+
327
import de.gematik.ws.conn.eventservice.v7.Event;
428
import de.gematik.ws.conn.vsds.vsdservice.v5.FaultMessage;
529
import de.gematik.ws.tel.error.v2.Error;
@@ -18,29 +42,6 @@
1842
import jakarta.ws.rs.core.Response;
1943
import jakarta.xml.bind.DatatypeConverter;
2044
import jakarta.xml.ws.Holder;
21-
import org.apache.commons.lang3.tuple.Pair;
22-
import org.junit.jupiter.api.Test;
23-
import org.mockito.ArgumentCaptor;
24-
25-
import java.io.InputStream;
26-
import java.math.BigInteger;
27-
import java.util.List;
28-
import java.util.Map;
29-
30-
import static org.junit.jupiter.api.Assertions.assertEquals;
31-
import static org.junit.jupiter.api.Assertions.assertNotNull;
32-
import static org.junit.jupiter.api.Assertions.assertTrue;
33-
import static org.mockito.ArgumentMatchers.any;
34-
import static org.mockito.ArgumentMatchers.anyString;
35-
import static org.mockito.ArgumentMatchers.eq;
36-
import static org.mockito.Mockito.doReturn;
37-
import static org.mockito.Mockito.doThrow;
38-
import static org.mockito.Mockito.mock;
39-
import static org.mockito.Mockito.never;
40-
import static org.mockito.Mockito.spy;
41-
import static org.mockito.Mockito.times;
42-
import static org.mockito.Mockito.verify;
43-
import static org.mockito.Mockito.when;
4445

4546
@QuarkusTest
4647
class CardInsertedTest {
@@ -51,7 +52,9 @@ class CardInsertedTest {
5152
void vsdmSensorDataWithEventIdIsSentOnCardInsertedEvent() throws Exception {
5253
PharmacyService pharmacyService = spy(createPharmacyService());
5354
Holder<byte[]> holder = prepareHolder(pharmacyService);
54-
doReturn(holder).when(pharmacyService).readVSD(any(), any(), any(), any());
55+
PharmacyService.ReadVSDResult readVSDResult = pharmacyService.new ReadVSDResult();
56+
readVSDResult.pruefungsnachweis = holder;
57+
doReturn(readVSDResult).when(pharmacyService).readVSD(any(), any(), any(), any());
5558

5659
TrackerService trackerService = mock(TrackerService.class);
5760
when(trackerService.submit(any(), any(), any(), any())).thenReturn(true);

src/test/java/health/ere/ps/service/gematik/PharmacyServiceTest.java

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
package health.ere.ps.service.gematik;
22

3-
import health.ere.ps.config.AppConfig;
4-
import health.ere.ps.config.RuntimeConfig;
5-
import health.ere.ps.jmx.ReadEPrescriptionsMXBeanImpl;
6-
import health.ere.ps.model.config.UserConfigurations;
7-
import health.ere.ps.service.idp.BearerTokenService;
8-
import jakarta.ws.rs.client.Client;
9-
import jakarta.ws.rs.client.Invocation.Builder;
10-
import jakarta.ws.rs.client.WebTarget;
11-
import jakarta.ws.rs.core.Response;
12-
import org.junit.jupiter.api.AfterEach;
13-
import org.junit.jupiter.api.BeforeEach;
14-
import org.junit.jupiter.api.Test;
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.fail;
6+
import static org.mockito.ArgumentMatchers.any;
7+
import static org.mockito.ArgumentMatchers.nullable;
8+
import static org.mockito.Mockito.mock;
9+
import static org.mockito.Mockito.when;
1510

1611
import java.io.IOException;
1712
import java.nio.file.Files;
@@ -21,12 +16,22 @@
2116
import java.util.concurrent.TimeUnit;
2217
import java.util.stream.Stream;
2318

24-
import static org.junit.jupiter.api.Assertions.assertEquals;
25-
import static org.junit.jupiter.api.Assertions.assertFalse;
26-
import static org.mockito.ArgumentMatchers.any;
27-
import static org.mockito.ArgumentMatchers.nullable;
28-
import static org.mockito.Mockito.mock;
29-
import static org.mockito.Mockito.when;
19+
import org.junit.jupiter.api.AfterEach;
20+
import org.junit.jupiter.api.BeforeEach;
21+
import org.junit.jupiter.api.Test;
22+
23+
import health.ere.ps.config.AppConfig;
24+
import health.ere.ps.config.RuntimeConfig;
25+
import health.ere.ps.jmx.ReadEPrescriptionsMXBeanImpl;
26+
import health.ere.ps.model.config.UserConfigurations;
27+
import health.ere.ps.service.gematik.PharmacyService.ReadVSDResult;
28+
import health.ere.ps.service.idp.BearerTokenService;
29+
import jakarta.ws.rs.client.Client;
30+
import jakarta.ws.rs.client.Invocation.Builder;
31+
import jakarta.ws.rs.client.WebTarget;
32+
import jakarta.ws.rs.core.Response;
33+
import jakarta.xml.bind.DatatypeConverter;
34+
import jakarta.xml.ws.Holder;
3035

3136
class PharmacyServiceTest {
3237
private static final Path FAILED_REJECTS_FILE = Paths.get("target/test-dangling-e-prescriptions.dat");
@@ -133,6 +138,20 @@ void testRetryFailedRejects() throws Exception {
133138
}
134139
}
135140

141+
@Test
142+
public void testExtractKvnr() {
143+
try (PharmacyService pharmacyService = new PharmacyService()) {
144+
ReadVSDResult readVSDResult = pharmacyService.new ReadVSDResult();
145+
readVSDResult.persoenlicheVersichertendaten = new Holder<byte[]>(DatatypeConverter.parseBase64Binary("H4sIAAAAAAAAAI1Sy27bMBD8FYH3iJITIXaxYhDERewijoO6dXMzGGltCSWXBUk5rb81H9NVHo4d9NALyRnOcpYcwsVva5It+tA6KkWeZiJBqlzd0qYU08X8ZDgsRid5IZIQNdXaOMJS/MEgLhR8v1rdcalDMm3V4LI/hmcfkZU83M9ukqvxbLX8/HUxnd+WokgHvQN7UihFE+OvT1I+hnSDVsf2Z1qjXGu5DbXtB7llvVBwcK4/QrSajtV9nmdnw2IwykF+3IPn9kjBNT50PgbuqrMqH50Ps7PBOcgjGpbOk7aovrhGEyWXZu0oJIvWOkom2Nbo2eFVA7e6ap5XT/5BE8g9Zq9QNQarJqpZb7FHXGORwq4LOu7UtdfrvuyAgm9tRKPuvFunydinIF8IWESvQ0C6rD3yzPdyIRps4043Rg2y06IAecTB3Ec10ZbvtwHZA7jh/BT8cA0FFhnNIaHnqFGNQf6LBvlS8uquJs4EfthHbQzINxImugvUWcvZnGYgD+Be9N63fAtEHocq/+Mrqb+FySMvrQIAAA=="));
146+
readVSDResult.pruefungsnachweis = new Holder<byte[]>(DatatypeConverter.parseBase64Binary("H4sIAAAAAAAA/7MJ8FNwdvGND3MNCvb097NVMtQz0DNQUqjIzckrtlXKKCkpsNLXLy/WS0/NTSzJzNZLSdVPS9QvK07J1S/IK9cvA6pXsrMJCbYzMjAyMTAysDA0NjAwMLTRBwrZuNoZ2+i72tnoB/jZAQBWMwfLagAAAA=="));
147+
148+
assertEquals("X110485291", PharmacyService.extractKVNR(readVSDResult));
149+
} catch(Exception e) {
150+
e.printStackTrace();
151+
fail(e);
152+
}
153+
}
154+
136155
private static PharmacyService getPharmacyServiceWithMocks() {
137156
Client client = mock(Client.class);
138157
WebTarget successTarget = mock(WebTarget.class);

0 commit comments

Comments
 (0)