package dk.silverbullet.telemed.questionnaire.node.monica.realtime;
import android.util.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.util.*;
import static dk.silverbullet.telemed.utils.Json.ISO8601_DATE_TIME_FORMAT;
public class MilouRealtimeDocumentBuilder {
private static final String XMLNS_MIL = "http://schemas.datacontract.org/2004/07/Milou.Server.OpenTeleRT";
private static final String XMLNS_ARR = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";
private static final String XMLNS_TEM = "http://tempuri.org/";
private static final String XMLNS_SOAP = "http://schemas.xmlsoap.org/soap/envelope/";
private static final String XMLNS_XSI = "http://www.w3.org/2001/XMLSchema-instance";
private final String deviceName;
private final UUID registrationIdentifier;
private PatientInfo patientInfo;
private DocumentBuilderFactory documentBuilderFactory;
private DocumentBuilder documentBuilder;
private ArrayList<RealTimeCTGMessage> messages;
public MilouRealtimeDocumentBuilder(String deviceName, UUID registrationIdentifier, PatientInfo patientInfo) {
this.deviceName = deviceName;
this.registrationIdentifier = registrationIdentifier;
this.patientInfo = patientInfo;
try {
documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
public void startNewMessagesDocument() {
messages = new ArrayList<RealTimeCTGMessage>();
}
public void addMessageToDocument(RealTimeCTGMessage message) {
messages.add(message);
}
public Document finishDocument() {
if(messages.size() > 0) {
return getDocumentForMessages(messages);
} else {
return null;
}
}
public Document buildStopDocument() {
Document stopMessageDocument = documentBuilder.newDocument();
Element soapEnvelope = createSoapEnvelope(stopMessageDocument);
stopMessageDocument.appendChild(soapEnvelope);
Element soapBody = (Element) soapEnvelope.getChildNodes().item(0);
Element stopMessage = stopMessageDocument.createElementNS(XMLNS_TEM, "StopRegistration");
soapBody.appendChild(stopMessage);
Element deviceID = stopMessageDocument.createElementNS(XMLNS_TEM, "deviceID");
deviceID.setTextContent(deviceName);
stopMessage.appendChild(deviceID);
Element registrationId = stopMessageDocument.createElementNS(XMLNS_TEM, "registrationID"); //Yes. It does have a different name in the StopRegistrationMessages
registrationId.setTextContent(registrationIdentifier.toString());
stopMessage.appendChild(registrationId);
Element stopTime = stopMessageDocument.createElementNS(XMLNS_TEM, "stopTime");
stopTime.setTextContent(calendarToXSDDateTime(Calendar.getInstance()));
stopMessage.appendChild(stopTime);
return stopMessageDocument;
}
private Document getDocumentForMessages(List<RealTimeCTGMessage> messages) {
Document messagesDocument = documentBuilder.newDocument();
Element soapEnvelope = createSoapEnvelope(messagesDocument);
messagesDocument.appendChild(soapEnvelope);
Element soapBody = (Element) soapEnvelope.getChildNodes().item(0);
Element newDocumentElement = messagesDocument.createElementNS(XMLNS_TEM, "NewMessage");
soapBody.appendChild(newDocumentElement);
Element messageElement = messagesDocument.createElementNS(XMLNS_TEM, "message");
newDocumentElement.appendChild(messageElement);
Element ctgFieldMessage = messagesDocument.createElementNS(XMLNS_MIL, "ctgField");
messageElement.appendChild(ctgFieldMessage);
Element deviceIDFieldMessage = messagesDocument.createElementNS(XMLNS_MIL, "deviceIDField");
deviceIDFieldMessage.setTextContent(deviceName);
messageElement.appendChild(deviceIDFieldMessage);
Element markersFieldMessage = messagesDocument.createElementNS(XMLNS_MIL, "markersField");
messageElement.appendChild(markersFieldMessage);
for(RealTimeCTGMessage message: messages) {
handleMessage(message, messagesDocument, markersFieldMessage, ctgFieldMessage);
}
if(!markersFieldMessage.hasChildNodes()) {
markersFieldMessage.setAttributeNS(XMLNS_XSI, "nil", "true");
}
addPatientFields(messageElement, messagesDocument);
addRegistrationIDField(messageElement, messagesDocument, registrationIdentifier);
Element tocoShift = messagesDocument.createElementNS(XMLNS_MIL, "tocoShiftField");
tocoShift.setTextContent("4"); //Prior to firmware 5.9 UA-Delay/tocoShift is always 4 seconds
messageElement.appendChild(tocoShift);
return messagesDocument;
}
private void handleMessage(RealTimeCTGMessage message, Document document, Element markersElement, Element sampleSetElement) {
if(message instanceof SignalMessage) {
addSignalMessage((SignalMessage) message, document, markersElement);
} else if(message instanceof SampleMessage) {
addSampleMessage((SampleMessage) message, document, sampleSetElement);
}
}
private Element createSoapEnvelope(Document document) {
Element envelope = document.createElementNS(XMLNS_SOAP, "Envelope");
Element body = document.createElementNS(XMLNS_SOAP, "Body");
envelope.appendChild(body);
return envelope;
}
private String calendarToXSDDateTime(Date date) {
return ISO8601_DATE_TIME_FORMAT.format(date);
}
private String calendarToXSDDateTime(Calendar calendar) {
return ISO8601_DATE_TIME_FORMAT.format(calendar.getTime());
}
private void addSampleMessage(SampleMessage message, Document document, Element parentElement) {
Element sampleElement = document.createElementNS(XMLNS_MIL, "CtgMessageBlock");
parentElement.appendChild(sampleElement);
Element fhrField = document.createElementNS(XMLNS_MIL, "fhrField");
fhrField.setTextContent(Arrays.toString(message.fhr));
sampleElement.appendChild(fhrField);
Element mhrField = document.createElementNS(XMLNS_MIL, "mhrField");
mhrField.setTextContent(Arrays.toString(message.mhr));
sampleElement.appendChild(mhrField);
Element sequenceNbrField = document.createElementNS(XMLNS_MIL, "sequenceNbrField");
sequenceNbrField.setTextContent(message.sampleCount + "");
sampleElement.appendChild(sequenceNbrField);
Element sqField = document.createElementNS(XMLNS_MIL, "sqField");
sqField.setTextContent(Arrays.toString(message.qfhr));
sampleElement.appendChild(sqField);
Element timeField = document.createElementNS(XMLNS_MIL, "timeField");
timeField.setTextContent(calendarToXSDDateTime(message.readTime));
sampleElement.appendChild(timeField);
Element tocoField = document.createElementNS(XMLNS_MIL, "tocoField");
tocoField.setTextContent(Arrays.toString(message.toco));
sampleElement.appendChild(tocoField);
}
private void addSignalMessage(SignalMessage message, Document document, Element parentElement) {
Element dateTimeField = document.createElementNS(XMLNS_ARR, "dateTime");
dateTimeField.setTextContent(calendarToXSDDateTime(message.dateTime));
parentElement.appendChild(dateTimeField);
}
private void addPatientFields(Element parentElement, Document document) {
Element patientElement = document.createElementNS(XMLNS_MIL, "patientField");
Element idElement = document.createElementNS(XMLNS_MIL, "idField");
idElement.setTextContent(patientInfo.id + "");
patientElement.appendChild(idElement);
Element nameElement = document.createElementNS(XMLNS_MIL, "nameField");
patientElement.appendChild(nameElement);
Element firstNameElement = document.createElementNS(XMLNS_MIL, "firstField");
firstNameElement.setTextContent(patientInfo.firstName);
nameElement.appendChild(firstNameElement);
Element lastNameElement = document.createElementNS(XMLNS_MIL, "lastField");
lastNameElement.setTextContent(patientInfo.lastName);
nameElement.appendChild(lastNameElement);
parentElement.appendChild(patientElement);
}
private void addRegistrationIDField(Element parentElement, Document document, UUID registrationIdentifier) {
Element registrationField = document.createElementNS(XMLNS_MIL, "registrationIDField");
registrationField.setTextContent(registrationIdentifier.toString());
parentElement.appendChild(registrationField);
}
}