Skip to content

Commit

Permalink
hapifhir#22: fix namespace handling in xml encoding
Browse files Browse the repository at this point in the history
hapifhir#35: Connection now implements Closeable
  • Loading branch information
Christian Ohr committed May 27, 2020
1 parent b28a11e commit 1b8c0eb
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 20 deletions.
8 changes: 2 additions & 6 deletions hapi-base/src/main/java/ca/uhn/hl7v2/app/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ GNU General Public License (the "GPL"), in which case the provisions of the GPL

package ca.uhn.hl7v2.app;

import java.io.Closeable;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;

/**
* Interface for a connection
*/
public interface Connection {
public interface Connection extends Closeable {

/**
* Activate this connection
Expand All @@ -46,11 +47,6 @@ public interface Connection {
Initiator getInitiator();


/**
* Closes the connection
*/
void close();

/**
* Returns true if this connection is open
*
Expand Down
7 changes: 6 additions & 1 deletion hapi-base/src/main/java/ca/uhn/hl7v2/app/ConnectionHub.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ GNU General Public License (the �GPL�), in which case the provisions of the

package ca.uhn.hl7v2.app;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -85,7 +86,11 @@ private ConnectionHub(HapiContext context) {

@Override
protected void dispose(Connection connection) {
connection.close();
try {
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
Expand Down
6 changes: 5 additions & 1 deletion hapi-base/src/main/java/ca/uhn/hl7v2/app/HL7Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ protected void afterTermination() {
super.afterTermination();
cleaner.stopAndWait();
for (Connection c : connections) {
c.close();
try {
c.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public Initiator getInitiator() {
return initiator;
}

public void close() {
public void close() throws IOException {
if (isEstablished()) {
activeConnection.close();
activeConnection = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ public Document encodeDocument(Message source) throws HL7Exception {
String messageName = messageClassName.substring(messageClassName.lastIndexOf('.') + 1);
try {
Document doc = XMLUtils.emptyDocument(messageName);
//Element root = doc.createElement(messageName);
//doc.appendChild(root);
encode(source, doc.getDocumentElement());
return doc;
} catch (Exception e) {
Expand All @@ -133,7 +131,7 @@ private void encode(Group groupObject, Element groupElement) throws HL7Exception
String elementName = makeGroupElementName(messageName, name);
Element childElement;
try {
childElement = groupElement.getOwnerDocument().createElement(elementName);
childElement = groupElement.getOwnerDocument().createElementNS(NS, elementName);
} catch (DOMException e) {
throw new HL7Exception(
"Can't encode element " + elementName + " in group " + groupObject.getClass().getName(), e);
Expand Down
6 changes: 3 additions & 3 deletions hapi-base/src/main/java/ca/uhn/hl7v2/parser/XMLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ public boolean encode(Segment segmentObject, Element segmentElement) throws HL7E
String name = makeElementName(segmentObject, i);
Type[] reps = segmentObject.getField(i);
for (Type rep : reps) {
Element newNode = segmentElement.getOwnerDocument().createElement(name);
Element newNode = segmentElement.getOwnerDocument().createElementNS(NS, name);
boolean componentHasValue = encode(rep, newNode);
if (componentHasValue) {
try {
Expand Down Expand Up @@ -617,7 +617,7 @@ private boolean encodePrimitive(Primitive datatypeObject, Element datatypeElemen
} else {
if (v.startsWith(".") || "H".equals(v) || "N".equals(v)) {
// currently in "escape mode", so create escape element from it
Element escape = datatypeElement.getOwnerDocument().createElement(
Element escape = datatypeElement.getOwnerDocument().createElementNS(NS,
ESCAPE_NODENAME);
escape.setAttribute(ESCAPE_ATTRNAME, v);
datatypeElement.appendChild(escape);
Expand Down Expand Up @@ -663,7 +663,7 @@ private boolean encodeComposite(Composite datatypeObject, Element datatypeElemen
boolean hasValue = false;
for (int i = 0; i < components.length; i++) {
String name = makeElementName(datatypeObject, i + 1);
Element newNode = datatypeElement.getOwnerDocument().createElement(name);
Element newNode = datatypeElement.getOwnerDocument().createElementNS(NS, name);
boolean componentHasValue = encode(components[i], newNode);
if (componentHasValue) {
try {
Expand Down
43 changes: 38 additions & 5 deletions hapi-test/src/test/java/ca/uhn/hl7v2/parser/XMLParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import java.io.InputStream;
import java.io.InputStreamReader;

import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HapiContext;
import ca.uhn.hl7v2.util.Hl7InputStreamMessageIterator;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
Expand Down Expand Up @@ -305,19 +308,19 @@ public void testEncodeMessageWithEscape() throws HL7Exception, IOException {

// Test a couple of cases of escape sequences
DefaultXMLParser p = new DefaultXMLParser();
p.getParserConfiguration().setPrettyPrintWhenEncodingXml(false);
String encoded = p.encode(msg);
assertTrue(encoded
.contains("<OBX.5>ABC<escape V=\"H\"/>highlighted<escape V=\"N\"/>EFG</OBX.5>"));
assertTrue(encoded.contains("<OBX.5>ABC<escape V=\"H\"/>highlighted<escape V=\"N\"/>EFG</OBX.5>"));

obx5Value = "\\H\\highlighted\\N\\EFG";
obx.getObservationValue(0).parse(obx5Value);
encoded = p.encode(msg);
assertTrue(encoded.contains(" <escape V=\"H\"/>highlighted<escape V=\"N\"/>EFG</OBX.5>"));
assertTrue(encoded.contains("<escape V=\"H\"/>highlighted<escape V=\"N\"/>EFG</OBX.5>"));

obx5Value = "ABC\\H\\highlighted\\N\\";
obx.getObservationValue(0).parse(obx5Value);
encoded = p.encode(msg);
assertTrue(encoded.contains("<OBX.5>ABC<escape V=\"H\"/>highlighted<escape V=\"N\"/>\n"));
assertTrue(encoded.contains("<OBX.5>ABC<escape V=\"H\"/>highlighted<escape V=\"N\"/>"));

obx5Value = "ABC\\E\\no escape sequence\\H\\highlighted\\N\\EFG";
obx.getObservationValue(0).parse(obx5Value);
Expand Down Expand Up @@ -348,6 +351,7 @@ public void testEncodeMessageWithTrailingEncodedBackslash() throws EncodingNotSu
msg.initQuickstart("ADT", "A01", "T");

XMLParser p = DefaultXMLParser.getInstanceWithNoValidation();
p.getParserConfiguration().setPrettyPrintWhenEncodingXml(false);
String encoded;

msg.getMSH().getMessageControlID().setValue("1234");
Expand All @@ -368,7 +372,7 @@ public void testEncodeMessageWithTrailingEncodedBackslash() throws EncodingNotSu

msg.getMSH().getMessageControlID().setValue("1234\\E\\\\.BR\\");
encoded = p.encode(msg);
assertTrue(encoded, encoded.contains("<MSH.10>1234\\E\\<escape V=\".BR\"/>\n"));
assertTrue(encoded, encoded.contains("<MSH.10>1234\\E\\<escape V=\".BR\"/>"));

}

Expand Down Expand Up @@ -431,6 +435,35 @@ public void testMessageParseMethodAndEncodeMethodWithEscapes() throws HL7Excepti

}

/**
* <p>
* Test to ensure that we can parse an XML document that we ourselves have encoded. Starting with a known Pipe message,
* parse it, encode it to XML, and then attempt to parse that resultant XML back to a {@link Message}. The expectation is that we
* can parse our own XML.
* </p>
*/
@Test
public void test_ParseEncodedXml() throws Exception {

// Create a context
HapiContext context = new DefaultHapiContext();
context.getParserConfiguration().setValidating(false);

XMLParser xp = context.getXMLParser();

InputStream str = getClass().getClassLoader().getResourceAsStream("ca/uhn/hl7v2/parser/adt_a03.txt");
Hl7InputStreamMessageIterator iter = new Hl7InputStreamMessageIterator(str, context);
while (iter.hasNext()) {

Message msg = iter.next();
Document dom = xp.encodeDocument(msg);

// We would expect to be able to parse this document back to a Message, as we encoded it.
Message outmsg = xp.parseDocument(dom, msg.getVersion());
outmsg.printStructure();
}
}

private String loadFile(String name) throws IOException {
return loadFile(name, '\n');
}
Expand Down
15 changes: 15 additions & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
</properties>
<body>
<release version="2.4" date="TBD">
<action type="fix" dev="Christian Ohr" issue="35">
The Connection interface now extends Closeable. As a consequence, the close()
method now throws IOException. Thanks to hauntingEcho for the proposal.
</action>
<action type="fix" dev="Christian Ohr" issue="33">
Fixes problem with missing items in PopulatingVisitor.
Thanks to mourezwell for the pull request.
</action>
<action type="fix" dev="Christian Ohr" issue="31">
Allow Visitor or Terser API to filter for repeated field. Thanks to
mourezwell for the pull request.
</action>
<action type="fix" dev="Christian Ohr" issue="22">
Fix namespace handling when XML-encoding messages. Thanks to kbalthaser for reporting.
</action>
<action type="fix" dev="Christian Ohr" issue="7">
Fix encoding of line breaks as \X000d\
</action>
Expand Down

0 comments on commit 1b8c0eb

Please sign in to comment.