From c2fa052bd6f961f3f5f3488486a63d56313551ec Mon Sep 17 00:00:00 2001 From: Petri Vuorio Date: Wed, 23 Oct 2019 12:16:24 +0300 Subject: [PATCH 1/3] Extract some operations within bulletin heading encoding/decoding into independent methods. --- .../fmi/avi/util/BulletinHeadingDecoder.java | 18 +- .../fmi/avi/util/BulletinHeadingEncoder.java | 118 ++++++++--- .../avi/util/BulletinHeadingDecoderTest.java | 39 +++- .../avi/util/BulletinHeadingEncoderTest.java | 190 ++++++++++++++++++ 4 files changed, 328 insertions(+), 37 deletions(-) create mode 100644 src/test/java/fi/fmi/avi/util/BulletinHeadingEncoderTest.java diff --git a/src/main/java/fi/fmi/avi/util/BulletinHeadingDecoder.java b/src/main/java/fi/fmi/avi/util/BulletinHeadingDecoder.java index 1577f21a..dd5ba81f 100644 --- a/src/main/java/fi/fmi/avi/util/BulletinHeadingDecoder.java +++ b/src/main/java/fi/fmi/avi/util/BulletinHeadingDecoder.java @@ -12,13 +12,17 @@ import fi.fmi.avi.model.bulletin.DataTypeDesignatorT2; import fi.fmi.avi.model.bulletin.immutable.BulletinHeadingImpl; -public class BulletinHeadingDecoder { +public final class BulletinHeadingDecoder { // Abbreviated heading with lenient augmentation indicator private static final Pattern ABBREVIATED_HEADING = Pattern.compile( "^(?[A-Z]{2})(?[A-Z]{2})(?[0-9]{2})\\s*(?[A-Z]{4})\\s*(?[0-9]{2})(?[0-9]{2})(?[0-9]{2})\\s*(?[A-Z0-9]+)?$"); // Strict augmentation indicator private static final Pattern AUGMENTATION_INDICATOR = Pattern.compile("(?(CC|RR|AA)[A-Z])?"); + private BulletinHeadingDecoder() { + throw new AssertionError(); + } + public static BulletinHeading decode(final String input, final ConversionHints hints) throws IllegalArgumentException { final Matcher m = ABBREVIATED_HEADING.matcher(input); final String illegalInputMessage = "String '" + input + "' does not match the Abbreviated heading formats 'T1T2A1A2iiCCCCYYGGgg[BBB]' " @@ -45,7 +49,7 @@ public static BulletinHeading decode(final String input, final ConversionHints h } type = BulletinHeading.Type.fromCode(bbb.substring(0, 2)); - bulletinAugmentationNumber = bbb.charAt(2) - 'A' + 1; + bulletinAugmentationNumber = decodeAugmentationNumber(bbb.charAt(2)); } final DataTypeDesignatorT1 t1 = DataTypeDesignatorT1.fromCode(m.group("TT").charAt(0)); @@ -65,4 +69,14 @@ public static BulletinHeading decode(final String input, final ConversionHints h .setIssueTime(PartialOrCompleteTimeInstant.of(PartialDateTime.parse(issueTime)))// .build(); } + + public static int decodeAugmentationNumber(final char tacChar) { + if (tacChar < BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN_CHAR || tacChar > BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX_CHAR) { + throw new IllegalArgumentException( + "Illegal augmentation number TAC char '" + tacChar + "'; the value must be between '" + BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN_CHAR + + "' and " + "'" + BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX_CHAR + "'"); + } + return tacChar - BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN_CHAR + BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN; + } + } diff --git a/src/main/java/fi/fmi/avi/util/BulletinHeadingEncoder.java b/src/main/java/fi/fmi/avi/util/BulletinHeadingEncoder.java index 104e172e..0b3ed972 100644 --- a/src/main/java/fi/fmi/avi/util/BulletinHeadingEncoder.java +++ b/src/main/java/fi/fmi/avi/util/BulletinHeadingEncoder.java @@ -2,15 +2,24 @@ import static java.util.Objects.requireNonNull; -import java.util.Optional; import java.util.OptionalInt; -import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import fi.fmi.avi.converter.ConversionHints; import fi.fmi.avi.model.MessageFormat; +import fi.fmi.avi.model.PartialOrCompleteTimeInstant; import fi.fmi.avi.model.bulletin.BulletinHeading; -public class BulletinHeadingEncoder { +public final class BulletinHeadingEncoder { + static final char AUGMENTATION_NUMBER_MIN_CHAR = 'A'; + static final char AUGMENTATION_NUMBER_MAX_CHAR = 'Z'; + static final int AUGMENTATION_NUMBER_MIN = 1; + static final int AUGMENTATION_NUMBER_MAX = AUGMENTATION_NUMBER_MAX_CHAR - AUGMENTATION_NUMBER_MIN_CHAR + AUGMENTATION_NUMBER_MIN; + + private BulletinHeadingEncoder() { + throw new AssertionError(); + } @Deprecated public static String encode(final BulletinHeading input, final ConversionHints hints) { @@ -20,13 +29,12 @@ public static String encode(final BulletinHeading input, final ConversionHints h public static String encode(final BulletinHeading input, final MessageFormat messageFormat, final ConversionHints hints) { requireNonNull(input, "input"); requireNonNull(messageFormat, "messageFormat"); - final Function dataDesignatorsReader = getDataDesignatorsReader(messageFormat); boolean useSpaces = true; if (hints != null && hints.containsKey(ConversionHints.KEY_BULLETIN_HEADING_SPACING)) { useSpaces = hints.get(ConversionHints.KEY_BULLETIN_HEADING_SPACING).equals(ConversionHints.VALUE_BULLETIN_HEADING_SPACING_SPACE); } final StringBuilder sb = new StringBuilder(); - sb.append(dataDesignatorsReader.apply(input)); + sb.append(getDataDesignators(input, messageFormat)); if (useSpaces) { sb.append(' '); } @@ -34,43 +42,91 @@ public static String encode(final BulletinHeading input, final MessageFormat mes if (useSpaces) { sb.append(' '); } - final OptionalInt day = input.getIssueTime().getDay(); - final OptionalInt hour = input.getIssueTime().getHour(); - final OptionalInt minute = input.getIssueTime().getMinute(); - if (day.isPresent() && hour.isPresent() && minute.isPresent()) { - sb.append(String.format("%02d", day.getAsInt())); - sb.append(String.format("%02d", hour.getAsInt())); - sb.append(String.format("%02d", minute.getAsInt())); - } else { - throw new IllegalArgumentException("Day, hour or minute missing from bulletin issue time"); - } - final Optional augNumber = input.getBulletinAugmentationNumber(); - if (augNumber.isPresent()) { - if (input.getType() == BulletinHeading.Type.NORMAL) { - throw new IllegalArgumentException("Bulletin contains augmentation number, but the type is " + BulletinHeading.Type.NORMAL); - } - final int seqNumber = Character.codePointAt("A", 0) + augNumber.get() - 1; - //Using Character.codePointAt here is a bit overdo here since we know that we are always operating with single char ASCII codes - if (seqNumber < Character.codePointAt("A", 0) || seqNumber > Character.codePointAt("Z", 0)) { - throw new IllegalArgumentException( - "Illegal bulletin augmentation number '" + augNumber.get() + "', the value must be between 1 and " + ('Z' - 'A' + 1)); - } + appendIssueTime(sb, input.getIssueTime()); + checkBBBIndicatorDataConsistency(input); + if (encodesBBBIndicator(input.getType())) { if (useSpaces) { sb.append(' '); } - sb.append(input.getType().getPrefix()); - sb.append(String.valueOf(Character.toChars(seqNumber))); + appendBBBIndicator(sb, input.getType(), input.getBulletinAugmentationNumber().orElse(1)); } return sb.toString(); } - private static Function getDataDesignatorsReader(final MessageFormat messageFormat) { + public static String getDataDesignators(final BulletinHeading input, final MessageFormat messageFormat) { + requireNonNull(input, "input"); + requireNonNull(messageFormat, "messageFormat"); if (messageFormat.equals(MessageFormat.TEXT)) { - return BulletinHeading::getDataDesignatorsForTAC; + return input.getDataDesignatorsForTAC(); } else if (messageFormat.equals(MessageFormat.XML)) { - return BulletinHeading::getDataDesignatorsForXML; + return input.getDataDesignatorsForXML(); } else { throw new IllegalArgumentException("Unsupported messageFormat: " + messageFormat); } } + + public static String encodeIssueTime(final PartialOrCompleteTimeInstant issueTime) { + requireNonNull(issueTime, "issueTime"); + return appendIssueTime(new StringBuilder(), issueTime).toString(); + } + + private static StringBuilder appendIssueTime(final StringBuilder sb, final PartialOrCompleteTimeInstant issueTime) { + final OptionalInt day = issueTime.getDay(); + final OptionalInt hour = issueTime.getHour(); + final OptionalInt minute = issueTime.getMinute(); + if (!day.isPresent() || !hour.isPresent() || !minute.isPresent()) { + final String emptyFields = Stream.of(// + day.isPresent() ? "" : "day", // + hour.isPresent() ? "" : "hour", // + minute.isPresent() ? "" : "minute")// + .filter(field -> !field.isEmpty())// + .collect(Collectors.joining(", ")); + throw new IllegalArgumentException("Missing " + emptyFields + " from bulletin issue time " + issueTime); + } + return sb.append(String.format("%02d", day.getAsInt()))// + .append(String.format("%02d", hour.getAsInt()))// + .append(String.format("%02d", minute.getAsInt())); + } + + private static void checkBBBIndicatorDataConsistency(final BulletinHeading input) { + final boolean encodesBBBIndicator = encodesBBBIndicator(input.getType()); + final boolean hasAugmentationNumber = input.getBulletinAugmentationNumber().isPresent(); + if (encodesBBBIndicator && !hasAugmentationNumber) { + throw new IllegalArgumentException("Missing bulletinAugmentationNumber; is required with type " + input.getType()); + } else if (!encodesBBBIndicator && hasAugmentationNumber) { + throw new IllegalArgumentException("Bulletin contains augmentation number, but it is unsupported with type " + input.getType()); + } + } + + private static boolean encodesBBBIndicator(final BulletinHeading.Type bulletinHeadingType) { + return !bulletinHeadingType.getPrefix().isEmpty(); + } + + public static String encodeBBBIndicator(final BulletinHeading input) { + requireNonNull(input, "input"); + checkBBBIndicatorDataConsistency(input); + return encodeBBBIndicator(input.getType(), input.getBulletinAugmentationNumber().orElse(1)); + } + + public static String encodeBBBIndicator(final BulletinHeading.Type bulletinHeadingType, final int augmentationNumber) { + requireNonNull(bulletinHeadingType, "bulletinHeadingType"); + if (!encodesBBBIndicator(bulletinHeadingType)) { + return ""; + } + return appendBBBIndicator(new StringBuilder(), bulletinHeadingType, augmentationNumber).toString(); + } + + private static StringBuilder appendBBBIndicator(final StringBuilder sb, final BulletinHeading.Type bulletinHeadingType, final int augmentationNumber) { + return sb.append(bulletinHeadingType.getPrefix())// + .append(encodeAugmentationNumber(augmentationNumber)); + } + + public static char encodeAugmentationNumber(final int augmentationNumber) { + if (augmentationNumber < AUGMENTATION_NUMBER_MIN || augmentationNumber > AUGMENTATION_NUMBER_MAX) { + throw new IllegalArgumentException( + "Illegal augmentation number <" + augmentationNumber + ">; the value must be between " + AUGMENTATION_NUMBER_MIN + " and " + + AUGMENTATION_NUMBER_MAX); + } + return (char) (augmentationNumber - AUGMENTATION_NUMBER_MIN + AUGMENTATION_NUMBER_MIN_CHAR); + } } diff --git a/src/test/java/fi/fmi/avi/util/BulletinHeadingDecoderTest.java b/src/test/java/fi/fmi/avi/util/BulletinHeadingDecoderTest.java index 3b1aa9fc..7c4d2b62 100644 --- a/src/test/java/fi/fmi/avi/util/BulletinHeadingDecoderTest.java +++ b/src/test/java/fi/fmi/avi/util/BulletinHeadingDecoderTest.java @@ -52,14 +52,14 @@ public class BulletinHeadingDecoderTest { private static final Map AUGMENTATION_INDICATOR_REPLACEMENTS = ImmutableMap.of("COR", "CCA", "RTD", "RRA", "AMD", "AAA"); private static final ConversionHints EXTENDED_AUGMENTATION_IDENTIFIERS = new ConversionHints(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - static { EXTENDED_AUGMENTATION_IDENTIFIERS.put(ConversionHints.KEY_BULLETIN_HEADING_AUGMENTATION_INDICATOR_EXTENSION, (BulletinHeadingIndicatorInterpreter) key -> AUGMENTATION_INDICATOR_REPLACEMENTS.getOrDefault(key, key)); } + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test @Parameters public void decode_bulletin_headings(final String input, final BulletinHeading expected, final ConversionHints conversionHints, @@ -82,7 +82,9 @@ public Object parametersForDecode_bulletin_headings() { ConversionHints.EMPTY, null },// new Object[] { "FTFI32 AAAA 250200 RRA", TAF_BULLETIN_HEADING.toBuilder() .setType(BulletinHeading.Type.DELAYED) - .setBulletinAugmentationNumber(1).setBulletinNumber(32).setLocationIndicator("AAAA").build(), ConversionHints.EMPTY, null },// + .setBulletinAugmentationNumber(1) + .setBulletinNumber(32) + .setLocationIndicator("AAAA").build(), ConversionHints.EMPTY, null },// // Extended augmentation indicators new Object[] { "FTFI31 EFLK 250200 COR", TAF_BULLETIN_HEADING.toBuilder().setType(BulletinHeading.Type.CORRECTED).setBulletinAugmentationNumber(1).build(), @@ -105,4 +107,33 @@ public Object parametersForDecode_bulletin_headings() { ConversionHints.EMPTY, null } }; } + @Test + public void decodeAugmentationNumber_GivenMinimumChar_ShouldReturnMinimumNumber() { + assertEquals(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN, + BulletinHeadingDecoder.decodeAugmentationNumber(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN_CHAR)); + } + + @Test + public void decodeAugmentationNumber_GivenMaximumChar_ShouldReturnMaximumNumber() { + assertEquals(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX, + BulletinHeadingDecoder.decodeAugmentationNumber(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX_CHAR)); + } + + @Test + public void decodeAugmentationNumber_GivenCharSmallerThanMinimum_ShouldThrowException() { + final char tacChar = BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN_CHAR - 1; + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'" + tacChar + "'"); + //noinspection ResultOfMethodCallIgnored + BulletinHeadingDecoder.decodeAugmentationNumber(tacChar); + } + + @Test + public void decodeAugmentationNumber_GivenCharGreaterThanMaximum_ShouldThrowException() { + final char tacChar = BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX_CHAR + 1; + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'" + tacChar + "'"); + //noinspection ResultOfMethodCallIgnored + BulletinHeadingDecoder.decodeAugmentationNumber(tacChar); + } } diff --git a/src/test/java/fi/fmi/avi/util/BulletinHeadingEncoderTest.java b/src/test/java/fi/fmi/avi/util/BulletinHeadingEncoderTest.java new file mode 100644 index 00000000..e3ef08b3 --- /dev/null +++ b/src/test/java/fi/fmi/avi/util/BulletinHeadingEncoderTest.java @@ -0,0 +1,190 @@ +package fi.fmi.avi.util; + +import static org.junit.Assert.assertEquals; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import fi.fmi.avi.converter.ConversionHints; +import fi.fmi.avi.model.MessageFormat; +import fi.fmi.avi.model.PartialDateTime; +import fi.fmi.avi.model.PartialOrCompleteTimeInstant; +import fi.fmi.avi.model.bulletin.BulletinHeading; +import fi.fmi.avi.model.bulletin.DataTypeDesignatorT1; +import fi.fmi.avi.model.bulletin.DataTypeDesignatorT2; +import fi.fmi.avi.model.bulletin.immutable.BulletinHeadingImpl; +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; + +@RunWith(JUnitParamsRunner.class) +public class BulletinHeadingEncoderTest { + private static final String GEOGRAPHICAL_DESIGNATOR = "FI"; + private static final int DEFAULT_BULLETIN_NUMBER = 31; + private static final String DEFAULT_LOCATION_INDICATOR = "EFLK"; + private static final PartialOrCompleteTimeInstant ISSUE_TIME = PartialOrCompleteTimeInstant.createDayHourInstant("250200"); + private static final PartialOrCompleteTimeInstant SIGMET_ISSUE_TIME = PartialOrCompleteTimeInstant.createDayHourInstant("231008"); + + private static final BulletinHeadingImpl TAF_BULLETIN_HEADING = BulletinHeadingImpl.builder()// + .setGeographicalDesignator(GEOGRAPHICAL_DESIGNATOR)// + .setLocationIndicator(DEFAULT_LOCATION_INDICATOR)// + .setBulletinNumber(DEFAULT_BULLETIN_NUMBER)// + .setType(BulletinHeading.Type.NORMAL)// + .setDataTypeDesignatorT1ForTAC(DataTypeDesignatorT1.FORECASTS)// + .setDataTypeDesignatorT2(DataTypeDesignatorT2.ForecastsDataTypeDesignatorT2.FCT_AERODROME_VT_LONG)// + .setIssueTime(ISSUE_TIME).build(); + private static final BulletinHeadingImpl SIGMET_BULLETIN_HEADING = BulletinHeadingImpl.builder()// + .setDataTypeDesignatorT2(DataTypeDesignatorT2.WarningsDataTypeDesignatorT2.WRN_SIGMET)// + .setGeographicalDesignator(GEOGRAPHICAL_DESIGNATOR)// + .setType(BulletinHeading.Type.NORMAL)// + .setLocationIndicator(DEFAULT_LOCATION_INDICATOR)// + .setBulletinNumber(DEFAULT_BULLETIN_NUMBER)// + .setDataTypeDesignatorT1ForTAC(DataTypeDesignatorT1.WARNINGS)// + .setDataTypeDesignatorT2(DataTypeDesignatorT2.WarningsDataTypeDesignatorT2.WRN_SIGMET)// + .setIssueTime(SIGMET_ISSUE_TIME).build(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + @Parameters + public void testEncode(final BulletinHeading heading, final String expected) { + final String actual = BulletinHeadingEncoder.encode(heading, MessageFormat.TEXT, ConversionHints.EMPTY); + assertEquals(expected, actual); + } + + @SuppressWarnings("OptionalGetWithoutIsPresent") + public Object parametersForTestEncode() { + final PartialOrCompleteTimeInstant issuetime1 = PartialOrCompleteTimeInstant.createDayHourInstant("251200"); + final PartialOrCompleteTimeInstant issueTime2 = PartialOrCompleteTimeInstant.of( + PartialOrCompleteTimeInstant.createDayHourInstant("251400").getPartialTime().get(), ZonedDateTime.parse("2019-02-25T14:00Z")); + final PartialOrCompleteTimeInstant issueTime3 = PartialOrCompleteTimeInstant.of(issueTime2.getCompleteTime().get()); + + return new Object[] {// + new Object[] { TAF_BULLETIN_HEADING, "FTFI31 EFLK 250200" },// + new Object[] { TAF_BULLETIN_HEADING.toBuilder() + .setDataTypeDesignatorT2(DataTypeDesignatorT2.ForecastsDataTypeDesignatorT2.FCT_AERODROME_VT_SHORT) + .setIssueTime(issueTime2)// + .setType(BulletinHeading.Type.AMENDED) + .setBulletinAugmentationNumber(2).build(), "FCFI31 EFLK 251400 AAB" },// + new Object[] { TAF_BULLETIN_HEADING.toBuilder() + .setType(BulletinHeading.Type.CORRECTED) + .setBulletinAugmentationNumber(3) + .setIssueTime(issuetime1).build(), "FTFI31 EFLK 251200 CCC" },// + new Object[] { TAF_BULLETIN_HEADING.toBuilder() + .setType(BulletinHeading.Type.DELAYED) + .setBulletinAugmentationNumber(1) + .setBulletinNumber(32) + .setIssueTime(issuetime1) + .setLocationIndicator("AAAA").build(), "FTFI32 AAAA 251200 RRA" },// + // SIGMETs + new Object[] { SIGMET_BULLETIN_HEADING.toBuilder().setIssueTime(issueTime3).build(), "WSFI31 EFLK 251400" }, + new Object[] { SIGMET_BULLETIN_HEADING.toBuilder().setBulletinNumber(32).setLocationIndicator("AAAA").setIssueTime(issuetime1).build(), + "WSFI32 AAAA 251200" } }; + } + + @Test + @Parameters(source = BBBIndicatorParametersProvider.class) + public void testEncodeBBBIndicatorBulletinHeadingTypeString(final BulletinHeading heading, final String expected) { + final String actual = BulletinHeadingEncoder.encodeBBBIndicator(heading.getType(), heading.getBulletinAugmentationNumber().orElse(1)); + assertEquals(expected, actual); + } + + @Test + @Parameters(source = BBBIndicatorParametersProvider.class) + public void testEncodeBBBIndicatorBulletinHeading(final BulletinHeading heading, final String expected) { + final String actual = BulletinHeadingEncoder.encodeBBBIndicator(heading); + assertEquals(expected, actual); + } + + @Parameters + @Test + public void testEncodeIssueTime(final PartialOrCompleteTimeInstant issueTime, final String expected) { + final String actual = BulletinHeadingEncoder.encodeIssueTime(issueTime); + assertEquals(expected, actual); + } + + public Object parametersForTestEncodeIssueTime() { + return new Object[][] {// + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.of(12, 34, 51, ZoneOffset.UTC)), "123451" }, // + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.of(2, 3, 4, ZoneOffset.UTC)), "020304" }, // + }; + } + + @Parameters + @Test + public void testEncodeIssueTimeMissingFields(final PartialOrCompleteTimeInstant issueTime, final Collection expectedMissingFields) { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(issueTime.toString()); + for (final String expectedMissingField : expectedMissingFields) { + thrown.expectMessage(expectedMissingField); + } + BulletinHeadingEncoder.encodeIssueTime(issueTime); + } + + public Object parametersForTestEncodeIssueTimeMissingFields() { + final String day = "day"; + final String hour = "hour"; + final String minute = "minute"; + return new Object[][] {// + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.ofHourMinute(1, 1)), Collections.singletonList(day) }, // + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.ofDayHour(1, 1)), Collections.singletonList(minute) }, // + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.of(PartialDateTime.PartialField.DAY, 1)), Arrays.asList(hour, minute) }, // + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.of(PartialDateTime.PartialField.HOUR, 1)), Arrays.asList(day, minute) }, // + new Object[] { PartialOrCompleteTimeInstant.of(PartialDateTime.of(PartialDateTime.PartialField.MINUTE, 1)), Arrays.asList(day, hour) }, // + }; + } + + @Test + public void augmentationNumberMaximum_is_26() { + assertEquals(26, BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX); + } + + @Test + public void encodeAugmentationNumber_GivenMinimum_ShouldReturnMinimumChar() { + assertEquals(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN_CHAR, + BulletinHeadingEncoder.encodeAugmentationNumber(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN)); + } + + @Test + public void encodeAugmentationNumber_GivenMaximum_ShouldReturnMaximumChar() { + assertEquals(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX_CHAR, + BulletinHeadingEncoder.encodeAugmentationNumber(BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX)); + } + + @Test + public void encodeAugmentationNumber_GivenNumberSmallerThanMinimum_ShouldThrowException() { + final int number = BulletinHeadingEncoder.AUGMENTATION_NUMBER_MIN - 1; + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("<" + number + ">"); + //noinspection ResultOfMethodCallIgnored + BulletinHeadingEncoder.encodeAugmentationNumber(number); + } + + @Test + public void encodeAugmentationNumber_GivenNumberGreaterThanMaximum_ShouldThrowException() { + final int number = BulletinHeadingEncoder.AUGMENTATION_NUMBER_MAX + 1; + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("<" + number + ">"); + //noinspection ResultOfMethodCallIgnored + BulletinHeadingEncoder.encodeAugmentationNumber(number); + } + + public static class BBBIndicatorParametersProvider { + public static Object[][] provideBBBIndicatorParameters() { + return new Object[][] {// + new Object[] { TAF_BULLETIN_HEADING, "" }, // + new Object[] { TAF_BULLETIN_HEADING.toBuilder().setType(BulletinHeading.Type.AMENDED).setBulletinAugmentationNumber(3).build(), "AAC" }, // + new Object[] { TAF_BULLETIN_HEADING.toBuilder().setType(BulletinHeading.Type.CORRECTED).setBulletinAugmentationNumber(2).build(), "CCB" },// + new Object[] { TAF_BULLETIN_HEADING.toBuilder().setType(BulletinHeading.Type.DELAYED).setBulletinAugmentationNumber(4).build(), "RRD" }, // + }; + } + } +} From 30949f1aecdc3c21c0d4f6fd75ed406c4e513f5e Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 1 Nov 2019 16:31:28 +0200 Subject: [PATCH 2/3] [maven-release-plugin](anonymous)prepare release fmi-avi-messageconverter-3.9.4 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8fddf6f9..3c8fb181 100644 --- a/pom.xml +++ b/pom.xml @@ -11,13 +11,13 @@ Aviation weather message conversions fi.fmi.avi.converter fmi-avi-messageconverter - 3.9.4-SNAPSHOT + 3.9.4 scm:git:https://github.com/fmidev/fmi-avi-messageconverter.git scm:git:https://github.com/fmidev/fmi-avi-messageconverter.git https://github.com/fmidev/fmi-avi-messageconverter - HEAD + fmi-avi-messageconverter-3.9.4 From 3a4858c9336bd1f3b01ffbdaf262a0c293ba32e1 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 1 Nov 2019 16:31:35 +0200 Subject: [PATCH 3/3] [maven-release-plugin](anonymous)prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3c8fb181..e1f18b46 100644 --- a/pom.xml +++ b/pom.xml @@ -11,13 +11,13 @@ Aviation weather message conversions fi.fmi.avi.converter fmi-avi-messageconverter - 3.9.4 + 3.9.5-SNAPSHOT scm:git:https://github.com/fmidev/fmi-avi-messageconverter.git scm:git:https://github.com/fmidev/fmi-avi-messageconverter.git https://github.com/fmidev/fmi-avi-messageconverter - fmi-avi-messageconverter-3.9.4 + HEAD