From 7313e311b4f4f0374a8899cd56a86898c1e0c027 Mon Sep 17 00:00:00 2001 From: Hilbrand Bouwkamp Date: Thu, 4 Jun 2026 17:14:46 +0200 Subject: [PATCH 1/2] AER-4271 When importing Non Urban Road with multiple vehicles to check if can be combined check on converted maximumspeed Because when creating a StandardVehicles source it changes the maximum speed for the source for non urban roads. Than the other vehicle sources should be compared to that speed to check on matching, otherwise it will try to match a non converted with converted source which will result in the vehicle source to be separated. Updated round trip sources to include 2 different vehicle type sources. Note that the round trip test did catch this case because when exporting it will merge again. Therefore the export was correct, and wasn't detecting the issue. --- .../aerius/gml/base/source/road/GML2Road.java | 11 ++++++----- .../gml/v0_5/roundtrip/road_non_urban.gml | 6 ++++++ .../gml/v1_0/roundtrip/road_non_urban.gml | 6 ++++++ .../gml/v1_1/roundtrip/road_non_urban.gml | 6 ++++++ .../gml/v2_0/roundtrip/road_non_urban.gml | 6 ++++++ .../gml/v2_1/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v2_2/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v3_0/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v3_1/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v4_0/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v5_0/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v5_1/roundtrip/road_non_urban.gml | 7 +++++++ .../gml/v6_0/roundtrip/road_non_urban.gml | 16 ++++++++++++---- 13 files changed, 91 insertions(+), 9 deletions(-) diff --git a/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java b/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java index 3395d0730..cc68a5ff3 100644 --- a/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java +++ b/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java @@ -78,9 +78,9 @@ protected void addVehicleEmissions(final String gmlRoadTypeCode, final List - addEmissionValues(gmlRoadTypeCode, addToVehicles, source, standardVehicle, mergingStandardVehicles); + addEmissionValues(gmlRoadTypeCode, addToVehicles, source, standardVehicle, mergingStandardVehicles); case final IsGmlSpecificVehicle specificVehicle -> - addToVehicles.add(GML2VehicleUtil.convertEmissionValuesSpecific(source, specificVehicle, getConversionData())); + addToVehicles.add(GML2VehicleUtil.convertEmissionValuesSpecific(source, specificVehicle, getConversionData())); case final IsGmlCustomVehicle customVehicle -> addToVehicles.add(GML2VehicleUtil.convertEmissionValuesCustom(customVehicle)); default -> throw new IllegalArgumentException("Instance not supported:" + av.getClass().getCanonicalName()); } @@ -88,7 +88,7 @@ protected void addVehicleEmissions(final String gmlRoadTypeCode, final List addToVehicles, final T source, final IsGmlStandardVehicle sv, final List mergingStandardVehicles) { - final StandardVehicles standardVehicle = findExistingMatch(sv, mergingStandardVehicles).orElseGet(() -> { + final StandardVehicles standardVehicle = findExistingMatch(sv, mergingStandardVehicles, gmlRoadTypeCode).orElseGet(() -> { final StandardVehicles vse = new StandardVehicles(); vse.setMaximumSpeed(getMaximumSpeed(gmlRoadTypeCode, sv.getMaximumSpeed())); @@ -124,9 +124,10 @@ private static Integer getMaximumSpeed(final String gmlRoadTypeCode, final Integ }; } - private Optional findExistingMatch(final IsGmlStandardVehicle sv, final List mergingStandardVehicles) { + private Optional findExistingMatch(final IsGmlStandardVehicle sv, final List mergingStandardVehicles, + final String gmlRoadTypeCode) { return mergingStandardVehicles.stream() - .filter(x -> Objects.equals(x.getMaximumSpeed(), sv.getMaximumSpeed())) + .filter(x -> Objects.equals(x.getMaximumSpeed(), getMaximumSpeed(gmlRoadTypeCode, sv.getMaximumSpeed()))) .filter(x -> Objects.equals(x.getStrictEnforcement(), sv.isStrictEnforcement())) .filter(x -> x.getTimeUnit() == TimeUnit.valueOf(sv.getTimeUnit().name())) .filter(x -> !x.getValuesPerVehicleTypes().containsKey(sv.getVehicleType())) diff --git a/source/imaer-gml/src/test/resources/gml/v0_5/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v0_5/roundtrip/road_non_urban.gml index 7f9a434f8..c417992b6 100644 --- a/source/imaer-gml/src/test/resources/gml/v0_5/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v0_5/roundtrip/road_non_urban.gml @@ -52,6 +52,12 @@ 248.53379071913935 + + + 5000.0 + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v1_0/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v1_0/roundtrip/road_non_urban.gml index 518e30430..8bf0498fe 100644 --- a/source/imaer-gml/src/test/resources/gml/v1_0/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v1_0/roundtrip/road_non_urban.gml @@ -52,6 +52,12 @@ 248.53379071913935 + + + 5000.0 + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v1_1/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v1_1/roundtrip/road_non_urban.gml index ae2d2d0d7..0345d4ce0 100644 --- a/source/imaer-gml/src/test/resources/gml/v1_1/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v1_1/roundtrip/road_non_urban.gml @@ -52,6 +52,12 @@ 248.53379071913935 + + + 5000.0 + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v2_0/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v2_0/roundtrip/road_non_urban.gml index e3c942c69..f1920c6f3 100644 --- a/source/imaer-gml/src/test/resources/gml/v2_0/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v2_0/roundtrip/road_non_urban.gml @@ -67,6 +67,12 @@ 248.53379071913935 + + + 5000.0 + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v2_1/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v2_1/roundtrip/road_non_urban.gml index e04e183ea..7169d672d 100644 --- a/source/imaer-gml/src/test/resources/gml/v2_1/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v2_1/roundtrip/road_non_urban.gml @@ -67,6 +67,13 @@ 248.53379071913935 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v2_2/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v2_2/roundtrip/road_non_urban.gml index 7ee804dd8..c39ed4594 100644 --- a/source/imaer-gml/src/test/resources/gml/v2_2/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v2_2/roundtrip/road_non_urban.gml @@ -71,6 +71,13 @@ 248.53379071913935 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v3_0/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v3_0/roundtrip/road_non_urban.gml index ef3ef14d3..f9032ec84 100644 --- a/source/imaer-gml/src/test/resources/gml/v3_0/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v3_0/roundtrip/road_non_urban.gml @@ -71,6 +71,13 @@ 177.63161565365507 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v3_1/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v3_1/roundtrip/road_non_urban.gml index f32525d5d..e61f9a6c0 100644 --- a/source/imaer-gml/src/test/resources/gml/v3_1/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v3_1/roundtrip/road_non_urban.gml @@ -71,6 +71,13 @@ 19.73090437453009 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v4_0/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v4_0/roundtrip/road_non_urban.gml index 3e95977d0..a4791a7bb 100644 --- a/source/imaer-gml/src/test/resources/gml/v4_0/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v4_0/roundtrip/road_non_urban.gml @@ -72,6 +72,13 @@ 19.73090437453009 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v5_0/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v5_0/roundtrip/road_non_urban.gml index eb2a16d9e..9be65f83e 100644 --- a/source/imaer-gml/src/test/resources/gml/v5_0/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v5_0/roundtrip/road_non_urban.gml @@ -72,6 +72,13 @@ 19.73090437453009 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v5_1/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v5_1/roundtrip/road_non_urban.gml index b3bce5804..8f4cb3917 100644 --- a/source/imaer-gml/src/test/resources/gml/v5_1/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v5_1/roundtrip/road_non_urban.gml @@ -72,6 +72,13 @@ 19.73090437453009 + + + 5000.0 + DAY + 0.2 + + 15000.0 diff --git a/source/imaer-gml/src/test/resources/gml/v6_0/roundtrip/road_non_urban.gml b/source/imaer-gml/src/test/resources/gml/v6_0/roundtrip/road_non_urban.gml index 1a233bb9e..a5430c923 100644 --- a/source/imaer-gml/src/test/resources/gml/v6_0/roundtrip/road_non_urban.gml +++ b/source/imaer-gml/src/test/resources/gml/v6_0/roundtrip/road_non_urban.gml @@ -54,24 +54,32 @@ - 24.525329736565443 + 54.36755426564444 - 95.61190577751265 + 1013.5599616318192 - 13.553471696523006 + 37.34119753123686 - 19.73090437453009 + 62.60413116965389 + + + 5000.0 + DAY + 0.2 + 80 + + 15000.0 From 49956dfde1eb27dfa5526336758b8fe714aeb97c Mon Sep 17 00:00:00 2001 From: Hilbrand Bouwkamp Date: Fri, 5 Jun 2026 15:29:01 +0200 Subject: [PATCH 2/2] AER-4271 Made merging road sub sources more robust and added unit test --- .../aerius/gml/base/source/road/GML2Road.java | 20 ++-- .../gml/base/source/road/GML2RoadTest.java | 91 +++++++++++++++++++ 2 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 source/imaer-gml/src/test/java/nl/overheid/aerius/gml/base/source/road/GML2RoadTest.java diff --git a/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java b/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java index cc68a5ff3..4f1ebf28d 100644 --- a/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java +++ b/source/imaer-gml/src/main/java/nl/overheid/aerius/gml/base/source/road/GML2Road.java @@ -92,16 +92,23 @@ private void addEmissionValues(final String gmlRoadTypeCode, final List { + final ValuesPerVehicleType valuesPerVehicleType = new ValuesPerVehicleType(); + + valuesPerVehicleType.setStagnationFraction(sv.getStagnationFactor()); + return valuesPerVehicleType; + }); + vpvt.setVehiclesPerTimeUnit(sv.getVehiclesPerTimeUnit() + vpvt.getVehiclesPerTimeUnit()); } /** @@ -128,10 +135,9 @@ private Optional findExistingMatch(final IsGmlStandardVehicle final String gmlRoadTypeCode) { return mergingStandardVehicles.stream() .filter(x -> Objects.equals(x.getMaximumSpeed(), getMaximumSpeed(gmlRoadTypeCode, sv.getMaximumSpeed()))) - .filter(x -> Objects.equals(x.getStrictEnforcement(), sv.isStrictEnforcement())) + .filter(x -> Boolean.TRUE.equals(x.getStrictEnforcement()) == Boolean.TRUE.equals((sv.isStrictEnforcement()))) .filter(x -> x.getTimeUnit() == TimeUnit.valueOf(sv.getTimeUnit().name())) .filter(x -> !x.getValuesPerVehicleTypes().containsKey(sv.getVehicleType())) .findFirst(); } - } diff --git a/source/imaer-gml/src/test/java/nl/overheid/aerius/gml/base/source/road/GML2RoadTest.java b/source/imaer-gml/src/test/java/nl/overheid/aerius/gml/base/source/road/GML2RoadTest.java new file mode 100644 index 000000000..5752dc698 --- /dev/null +++ b/source/imaer-gml/src/test/java/nl/overheid/aerius/gml/base/source/road/GML2RoadTest.java @@ -0,0 +1,91 @@ +/* + * Copyright the State of the Netherlands + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package nl.overheid.aerius.gml.base.source.road; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import nl.overheid.aerius.gml.base.GMLConversionData; +import nl.overheid.aerius.gml.v6_0.source.TimeUnit; +import nl.overheid.aerius.gml.v6_0.source.road.SRM2Road; +import nl.overheid.aerius.gml.v6_0.source.road.StandardVehicle; +import nl.overheid.aerius.gml.v6_0.source.road.VehiclesProperty; +import nl.overheid.aerius.shared.domain.v2.source.SRM2RoadEmissionSource; +import nl.overheid.aerius.shared.exception.AeriusException; + +/** + * Unit test to test merging of standardVehicle sub sources. + */ +@ExtendWith(MockitoExtension.class) +class GML2RoadTest { + + private @Mock GMLConversionData conversionData; + + /** + * Test merging sub sources. vehicle types with the same configuration can be joined into a single sub source. + */ + @ParameterizedTest + @CsvSource({"NON_URBAN_ROAD_NATIONAL", "Other"}) + void testStandardVehicleMerge(final String roadTypeCode) throws AeriusException { + final SRM2Road gmlRoad = new SRM2Road(); + gmlRoad.setRoadTypeCode(roadTypeCode); + gmlRoad.getVehicles().addAll(generateAllCombinations()); + + final SRM2RoadEmissionSource converted = new GML2SRM2Road<>(conversionData).convert(gmlRoad); + assertEquals(24, converted.getSubSources().size(), "Merging sub sources did not give the expected number of sub sources "); + } + + private static List generateAllCombinations() { + final TimeUnit[] timeUnits = {TimeUnit.DAY, TimeUnit.YEAR}; + final Boolean[] strictEnforcements = {null, false, true}; + final Integer[] maxSpeeds = {null, 0, 80, 100}; + final String[] vehicleTypes = {"A", "B"}; + final List subSources = new ArrayList<>(); + + for (final TimeUnit second : timeUnits) { + for (final Boolean third : strictEnforcements) { + for (final Integer fourth : maxSpeeds) { + for (final String first : vehicleTypes) { + subSources.add(createStandardVehicle(first, second, third, fourth)); + } + } + } + } + return subSources; + } + + private static VehiclesProperty createStandardVehicle(final String vehicleType, final TimeUnit timeUnit, final Boolean strictEnforcement, + final Integer maxSpeed) { + final StandardVehicle vehicle = new StandardVehicle(); + + vehicle.setVehicleType(vehicleType); + vehicle.setTimeUnit(timeUnit); + vehicle.setStrictEnforcement(strictEnforcement); + vehicle.setMaximumSpeed(maxSpeed); + vehicle.setVehiclesPerTimeUnit(10); + vehicle.setStagnationFactor(20); + return new VehiclesProperty(vehicle); + } +}