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

Refactor transport mode resolution #260

Merged
merged 5 commits into from
Dec 3, 2024
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
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