diff --git a/lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParser.java b/lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParser.java index be1d07df..e81f91cb 100644 --- a/lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParser.java +++ b/lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParser.java @@ -33,6 +33,10 @@ public static PolygonIdentifier parse(String description) throws ResourceParseEx Integer year; String name; + if (description.length() != PolygonIdentifier.ID_LENGTH) { + throw new ResourceParseException("Polygon description " + description + " was not 25 characters long"); + } + if (matcher.matches() && matcher.group(2) != null) { year = Integer.parseInt(matcher.group(2)); name = matcher.group(1).trim(); diff --git a/lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParserTest.java b/lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParserTest.java new file mode 100644 index 00000000..6c510617 --- /dev/null +++ b/lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/parse/model/VdypPolygonDescriptionParserTest.java @@ -0,0 +1,199 @@ +package ca.bc.gov.nrs.vdyp.io.parse.model; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.NoSuchElementException; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import ca.bc.gov.nrs.vdyp.io.parse.common.ResourceParseException; +import ca.bc.gov.nrs.vdyp.model.LayerType; +import ca.bc.gov.nrs.vdyp.model.UtilizationClass; +import ca.bc.gov.nrs.vdyp.test.MockFileResolver; +import ca.bc.gov.nrs.vdyp.test.TestUtils; +import ca.bc.gov.nrs.vdyp.test.VdypMatchers; + +import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.*; + +class VdypPolygonDescriptionParserTest { + + @Test + void testEmpty() throws IOException, ResourceParseException { + var controlMap = TestUtils.loadControlMap(); + var resolver = new MockFileResolver("testResolver"); + + try (var is = TestUtils.makeInputStream("")) { + + resolver.addStream("test.dat", is); + + var parser = new VdypPolygonParser().map("test.dat", resolver, controlMap); + + var stream = parser.get(); + + assertTrue(!stream.hasNext(), "stream is not empty"); + + assertThrows(NoSuchElementException.class, () -> stream.next()); + } + } + + @Test + void testOnePoly() throws IOException, ResourceParseException { + var controlMap = TestUtils.loadControlMap(); + var resolver = new MockFileResolver("testResolver"); + + try (var is = TestUtils.makeInputStream("01002 S000001 00 1970")) { + + resolver.addStream("test.dat", is); + + var parser = new VdypPolygonDescriptionParser().map("test.dat", resolver, controlMap); + + var stream = parser.get(); + + assertTrue(stream.hasNext(), "stream is empty"); + + var result = stream.next(); + + assertThat(result, isPolyId("01002 S000001 00", 1970)); + + assertTrue(!stream.hasNext(), "stream is not empty"); + + assertThrows(NoSuchElementException.class, () -> stream.next()); + + } + } + + @Test + void testMultiplePoly() throws IOException, ResourceParseException { + var controlMap = TestUtils.loadControlMap(); + var resolver = new MockFileResolver("testResolver"); + + try ( + var is = TestUtils.makeInputStream( + "01002 S000001 00 1970", "01002 S000002 00 1970", "01002 S000003 00 1973" + + ) + ) { + + resolver.addStream("test.dat", is); + + var parser = new VdypPolygonDescriptionParser().map("test.dat", resolver, controlMap); + + var stream = parser.get(); + + assertTrue(stream.hasNext(), "stream is empty"); + + var result = stream.next(); + + assertThat(result, isPolyId("01002 S000001 00", 1970)); + + assertTrue(stream.hasNext(), "stream is empty"); + + result = stream.next(); + + assertThat(result, isPolyId("01002 S000002 00", 1970)); + + assertTrue(stream.hasNext(), "stream is empty"); + + result = stream.next(); + + assertThat(result, isPolyId("01002 S000003 00", 1973)); + + assertTrue(!stream.hasNext(), "stream is not empty"); + + assertThrows(NoSuchElementException.class, () -> stream.next()); + + } + } + + @ParameterizedTest + @ValueSource( + strings = { "01002 S000001 00 XXXX", "01002 S000001 00 199X", "01002 S000001 00 999", + "01002 S000001 00 999 ", "01002 S000001 00 19 9", "01002 S000001 00 " } + ) + void testIDsWithoutAValidYear(String id) throws IOException, ResourceParseException { + var controlMap = TestUtils.loadControlMap(); + var resolver = new MockFileResolver("testResolver"); + + try (var is = TestUtils.makeInputStream(id)) { + + resolver.addStream("test.dat", is); + + var parser = new VdypPolygonDescriptionParser().map("test.dat", resolver, controlMap); + + var stream = parser.get(); + + assertTrue(stream.hasNext(), "stream is empty"); + + var ex = assertThrows(ResourceParseException.class, () -> stream.next()); + + } + + } + + @ParameterizedTest + @ValueSource( + strings = { "01002 S000001 00 2024", // short (24) + "01002 S000001 00 2024" // long (26) + } + ) + void testIdsWithWrongLength(String id) throws IOException, ResourceParseException { + var controlMap = TestUtils.loadControlMap(); + var resolver = new MockFileResolver("testResolver"); + + try (var is = TestUtils.makeInputStream(id)) { + + resolver.addStream("test.dat", is); + + var parser = new VdypPolygonDescriptionParser().map("test.dat", resolver, controlMap); + + var stream = parser.get(); + + assertTrue(stream.hasNext(), "stream is empty"); + + var ex = assertThrows(ResourceParseException.class, () -> stream.next()); + + } + + } + + @ParameterizedTest + @ValueSource( + strings = { "01002 S000001 00 XXXX", // bad year + "01002 S000001 00 2024", // short + "01002 S000001 00 2024" // long + } + ) + void testCanProgressToNextLineAfterError(String id) throws IOException, ResourceParseException { + var controlMap = TestUtils.loadControlMap(); + var resolver = new MockFileResolver("testResolver"); + + try (var is = TestUtils.makeInputStream(id, "01002 S000002 00 1970")) { + + resolver.addStream("test.dat", is); + + var parser = new VdypPolygonDescriptionParser().map("test.dat", resolver, controlMap); + + var stream = parser.get(); + + assertTrue(stream.hasNext(), "stream is empty"); + + var ex = assertThrows(ResourceParseException.class, () -> stream.next()); + + assertTrue(stream.hasNext(), "stream is empty"); + + var result = stream.next(); + + assertThat(result, isPolyId("01002 S000002 00", 1970)); + + } + + } + +}