Java tutorial
/* * Copyright (c) Mirth Corporation. All rights reserved. * http://www.mirthcorp.com * * The software in this package is published under the terms of the MPL * license a copy of which has been included with this distribution in * the LICENSE.txt file. */ package com.mirth.connect.model.converters; import java.io.StringReader; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; import ca.uhn.hl7v2.model.Message; import ca.uhn.hl7v2.parser.DefaultXMLParser; import ca.uhn.hl7v2.parser.PipeParser; import ca.uhn.hl7v2.parser.XMLParser; import ca.uhn.hl7v2.util.Terser; import ca.uhn.hl7v2.validation.impl.NoValidation; public class ER7Serializer implements IXMLSerializer<String> { private Logger logger = Logger.getLogger(this.getClass()); private PipeParser pipeParser = null; private XMLParser xmlParser = null; private boolean useStrictParser = false; private boolean useStrictValidation = false; private boolean stripNamespaces = true; // Used in JST for strict parser private boolean handleRepetitions = false; private boolean handleSubcomponents = false; private boolean convertLFtoCR = true; public ER7Serializer() { initializeParser(); } public ER7Serializer(Map properties) { if (properties != null) { if (properties.get("useStrictParser") != null) { this.useStrictParser = Boolean.parseBoolean((String) properties.get("useStrictParser")); } if (properties.get("useStrictValidation") != null) { this.useStrictValidation = Boolean.parseBoolean((String) properties.get("useStrictValidation")); } if (properties.get("stripNamespaces") != null) { this.stripNamespaces = Boolean.parseBoolean((String) properties.get("stripNamespaces")); } if (properties.get("handleRepetitions") != null) { this.handleRepetitions = Boolean.parseBoolean((String) properties.get("handleRepetitions")); } if (properties.get("handleSubcomponents") != null) { this.handleSubcomponents = Boolean.parseBoolean((String) properties.get("handleSubcomponents")); } if (properties.get("convertLFtoCR") != null) { this.convertLFtoCR = Boolean.parseBoolean((String) properties.get("convertLFtoCR")); } } if (useStrictParser) { initializeParser(); } } public static Map<String, String> getDefaultProperties() { Map<String, String> properties = new HashMap<String, String>(); properties.put("useStrictParser", "false"); properties.put("useStrictValidation", "false"); properties.put("stripNamespaces", "true"); properties.put("handleRepetitions", "false"); properties.put("convertLFtoCR", "true"); properties.put("handleSubcomponents", "false"); return properties; } private void initializeParser() { pipeParser = new PipeParser(); xmlParser = new DefaultXMLParser(); // turn off strict validation if needed if (!useStrictValidation) { pipeParser.setValidationContext(new NoValidation()); xmlParser.setValidationContext(new NoValidation()); } xmlParser.setKeepAsOriginalNodes(new String[] { "NTE.3", "OBX.5" }); } /** * Returns an XML-encoded HL7 message given an ER7-enconded HL7 message. * * @param source * an ER7-encoded HL7 message. * @return */ public String toXML(String source) throws SerializerException { try { if (useStrictParser) { return xmlParser.encode(pipeParser.parse(source.trim())); } else { ER7Reader er7Reader = new ER7Reader(handleRepetitions, handleSubcomponents, convertLFtoCR); StringWriter stringWriter = new StringWriter(); XMLPrettyPrinter serializer = new XMLPrettyPrinter(stringWriter); serializer.setEncodeEntities(true); er7Reader.setContentHandler(serializer); er7Reader.parse(new InputSource(new StringReader(source))); return stringWriter.toString(); } } catch (Exception e) { throw new SerializerException(e); } } /** * Returns an ER7-encoded HL7 message given an XML-encoded HL7 message. * * @param source * a XML-encoded HL7 message. * @return */ public String fromXML(String source) throws SerializerException { try { if (useStrictParser) { return pipeParser.encode(xmlParser.parse(source)); } else { /* * The delimiters below need to come from the XML somehow. The * ER7 handler should take care of it TODO: Ensure you get these * elements from the XML */ String segmentSeparator = "\r"; String fieldSeparator = getNodeValue(source, "<MSH.1>", "</MSH.1>"); if (StringUtils.isEmpty(fieldSeparator)) { fieldSeparator = "|"; } String componentSeparator = "^"; String repetitionSeparator = "~"; String subcomponentSeparator = "&"; String escapeCharacter = "\\"; /* * Our delimiters usually look like this: * <MSH.2>^~\&</MSH.2> We need to decode XML entities */ String separators = getNodeValue(source, "<MSH.2>", "</MSH.2>").replaceAll("&", "&"); if (separators.length() == 4) { // usually ^ componentSeparator = separators.substring(0, 1); // usually ~ repetitionSeparator = separators.substring(1, 2); // usually \ escapeCharacter = separators.substring(2, 3); // usually & subcomponentSeparator = separators.substring(3, 4); } XMLEncodedHL7Handler handler = new XMLEncodedHL7Handler(segmentSeparator, fieldSeparator, componentSeparator, repetitionSeparator, escapeCharacter, subcomponentSeparator, true); XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(handler); reader.setErrorHandler(handler); /* * Parse, but first replace all spaces between brackets. This * fixes pretty-printed XML we might receive. */ reader.parse(new InputSource(new StringReader( source.replaceAll("\\s*<([^/][^>]*)>", "<$1>").replaceAll("<(/[^>]*)>\\s*", "<$1>")))); return handler.getOutput().toString(); } } catch (Exception e) { throw new SerializerException(e); } } public Map<String, String> getMetadataFromXML(String source) throws SerializerException { Map<String, String> metadata = new HashMap<String, String>(); if (useStrictParser) { try { Message message = xmlParser.parse(source); Terser terser = new Terser(message); String sendingFacility = terser.get("/MSH-4-1"); String event = terser.get("/MSH-9-1") + "-" + terser.get("/MSH-9-2"); metadata.put("version", message.getVersion()); metadata.put("type", event); metadata.put("source", sendingFacility); } catch (Exception e) { new SerializerException(e); } return metadata; } else { String event = getNodeValue(source, "<MSH.9.1>", "</MSH.9.1>"); String subType = getNodeValue(source, "<MSH.9.2>", "</MSH.9.2>"); if (!subType.equals("")) { event += "-" + subType; } if (event.equals("")) { event = "Unknown"; } metadata.put("version", getNodeValue(source, "<MSH.12.1>", "</MSH.12.1>")); metadata.put("type", event); metadata.put("source", getNodeValue(source, "<MSH.4.1>", "</MSH.4.1>")); return metadata; } } public Map<String, String> getMetadataFromEncoded(String source) throws SerializerException { Map<String, String> metadata = new HashMap<String, String>(); if (useStrictParser) { try { // XXX: This had a replaceAll("\n", "\r") before 1.7 Message message = pipeParser.parse(source.trim()); Terser terser = new Terser(message); metadata.put("version", message.getVersion()); metadata.put("type", terser.get("/MSH-9-1") + "-" + terser.get("/MSH-9-2")); metadata.put("source", terser.get("/MSH-4-1")); } catch (Exception e) { new SerializerException(e); } return metadata; } else { // XXX: This had a replaceAll("\n", "\r") before 1.7 source = source.trim(); if ((source == null) || (source.length() < 3)) { logger.error("Unable to parse, message is null or too short: " + source); throw new SerializerException("Unable to parse, message is null or too short: " + source); } else if (source.substring(0, 3).equalsIgnoreCase("MSH")) { String segmentDelimeter = "\r"; String fieldDelimeter = String.valueOf(source.charAt(3)); String elementDelimeter = String.valueOf(source.charAt(4)); String mshFields[] = source.split(segmentDelimeter)[0].split(Pattern.quote(fieldDelimeter)); Pattern elementPattern = Pattern.compile(Pattern.quote(elementDelimeter)); if (mshFields.length > 8) { // MSH.9 String[] msh9 = elementPattern.split(mshFields[8]); // MSH.9.1 String type = msh9[0]; if (msh9.length > 1) { // MSH.9.2 type += "-" + msh9[1]; } metadata.put("type", type); } else { metadata.put("type", "Unknown"); } if (mshFields.length > 3) { // MSH.4.1 metadata.put("source", elementPattern.split(mshFields[3])[0]); } else { metadata.put("source", ""); } if (mshFields.length > 11) { // MSH.12.1 metadata.put("version", elementPattern.split(mshFields[11])[0]); } else { metadata.put("version", ""); } } else { metadata.put("type", "Unknown"); metadata.put("source", "Unknown"); metadata.put("version", "Unknown"); } return metadata; } } public Map<String, String> getMetadataFromDocument(Document document) { Map<String, String> metadata = new HashMap<String, String>(); if (useStrictParser) { try { DocumentSerializer serializer = new DocumentSerializer(); String source = serializer.toXML(document); Message message = xmlParser.parse(source); Terser terser = new Terser(message); String sendingFacility = terser.get("/MSH-4-1"); String event = terser.get("/MSH-9-1") + "-" + terser.get("/MSH-9-2"); metadata.put("version", message.getVersion()); metadata.put("type", event); metadata.put("source", sendingFacility); return metadata; } catch (Exception e) { logger.error(e.getMessage()); return metadata; } } else { if (document.getElementsByTagName("MSH.4.1").getLength() > 0) { Node senderNode = document.getElementsByTagName("MSH.4.1").item(0); if ((senderNode != null) && (senderNode.getFirstChild() != null)) { metadata.put("source", senderNode.getFirstChild().getTextContent()); } else { metadata.put("source", ""); } } if (document.getElementsByTagName("MSH.9").getLength() > 0) { if (document.getElementsByTagName("MSH.9.1").getLength() > 0) { Node typeNode = document.getElementsByTagName("MSH.9.1").item(0); if (typeNode != null) { String type = typeNode.getFirstChild().getNodeValue(); if (document.getElementsByTagName("MSH.9.2").getLength() > 0) { Node subTypeNode = document.getElementsByTagName("MSH.9.2").item(0); type += "-" + subTypeNode.getFirstChild().getTextContent(); } metadata.put("type", type); } else { metadata.put("type", "Unknown"); } } } if (document.getElementsByTagName("MSH.12.1").getLength() > 0) { Node versionNode = document.getElementsByTagName("MSH.12.1").item(0); if (versionNode != null) { metadata.put("version", versionNode.getFirstChild().getTextContent()); } else { metadata.put("version", ""); } } return metadata; } } private String getNodeValue(String source, String startTag, String endTag) { int startIndex = -1; if ((startIndex = source.indexOf(startTag)) != -1) { return source.substring(startIndex + startTag.length(), source.indexOf(endTag, startIndex)); } else { return ""; } } }