Skip to content

Commit

Permalink
Add option to declare xmlns attributes on TRANSACTION element
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeEdgar committed May 19, 2020
1 parent 261c9a7 commit 56d30af
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class StaEDIInputFactory extends EDIInputFactory {
public StaEDIInputFactory() {
supportedProperties.add(EDI_VALIDATE_CONTROL_STRUCTURE);
supportedProperties.add(EDI_VALIDATE_CONTROL_CODE_VALUES);
supportedProperties.add(XML_DECLARE_TRANSACTION_XMLNS);

supportedCharsets = new HashSet<>();
supportedCharsets.add(DEFAULT_ENCODING);
Expand Down Expand Up @@ -79,7 +80,7 @@ public EDIStreamReader createFilteredReader(EDIStreamReader reader, EDIStreamFil

@Override
public XMLStreamReader createXMLStreamReader(EDIStreamReader reader) throws XMLStreamException {
return new StaEDIXMLStreamReader(reader);
return new StaEDIXMLStreamReader(reader, properties);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Logger;

Expand All @@ -31,6 +34,7 @@
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import io.xlate.edi.stream.EDIInputFactory;
import io.xlate.edi.stream.EDINamespaces;
import io.xlate.edi.stream.EDIStreamEvent;
import io.xlate.edi.stream.EDIStreamReader;
Expand All @@ -40,8 +44,11 @@ final class StaEDIXMLStreamReader implements XMLStreamReader {
private static final Logger LOGGER = Logger.getLogger(StaEDIXMLStreamReader.class.getName());
private static final QName DUMMY_QNAME = new QName("DUMMY");
private static final QName INTERCHANGE = new QName(EDINamespaces.LOOPS, "INTERCHANGE", prefixOf(EDINamespaces.LOOPS));
private static final QName TRANSACTION = new QName(EDINamespaces.LOOPS, "TRANSACTION", prefixOf(EDINamespaces.LOOPS));

private final EDIStreamReader ediReader;
private final Map<String, Object> properties;
private final boolean transactionDeclaresXmlns;
private final Location location = new ProxyLocation();
private boolean autoAdvance;

Expand All @@ -61,8 +68,10 @@ public void write(int b) throws IOException {

private char[] cdata;

StaEDIXMLStreamReader(EDIStreamReader ediReader) throws XMLStreamException {
StaEDIXMLStreamReader(EDIStreamReader ediReader, Map<String, Object> properties) throws XMLStreamException {
this.ediReader = ediReader;
this.properties = new HashMap<>(properties);
transactionDeclaresXmlns = Boolean.valueOf(String.valueOf(properties.get(EDIInputFactory.XML_DECLARE_TRANSACTION_XMLNS)));

if (ediReader.getEventType() == EDIStreamEvent.START_INTERCHANGE) {
autoAdvance = false;
Expand All @@ -72,12 +81,23 @@ public void write(int b) throws IOException {
}
}

StaEDIXMLStreamReader(EDIStreamReader ediReader) throws XMLStreamException {
this(ediReader, Collections.emptyMap());
}

@Override
public Object getProperty(String name) {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
return null;
return properties.get(name);
}

boolean declareNamespaces(QName element) {
if (INTERCHANGE.equals(element)) {
return true;
}
return this.transactionDeclaresXmlns && TRANSACTION.equals(element);
}

private boolean isEvent(int... eventTypes) {
Expand Down Expand Up @@ -415,15 +435,15 @@ public boolean isAttributeSpecified(int index) {

@Override
public int getNamespaceCount() {
if (INTERCHANGE.equals(elementQueue.element())) {
if (declareNamespaces(elementQueue.element())) {
return EDINamespaces.all().size();
}
return 0;
}

@Override
public String getNamespacePrefix(int index) {
if (INTERCHANGE.equals(elementQueue.element())) {
if (declareNamespaces(elementQueue.element())) {
String namespace = EDINamespaces.all().get(index);
return prefixOf(namespace);
}
Expand All @@ -432,7 +452,7 @@ public String getNamespacePrefix(int index) {

@Override
public String getNamespaceURI(int index) {
if (INTERCHANGE.equals(elementQueue.element())) {
if (declareNamespaces(elementQueue.element())) {
return EDINamespaces.all().get(index);
}
return null;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/io/xlate/edi/stream/EDIInputFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,20 @@
public abstract class EDIInputFactory extends PropertySupport {

public static final String EDI_VALIDATE_CONTROL_STRUCTURE = "io.xlate.edi.stream.EDI_VALIDATE_CONTROL_STRUCTURE";

/**
* When set to false, enumerated code values of control structure elements will be ignore. Element size and type
* validation will still occur.
*/
public static final String EDI_VALIDATE_CONTROL_CODE_VALUES = "io.xlate.edi.stream.EDI_VALIDATE_CONTROL_CODE_VALUES";

/**
* When set to true, XMLStreamReader instances created from an EDIInputFactory
* will generate XMLNS attributes on the TRANSACTION element in addition to the
* INTERCHANGE element.
*/
public static final String XML_DECLARE_TRANSACTION_XMLNS = "io.xlate.edi.stream.XML_DECLARE_TRANSACTION_XMLNS";

/**
* Create a new instance of the factory. This static method creates a new
* factory instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,27 @@ public void testReadXml() throws Exception {
assertTrue(!d.hasDifferences(), () -> "XML unexpectedly different:\n" + d.toString(new DefaultComparisonFormatter()));
}

@Test
public void testTransactionElementWithXmlns() throws Exception {
EDIInputFactory ediFactory = EDIInputFactory.newFactory();
ediFactory.setProperty(EDIInputFactory.XML_DECLARE_TRANSACTION_XMLNS, Boolean.TRUE);
InputStream stream = getClass().getResourceAsStream("/x12/extraDelimiter997.edi");
ediReader = ediFactory.createEDIStreamReader(stream);
XMLStreamReader xmlReader = ediFactory.createXMLStreamReader(ediReader);

xmlReader.next(); // Per StAXSource JavaDoc, put in START_DOCUMENT state
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
StringWriter result = new StringWriter();
transformer.transform(new StAXSource(xmlReader), new StreamResult(result));
String resultString = result.toString();
Diff d = DiffBuilder.compare(Input.fromFile("src/test/resources/x12/extraDelimiter997-transaction-xmlns.xml"))
.withTest(resultString).build();
assertTrue(!d.hasDifferences(), () -> "XML unexpectedly different:\n" + d.toString(new DefaultComparisonFormatter()));
}

@Test
public void testXmlIOEquivalence() throws Exception {
XMLStreamReader xmlReader = getXmlReader("/x12/extraDelimiter997.edi");
Expand Down
97 changes: 97 additions & 0 deletions src/test/resources/x12/extraDelimiter997-transaction-xmlns.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE INTERCHANGE>
<l:INTERCHANGE xmlns:l="urn:xlate.io:staedi:names:loops" xmlns:s="urn:xlate.io:staedi:names:segments" xmlns:c="urn:xlate.io:staedi:names:composites" xmlns:e="urn:xlate.io:staedi:names:elements">
<s:ISA>
<e:ISA01>00</e:ISA01>
<e:ISA02> </e:ISA02>
<e:ISA03>00</e:ISA03>
<e:ISA04> </e:ISA04>
<e:ISA05>ZZ</e:ISA05>
<e:ISA06>ReceiverID </e:ISA06>
<e:ISA07>ZZ</e:ISA07>
<e:ISA08>Sender </e:ISA08>
<e:ISA09>050812</e:ISA09>
<e:ISA10>1953</e:ISA10>
<e:ISA11>^</e:ISA11>
<e:ISA12>00501</e:ISA12>
<e:ISA13>508121953</e:ISA13>
<e:ISA14>0</e:ISA14>
<e:ISA15>P</e:ISA15>
<e:ISA16>:</e:ISA16>
</s:ISA>
<l:GROUP>
<s:GS>
<e:GS01>FA</e:GS01>
<e:GS02>ReceiverDept</e:GS02>
<e:GS03>SenderDept</e:GS03>
<e:GS04>20050812</e:GS04>
<e:GS05>195335</e:GS05>
<e:GS06>000005</e:GS06>
<e:GS07>X</e:GS07>
<e:GS08>005010X230</e:GS08>
</s:GS>
<l:TRANSACTION xmlns:l="urn:xlate.io:staedi:names:loops" xmlns:s="urn:xlate.io:staedi:names:segments" xmlns:c="urn:xlate.io:staedi:names:composites" xmlns:e="urn:xlate.io:staedi:names:elements">
<s:ST>
<e:ST01>997</e:ST01>
<e:ST02>0001</e:ST02>
</s:ST>
<s:AK1>
<e:AK101>HC</e:AK101>
<e:AK102>000001</e:AK102>
</s:AK1>
<s:AK2>
<e:AK201>837</e:AK201>
<e:AK202>0021</e:AK202>
</s:AK2>
<s:AK3>
<e:AK301>NM1</e:AK301>
<e:AK302>AK302-R1</e:AK302>
<e:AK302>AK302-R2</e:AK302>
<c:AK302>
<e:AK302-01>AK302-R3-COMP1</e:AK302-01>
<e:AK302-02>AK302-R3-COMP2</e:AK302-02>
</c:AK302>
<e:AK303/>
<e:AK304>AK304-R1</e:AK304>
<e:AK304>AK304-R2</e:AK304>
<e:AK304>AK304-R3</e:AK304>
</s:AK3>
<s:AK4>
<e:AK401>8</e:AK401>
<e:AK402>66</e:AK402>
<e:AK403>7</e:AK403>
<c:AK404>
<e:AK404-01>AK404-R1-COMP1</e:AK404-01>
<e:AK404-02>AK404-R1-COMP2</e:AK404-02>
<e:AK404-03>AK404-R1-COMP3</e:AK404-03>
</c:AK404>
<c:AK404>
<e:AK404-01>AK404-R2-COMP1</e:AK404-01>
<e:AK404-02>AK404-R2-COMP2</e:AK404-02>
</c:AK404>
</s:AK4>
<s:AK5>
<e:AK501>R</e:AK501>
<e:AK502>5</e:AK502>
</s:AK5>
<s:AK9>
<e:AK901>R</e:AK901>
<e:AK902>1</e:AK902>
<e:AK903>1</e:AK903>
<e:AK904>0</e:AK904>
</s:AK9>
<s:SE>
<e:SE01>8</e:SE01>
<e:SE02>0001</e:SE02>
</s:SE>
</l:TRANSACTION>
<s:GE>
<e:GE01>1</e:GE01>
<e:GE02>000005</e:GE02>
</s:GE>
</l:GROUP>
<s:IEA>
<e:IEA01>1</e:IEA01>
<e:IEA02>508121953</e:IEA02>
</s:IEA>
</l:INTERCHANGE>

0 comments on commit 56d30af

Please sign in to comment.