Skip to content

Commit

Permalink
Refactor transport mode resolution (#260)
Browse files Browse the repository at this point in the history
* Refactor transport mode resolution

* Add validation rule for transport mode on ServiceJourney

* Remove unused code

* Add unit tests

* Add unit tests
  • Loading branch information
vpaturet authored Dec 3, 2024
1 parent 3b8b4f4 commit 34d4f3a
Show file tree
Hide file tree
Showing 24 changed files with 1,034 additions and 120 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.entur</groupId>
<artifactId>netex-validator-java</artifactId>
<version>7.0.3-SNAPSHOT</version>
<version>8.0.0-SNAPSHOT</version>

<name>netex-validator-java</name>
<description>Library for validating NeTEx datasets against the Nordic NeTEx Profile.</description>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.entur.netex.validation.validator;

/**
* Simple ValidationEntryFactory that .
* Simple ValidationEntryFactory that builds report entry based on the default rule configuration.
*/
public class SimpleValidationEntryFactory
implements ValidationReportEntryFactory {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.entur.netex.validation.validator;

import java.util.Objects;

/**
* A validation rule, identified by a unique code.
* The validation rule has a default name, message and severity that can be overridden by configuration.
Expand All @@ -21,10 +23,10 @@ public ValidationRule(
String message,
Severity severity
) {
this.code = code;
this.name = name;
this.message = message;
this.severity = severity;
this.code = Objects.requireNonNull(code);
this.name = Objects.requireNonNull(name);
this.message = Objects.requireNonNull(message);
this.severity = Objects.requireNonNull(severity);
}

/**
Expand Down Expand Up @@ -59,4 +61,17 @@ public String message() {
public Severity severity() {
return severity;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ValidationRule that = (ValidationRule) o;
return Objects.equals(code, that.code);
}

@Override
public int hashCode() {
return Objects.hashCode(code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.entur.netex.validation.validator.ValidationContext;
import org.entur.netex.validation.validator.id.IdVersion;
import org.entur.netex.validation.validator.jaxb.support.DatedServiceJourneyUtils;
import org.entur.netex.validation.validator.jaxb.support.FlexibleLineUtils;
import org.entur.netex.validation.validator.model.*;
import org.rutebanken.netex.model.*;
import org.slf4j.Logger;
Expand Down Expand Up @@ -121,6 +120,16 @@ public QuayCoordinates coordinatesForQuayId(QuayId quayId) {
return stopPlaceRepository.getCoordinatesForQuayId(quayId);
}

/**
* Return the transport mode for a given Quay.
*/
@Nullable
public TransportModeAndSubMode transportModeAndSubModeForQuayId(
QuayId quayId
) {
return stopPlaceRepository.getTransportModesForQuayId(quayId);
}

/**
* Return the coordinates for a given scheduledStopPoint.
*/
Expand Down Expand Up @@ -332,23 +341,29 @@ public Collection<ServiceCalendarFrame> serviceCalendarFrames() {
* If the transport mode is not set on the service journey,
* it will be looked up from the line or flexible line.
*/
public AllVehicleModesOfTransportEnumeration transportMode(
@Nullable
public TransportModeAndSubMode transportModeAndSubMode(
ServiceJourney serviceJourney
) {
AllVehicleModesOfTransportEnumeration transportMode =
serviceJourney.getTransportMode();

TransportSubmodeStructure subModeStructure =
serviceJourney.getTransportSubmode();

if (transportMode == null) {
JourneyPattern journeyPattern = journeyPattern(serviceJourney);
return transportMode(journeyPattern);
return transportModeAndSubMode(journeyPattern);
}
return transportMode;
return TransportModeAndSubMode.of(transportMode, subModeStructure);
}

/**
* Find the transport mode for the given journey pattern.
* it will be looked up from the line or flexible line with FIXED Type
*/
public AllVehicleModesOfTransportEnumeration transportMode(
@Nullable
public TransportModeAndSubMode transportModeAndSubMode(
JourneyPattern journeyPattern
) {
Route route = netexEntitiesIndex
Expand All @@ -359,15 +374,19 @@ public AllVehicleModesOfTransportEnumeration transportMode(
.get(route.getLineRef().getValue().getRef());

if (line != null) {
return line.getTransportMode();
return TransportModeAndSubMode.of(
line.getTransportMode(),
line.getTransportSubmode()
);
}

FlexibleLine flexibleLine = netexEntitiesIndex
.getFlexibleLineIndex()
.get(route.getLineRef().getValue().getRef());

return FlexibleLineUtils.isFixedFlexibleLine(flexibleLine)
? flexibleLine.getTransportMode()
: null;
return TransportModeAndSubMode.of(
flexibleLine.getTransportMode(),
flexibleLine.getTransportSubmode()
);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package org.entur.netex.validation.validator.model;

import org.entur.netex.validation.exception.NetexValidationException;
import java.util.Objects;
import javax.annotation.Nullable;
import org.rutebanken.netex.model.AllVehicleModesOfTransportEnumeration;
import org.rutebanken.netex.model.StopPlace;
import org.rutebanken.netex.model.TransportSubmodeStructure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A pair of mode and sub-mode.
Expand All @@ -11,43 +15,41 @@ public record TransportModeAndSubMode(
AllVehicleModesOfTransportEnumeration mode,
TransportSubMode subMode
) {
public static TransportModeAndSubMode of(StopPlace stopPlace) {
return new TransportModeAndSubMode(
stopPlace.getTransportMode(),
TransportSubMode.of(stopPlace).orElse(null)
);
private static final Logger LOGGER = LoggerFactory.getLogger(
TransportModeAndSubMode.class
);

public TransportModeAndSubMode {
Objects.requireNonNull(mode, "Transport mode cannot be null");
Objects.requireNonNull(mode, "Transport submode cannot be null");
}

@Override
public String toString() {
return (
(mode != null ? mode.value() : "") +
(subMode != null ? "§" + subMode.name() : "")
);
@Nullable
public static TransportModeAndSubMode of(StopPlace stopPlace) {
AllVehicleModesOfTransportEnumeration transportMode =
stopPlace.getTransportMode();
if (transportMode == null) {
return null;
}
return TransportSubMode
.of(stopPlace)
.map(submode -> new TransportModeAndSubMode(transportMode, submode))
.orElse(null);
}

public static TransportModeAndSubMode fromString(
String stopPlaceTransportModeAndSubMode
@Nullable
public static TransportModeAndSubMode of(
AllVehicleModesOfTransportEnumeration transportMode,
TransportSubmodeStructure submodeStructure
) {
if (stopPlaceTransportModeAndSubMode != null) {
String[] split = stopPlaceTransportModeAndSubMode.split("§");
if (split.length == 1) {
return new TransportModeAndSubMode(
AllVehicleModesOfTransportEnumeration.fromValue(split[0]),
null
);
} else if (split.length == 2) {
return new TransportModeAndSubMode(
AllVehicleModesOfTransportEnumeration.fromValue(split[0]),
new TransportSubMode(split[1])
);
} else {
throw new NetexValidationException(
"Invalid stopPlaceTransportModeAndSubMode string: " +
stopPlaceTransportModeAndSubMode
);
}
if (transportMode == null) {
return null;
}
return null;
return TransportSubMode
.of(transportMode, submodeStructure)
.map(submode -> new TransportModeAndSubMode(transportMode, submode))
.orElse(
new TransportModeAndSubMode(transportMode, TransportSubMode.MISSING)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
import java.util.Objects;
import java.util.Optional;
import org.entur.netex.validation.exception.NetexValidationException;
import org.rutebanken.netex.model.AllVehicleModesOfTransportEnumeration;
import org.rutebanken.netex.model.StopPlace;
import org.rutebanken.netex.model.TransportSubmodeStructure;

/**
* A NeTEx transport sub-mode.
*/
public record TransportSubMode(String name) {
public static final TransportSubMode MISSING = new TransportSubMode("");

public TransportSubMode {
Objects.requireNonNull(name, "Invalid transport sub mode " + name);
Objects.requireNonNull(name, "Transport submode cannot be null");
}

public static Optional<TransportSubMode> of(StopPlace stopPlace) {
Expand Down Expand Up @@ -58,4 +62,55 @@ public static Optional<TransportSubMode> of(StopPlace stopPlace) {
subModeName == null ? null : new TransportSubMode(subModeName)
);
}

public static Optional<TransportSubMode> of(
AllVehicleModesOfTransportEnumeration transportMode,
TransportSubmodeStructure subModeStructure
) {
if (transportMode == null || subModeStructure == null) {
return Optional.empty();
}
String subModeName =
switch (transportMode) {
case AIR -> subModeStructure.getAirSubmode() == null
? null
: subModeStructure.getAirSubmode().value();
case BUS -> subModeStructure.getBusSubmode() == null
? null
: subModeStructure.getBusSubmode().value();
case COACH -> subModeStructure.getCoachSubmode() == null
? null
: subModeStructure.getCoachSubmode().value();
case METRO -> subModeStructure.getMetroSubmode() == null
? null
: subModeStructure.getMetroSubmode().value();
case RAIL -> subModeStructure.getRailSubmode() == null
? null
: subModeStructure.getRailSubmode().value();
case TAXI -> subModeStructure.getTaxiSubmode() == null
? null
: subModeStructure.getTaxiSubmode().value();
case TRAM -> subModeStructure.getTramSubmode() == null
? null
: subModeStructure.getTramSubmode().value();
case WATER -> subModeStructure.getWaterSubmode() == null
? null
: subModeStructure.getWaterSubmode().value();
case CABLEWAY -> subModeStructure.getTelecabinSubmode() == null
? null
: subModeStructure.getTelecabinSubmode().value();
case FUNICULAR -> subModeStructure.getFunicularSubmode() == null
? null
: subModeStructure.getFunicularSubmode().value();
case SNOW_AND_ICE -> subModeStructure.getSnowAndIceSubmode() == null
? null
: subModeStructure.getSnowAndIceSubmode().value();
default -> null;
};

if (subModeName == null) {
return Optional.empty();
}
return Optional.of(new TransportSubMode(subModeName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -422,12 +422,10 @@ protected ValidationTree getServiceFrameValidationTreeForLineFile(
);

serviceFrameValidationTree.addValidationRule(
new ValidatedAllowedTransportMode(
ValidatedAllowedTransportMode.DEFAULT_VALID_TRANSPORT_MODES
)
new ValidateAllowedTransportModeOnLine()
);
serviceFrameValidationTree.addValidationRule(
new ValidatedAllowedTransportSubMode()
new ValidateAllowedTransportSubModeOnLine()
);

serviceFrameValidationTree.addValidationRule(
Expand Down Expand Up @@ -628,6 +626,14 @@ protected ValidationTree getTimetableFrameValidationTree(String path) {
"SERVICE_JOURNEY_2"
)
);

validationTree.addValidationRule(
new ValidateAllowedTransportModeOnServiceJourney()
);
validationTree.addValidationRule(
new ValidateAllowedTransportSubModeOnServiceJourney()
);

validationTree.addValidationRule(
new ValidateNotExist(
"vehicleJourneys/ServiceJourney[not(passingTimes)]",
Expand Down
Loading

0 comments on commit 34d4f3a

Please sign in to comment.