Skip to content
Merged
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 @@ -246,4 +246,20 @@ public <S extends SourceCharacteristics> S determineDefaultCharacteristicsBySect
public <S extends SourceCharacteristics> S determineDefaultCharacteristicsBySectorId(final int sectorId, final GeometryType geometryType) {
return characteristicsSupplier.determineDefaultCharacteristicsBySectorId(sectorId, geometryType);
}

/**
* Checks if the given code is a removed code and adds a warning if so.
*
* @param type the type of legacy code
* @param code the code to check
* @param sourceLabel the label of the source for warning messages
* @return true if the code is a removed code, false otherwise
*/
public boolean warnIfRemovedCode(final GMLLegacyCodeType type, final String code, final String sourceLabel) {
if (legacyCodeConverter.isRemovedCode(type, code)) {
warnings.add(new AeriusException(ImaerExceptionReason.GML_REMOVED_CODE_CONVERTED, sourceLabel, code));
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package nl.overheid.aerius.gml.base;

import java.util.Map;
import java.util.Set;

import nl.overheid.aerius.gml.base.conversion.FarmLodgingConversion;
import nl.overheid.aerius.gml.base.conversion.MobileSourceOffRoadConversion;
Expand All @@ -42,20 +43,24 @@ public enum GMLLegacyCodeType {
private final Map<String, MobileSourceOffRoadConversion> mobileSourceOffRoadConversions;
private final Map<String, PlanConversion> planConversions;
private final Map<String, FarmLodgingConversion> farmLodgingConversions;
private final Map<GMLLegacyCodeType, Set<String>> removedCodes;

/**
* @param codeMaps The &lt;OldCode, NewCode&gt; maps to use for each legacy code type.
* @param mobileSourceOffRoadConversions The &lt;OldCode, ConversionValues&gt; to use for mobile sources.
* @param planConversions The &lt;OldCode, ConversionValues&gt; to use for plan activities.
* @param farmLodgingConversions The &lt;OldCode, ConversionValues&gt; to use for farm lodgings.
* @param removedCodes The removed codes by type.
*/
public GMLLegacyCodeConverter(final Map<GMLLegacyCodeType, Map<String, Conversion>> codeMaps,
final Map<String, MobileSourceOffRoadConversion> mobileSourceOffRoadConversions,
final Map<String, PlanConversion> planConversions, final Map<String, FarmLodgingConversion> farmLodgingConversions) {
final Map<String, PlanConversion> planConversions, final Map<String, FarmLodgingConversion> farmLodgingConversions,
final Map<GMLLegacyCodeType, Set<String>> removedCodes) {
this.codeMaps = safe(codeMaps);
this.mobileSourceOffRoadConversions = safe(mobileSourceOffRoadConversions);
this.planConversions = safe(planConversions);
this.farmLodgingConversions = safe(farmLodgingConversions);
this.removedCodes = safe(removedCodes);
}

private static <S, Y> Map<S, Y> safe(final Map<S, Y> map) {
Expand Down Expand Up @@ -89,6 +94,16 @@ protected FarmLodgingConversion getFarmLodgingConversion(final String oldCode) {
return farmLodgingConversions.get(oldCode);
}

/**
* Check if a code is a removed code.
* @param type The type of legacy code.
* @param code The code to check.
* @return true if the code is a removed code, false otherwise.
*/
protected boolean isRemovedCode(final GMLLegacyCodeType type, final String code) {
return removedCodes.getOrDefault(type, Set.of()).contains(code);
}

/**
* The conversion of a an old code.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package nl.overheid.aerius.gml.base;

import java.util.Map;
import java.util.Set;

import nl.overheid.aerius.gml.base.GMLLegacyCodeConverter.Conversion;
import nl.overheid.aerius.gml.base.GMLLegacyCodeConverter.GMLLegacyCodeType;
Expand Down Expand Up @@ -69,4 +70,15 @@ default Map<String, FarmLodgingConversion> getLegacyFarmLodgingConversions() thr
return Map.of();
}

/**
* Returns a map of removed codes by type.
* Sources with these codes will be converted to alternative representations during import.
*
* @return map of code type to set of removed codes
* @throws AeriusException
*/
default Map<GMLLegacyCodeType, Set<String>> getRemovedCodes() throws AeriusException {
return Map.of();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected GMLVersionReaderFactory(final GMLLegacyCodesSupplier legacyCodeSupplie
schema = GMLSchemaFactory.createSchema(schemaLocation);
legacyCodeConverter = new GMLLegacyCodeConverter(legacyCodeSupplier.getLegacyCodes(version),
legacyCodeSupplier.getLegacyMobileSourceOffRoadConversions(), legacyCodeSupplier.getLegacyPlanConversions(),
legacyCodeSupplier.getLegacyFarmLodgingConversions());
legacyCodeSupplier.getLegacyFarmLodgingConversions(), legacyCodeSupplier.getRemovedCodes());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ private GML2VehicleUtil() {

static void addEmissionValuesSpecific(final List<Vehicles> addToVehicles, final IsGmlEmissionSource source, final IsGmlSpecificVehicle sv,
final GMLConversionData conversionData) {
final SpecificVehicles vse = new SpecificVehicles();
final String vehicleCode = conversionData.getCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, sv.getCode(), source.getLabel());

if (conversionData.warnIfRemovedCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, vehicleCode, source.getLabel())) {
addToVehicles.add(RemovedVehicleUtil.toCustomVehicles(sv, vehicleCode));
return;
}

final SpecificVehicles vse = new SpecificVehicles();
vse.setVehicleCode(vehicleCode);
vse.setTimeUnit(TimeUnit.valueOf(sv.getTimeUnit().name()));
vse.setVehiclesPerTimeUnit(sv.getVehiclesPerTimeUnit());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 nl.overheid.aerius.shared.domain.v2.base.TimeUnit;
import nl.overheid.aerius.shared.domain.v2.source.road.CustomVehicles;

/**
* Utility for converting removed vehicle codes to custom vehicles.
*/
public final class RemovedVehicleUtil {

private RemovedVehicleUtil() {
// Util class
}

/**
* Converts a specific vehicle with a removed code to a custom vehicle with zero emissions.
*
* @param sv the specific vehicle to convert
* @param vehicleCode the removed vehicle code
* @return a custom vehicle preserving the vehicle count and time unit
*/
public static CustomVehicles toCustomVehicles(final IsGmlSpecificVehicle sv, final String vehicleCode) {
final CustomVehicles custom = new CustomVehicles();
custom.setTimeUnit(TimeUnit.valueOf(sv.getTimeUnit().name()));
custom.setVehiclesPerTimeUnit(sv.getVehiclesPerTimeUnit());
custom.setDescription(vehicleCode);
return custom;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import nl.overheid.aerius.gml.base.source.road.IsGmlCustomVehicle;
import nl.overheid.aerius.gml.base.source.road.IsGmlSpecificVehicle;
import nl.overheid.aerius.gml.base.source.road.IsGmlVehicle;
import nl.overheid.aerius.gml.base.source.road.RemovedVehicleUtil;
import nl.overheid.aerius.shared.domain.v2.base.TimeUnit;
import nl.overheid.aerius.shared.domain.v2.source.RoadEmissionSource;
import nl.overheid.aerius.shared.domain.v2.source.road.CustomVehicles;
Expand Down Expand Up @@ -121,8 +122,14 @@ protected Optional<StandardVehicles> findExistingMatch(final IsGmlStandardVehicl
}

protected void addEmissionValues(final List<Vehicles> addToVehicles, final T source, final IsGmlSpecificVehicle sv) {
final SpecificVehicles vse = new SpecificVehicles();
final String vehicleCode = getConversionData().getCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, sv.getCode(), source.getLabel());

if (getConversionData().warnIfRemovedCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, vehicleCode, source.getLabel())) {
addToVehicles.add(RemovedVehicleUtil.toCustomVehicles(sv, vehicleCode));
return;
}

final SpecificVehicles vse = new SpecificVehicles();
vse.setVehicleCode(vehicleCode);
vse.setTimeUnit(TimeUnit.valueOf(sv.getTimeUnit().name()));
vse.setVehiclesPerTimeUnit(sv.getVehiclesPerTimeUnit());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -255,6 +256,7 @@ static GMLHelper mockGMLHelper(final CharacteristicsType ct) throws AeriusExcept
when(gmlHelper.getLegacyMobileSourceOffRoadConversions()).thenReturn(TestValidationAndEmissionHelper.legacyMobileSourceOffRoadConversions());
when(gmlHelper.getLegacyPlanConversions()).thenReturn(TestValidationAndEmissionHelper.legacyPlanConversions());
when(gmlHelper.getLegacyFarmLodgingConversions()).thenReturn(TestValidationAndEmissionHelper.legacyFarmLodgingConversions());
when(gmlHelper.getRemovedCodes()).thenReturn(Map.of());
when(gmlHelper.determineDefaultCharacteristicsBySectorId(anyInt(), any())).thenReturn(determineDefaultCharacteristics(ct));
when(gmlHelper.getValidationHelper()).thenReturn(validationAndEmissionHelper);
when(gmlHelper.getDefaultSector()).thenReturn(new Sector(GMLTestDomain.DEFAULT_SECTOR_ID, SectorGroup.INDUSTRY, ""));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.InputStream;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;

import org.junit.jupiter.api.Test;

import nl.overheid.aerius.gml.base.GMLHelper;
import nl.overheid.aerius.gml.base.GMLLegacyCodeConverter.GMLLegacyCodeType;
import nl.overheid.aerius.importer.ImaerImporter;
import nl.overheid.aerius.importer.ImportOption;
import nl.overheid.aerius.shared.domain.v2.importer.ImportParcel;
import nl.overheid.aerius.shared.domain.v2.source.SRM2RoadEmissionSource;
import nl.overheid.aerius.shared.domain.v2.source.road.CustomVehicles;
import nl.overheid.aerius.shared.exception.AeriusException;
import nl.overheid.aerius.shared.exception.ImaerExceptionReason;

/**
* Integration test verifying that ImaerImporter calls convertRemovedVehicleCodes during import.
*/
class RemovedVehicleCodeImportTest {

private static final String REMOVED_CODE = "BA-B-E3";

@Test
void testRemovedVehicleCodeIsConvertedDuringImport() throws IOException, AeriusException {
final GMLHelper mockHelper = AssertGML.mockGMLHelper();
when(mockHelper.getRemovedCodes()).thenReturn(Map.of(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, Set.of(REMOVED_CODE)));

// Create fresh factory with our mock helper (not cached) so getRemovedVehicleCodes is used
final GMLReaderFactory factory = new GMLReaderFactory(mockHelper);
final ImaerImporter importer = new ImaerImporter(mockHelper, factory);
final ImportParcel result = new ImportParcel();

try (final InputStream inputStream = AssertGML.getFileInputStream(
AssertGML.PATH_LATEST_VERSION + "roundtrip", "road_specific_and_custom")) {
importer.importStream(inputStream, EnumSet.of(ImportOption.INCLUDE_SOURCES), result);
}

assertEquals(0, result.getExceptions().size(), "Expected no exceptions");
assertTrue(result.getWarnings().stream()
.anyMatch(w -> w.getReason() == ImaerExceptionReason.GML_REMOVED_CODE_CONVERTED),
"Expected warning for removed vehicle code");

final SRM2RoadEmissionSource roadSource =
(SRM2RoadEmissionSource) result.getSituation().getEmissionSourcesList().get(0).getProperties();
final CustomVehicles converted = assertInstanceOf(CustomVehicles.class, roadSource.getSubSources().get(0));
assertEquals(REMOVED_CODE, converted.getDescription());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* 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 static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;

import nl.overheid.aerius.gml.base.GMLConversionData;
import nl.overheid.aerius.gml.base.GMLLegacyCodeConverter.GMLLegacyCodeType;
import nl.overheid.aerius.gml.base.source.IsGmlEmissionSource;
import nl.overheid.aerius.gml.base.source.IsGmlTimeUnit;
import nl.overheid.aerius.shared.domain.v2.source.road.CustomVehicles;
import nl.overheid.aerius.shared.domain.v2.source.road.SpecificVehicles;
import nl.overheid.aerius.shared.domain.v2.source.road.Vehicles;
import nl.overheid.aerius.shared.exception.AeriusException;

class GML2VehicleUtilTest {

private static final String REMOVED_CODE = "BABCEUR4";
private static final String VALID_CODE = "VALID_CODE";
private static final String SOURCE_LABEL = "Test source";

@Test
void testRemovedCodeRoutesToCustomVehicles() throws AeriusException {
final GMLConversionData conversionData = mock(GMLConversionData.class);
when(conversionData.getCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, REMOVED_CODE, SOURCE_LABEL))
.thenReturn(REMOVED_CODE);
when(conversionData.warnIfRemovedCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, REMOVED_CODE, SOURCE_LABEL))
.thenReturn(true);

final List<Vehicles> vehicles = new ArrayList<>();
GML2VehicleUtil.addEmissionValuesSpecific(vehicles, mockSource(), mockSpecificVehicle(REMOVED_CODE), conversionData);

assertEquals(1, vehicles.size());
assertInstanceOf(CustomVehicles.class, vehicles.get(0));
}

@Test
void testUnknownCodeStaysSpecificVehicle() throws AeriusException {
final GMLConversionData conversionData = mock(GMLConversionData.class);
when(conversionData.getCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, VALID_CODE, SOURCE_LABEL))
.thenReturn(VALID_CODE);
when(conversionData.warnIfRemovedCode(GMLLegacyCodeType.ON_ROAD_MOBILE_SOURCE, VALID_CODE, SOURCE_LABEL))
.thenReturn(false);

final List<Vehicles> vehicles = new ArrayList<>();
GML2VehicleUtil.addEmissionValuesSpecific(vehicles, mockSource(), mockSpecificVehicle(VALID_CODE), conversionData);

assertEquals(1, vehicles.size());
assertInstanceOf(SpecificVehicles.class, vehicles.get(0));
}

private IsGmlEmissionSource mockSource() {
final IsGmlEmissionSource source = mock(IsGmlEmissionSource.class);
when(source.getLabel()).thenReturn(SOURCE_LABEL);
return source;
}

private IsGmlSpecificVehicle mockSpecificVehicle(final String code) {
final IsGmlSpecificVehicle vehicle = mock(IsGmlSpecificVehicle.class);
when(vehicle.getCode()).thenReturn(code);
when(vehicle.getVehiclesPerTimeUnit()).thenReturn(100.0);
final IsGmlTimeUnit timeUnit = mock(IsGmlTimeUnit.class);
when(timeUnit.name()).thenReturn("DAY");
when(vehicle.getTimeUnit()).thenReturn(timeUnit);
return vehicle;
}

}
Loading