Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public Metar parse(final String code) throws ParseException {
}

/**
* Parses the report-type prefix, station and delivery time.
* Parses the report-type prefix, the report modifiers, the station and the delivery time.
*
* @param m the metar being built.
* @param metarTab the tokenized message.
Expand All @@ -101,6 +101,8 @@ private int parseIdentification(final Metar m, final String[] metarTab, final St
m.setReportType(io.github.mivek.enums.ReportType.SPECI);
startIndex = 1;
}
// a modifier may follow the report type, as in "METAR COR LFPG 081130Z"
startIndex = parseLeadingFlags(m, metarTab, startIndex);
}
if (startIndex >= metarTab.length) {
throw new ParseException(ErrorCodes.ERROR_CODE_INVALID_MESSAGE, ParseErrorType.STATION, null, startIndex);
Expand All @@ -112,11 +114,31 @@ private int parseIdentification(final Metar m, final String[] metarTab, final St
m.setStation(stationToken);
m.setAirport(getAirportSupplier().get(stationToken));
m.setMessage(code);
if (startIndex + 1 >= metarTab.length) {
throw new ParseException(ErrorCodes.ERROR_CODE_INVALID_MESSAGE, ParseErrorType.DELIVERY_TIME, null, startIndex + 1);
// it may also sit between the station and the delivery time, as in "LFPG COR 081130Z"
int timeIndex = parseLeadingFlags(m, metarTab, startIndex + 1);
if (timeIndex >= metarTab.length) {
throw new ParseException(ErrorCodes.ERROR_CODE_INVALID_MESSAGE, ParseErrorType.DELIVERY_TIME, null, timeIndex);
}
parseDeliveryTime(m, metarTab[startIndex + 1], startIndex + 1);
return startIndex + 2;
parseDeliveryTime(m, metarTab[timeIndex], timeIndex);
return timeIndex + 1;
}

/**
* Consumes the report modifiers (COR, AMD, ...) preceding the delivery time. Modifiers placed
* after the delivery time are consumed by the body of the message instead.
*
* @param m the metar being built.
* @param metarTab the tokenized message.
* @param index the index to start at.
* @return the index of the first token that is not a modifier.
*/
private int parseLeadingFlags(final Metar m, final String[] metarTab, final int index) {
int flagIndex = index;
// index 0 holds the report type or the station, never a modifier
while (flagIndex > 0 && flagIndex < metarTab.length && parseFlags(m, metarTab[flagIndex])) {
flagIndex++;
}
return flagIndex;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,67 @@ void testParseWithoutDeliveryTimeThrowsDeliveryTimeError() {
assertEquals(ParseErrorType.DELIVERY_TIME, e.getType());
}

@Test
void testParseWithCorrectionBetweenStationAndDeliveryTime() throws ParseException {
Metar m = parser.parse("MRLB COR 071700Z 11013KT 9999 FEW045 34/22 A2983");

assertTrue(m.isCorrected());
assertEquals("MRLB", m.getStation());
assertEquals(Integer.valueOf(7), m.getDay());
assertEquals(17, m.getTime().getHour());
assertEquals(0, m.getTime().getMinute());
assertEquals(Integer.valueOf(34), m.getTemperature());
}

@Test
void testParseWithCorrectionBetweenReportTypeAndStation() throws ParseException {
Metar m = parser.parse("METAR COR LFPG 081130Z 00000KT 0350 FG SCT000 M01/M01 Q1026");

assertTrue(m.isCorrected());
assertEquals(ReportType.METAR, m.getReportType());
assertEquals("LFPG", m.getStation());
assertEquals(Integer.valueOf(8), m.getDay());
assertEquals(11, m.getTime().getHour());
assertEquals(30, m.getTime().getMinute());
}

@Test
void testParseWithCorrectionAfterDeliveryTime() throws ParseException {
Metar m = parser.parse("MRLB 071700Z COR 11013KT 9999 FEW045 34/22 A2983");

assertTrue(m.isCorrected());
assertEquals(Integer.valueOf(7), m.getDay());
assertEquals(Integer.valueOf(34), m.getTemperature());
}

@Test
void testParseWithoutCorrectionIsNotFlaggedAsCorrected() throws ParseException {
Metar m = parser.parse("MRLB 071700Z 11013KT 9999 FEW045 34/22 A2983");

assertFalse(m.isCorrected());
assertEquals(Integer.valueOf(7), m.getDay());
}

@Test
void testParseWithModifierButWithoutDeliveryTimeThrowsDeliveryTimeError() {
ParseException e = assertThrows(ParseException.class, () -> parser.parse("LFPG COR"));
assertEquals(ParseErrorType.DELIVERY_TIME, e.getType());
assertEquals(2, e.getPosition());
}

@Test
void testParseWithModifierButWithoutStationThrowsStationError() {
ParseException e = assertThrows(ParseException.class, () -> parser.parse("METAR COR"));
assertEquals(ParseErrorType.STATION, e.getType());
assertEquals(2, e.getPosition());
}

@Test
void testParseKeepsAutoAsStationWhenItLeadsTheMessage() {
// a modifier is only expected after the report type or the station, never in first position
ParseException e = assertThrows(ParseException.class, () -> parser.parse("AUTO 11013KT 9999"));
assertEquals(ParseErrorType.DELIVERY_TIME, e.getType());
assertEquals("11013KT", e.getOffendingToken());
}

}
Loading