diff --git a/README.md b/README.md
index a22d2015..296a8046 100644
--- a/README.md
+++ b/README.md
@@ -246,6 +246,8 @@ The NeTEx validator library comes with the following rule set by default:
| SERVICE_LINK_1 | ServiceLink missing FromPointRef |
| SERVICE_LINK_2 | ServiceLink missing ToPointRef |
| SERVICE_LINK_3 | ServiceLink missing element Projections |
+| SERVICE_LINK_4 | ServiceLink missing coordinate list |
+| SERVICE_LINK_5 | ServiceLink less than 2 points |
| SITE_FRAME_IN_COMMON_FILE | SiteFrame unexpected SiteFrame in Common file |
| SITE_FRAME_IN_LINE_FILE | SiteFrame unexpected SiteFrame in Line file |
| TIMETABLE_FRAME_IN_COMMON_FILE | TimetableFrame illegal in Common file |
diff --git a/pom.xml b/pom.xml
index 6001b6ab..23b246b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.entur
netex-validator-java
- 9.0.5-SNAPSHOT
+ 9.1.0-SNAPSHOT
netex-validator-java
Library for validating NeTEx datasets against the Nordic NeTEx Profile.
diff --git a/src/main/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactory.java b/src/main/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactory.java
index 8eca4d97..808237bf 100644
--- a/src/main/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactory.java
+++ b/src/main/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactory.java
@@ -59,6 +59,8 @@ public class DefaultServiceFrameValidationTreeFactory
public static final String CODE_SERVICE_LINK_1 = "SERVICE_LINK_1";
public static final String CODE_SERVICE_LINK_2 = "SERVICE_LINK_2";
public static final String CODE_SERVICE_LINK_3 = "SERVICE_LINK_3";
+ public static final String CODE_SERVICE_LINK_4 = "SERVICE_LINK_4";
+ public static final String CODE_SERVICE_LINK_5 = "SERVICE_LINK_5";
public static final String CODE_FLEXIBLE_LINE_1 = "FLEXIBLE_LINE_1";
public static final String CODE_FLEXIBLE_LINE_10 = "FLEXIBLE_LINE_10";
public static final String CODE_FLEXIBLE_LINE_11 = "FLEXIBLE_LINE_11";
@@ -176,13 +178,31 @@ public ValidationTreeBuilder builder() {
)
.withRule(
new ValidateNotExist(
- "serviceLinks/ServiceLink/projections/LinkSequenceProjection/g:LineString/g:posList[not(normalize-space(text()))]",
+ "serviceLinks/ServiceLink[not(projections)]",
CODE_SERVICE_LINK_3,
"ServiceLink missing element Projections",
"Missing projections element on ServiceLink",
+ Severity.WARNING
+ )
+ )
+ .withRule(
+ new ValidateNotExist(
+ "serviceLinks/ServiceLink/projections/LinkSequenceProjection/g:LineString/g:posList[not(normalize-space(text()))]",
+ CODE_SERVICE_LINK_4,
+ "ServiceLink missing coordinate list",
+ "Missing coordinates list on ServiceLink",
Severity.ERROR
)
)
+ .withRule(
+ new ValidateNotExist(
+ "serviceLinks/ServiceLink/projections/LinkSequenceProjection/g:LineString[count(g:pos) < 2]",
+ CODE_SERVICE_LINK_5,
+ "ServiceLink less than 2 points",
+ "Less then 2 points on ServiceLink",
+ Severity.WARNING
+ )
+ )
.withRule(
new ValidateNotExist(
"destinationDisplays/DestinationDisplay[not(FrontText) or normalize-space(FrontText) = '']",
diff --git a/src/test/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactoryTest.java b/src/test/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactoryTest.java
index 2d699d31..e8ac85fe 100644
--- a/src/test/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactoryTest.java
+++ b/src/test/java/org/entur/netex/validation/validator/xpath/tree/DefaultServiceFrameValidationTreeFactoryTest.java
@@ -11,6 +11,7 @@
import org.entur.netex.validation.validator.xpath.ValidationTree;
import org.entur.netex.validation.validator.xpath.XPathRuleValidationContext;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@@ -140,6 +141,100 @@ class DefaultServiceFrameValidationTreeFactoryTest {
""";
+ private static final String NETEX_FRAGMENT_INVALID_SERVICE_LINK_NO_PROJECTION =
+ """
+
+
+
+ 2030.0
+
+
+
+
+
+ """;
+
+ private static final String NETEX_FRAGMENT_INVALID_SERVICE_LINK_NO_COORDINATE_LIST =
+ """
+
+
+
+ 2030.0
+
+
+
+
+
+
+
+
+
+
+
+
+ """;
+
+ private static final String NETEX_FRAGMENT_SERVICE_LINK_VALID_COORDINATE_LIST =
+ """
+
+
+
+ 2030.0
+
+
+
+ 59.551598 9.803644 59.5307 9.805698
+
+
+
+
+
+
+
+
+ """;
+
+ private static final String NETEX_FRAGMENT_INVALID_SERVICE_LINK_LESS_THAN_TWO_POINTS =
+ """
+
+
+
+ 2030.0
+
+
+
+ 60.075463 9.121449
+
+
+
+
+
+
+
+
+ """;
+
+ private static final String NETEX_FRAGMENT_SERVICE_LINK_VALID_TWO_POINTS =
+ """
+
+
+
+ 2030.0
+
+
+
+ 60.075463 9.121449
+ 60.07577 9.121238
+
+
+
+
+
+
+
+
+ """;
+
private ValidationTree validationTree;
@BeforeEach
@@ -202,4 +297,71 @@ void testValidServiceFrame(String code) {
);
assertTrue(validationIssues.isEmpty());
}
+
+ @Test
+ void testMissingProjectionOnServiceLink() {
+ XPathRuleValidationContext xpathValidationContext =
+ TestValidationContextBuilder
+ .ofNetexFragment(NETEX_FRAGMENT_INVALID_SERVICE_LINK_NO_PROJECTION)
+ .build();
+ List validationIssues = validationTree.validate(
+ xpathValidationContext,
+ CODE_SERVICE_LINK_3
+ );
+ assertEquals(1, validationIssues.size());
+ }
+
+ @Test
+ void testMissingCoordinateListOnServiceLink() {
+ XPathRuleValidationContext xpathValidationContext =
+ TestValidationContextBuilder
+ .ofNetexFragment(NETEX_FRAGMENT_INVALID_SERVICE_LINK_NO_COORDINATE_LIST)
+ .build();
+ List validationIssues = validationTree.validate(
+ xpathValidationContext,
+ CODE_SERVICE_LINK_4
+ );
+ assertEquals(1, validationIssues.size());
+ }
+
+ @Test
+ void testValidCoordinateListOnServiceLink() {
+ XPathRuleValidationContext xpathValidationContext =
+ TestValidationContextBuilder
+ .ofNetexFragment(NETEX_FRAGMENT_SERVICE_LINK_VALID_COORDINATE_LIST)
+ .build();
+ List validationIssues = validationTree.validate(
+ xpathValidationContext,
+ CODE_SERVICE_LINK_4
+ );
+ assertTrue(validationIssues.isEmpty());
+ }
+
+ @Test
+ void testLessThanTwoPointsOnServiceLink() {
+ XPathRuleValidationContext xpathValidationContext =
+ TestValidationContextBuilder
+ .ofNetexFragment(
+ NETEX_FRAGMENT_INVALID_SERVICE_LINK_LESS_THAN_TWO_POINTS
+ )
+ .build();
+ List validationIssues = validationTree.validate(
+ xpathValidationContext,
+ CODE_SERVICE_LINK_5
+ );
+ assertEquals(1, validationIssues.size());
+ }
+
+ @Test
+ void testServiceLinkWithTwoPoints() {
+ XPathRuleValidationContext xpathValidationContext =
+ TestValidationContextBuilder
+ .ofNetexFragment(NETEX_FRAGMENT_SERVICE_LINK_VALID_TWO_POINTS)
+ .build();
+ List validationIssues = validationTree.validate(
+ xpathValidationContext,
+ CODE_SERVICE_LINK_5
+ );
+ assertTrue(validationIssues.isEmpty());
+ }
}