Skip to content

Commit

Permalink
Additional schema reader exception case tests, re-factoring
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeEdgar committed May 18, 2020
1 parent b411eba commit cbc2900
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 69 deletions.
62 changes: 4 additions & 58 deletions src/main/java/io/xlate/edi/internal/schema/SchemaReaderBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
Expand Down Expand Up @@ -238,10 +237,9 @@ Reference readControlStructure(XMLStreamReader reader,
Reference trailerRef = createControlReference(reader, "trailer");

readDescription(reader);
QName nextElement = reader.getName();

if (subelement != null && !subelement.equals(nextElement)) {
throw unexpectedElement(nextElement, reader);
if (subelement != null) {
requireElementStart(subelement, reader);
}

List<EDIReference> refs = new ArrayList<>(3);
Expand Down Expand Up @@ -635,63 +633,11 @@ void setReferences(StructureType struct, Map<String, EDIType> types) {

final EDIType.Type refType = target.getType();

if (refType != refTypeId(impl.getRefTag())) {
if (refType != EDIType.Type.valueOf(impl.getRefTag().toUpperCase())) {
throw schemaException(String.format(REFERR_ILLEGAL, impl.getRefId(), impl.getRefTag(), struct.getId()));
}

switch (struct.getType()) {
case INTERCHANGE:
// Transactions may be located directly within the interchange in EDIFACT.
setReference(struct,
(Reference) ref,
target,
EDIType.Type.GROUP,
EDIType.Type.TRANSACTION,
EDIType.Type.SEGMENT);
break;
case GROUP:
setReference(struct, (Reference) ref, target, EDIType.Type.TRANSACTION, EDIType.Type.SEGMENT);
break;
case TRANSACTION:
setReference(struct, (Reference) ref, target, EDIType.Type.LOOP, EDIType.Type.SEGMENT);
break;
case LOOP:
setReference(struct, (Reference) ref, target, EDIType.Type.LOOP, EDIType.Type.SEGMENT);
break;
case SEGMENT:
setReference(struct, (Reference) ref, target, EDIType.Type.COMPOSITE, EDIType.Type.ELEMENT);
break;
case COMPOSITE:
setReference(struct, (Reference) ref, target, EDIType.Type.ELEMENT);
break;
default:
break;
}
}
}

EDIType.Type refTypeId(String tag) {
if (tag != null) {
return EDIType.Type.valueOf(tag.toUpperCase());
}
throw new IllegalArgumentException("Unexpected element: " + tag);
}

void setReference(StructureType struct, Reference reference, EDIType target, EDIType.Type... allowedTargets) {
boolean isAllowed = Arrays.stream(allowedTargets).anyMatch(target.getType()::equals);

if (isAllowed) {
reference.setReferencedType(target);
} else {
StringBuilder excp = new StringBuilder();
excp.append("Structure ");
excp.append(struct.getId());
excp.append(" attempts to reference type with id = ");
excp.append(reference.getRefId());
excp.append(". Allowed types: " + Arrays.stream(allowedTargets)
.map(Object::toString)
.collect(Collectors.joining(", ")));
throw schemaException(excp.toString());
impl.setReferencedType(target);
}
}

Expand Down
167 changes: 156 additions & 11 deletions src/test/java/io/xlate/edi/internal/schema/StaEDISchemaFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import org.junit.jupiter.api.Test;

import io.xlate.edi.schema.EDIComplexType;
import io.xlate.edi.schema.EDISchemaException;
import io.xlate.edi.schema.EDIType;
import io.xlate.edi.schema.Schema;
Expand All @@ -38,6 +39,7 @@ public class StaEDISchemaFactoryTest {
final String INTERCHANGE_V2 = "{http://xlate.io/EDISchema/v2}interchange";
final String TRANSACTION_V2 = "{http://xlate.io/EDISchema/v2}transaction";

final String INTERCHANGE_V3 = "{http://xlate.io/EDISchema/v3}interchange";
final String STANDARD_V3 = "{http://xlate.io/EDISchema/v3}transaction";
final String IMPL_V3 = "{http://xlate.io/EDISchema/v3}implementation";

Expand Down Expand Up @@ -104,19 +106,22 @@ public void testExceptionThrownWithoutSchema() {
@Test
public void testExceptionThrownWithoutInterchangeAndTransactionV2() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream(("<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2 + "'><random/></schema>").getBytes());
InputStream stream = new ByteArrayInputStream(("<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2
+ "'><random/></schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Unexpected XML element [{"+StaEDISchemaFactory.XMLNS_V2+"}random]", thrown.getOriginalMessage());
assertEquals("Unexpected XML element [{" + StaEDISchemaFactory.XMLNS_V2 + "}random]", thrown.getOriginalMessage());
}

@Test
public void testInterchangeRequiredAttributesV2() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream1 = new ByteArrayInputStream(("<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2 + "'><interchange _header='ABC' trailer='XYZ' /></schema>").getBytes());
InputStream stream1 = new ByteArrayInputStream(("<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2
+ "'><interchange _header='ABC' trailer='XYZ' /></schema>").getBytes());
EDISchemaException thrown1 = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream1));
assertEquals("Missing required attribute: [header]", thrown1.getOriginalMessage());

InputStream stream2 = new ByteArrayInputStream(("<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2 + "'><interchange header='ABC' _trailer='XYZ' /></schema>").getBytes());
InputStream stream2 = new ByteArrayInputStream(("<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2
+ "'><interchange header='ABC' _trailer='XYZ' /></schema>").getBytes());
EDISchemaException thrown2 = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream2));
assertEquals("Missing required attribute: [trailer]", thrown2.getOriginalMessage());

Expand All @@ -127,14 +132,14 @@ public void testUnexpectedElementBeforeSequenceV2() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V2 + "'>"
+ "<interchange header='ABC' trailer='XYZ'>"
+ "<description><![CDATA[TEXT ALLOWED]]></description>"
+ "<unexpected></unexpected>"
+ "<sequence></sequence>"
+ "</interchange>"
+ "</schema>").getBytes());
+ "<interchange header='ABC' trailer='XYZ'>"
+ "<description><![CDATA[TEXT ALLOWED]]></description>"
+ "<unexpected></unexpected>"
+ "<sequence></sequence>"
+ "</interchange>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Unexpected XML element [{"+StaEDISchemaFactory.XMLNS_V2+"}unexpected]", thrown.getOriginalMessage());
assertEquals("Unexpected XML element [{" + StaEDISchemaFactory.XMLNS_V2 + "}unexpected]", thrown.getOriginalMessage());
}

@Test
Expand Down Expand Up @@ -264,4 +269,144 @@ public void testGetControlSchema() throws EDISchemaException {
assertEquals(EDIType.Type.SEGMENT, schema.getType("GS").getType());
assertEquals(EDIType.Type.SEGMENT, schema.getType("ST").getType());
}

@Test
public void testReferenceUndeclared() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='ABC' trailer='XYZ'>"
+ "<sequence>"
+ " <segment type='NUL'/>"
+ "</sequence>"
+ "</interchange>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Type " + INTERCHANGE_V3 + " references undeclared segment with ref='ABC'", thrown.getOriginalMessage());
}

@Test
public void testReferenceIncorrectType() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='SG1' trailer='SG2'>"
+ "<sequence>"
+ " <segment type='E1'/>"
+ "</sequence>"
+ "</interchange>"
+ "<elementType name=\"E1\" base=\"string\" maxLength=\"5\" />"
+ "<segmentType name=\"SG1\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG2\"><sequence><element type='E1'/></sequence></segmentType>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Type 'E1' must not be referenced as 'segment' in definition of type '" + INTERCHANGE_V3 + "'",
thrown.getOriginalMessage());
}

@Test
public void testUnexpectedUnknownTypeElement() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='SG1' trailer='SG2'>"
+ "<sequence>"
+ " <segment type='SG3'/>"
+ "</sequence>"
+ "</interchange>"
+ "<elementType name=\"E1\" base=\"string\" maxLength=\"5\" />"
+ "<segmentType name=\"SG1\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG2\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG3\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<unknownType xmlns='http://xlate.io'/>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Unexpected XML element [{http://xlate.io}unknownType]",
thrown.getOriginalMessage());
}

@Test
public void testMissingRequiredTransactionElement() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='SG1' trailer='SG2'>"
+ "<sequence>"
+ " <group header='SG3' trailer='SG4' use='prohibited'></group>"
+ "</sequence>"
+ "</interchange>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Expected XML element [" + STANDARD_V3 + "] not found",
thrown.getOriginalMessage());
}

@Test
public void testProhibitedUseType() throws EDISchemaException {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='SG1' trailer='SG2'>"
+ "<sequence>"
+ " <group header='SG3' trailer='SG4' use='prohibited'>"
+ " <transaction header='SG5' trailer='SG6' use='prohibited'></transaction>"
+ " </group>"
+ "</sequence>"
+ "</interchange>"
+ "<elementType name=\"E1\" base=\"string\" maxLength=\"5\" />"
+ "<segmentType name=\"SG1\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG2\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG3\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG4\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG5\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG6\"><sequence><element type='E1'/></sequence></segmentType>"
+ "</schema>").getBytes());
Schema schema = factory.createSchema(stream);
EDIComplexType interchange = schema.getStandard();
assertEquals(0, interchange.getReferences().get(1).getMinOccurs());
assertEquals(0, interchange.getReferences().get(1).getMaxOccurs());
}

@Test
public void testInvalidUseType() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='SG1' trailer='SG2'>"
+ "<sequence>"
+ " <group header='SG3' trailer='SG4' use='junk'>"
+ " <transaction header='SG5' trailer='SG6' use='prohibited'></transaction>"
+ " </group>"
+ "</sequence>"
+ "</interchange>"
+ "<elementType name=\"E1\" base=\"string\" maxLength=\"5\" />"
+ "<segmentType name=\"SG1\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG2\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG3\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG4\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG5\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG6\"><sequence><element type='E1'/></sequence></segmentType>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Invalid value for 'use': junk",
thrown.getOriginalMessage());
}

@Test
public void testInvalidSegmentName() {
SchemaFactory factory = SchemaFactory.newFactory();
InputStream stream = new ByteArrayInputStream((""
+ "<schema xmlns='" + StaEDISchemaFactory.XMLNS_V3 + "'>"
+ "<interchange header='sg1' trailer='SG2'>"
+ "<sequence>"
+ "</sequence>"
+ "</interchange>"
+ "<elementType name=\"E1\" base=\"string\" maxLength=\"5\" />"
+ "<segmentType name=\"sg1\"><sequence><element type='E1'/></sequence></segmentType>"
+ "<segmentType name=\"SG2\"><sequence><element type='E1'/></sequence></segmentType>"
+ "</schema>").getBytes());
EDISchemaException thrown = assertThrows(EDISchemaException.class, () -> factory.createSchema(stream));
assertEquals("Invalid segment name [sg1]",
thrown.getOriginalMessage());
}
}

0 comments on commit cbc2900

Please sign in to comment.