package dk.silverbullet.telemed.questionnaire.node.monica.realtime; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import java.io.File; import java.io.StringReader; import java.io.StringWriter; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.UUID; /* * If you're having trouble running these tests from your IDE try running 'mvn test' from the commandline first */ public class MilouRealtimeDocumentBuilderTest { PatientInfo patientInfo; UUID registratonId; String deviceName; File newMessageSchema = fileFor("schemas/newMessageSchema.xsd"); @Before public void setupPatientInfo() { this.patientInfo = new PatientInfo(); patientInfo.firstName = "NancyAnn"; patientInfo.lastName = "Berggren"; patientInfo.id = 1l; } @Before public void setupRegistrationId() { this.registratonId = UUID.randomUUID(); } @Before public void setupDeviceName() { this.deviceName = "UnitTest-Device"; } @Test public void canBuildDocumentFromSingleSignalMessage() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); SignalMessage signalMessage = new SignalMessage(Calendar.getInstance().getTime()); builder.startNewMessagesDocument(); builder.addMessageToDocument(signalMessage); Document document = builder.finishDocument(); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); } @Test public void canBuildDocumentFromSingleSampleMessage() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); float[] mhr = {1f, 2f, 3f, 4f}; float[] fhr = {5f, 6f, 7f, 8f}; int[] qfhr = {9, 10, 11, 12}; float[] toco = {13f, 14f, 15f, 16f}; SampleMessage sampleMessage = new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime()); builder.startNewMessagesDocument(); builder.addMessageToDocument(sampleMessage); Document document = builder.finishDocument(); System.out.println(documentToString(document)); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); } @Test public void canBuildDocumentFromMultipleSignalAndSampleMessages() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); float[] mhr = {1f, 2f, 3f, 4f}; float[] fhr = {5f, 6f, 7f, 8f}; int[] qfhr = {9, 10, 11, 12}; float[] toco = {13f, 14f, 15f, 16f}; List<RealTimeCTGMessage> messages = new ArrayList<RealTimeCTGMessage>(); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SignalMessage(Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SignalMessage(Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SignalMessage(Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SignalMessage(Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime())); messages.add(new SignalMessage(Calendar.getInstance().getTime())); builder.startNewMessagesDocument(); for(RealTimeCTGMessage message: messages) { builder.addMessageToDocument(message); } Document document = builder.finishDocument(); System.out.println(documentToString(document)); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); } @Test public void canBuildStopMessage() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); Document document = builder.buildStopDocument(); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); } @Test public void addsRegistrationIDToNewMessageDocument() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); SignalMessage signalMessage = new SignalMessage(Calendar.getInstance().getTime()); builder.startNewMessagesDocument(); builder.addMessageToDocument(signalMessage); Document document = builder.finishDocument(); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); assertRegistrationID(document, "registrationIDField"); } @Test public void addsRegistrationIDToNStopRegistrationMessageDocument() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); Document document = builder.buildStopDocument(); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); assertRegistrationID(document, "registrationID"); } @Test public void addsPatientInfoNewMessageDocument() { MilouRealtimeDocumentBuilder builder = new MilouRealtimeDocumentBuilder(deviceName, registratonId, patientInfo); float[] mhr = {1f, 2f, 3f, 4f}; float[] fhr = {5f, 6f, 7f, 8f}; int[] qfhr = {9, 10, 11, 12}; float[] toco = {13f, 14f, 15f, 16f}; SampleMessage sampleMessage = new SampleMessage(mhr, fhr, qfhr, toco, 0, Calendar.getInstance().getTime()); builder.startNewMessagesDocument(); builder.addMessageToDocument(sampleMessage); Document document = builder.finishDocument(); Assert.assertTrue(soapBodyContentsAreSchemaValid(document)); NodeList registratonIdNodes = document.getElementsByTagName("patientField"); Assert.assertEquals(1, registratonIdNodes.getLength()); NodeList idFieldNodes = document.getElementsByTagName("idField"); Assert.assertEquals(1, idFieldNodes.getLength()); Assert.assertEquals(patientInfo.id + "", idFieldNodes.item(0).getTextContent()); NodeList firstFieldNodes = document.getElementsByTagName("firstField"); Assert.assertEquals(1, firstFieldNodes.getLength()); Assert.assertEquals(patientInfo.firstName + "", firstFieldNodes.item(0).getTextContent()); NodeList lastFieldNodes = document.getElementsByTagName("lastField"); Assert.assertEquals(1, lastFieldNodes.getLength()); Assert.assertEquals(patientInfo.lastName + "", lastFieldNodes.item(0).getTextContent()); } private void assertRegistrationID(Document document, String registrationFieldName) { NodeList registratonIdNodes = document.getElementsByTagName(registrationFieldName); Assert.assertEquals(1, registratonIdNodes.getLength()); Assert.assertEquals(registratonId.toString(), registratonIdNodes.item(0).getTextContent()); } private String documentToString(Document doc) { try { DOMSource domSource = new DOMSource(doc); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); transformer.transform(domSource, result); return writer.toString(); } catch (TransformerException e) { e.printStackTrace(); } return "<serializationError/>"; } private boolean soapBodyContentsAreSchemaValid(Document soapEnvelopeDocument) { Document bodyContents = documentFromSoapBodyContents(soapEnvelopeDocument); try { DocumentBuilder builder = null; SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(newMessageSchema); Validator validator = schema.newValidator(); validator.setErrorHandler(new ErrorHandler() { @Override public void warning(SAXParseException exception) throws SAXException { } @Override public void error(SAXParseException exception) throws SAXException { throw new RuntimeException("Validation error", exception); } @Override public void fatalError(SAXParseException exception) throws SAXException { throw new RuntimeException("Validation error", exception); } }); DocumentBuilderFactory domParserFactory = DocumentBuilderFactory.newInstance(); domParserFactory.setValidating(true); domParserFactory.setSchema(schema); SAXSource source = new SAXSource(new InputSource(new StringReader(documentToString(bodyContents)))); validator.validate(source); } catch (Exception e) { e.printStackTrace(); return false; } return true; } private static File fileFor(String resource) { try { return new File(MilouRealtimeDocumentBuilderTest.class.getResource(resource).toURI()); } catch (URISyntaxException e) { // Should never, ever be able to happen throw new IllegalStateException("class.getResource(...) gives an invalid URI? I don't think so.", e); } } private Document documentFromSoapBodyContents(Document document) { try { //Envelope //Body //Body contents Node node = document.getFirstChild().getFirstChild().getFirstChild(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = null; builder = factory.newDocumentBuilder(); Document newDocument = builder.newDocument(); Node importedNode = newDocument.importNode(node, true); newDocument.appendChild(importedNode); return newDocument; } catch (ParserConfigurationException e) { e.printStackTrace(); } return null; } }