diff --git a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/_remote.repositories b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/_remote.repositories index 723a6a97..262fc994 100644 --- a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/_remote.repositories +++ b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/_remote.repositories @@ -1,5 +1,5 @@ #NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. -#Wed Oct 16 22:40:04 AMT 2024 +#Thu Oct 17 14:12:52 AMT 2024 lib-cetp-1.0.0-SNAPSHOT-sources.jar>= lib-cetp-1.0.0-SNAPSHOT.jar>= lib-cetp-1.0.0-SNAPSHOT.pom>= diff --git a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT-sources.jar b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT-sources.jar index d008e846..40f564ac 100644 Binary files a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT-sources.jar and b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT-sources.jar differ diff --git a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT.jar b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT.jar index 07975714..afe4a410 100644 Binary files a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT.jar and b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/lib-cetp-1.0.0-SNAPSHOT.jar differ diff --git a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/maven-metadata-local.xml b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/maven-metadata-local.xml index fae84606..6fff50d9 100644 --- a/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/maven-metadata-local.xml +++ b/project-repo/de/servicehealth/lib-cetp/1.0.0-SNAPSHOT/maven-metadata-local.xml @@ -3,7 +3,7 @@ de.servicehealth lib-cetp - 20241016183958 + 20241017101246 true @@ -11,18 +11,18 @@ pom 1.0.0-SNAPSHOT - 20241016183958 + 20241017101246 jar 1.0.0-SNAPSHOT - 20241016183958 + 20241017101246 sources jar 1.0.0-SNAPSHOT - 20241016183958 + 20241017101246 diff --git a/project-repo/de/servicehealth/lib-cetp/maven-metadata-local.xml b/project-repo/de/servicehealth/lib-cetp/maven-metadata-local.xml index 61eaba45..5c33e583 100644 --- a/project-repo/de/servicehealth/lib-cetp/maven-metadata-local.xml +++ b/project-repo/de/servicehealth/lib-cetp/maven-metadata-local.xml @@ -6,6 +6,6 @@ 1.0.0-SNAPSHOT - 20241016183958 + 20241017101246 diff --git a/src/main/java/health/ere/ps/service/cetp/CETPServerHandler.java b/src/main/java/health/ere/ps/service/cetp/CETPServerHandler.java index 9a10ada5..780db06c 100644 --- a/src/main/java/health/ere/ps/service/cetp/CETPServerHandler.java +++ b/src/main/java/health/ere/ps/service/cetp/CETPServerHandler.java @@ -2,22 +2,21 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; -import de.gematik.ws.conn.eventservice.v7.Event; +import de.health.service.cetp.AbstractCETPEventHandler; import de.health.service.cetp.cardlink.CardlinkWebsocketClient; import de.servicehealth.config.api.IUserConfigurations; import health.ere.ps.config.RuntimeConfig; import health.ere.ps.service.cetp.tracker.TrackerService; import health.ere.ps.service.gematik.PharmacyService; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Task; import org.jboss.logging.MDC; -import java.net.InetSocketAddress; import java.util.Map; import java.util.UUID; import java.util.logging.Level; @@ -26,13 +25,12 @@ import static de.health.service.cetp.utils.Utils.printException; -public class CETPServerHandler extends ChannelInboundHandlerAdapter { +public class CETPServerHandler extends AbstractCETPEventHandler { private static final Logger log = Logger.getLogger(CETPServerHandler.class.getName()); TrackerService trackerService; PharmacyService pharmacyService; - CardlinkWebsocketClient cardlinkWebsocketClient; IParser parser = FhirContext.forR4().newXmlParser(); @@ -41,130 +39,85 @@ public CETPServerHandler( PharmacyService pharmacyService, CardlinkWebsocketClient cardlinkWebsocketClient ) { + super(cardlinkWebsocketClient); this.trackerService = trackerService; this.pharmacyService = pharmacyService; - this.cardlinkWebsocketClient = cardlinkWebsocketClient; } @Override - public void handlerAdded(ChannelHandlerContext ctx) { + protected String getTopicName() { + return "CARD/INSERTED"; } @Override - public void handlerRemoved(ChannelHandlerContext ctx) { - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - try { - String correlationId = UUID.randomUUID().toString(); - MDC.put("requestCorrelationId", correlationId); // Keep MDC name in snyc with virtual-nfc-cardlink - cardlinkWebsocketClient.connect(); - - @SuppressWarnings("unchecked") - Pair input = (Pair) msg; - Event event = input.getKey(); - - if (event.getTopic().equals("CARD/INSERTED")) { - final Map eventMap = event.getMessage().getParameter().stream() - .collect(Collectors.toMap(Event.Message.Parameter::getKey, Event.Message.Parameter::getValue)); - - // Keep MDC names in sync with virtual-nfc-cardlink - MDC.put("iccsn", eventMap.getOrDefault("ICCSN", "NoICCSNProvided")); - MDC.put("ctid", eventMap.getOrDefault("CtID", "NoCtIDProvided")); - MDC.put("slot", eventMap.getOrDefault("SlotID", "NoSlotIDProvided")); - log.fine("CARD/INSERTED event received with the following payload: %s".formatted(eventMap)); - - if ("EGK".equalsIgnoreCase(eventMap.get("CardType")) && eventMap.containsKey("CardHandle") && eventMap.containsKey("SlotID") && eventMap.containsKey("CtID")) { - String cardHandle = eventMap.get("CardHandle"); - Integer slotId = Integer.parseInt(eventMap.get("SlotID")); - String ctId = eventMap.get("CtID"); - String iccsn = eventMap.get("ICCSN"); - Long endTime = System.currentTimeMillis(); - - - String paramsStr = event.getMessage().getParameter().stream() - .filter(p -> !p.getKey().equals("CardHolderName")) - .map(p -> String.format("key=%s value=%s", p.getKey(), p.getValue())).collect(Collectors.joining(", ")); - - log.fine(String.format("[%s] Card inserted: params: %s", correlationId, paramsStr)); - try { - IUserConfigurations uc = input.getValue(); - RuntimeConfig runtimeConfig = new RuntimeConfig(uc); - Pair pair = pharmacyService.getEPrescriptionsForCardHandle( - correlationId, cardHandle, null, runtimeConfig - ); - Bundle bundle = pair.getKey(); - String eventId = pair.getValue(); - String xml = parser.encodeToString(bundle); - cardlinkWebsocketClient.sendJson(correlationId, iccsn, "eRezeptTokensFromAVS", Map.of("slotId", slotId, "ctId", ctId, "tokens", xml)); - - JsonArrayBuilder bundles = prepareBundles(correlationId, bundle, runtimeConfig); - cardlinkWebsocketClient.sendJson(correlationId, iccsn, "eRezeptBundlesFromAVS", Map.of("slotId", slotId, "ctId", ctId, "bundles", bundles)); - - cardlinkWebsocketClient.sendJson(correlationId, iccsn, "vsdmSensorData", Map.of("slotId", slotId, "ctId", ctId, "endTime", endTime, "eventId", eventId)); - - trackerService.submit(ctId, uc.getMandantId(), uc.getWorkplaceId(), uc.getClientSystemId()); - } catch (Exception e ) { - log.log(Level.WARNING, String.format("[%s] Could not get prescription for Bundle", correlationId), e); - - if (e instanceof de.gematik.ws.conn.vsds.vsdservice.v5.FaultMessage faultMessage) { - String code = faultMessage.getFaultInfo().getTrace().get(0).getCode().toString(); - cardlinkWebsocketClient.sendJson(correlationId, iccsn, "vsdmSensorData", Map.of("slotId", slotId, "ctId", ctId, "endTime", endTime, "err", code)); - } - if (e instanceof de.gematik.ws.conn.eventservice.wsdl.v7.FaultMessage faultMessage) { - String code = faultMessage.getFaultInfo().getTrace().get(0).getCode().toString(); - cardlinkWebsocketClient.sendJson(correlationId, iccsn, "vsdmSensorData", Map.of("slotId", slotId, "ctId", ctId, "endTime", endTime, "err", code)); - } - - String error = printException(e); - cardlinkWebsocketClient.sendJson( - correlationId, - iccsn, - "receiveTasklistError", - Map.of("slotId", slotId, "cardSessionId", "null", "status", 500, "tistatus", "500", "errormessage", error) - ); - } - } else { - String msgFormat = "Ignored \"CARD/INSERTED\" event=%s: values=%s"; - log.log(Level.INFO, String.format(msgFormat, event.getMessage(), eventMap)); + protected void processEvent(IUserConfigurations uc, Map paramsMap) { + // Keep MDC names in sync with virtual-nfc-cardlink + String correlationId = UUID.randomUUID().toString(); + MDC.put("requestCorrelationId", correlationId); + MDC.put("iccsn", paramsMap.getOrDefault("ICCSN", "NoICCSNProvided")); + MDC.put("ctid", paramsMap.getOrDefault("CtID", "NoCtIDProvided")); + MDC.put("slot", paramsMap.getOrDefault("SlotID", "NoSlotIDProvided")); + log.fine("CARD/INSERTED event received with the following payload: %s".formatted(paramsMap)); + + if ("EGK".equalsIgnoreCase(paramsMap.get("CardType")) && paramsMap.containsKey("CardHandle") && paramsMap.containsKey("SlotID") && paramsMap.containsKey("CtID")) { + String cardHandle = paramsMap.get("CardHandle"); + Integer slotId = Integer.parseInt(paramsMap.get("SlotID")); + String ctId = paramsMap.get("CtID"); + String iccsn = paramsMap.get("ICCSN"); + Long endTime = System.currentTimeMillis(); + + + String paramsStr = paramsMap.entrySet().stream() + .filter(p -> !p.getKey().equals("CardHolderName")) + .map(p -> String.format("key=%s value=%s", p.getKey(), p.getValue())).collect(Collectors.joining(", ")); + + log.fine(String.format("[%s] Card inserted: params: %s", correlationId, paramsStr)); + try { + RuntimeConfig runtimeConfig = new RuntimeConfig(uc); + Pair pair = pharmacyService.getEPrescriptionsForCardHandle( + correlationId, cardHandle, null, runtimeConfig + ); + Bundle bundle = pair.getKey(); + String eventId = pair.getValue(); + String xml = parser.encodeToString(bundle); + cardlinkWebsocketClient.sendJson(correlationId, iccsn, "eRezeptTokensFromAVS", Map.of("slotId", slotId, "ctId", ctId, "tokens", xml)); + + JsonArrayBuilder bundles = prepareBundles(correlationId, bundle, runtimeConfig); + cardlinkWebsocketClient.sendJson(correlationId, iccsn, "eRezeptBundlesFromAVS", Map.of("slotId", slotId, "ctId", ctId, "bundles", bundles)); + + cardlinkWebsocketClient.sendJson(correlationId, iccsn, "vsdmSensorData", Map.of("slotId", slotId, "ctId", ctId, "endTime", endTime, "eventId", eventId)); + + trackerService.submit(ctId, uc.getMandantId(), uc.getWorkplaceId(), uc.getClientSystemId()); + } catch (Exception e ) { + log.log(Level.WARNING, String.format("[%s] Could not get prescription for Bundle", correlationId), e); + + if (e instanceof de.gematik.ws.conn.vsds.vsdservice.v5.FaultMessage faultMessage) { + String code = faultMessage.getFaultInfo().getTrace().get(0).getCode().toString(); + cardlinkWebsocketClient.sendJson(correlationId, iccsn, "vsdmSensorData", Map.of("slotId", slotId, "ctId", ctId, "endTime", endTime, "err", code)); + } + if (e instanceof de.gematik.ws.conn.eventservice.wsdl.v7.FaultMessage faultMessage) { + String code = faultMessage.getFaultInfo().getTrace().get(0).getCode().toString(); + cardlinkWebsocketClient.sendJson(correlationId, iccsn, "vsdmSensorData", Map.of("slotId", slotId, "ctId", ctId, "endTime", endTime, "err", code)); } - } - - } finally { - cardlinkWebsocketClient.close(); - MDC.clear(); - } - } - - @Override - public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - if (log.isLoggable(Level.FINE)) { - String port = "unknown"; - if (ctx.channel().localAddress() instanceof InetSocketAddress inetSocketAddress) { - port = String.valueOf(inetSocketAddress.getPort()); - } - log.fine(String.format("New CETP connection established (on port %s)", port)); - } - super.channelRegistered(ctx); - } - @Override - public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { - if (log.isLoggable(Level.FINE)) { - String port = "unknown"; - if (ctx.channel().localAddress() instanceof InetSocketAddress inetSocketAddress) { - port = String.valueOf(inetSocketAddress.getPort()); + String error = printException(e); + cardlinkWebsocketClient.sendJson( + correlationId, + iccsn, + "receiveTasklistError", + Map.of("slotId", slotId, "cardSessionId", "null", "status", 500, "tistatus", "500", "errormessage", error) + ); } - log.fine(String.format("CETP connection was closed (on port %s)", port)); + } else { + String msgFormat = "Ignored \"CARD/INSERTED\" values=%s"; + log.log(Level.INFO, String.format(msgFormat, paramsMap)); } - super.channelUnregistered(ctx); } private JsonArrayBuilder prepareBundles(String correlationId, Bundle bundle, RuntimeConfig runtimeConfig) { JsonArrayBuilder bundles = Json.createArrayBuilder(); for (BundleEntryComponent entry : bundle.getEntry()) { - if (entry.getResource() instanceof org.hl7.fhir.r4.model.Task) { + if (entry.getResource() instanceof Task task) { /* * * @@ -178,9 +131,8 @@ private JsonArrayBuilder prepareBundles(String correlationId, Bundle bundle, Run * */ - org.hl7.fhir.r4.model.Task task = (org.hl7.fhir.r4.model.Task) entry.getResource(); - String taskId = task.getIdentifier().stream().filter(t -> "https://gematik.de/fhir/erp/NamingSystem/GEM_ERP_NS_PrescriptionId".equals(t.getSystem())).map(t -> t.getValue()).findAny().orElse(null); - String accessCode = task.getIdentifier().stream().filter(t -> "https://gematik.de/fhir/erp/NamingSystem/GEM_ERP_NS_AccessCode".equals(t.getSystem())).map(t -> t.getValue()).findAny().orElse(null); + String taskId = task.getIdentifier().stream().filter(t -> "https://gematik.de/fhir/erp/NamingSystem/GEM_ERP_NS_PrescriptionId".equals(t.getSystem())).map(Identifier::getValue).findAny().orElse(null); + String accessCode = task.getIdentifier().stream().filter(t -> "https://gematik.de/fhir/erp/NamingSystem/GEM_ERP_NS_AccessCode".equals(t.getSystem())).map(Identifier::getValue).findAny().orElse(null); log.fine("TaskId: " + taskId + " AccessCode: " + accessCode); String token = "/Task/" + taskId + "/$accept?ac=" + accessCode; try { @@ -193,10 +145,4 @@ private JsonArrayBuilder prepareBundles(String correlationId, Bundle bundle, Run } return bundles; } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - log.log(Level.SEVERE, "Caught an exception handling CETP input", cause); - ctx.close(); - } } diff --git a/src/main/java/health/ere/ps/service/cetp/CETPServerHandlerFactory.java b/src/main/java/health/ere/ps/service/cetp/CETPServerHandlerFactory.java index 46026270..89cd5e4b 100644 --- a/src/main/java/health/ere/ps/service/cetp/CETPServerHandlerFactory.java +++ b/src/main/java/health/ere/ps/service/cetp/CETPServerHandlerFactory.java @@ -43,7 +43,7 @@ public CETPServerHandlerFactory( } @Override - public ChannelInboundHandler build(KonnektorConfig kc) { + public ChannelInboundHandler[] build(KonnektorConfig kc) { CardlinkWebsocketClient cardlinkWebsocketClient = new CardlinkWebsocketClient( kc.getCardlinkEndpoint(), new EreJwtConfigurator( @@ -56,6 +56,8 @@ public ChannelInboundHandler build(KonnektorConfig kc) { kc.getCardlinkEndpoint(), cardlinkWebsocketClient.connected() ); - return new CETPServerHandler(trackerService, pharmacyService, cardlinkWebsocketClient); + return new CETPServerHandler[] { + new CETPServerHandler(trackerService, pharmacyService, cardlinkWebsocketClient) + }; } } diff --git a/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoder.java b/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoder.java index d0d296f6..e78fa941 100644 --- a/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoder.java +++ b/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoder.java @@ -1,13 +1,14 @@ package health.ere.ps.service.cetp.codec; import de.gematik.ws.conn.eventservice.v7.Event; +import de.health.service.cetp.domain.eventservice.event.DecodeResult; +import de.health.service.cetp.domain.eventservice.event.mapper.CetpEventMapper; import de.servicehealth.config.api.IUserConfigurations; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; -import org.apache.commons.lang3.tuple.Pair; import java.io.StringReader; import java.nio.charset.StandardCharsets; @@ -20,7 +21,6 @@ public class CETPDecoder extends ByteToMessageDecoder { private static final Logger log = Logger.getLogger(CETPDecoder.class.getName()); static JAXBContext jaxbContext; - static { try { jaxbContext = JAXBContext.newInstance(Event.class); @@ -28,37 +28,35 @@ public class CETPDecoder extends ByteToMessageDecoder { log.log(Level.SEVERE, "Failed to create JAXB context", e); } } - IUserConfigurations userConfigurations; - public CETPDecoder() { + IUserConfigurations configurations; + CetpEventMapper eventMapper; + public CETPDecoder() { } - public CETPDecoder(IUserConfigurations userConfigurations) { - this.userConfigurations = userConfigurations; + public CETPDecoder(IUserConfigurations configurations, CetpEventMapper eventMapper) { + this.configurations = configurations; + this.eventMapper = eventMapper; } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { // (2) - if(!in.isReadable(4)) { - return; - } - byte[] header = new byte[4]; + if (!in.isReadable(4)) { + return; + } + byte[] header = new byte[4]; in.readBytes(header); - - if(header[0] != 'C' || header[1] != 'E' || header[2] != 'T' || header[3] != 'P') { + if (header[0] != 'C' || header[1] != 'E' || header[2] != 'T' || header[3] != 'P') { throw new IllegalArgumentException("Invalid CETP header"); } int lengthOfMessage = in.readInt(); - String message = in.readCharSequence(lengthOfMessage, StandardCharsets.UTF_8).toString(); - log.info(message); - try { Event eventType = (Event) jaxbContext.createUnmarshaller().unmarshal(new StringReader(message)); - out.add(Pair.of(eventType, userConfigurations)); + out.add(new DecodeResult(eventMapper.toDomain(eventType), configurations)); } catch (JAXBException e) { log.log(Level.SEVERE, "Failed to unmarshal CETP message", e); } diff --git a/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoderFactory.java b/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoderFactory.java index ba588af7..b68eaa6e 100644 --- a/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoderFactory.java +++ b/src/main/java/health/ere/ps/service/cetp/codec/CETPDecoderFactory.java @@ -1,6 +1,7 @@ package health.ere.ps.service.cetp.codec; import de.health.service.cetp.codec.CETPEventDecoderFactory; +import de.health.service.cetp.domain.eventservice.event.mapper.CetpEventMapper; import de.servicehealth.config.api.IUserConfigurations; import io.netty.channel.ChannelInboundHandler; import jakarta.enterprise.context.ApplicationScoped; @@ -9,7 +10,7 @@ public class CETPDecoderFactory implements CETPEventDecoderFactory { @Override - public ChannelInboundHandler build(IUserConfigurations userConfigurations) { - return new CETPDecoder(userConfigurations); + public ChannelInboundHandler build(IUserConfigurations configurations, CetpEventMapper eventMapper) { + return new CETPDecoder(configurations, eventMapper); } } diff --git a/src/main/java/health/ere/ps/service/cetp/mapper/event/EventMapper.java b/src/main/java/health/ere/ps/service/cetp/mapper/event/EventMapper.java new file mode 100644 index 00000000..bd2cdaf8 --- /dev/null +++ b/src/main/java/health/ere/ps/service/cetp/mapper/event/EventMapper.java @@ -0,0 +1,20 @@ +package health.ere.ps.service.cetp.mapper.event; + +import de.gematik.ws.conn.eventservice.v7.Event; +import de.health.service.cetp.domain.eventservice.event.CetpEvent; +import de.health.service.cetp.domain.eventservice.event.mapper.CetpEventMapper; +import health.ere.ps.service.cetp.mapper.DefaultMappingConfig; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper( + config = DefaultMappingConfig.class, + uses = {EventTypeMapper.class, SeverityTypeMapper.class, ParameterMapper.class} +) +public abstract class EventMapper implements CetpEventMapper { + + @Override + @Mapping(target = "subscriptionId", source = "subscriptionID") + @Mapping(target = "parameters", source = "message.parameter") + public abstract CetpEvent toDomain(Event soap); +} diff --git a/src/main/java/health/ere/ps/service/cetp/mapper/event/EventTypeMapper.java b/src/main/java/health/ere/ps/service/cetp/mapper/event/EventTypeMapper.java new file mode 100644 index 00000000..084bb159 --- /dev/null +++ b/src/main/java/health/ere/ps/service/cetp/mapper/event/EventTypeMapper.java @@ -0,0 +1,13 @@ +package health.ere.ps.service.cetp.mapper.event; + +import de.gematik.ws.conn.eventservice.v7.EventType; +import de.health.service.cetp.domain.eventservice.event.CetpEventType; +import health.ere.ps.service.cetp.mapper.DefaultMappingConfig; +import org.mapstruct.Mapper; + +@Mapper(config = DefaultMappingConfig.class) +public interface EventTypeMapper { + + CetpEventType toDomain(EventType eventType); + +} diff --git a/src/main/java/health/ere/ps/service/cetp/mapper/event/ParameterMapper.java b/src/main/java/health/ere/ps/service/cetp/mapper/event/ParameterMapper.java new file mode 100644 index 00000000..9e876a32 --- /dev/null +++ b/src/main/java/health/ere/ps/service/cetp/mapper/event/ParameterMapper.java @@ -0,0 +1,12 @@ +package health.ere.ps.service.cetp.mapper.event; + +import de.gematik.ws.conn.eventservice.v7.Event; +import de.health.service.cetp.domain.eventservice.event.CetpParameter; +import health.ere.ps.service.cetp.mapper.DefaultMappingConfig; +import org.mapstruct.Mapper; + +@Mapper(config = DefaultMappingConfig.class) +public interface ParameterMapper { + + CetpParameter toDomain(Event.Message.Parameter soap); +} diff --git a/src/main/java/health/ere/ps/service/cetp/mapper/event/SeverityTypeMapper.java b/src/main/java/health/ere/ps/service/cetp/mapper/event/SeverityTypeMapper.java new file mode 100644 index 00000000..61d21320 --- /dev/null +++ b/src/main/java/health/ere/ps/service/cetp/mapper/event/SeverityTypeMapper.java @@ -0,0 +1,14 @@ +package health.ere.ps.service.cetp.mapper.event; + +import de.gematik.ws.conn.eventservice.v7.EventSeverityType; +import de.gematik.ws.conn.eventservice.v7.EventType; +import de.health.service.cetp.domain.eventservice.event.CetpEventType; +import de.health.service.cetp.domain.eventservice.event.CetpSeverityType; +import health.ere.ps.service.cetp.mapper.DefaultMappingConfig; +import org.mapstruct.Mapper; + +@Mapper(config = DefaultMappingConfig.class) +public interface SeverityTypeMapper { + + CetpSeverityType toDomain(EventSeverityType eventSeverityType); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a60812a1..c0e74be0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,12 +1,14 @@ # For dev mode purposes, specify the environment variables in this file in a file named .env which # should be located in the root project folder. # -# In regards to file and directory paths, configure the values for the environment variables in the +# In regard to file and directory paths, configure the values for the environment variables in the # .env file to be specific to directory and file paths on your local computer. # # Important! Configure the .env file to be ignored and not checked into the source code repository. quarkus.ssl.native=true +quarkus.http.test-port=8888 + quarkus.http.ssl-port=8443 quarkus.http.ssl.certificate.key-store-file=META-INF/resources/server.keystore quarkus.http.ssl.certificate.key-store-password=password diff --git a/src/test/java/health/ere/ps/service/cetp/event/EventMapperTest.java b/src/test/java/health/ere/ps/service/cetp/event/EventMapperTest.java new file mode 100644 index 00000000..51d21d41 --- /dev/null +++ b/src/test/java/health/ere/ps/service/cetp/event/EventMapperTest.java @@ -0,0 +1,62 @@ +package health.ere.ps.service.cetp.event; + +import de.gematik.ws.conn.eventservice.v7.Event; +import de.gematik.ws.conn.eventservice.v7.EventSeverityType; +import de.gematik.ws.conn.eventservice.v7.EventType; +import de.health.service.cetp.domain.eventservice.event.CetpEvent; +import health.ere.ps.profile.RUDevTestProfile; +import health.ere.ps.service.cetp.mapper.event.EventMapper; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@QuarkusTest +@TestProfile(RUDevTestProfile.class) +public class EventMapperTest { + + @Inject + EventMapper eventMapper; + + @Test + public void soapEventMappedCorrectly() { + Event event = new Event(); + event.setTopic("CARD/INSERTED"); + event.setType(EventType.OPERATION); + event.setSeverity(EventSeverityType.INFO); + event.setSubscriptionID("subscriptionID"); + + Event.Message message = new Event.Message(); + Event.Message.Parameter p1 = new Event.Message.Parameter(); + p1.setKey("Key1"); + p1.setValue("Value1"); + message.getParameter().add(p1); + Event.Message.Parameter p2 = new Event.Message.Parameter(); + p2.setKey("Key2"); + p2.setValue("Value2"); + message.getParameter().add(p2); + + event.setMessage(message); + + CetpEvent domain = eventMapper.toDomain(event); + assertEquals(event.getTopic(), domain.getTopic()); + assertEquals(event.getType().value(), domain.getType().getValue()); + assertEquals(event.getSeverity().value(), domain.getSeverity().getValue()); + assertEquals(event.getSubscriptionID(), domain.getSubscriptionId()); + + List parameter = event.getMessage().getParameter(); + assertEquals(parameter.size(), domain.getParameters().size()); + assertParameter(event, domain, 0); + assertParameter(event, domain, 1); + } + + private void assertParameter(Event event, CetpEvent domain, int index) { + List parameter = event.getMessage().getParameter(); + assertEquals(parameter.get(index).getKey(), domain.getParameters().get(index).getKey()); + assertEquals(parameter.get(index).getValue(), domain.getParameters().get(index).getValue()); + } +} diff --git a/src/test/java/health/ere/ps/service/gematik/CardInsertedTest.java b/src/test/java/health/ere/ps/service/gematik/CardInsertedTest.java index 05467374..5645c0ed 100644 --- a/src/test/java/health/ere/ps/service/gematik/CardInsertedTest.java +++ b/src/test/java/health/ere/ps/service/gematik/CardInsertedTest.java @@ -1,53 +1,57 @@ package health.ere.ps.service.gematik; -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 static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.InputStream; -import java.math.BigInteger; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.tuple.Pair; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - import de.gematik.ws.conn.eventservice.v7.Event; import de.gematik.ws.conn.vsds.vsdservice.v5.FaultMessage; import de.gematik.ws.tel.error.v2.Error; import de.health.service.cetp.cardlink.CardlinkWebsocketClient; +import de.health.service.cetp.domain.eventservice.event.DecodeResult; import health.ere.ps.config.AppConfig; import health.ere.ps.jmx.ReadEPrescriptionsMXBeanImpl; import health.ere.ps.model.config.UserConfigurations; import health.ere.ps.service.cetp.CETPServerHandler; +import health.ere.ps.service.cetp.mapper.event.EventMapper; import health.ere.ps.service.cetp.tracker.TrackerService; import health.ere.ps.service.idp.BearerTokenService; import io.netty.channel.embedded.EmbeddedChannel; import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.Invocation; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.Response; import jakarta.xml.bind.DatatypeConverter; import jakarta.xml.ws.Holder; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.io.InputStream; +import java.math.BigInteger; +import java.util.List; +import java.util.Map; + +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 static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @QuarkusTest class CardInsertedTest { private static final String READ_VSD_RESPONSE = "H4sIAAAAAAAA/w2M3QqCMBhAXyV8AL+5oj/mQNyKgk3ROaKbKLT8T1L8e/q8OReHwyG+XLlMPDQPwosnbcMykYmM1ViVdWsbadc1R4ChNT9J9eyywowTeD+hb+MKmnqAfukNSlRIMcJrtMN7tMW7zYHAoginmACnxL9TzZxJsGgtcmeWjGNPOZbIIyzzVGt2fo1zVvIrFEqq7BZZwVd7Z81+vSsmfzgVNoFlskDSP8uj5+izAAAA"; + @Inject + EventMapper eventMapper; + @Test void vsdmSensorDataWithEventIdIsSentOnCardInsertedEvent() throws Exception { PharmacyService pharmacyService = spy(createPharmacyService()); @@ -66,7 +70,7 @@ void vsdmSensorDataWithEventIdIsSentOnCardInsertedEvent() throws Exception { String slotIdValue = "3"; String ctIdValue = "CtIDValue"; - channel.writeOneInbound(prepareEvent(slotIdValue, ctIdValue)); + channel.writeOneInbound(decode(slotIdValue, ctIdValue)); channel.pipeline().fireChannelReadComplete(); ArgumentCaptor messageTypeCaptor = ArgumentCaptor.forClass(String.class); @@ -110,7 +114,7 @@ void vsdmSensorDataWithErrorIsSentOnCardInsertedEvent() throws Exception { String slotIdValue = "3"; String ctIdValue = "9"; - channel.writeOneInbound(prepareEvent(slotIdValue, ctIdValue)); + channel.writeOneInbound(decode(slotIdValue, ctIdValue)); channel.pipeline().fireChannelReadComplete(); ArgumentCaptor messageTypeCaptor = ArgumentCaptor.forClass(String.class); @@ -162,7 +166,7 @@ private Holder prepareHolder(PharmacyService pharmacyService) { return holder; } - private Pair prepareEvent(String slotIdValue, String ctIdValue) { + private DecodeResult decode(String slotIdValue, String ctIdValue) { Event event = new Event(); event.setTopic("CARD/INSERTED"); Event.Message message = new Event.Message(); @@ -184,7 +188,7 @@ private Pair prepareEvent(String slotIdValue, String message.getParameter().add(parameterCtId); message.getParameter().add(parameterCardType); event.setMessage(message); - return Pair.of(event, new UserConfigurations()); + return new DecodeResult(eventMapper.toDomain(event), new UserConfigurations()); } private static PharmacyService createPharmacyService() {