Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fmi avi messageconverter iwxxm #80 #81

Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import fi.fmi.avi.converter.IssueList;
import fi.fmi.avi.converter.iwxxm.IWXXMNamespaceContext;
import fi.fmi.avi.model.Aerodrome;
import fi.fmi.avi.model.AviationWeatherMessage;
import fi.fmi.avi.model.GenericAviationWeatherMessage;
import fi.fmi.avi.model.MessageType;
import fi.fmi.avi.model.PartialOrCompleteTimeInstant;
Expand Down Expand Up @@ -82,22 +83,48 @@ private static IssueList collectTAFMessage(final Element featureElement, final X
"./iwxxm:baseForecast/om:OM_Observation/om:featureOfInterest/sams:SF_SpatialSamplingFeature/sam:sampledFeature/" + "aixm:AirportHeliport");
}
if (expr != null) {
final NodeList nodes = (NodeList) expr.evaluate(featureElement, XPathConstants.NODESET);
if (nodes.getLength() == 1) {
Optional<Aerodrome> aerodrome = parseAerodromeInfo((Element) nodes.item(0), xpath, retval);
if(aerodrome.isPresent()) {
builder.putLocationIndicators(GenericAviationWeatherMessage.LocationIndicatorType.AERODROME, aerodrome.get().getDesignator());
} else {
retval.add(ConversionIssue.Severity.ERROR, ConversionIssue.Type.SYNTAX, "Aerodrome info could not be parsed for TAF of status " + status);
}
} else {
retval.add(ConversionIssue.Severity.ERROR, ConversionIssue.Type.SYNTAX, "Aerodrome info not available for TAF of status " + status);
}
parseAerodromeInfo(featureElement, expr, xpath, builder, retval, status);
}

return retval;
}

private static IssueList collectTAF30Message(final Element featureElement, final XPath xpath, final GenericAviationWeatherMessageImpl.Builder builder)
throws XPathExpressionException {
final IssueList retval = new IssueList();
//Issue time:
final String timeStr;
XPathExpression expr = xpath.compile("./iwxxm30:issueTime/gml:TimeInstant/gml:timePosition");
timeStr = expr.evaluate(featureElement);
if (!timeStr.isEmpty()) {
builder.setIssueTime(PartialOrCompleteTimeInstant.of(ZonedDateTime.parse(timeStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME)));
} else {
retval.add(ConversionIssue.Severity.ERROR, ConversionIssue.Type.MISSING_DATA, "No issue time found for IWXXM TAF");
}

expr = xpath.compile("@isCancelReport");
final boolean isCancelMessage = (expr.evaluate(featureElement) != null && expr.evaluate(featureElement).toLowerCase().equals("true"));
if (isCancelMessage) {
collectValidTime(featureElement, "./iwxxm30:cancelledReportValidPeriod", xpath, builder);
} else {
collectValidTime(featureElement, "./iwxxm30:validPeriod", xpath, builder);
}

expr = xpath.compile("@reportStatus");
final String status = expr.evaluate(featureElement);
try {
builder.setReportStatus(AviationWeatherMessage.ReportStatus.valueOf(status));
} catch (IllegalArgumentException e) {
retval.add(ConversionIssue.Severity.ERROR, "The report status could not be parsed");
}

//target aerodrome
expr = xpath.compile("./iwxxm30:aerodrome/aixm:AirportHeliport");
parseAerodromeInfo(featureElement, expr, xpath, builder, retval, status);

return retval;
}

private static IssueList collectValidTime(final Element featureElement, final String selector, final XPath xpath,
final GenericAviationWeatherMessageImpl.Builder builder) {
final IssueList retval = new IssueList();
Expand All @@ -123,6 +150,21 @@ private static IssueList collectValidTime(final Element featureElement, final St
return retval;
}

private static void parseAerodromeInfo(final Element featureElement, final XPathExpression timeSliceExpretion, final XPath xpath,
final GenericAviationWeatherMessageImpl.Builder builder, final IssueList issues, final String status) throws XPathExpressionException {
final NodeList nodes = (NodeList) timeSliceExpretion.evaluate(featureElement, XPathConstants.NODESET);
if (nodes.getLength() == 1) {
Optional<Aerodrome> aerodrome = parseAerodromeInfo((Element) nodes.item(0), xpath, issues);
if (aerodrome.isPresent()) {
builder.putLocationIndicators(GenericAviationWeatherMessage.LocationIndicatorType.AERODROME, aerodrome.get().getDesignator());
} else {
issues.add(ConversionIssue.Severity.ERROR, ConversionIssue.Type.SYNTAX, "Aerodrome info could not be parsed for TAF of status " + status);
}
} else {
issues.add(ConversionIssue.Severity.ERROR, ConversionIssue.Type.SYNTAX, "Aerodrome info not available for TAF of status " + status);
}
}

private static Optional<Aerodrome> parseAerodromeInfo(final Element airportHeliport, final XPath xpath, final IssueList issues)
throws XPathExpressionException {
Optional<Aerodrome> retval = Optional.empty();
Expand Down Expand Up @@ -201,7 +243,11 @@ protected ConversionResult<GenericAviationWeatherMessage> createAviationWeatherM
switch (messageType) {
case "TAF":
builder.setMessageType(MessageType.TAF);
retval.addIssue(collectTAFMessage(featureElement, xpath, builder));
if (featureElement.getNamespaceURI().equals("http://icao.int/iwxxm/3.0")) {
retval.addIssue(collectTAF30Message(featureElement, xpath, builder));
} else {
retval.addIssue(collectTAFMessage(featureElement, xpath, builder));
}
break;

case "METAR":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,15 +255,14 @@ public class IWXXMConverter {
// *******************

/**
* Pre-configured spec for WMO COLLECT 1.2 XML DOM document to {@link GenericMeteorologicalBulletin}
* Pre-configured spec for WMO COLLECT 1.2 and 1.3 XML DOM document to {@link GenericMeteorologicalBulletin}
patrick-alaspaa marked this conversation as resolved.
Show resolved Hide resolved
*/
public static final ConversionSpecification<Document, GenericMeteorologicalBulletin> IWXXM21_DOM_TO_GENERIC_BULLETIN_POJO = new ConversionSpecification<>(
public static final ConversionSpecification<Document, GenericMeteorologicalBulletin> WMO_COLLECT_DOM_TO_GENERIC_BULLETIN_POJO = new ConversionSpecification<>(
Document.class, GenericMeteorologicalBulletin.class, "XML/WMO COLLECT 1.2", null);

/**
* Pre-configured spec for WMO COLLECT 1.2 XML document String to {@link GenericMeteorologicalBulletin}
* Pre-configured spec for WMO COLLECT 1.2 and 1.3 XML document String to {@link GenericMeteorologicalBulletin}
*/
public static final ConversionSpecification<String, GenericMeteorologicalBulletin> IWXXM21_STRING_TO_GENERIC_BULLETIN_POJO = new ConversionSpecification<>(
public static final ConversionSpecification<String, GenericMeteorologicalBulletin> WMO_COLLECT_STRING_TO_GENERIC_BULLETIN_POJO = new ConversionSpecification<>(
String.class, GenericMeteorologicalBulletin.class, "XML/WMO COLLECT 1.2", null);

}
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ public AviMessageConverter aviMessageConverter() {
p.setMessageSpecificConverter(IWXXMConverter.WMO_COLLECT_DOM_TO_SWX_BULLETIN_POJO, spaceWeatherBulletinIWXXMDOMParser);

// Generic bulletin messages:
p.setMessageSpecificConverter(IWXXMConverter.IWXXM21_DOM_TO_GENERIC_BULLETIN_POJO, genericBulletinIWXXMDOMParser);
p.setMessageSpecificConverter(IWXXMConverter.IWXXM21_STRING_TO_GENERIC_BULLETIN_POJO, genericBulletinIWXXMStringParser);
p.setMessageSpecificConverter(IWXXMConverter.WMO_COLLECT_DOM_TO_GENERIC_BULLETIN_POJO, genericBulletinIWXXMDOMParser);
p.setMessageSpecificConverter(IWXXMConverter.WMO_COLLECT_STRING_TO_GENERIC_BULLETIN_POJO, genericBulletinIWXXMStringParser);
return p;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
import fi.fmi.avi.converter.ConversionResult;
import fi.fmi.avi.converter.iwxxm.IWXXMTestConfiguration;
import fi.fmi.avi.converter.iwxxm.conf.IWXXMConverter;
import fi.fmi.avi.model.Aerodrome;
import fi.fmi.avi.model.AviationWeatherMessage;
import fi.fmi.avi.model.GenericAviationWeatherMessage;
import fi.fmi.avi.model.MessageType;
import fi.fmi.avi.model.bulletin.GenericMeteorologicalBulletin;

/**
Expand Down Expand Up @@ -56,16 +60,62 @@ public void testScanner() throws Exception {
@Test
public void testParserWithTAF() throws Exception {
final Document input = this.getBulletinDocument("taf-bulletin.xml");
final ConversionResult<GenericMeteorologicalBulletin> result = this.converter.convertMessage(input, IWXXMConverter.IWXXM21_DOM_TO_GENERIC_BULLETIN_POJO,
final ConversionResult<GenericMeteorologicalBulletin> result = this.converter.convertMessage(input, IWXXMConverter.WMO_COLLECT_DOM_TO_GENERIC_BULLETIN_POJO,
ConversionHints.EMPTY);
assertEquals(ConversionResult.Status.SUCCESS, result.getStatus());
}

@Test
public void testParserWithSIGMET() throws Exception {
final Document input = this.getBulletinDocument("sigmet-bulletin.xml");
final ConversionResult<GenericMeteorologicalBulletin> result = this.converter.convertMessage(input, IWXXMConverter.IWXXM21_DOM_TO_GENERIC_BULLETIN_POJO,
final ConversionResult<GenericMeteorologicalBulletin> result = this.converter.convertMessage(input, IWXXMConverter.WMO_COLLECT_DOM_TO_GENERIC_BULLETIN_POJO,
ConversionHints.EMPTY);
assertEquals(ConversionResult.Status.SUCCESS, result.getStatus());
}

@Test
public void testParserWithIWXXM30() throws Exception {
patrick-alaspaa marked this conversation as resolved.
Show resolved Hide resolved
final Document input = this.getBulletinDocument("iwxxm-30-bulletin.xml");
final ConversionResult<GenericMeteorologicalBulletin> result = this.converter.convertMessage(input, IWXXMConverter.WMO_COLLECT_DOM_TO_GENERIC_BULLETIN_POJO,
ConversionHints.EMPTY);
assertEquals(ConversionResult.Status.SUCCESS, result.getStatus());

GenericAviationWeatherMessage message = result.getConvertedMessage().get().getMessages().get(0);

//check validtime
assertEquals("2012-08-16T00:00Z", message.getValidityTime().get().getStartTime().get().getCompleteTime().get().toString());
assertEquals("2012-08-16T18:00Z", message.getValidityTime().get().getEndTime().get().getCompleteTime().get().toString());

assertTrue(message.getIssueTime().isPresent());
assertEquals("2012-08-15T18:00Z", message.getIssueTime().get().getCompleteTime().get().toString());
patrick-alaspaa marked this conversation as resolved.
Show resolved Hide resolved

//check aerodrome
assertEquals(message.getLocationIndicators().get(GenericAviationWeatherMessage.LocationIndicatorType.AERODROME), "YUDO");

//check status
assertEquals(AviationWeatherMessage.ReportStatus.NORMAL, message.getReportStatus());
assertTrue(message.getMessageType().isPresent());
assertEquals(MessageType.TAF, message.getMessageType().get());
assertEquals(GenericAviationWeatherMessage.Format.IWXXM, message.getMessageFormat());

}

@Test
public void testParserWithIWXXM30Cancellation() throws Exception {
final Document input = this.getBulletinDocument("iwxxm-30-cancellation-bulletin.xml");
final ConversionResult<GenericMeteorologicalBulletin> result = this.converter.convertMessage(input, IWXXMConverter.WMO_COLLECT_DOM_TO_GENERIC_BULLETIN_POJO,
ConversionHints.EMPTY);
assertEquals(ConversionResult.Status.SUCCESS, result.getStatus());

GenericAviationWeatherMessage message = result.getConvertedMessage().get().getMessages().get(0);
assertEquals("2012-08-16T00:00Z", message.getValidityTime().get().getStartTime().get().getCompleteTime().get().toString());
assertEquals("2012-08-16T18:00Z", message.getValidityTime().get().getEndTime().get().getCompleteTime().get().toString());

assertTrue(message.getIssueTime().isPresent());
assertEquals("2012-08-16T15:00Z", message.getIssueTime().get().getCompleteTime().get().toString());

assertEquals(message.getLocationIndicators().get(GenericAviationWeatherMessage.LocationIndicatorType.AERODROME), "YUDO");

assertEquals(AviationWeatherMessage.ReportStatus.AMENDMENT, message.getReportStatus());
patrick-alaspaa marked this conversation as resolved.
Show resolved Hide resolved
}
}
Loading