Skip to content

Commit 239de56

Browse files
authored
Normalize message skeleton (#1331)
* normalize message skeleton * pitest coverage * pitest coverage * pitest coverage * test removal
1 parent a319c2b commit 239de56

2 files changed

Lines changed: 98 additions & 4 deletions

File tree

gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/service/SkeletonProcessingService.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
2222
public class SkeletonProcessingService {
2323

24-
private static final int XML_CONCAT_CONSTANT_LENGTH = 100;
2524

2625
private final AttachmentHandlerService attachmentHandlerService;
2726
private final XmlParseUtilService xmlParseUtilService;
@@ -38,11 +37,11 @@ public InboundMessage updateInboundMessageWithSkeleton(PatientAttachmentLog skel
3837
var skeletonFileAsString = new String(skeletonAttachment, StandardCharsets.UTF_8);
3938

4039
try {
40+
var normalizedSkeleton = normalizeSkeletonXml(skeletonFileAsString);
4141
// if the skeleton starts with the RCMR tag, then we are replacing the whole message.
4242
// this behaviour is not a part of the specification but we have found this format in some messages
43-
var replaceEntirePayload = skeletonFileAsString
44-
.substring(0, XML_CONCAT_CONSTANT_LENGTH).contains("<RCMR_IN030000UK06");
45-
var skeletonExtractDocument = xPathService.parseDocumentFromXml(skeletonFileAsString);
43+
var replaceEntirePayload = isEntireRcmrSkeleton(normalizedSkeleton);
44+
var skeletonExtractDocument = xPathService.parseDocumentFromXml(normalizedSkeleton);
4645

4746
if (replaceEntirePayload) {
4847
// replace the entire inbound message payload
@@ -61,6 +60,21 @@ public InboundMessage updateInboundMessageWithSkeleton(PatientAttachmentLog skel
6160
}
6261
}
6362

63+
private String normalizeSkeletonXml(String skeletonFileAsString) {
64+
if (skeletonFileAsString == null || skeletonFileAsString.isBlank()) {
65+
return skeletonFileAsString;
66+
}
67+
68+
return skeletonFileAsString
69+
.replace("\uFEFF", "")
70+
.replaceFirst("^(?s)\\s*<\\?xml[^>]*>\\s*", "")
71+
.stripLeading();
72+
}
73+
74+
private boolean isEntireRcmrSkeleton(String normalizedSkeleton) {
75+
return normalizedSkeleton != null && normalizedSkeleton.startsWith("<RCMR_IN030000UK06");
76+
}
77+
6478
private InboundMessage insertSkeletonIntoInboundMessagePayload(PatientAttachmentLog skeletonLog,
6579
InboundMessage inboundMessage, Document skeletonExtractDocument)
6680
throws SAXException, TransformerException {

gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/service/SkeletonProcessingServiceTests.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import static java.util.UUID.randomUUID;
44

55
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
import static org.junit.jupiter.api.Assertions.assertFalse;
7+
import static org.junit.jupiter.api.Assertions.assertNull;
68
import static org.junit.jupiter.api.Assertions.assertThrows;
9+
import static org.junit.jupiter.api.Assertions.assertTrue;
710
import static org.mockito.ArgumentMatchers.any;
811

912
import static org.mockito.ArgumentMatchers.eq;
@@ -143,6 +146,83 @@ void When_HappyPathWithSkeletonAsRCMRMessage_Expect_ThrowNoErrors() throws Trans
143146
skeletonProcessingService.updateInboundMessageWithSkeleton(attachmentLog, inboundMessage, CONVERSATION_ID);
144147
}
145148

149+
@Test
150+
void When_SkeletonAsWholeRCMRMessageHasLeadingWhitespace_Expect_InboundMessagePayloadIsNewRCMRMessage()
151+
throws TransformerException, SAXException {
152+
var inboundMessage = new InboundMessage();
153+
var attachmentLog = createSkeletonPatientAttachmentLog();
154+
var skeletonMessage = "\n " + readInboundMessagePayloadFromFile();
155+
156+
inboundMessage.setPayload(readInboundMessagePayloadFromFile());
157+
inboundMessage.setEbXML(readInboundMessageEbXmlFromFile());
158+
159+
when(attachmentHandlerService.getAttachment(any(), any())).thenReturn(skeletonMessage.getBytes(StandardCharsets.UTF_8));
160+
when(xmlParseUtilService.getStringFromDocument(any())).thenReturn(readInboundMessagePayloadFromFile());
161+
162+
var newInboundMessage =
163+
skeletonProcessingService.updateInboundMessageWithSkeleton(attachmentLog, inboundMessage, CONVERSATION_ID);
164+
165+
assertTrue(newInboundMessage.getPayload().contains("<RCMR_IN030000UK06"));
166+
}
167+
168+
@Test
169+
void When_NormalizeSkeletonXmlCalledWithNull_Expect_ReturnsNull() throws Exception {
170+
var method = SkeletonProcessingService.class.getDeclaredMethod("normalizeSkeletonXml", String.class);
171+
method.setAccessible(true);
172+
173+
assertNull(method.invoke(skeletonProcessingService, new Object[] {null}));
174+
}
175+
176+
@Test
177+
void When_NormalizeSkeletonXmlCalledWithBlankString_Expect_ReturnsOriginalBlankString() throws Exception {
178+
var method = SkeletonProcessingService.class.getDeclaredMethod("normalizeSkeletonXml", String.class);
179+
method.setAccessible(true);
180+
181+
var blankInput = " \n\t ";
182+
assertEquals(blankInput, method.invoke(skeletonProcessingService, blankInput));
183+
}
184+
185+
@Test
186+
void When_IsEntireRcmrSkeletonCalledWithNonRcmrPayload_Expect_ReturnsFalse() throws Exception {
187+
var method = SkeletonProcessingService.class.getDeclaredMethod("isEntireRcmrSkeleton", String.class);
188+
method.setAccessible(true);
189+
190+
assertFalse((Boolean) method.invoke(skeletonProcessingService, "<MCCI_IN010000UK13>"));
191+
}
192+
193+
@Test
194+
void When_NormalizeSkeletonXmlCalledWithXmlDeclaration_Expect_StripsDeclarationBeforeRcmrCheck() throws Exception {
195+
var normalizeMethod = SkeletonProcessingService.class.getDeclaredMethod("normalizeSkeletonXml", String.class);
196+
normalizeMethod.setAccessible(true);
197+
var isRcmrMethod = SkeletonProcessingService.class.getDeclaredMethod("isEntireRcmrSkeleton", String.class);
198+
isRcmrMethod.setAccessible(true);
199+
200+
var xmlWithDeclaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<RCMR_IN030000UK06>";
201+
var normalized = (String) normalizeMethod.invoke(skeletonProcessingService, xmlWithDeclaration);
202+
203+
assertTrue(normalized.startsWith("<RCMR_IN030000UK06"));
204+
assertTrue((Boolean) isRcmrMethod.invoke(skeletonProcessingService, normalized));
205+
}
206+
207+
@Test
208+
void When_SkeletonAsWholeRCMRMessageHasBomPrefix_Expect_InboundMessagePayloadIsNewRCMRMessage()
209+
throws TransformerException, SAXException {
210+
var inboundMessage = new InboundMessage();
211+
var attachmentLog = createSkeletonPatientAttachmentLog();
212+
var skeletonMessage = "\uFEFF" + readInboundMessagePayloadFromFile();
213+
214+
inboundMessage.setPayload(readInboundMessagePayloadFromFile());
215+
inboundMessage.setEbXML(readInboundMessageEbXmlFromFile());
216+
217+
when(attachmentHandlerService.getAttachment(any(), any())).thenReturn(skeletonMessage.getBytes(StandardCharsets.UTF_8));
218+
when(xmlParseUtilService.getStringFromDocument(any())).thenReturn(readInboundMessagePayloadFromFile());
219+
220+
var newInboundMessage =
221+
skeletonProcessingService.updateInboundMessageWithSkeleton(attachmentLog, inboundMessage, CONVERSATION_ID);
222+
223+
assertTrue(newInboundMessage.getPayload().contains("<RCMR_IN030000UK06"));
224+
}
225+
146226
@Test
147227
void When_HappyPathWithSkeletonAsRCMRMessage_Expect_InboundMessagePayloadIsNewRCMRMessage()
148228
throws TransformerException, SAXException {

0 commit comments

Comments
 (0)