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

Add NonIncreasingTimeValidator and MismatchedTransportModeValidator #267

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
16 changes: 15 additions & 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>9.0.2-SNAPSHOT</version>
<version>10.0.0-SNAPSHOT</version>

<name>netex-validator-java</name>
<description>Library for validating NeTEx datasets against the Nordic NeTEx Profile.</description>
Expand Down Expand Up @@ -64,6 +64,7 @@
<zt-zip.version>1.17</zt-zip.version>
<junit.version>5.11.3</junit.version>
<mockito-core.version>5.14.2</mockito-core.version>
<hamcrest.version>2.2</hamcrest.version>
<logback-classic.version>1.5.12</logback-classic.version>

<maven-exec-plugin.version>1.6.0</maven-exec-plugin.version>
Expand Down Expand Up @@ -102,6 +103,7 @@
<!-- GPG configuration for jar signing-->
<gpg.executable>gpg</gpg.executable>
<gpg.keyname>${env.GPG_KEY_NAME}</gpg.keyname>

</properties>

<dependencies>
Expand Down Expand Up @@ -154,6 +156,12 @@
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>3.0.0</version>
</dependency>

<!-- testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand All @@ -179,6 +187,12 @@
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.zeroturnaround</groupId>
<artifactId>zt-zip</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.entur.netex.validation.validator.jaxb;

import jakarta.annotation.Nullable;
import java.util.*;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.entur.netex.index.api.NetexEntitiesIndex;
import org.entur.netex.validation.validator.DataLocation;
import org.entur.netex.validation.validator.ValidationContext;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.entur.netex.validation.validator.jaxb;

import javax.annotation.Nullable;
import jakarta.annotation.Nullable;
import org.entur.netex.index.api.NetexEntitiesIndex;
import org.entur.netex.validation.validator.model.QuayCoordinates;
import org.entur.netex.validation.validator.model.QuayId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

package org.entur.netex.validation.validator.jaxb;

import javax.annotation.Nullable;
import jakarta.annotation.Nullable;
import org.entur.netex.validation.validator.model.QuayCoordinates;
import org.entur.netex.validation.validator.model.QuayId;
import org.entur.netex.validation.validator.model.StopPlaceId;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.entur.netex.validation.validator.jaxb.model.stoptime;

import java.math.BigInteger;
import java.time.LocalTime;
import org.entur.netex.validation.validator.model.ScheduledStopPointId;
import org.rutebanken.netex.model.TimetabledPassingTime;

/**
* Wrapper around {@link TimetabledPassingTime} that provides a simpler interface for passing times
* comparison. Passing times are exposed as seconds since midnight, taking into account the day
* offset.
* <p>
* This class does not take Daylight Saving Time transitions into account, this is an error and
* should be fixed. See https://github.com/opentripplanner/OpenTripPlanner/issues/5109
*/
abstract sealed class AbstractStopTime
implements StopTime
permits FlexibleStopTime, RegularStopTime {

private final ScheduledStopPointId scheduledStopPointId;
private final TimetabledPassingTime timetabledPassingTime;

protected AbstractStopTime(
ScheduledStopPointId scheduledStopPointId,
TimetabledPassingTime timetabledPassingTime
) {
this.scheduledStopPointId = scheduledStopPointId;
this.timetabledPassingTime = timetabledPassingTime;
}

@Override
public ScheduledStopPointId scheduledStopPointId() {
return scheduledStopPointId;
}

protected LocalTime arrivalTime() {
return timetabledPassingTime.getArrivalTime();
}

protected BigInteger arrivalDayOffset() {
return timetabledPassingTime.getArrivalDayOffset();
}

protected LocalTime latestArrivalTime() {
return timetabledPassingTime.getLatestArrivalTime();
}

protected BigInteger latestArrivalDayOffset() {
return timetabledPassingTime.getLatestArrivalDayOffset();
}

protected LocalTime departureTime() {
return timetabledPassingTime.getDepartureTime();
}

protected BigInteger departureDayOffset() {
return timetabledPassingTime.getDepartureDayOffset();
}

protected LocalTime earliestDepartureTime() {
return timetabledPassingTime.getEarliestDepartureTime();
}

protected BigInteger earliestDepartureDayOffset() {
return timetabledPassingTime.getEarliestDepartureDayOffset();
}

protected boolean isRegularStopFollowedByAreaStopValid(
FlexibleStopTime next
) {
return (
normalizedDepartureTimeOrElseArrivalTime() <=
next.normalizedEarliestDepartureTime()
);
}

protected boolean isAreaStopFollowedByRegularStopValid(RegularStopTime next) {
return (
normalizedLatestArrivalTime() <=
next.normalizedArrivalTimeOrElseDepartureTime()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.entur.netex.validation.validator.jaxb.model.stoptime;

import org.entur.netex.validation.validator.model.ScheduledStopPointId;
import org.rutebanken.netex.model.TimetabledPassingTime;

/**
* Wrapper around {@link TimetabledPassingTime} that provides a simpler interface
* for passing times comparison.
* Passing times are exposed as seconds since midnight, taking into account the day offset.
*/
final class FlexibleStopTime extends AbstractStopTime {

FlexibleStopTime(
ScheduledStopPointId scheduledStopPointId,
TimetabledPassingTime timetabledPassingTime
) {
super(scheduledStopPointId, timetabledPassingTime);
}

@Override
public boolean isComplete() {
return hasLatestArrivalTime() && hasEarliestDepartureTime();
}

@Override
public boolean isConsistent() {
return (
!isComplete() ||
normalizedLatestArrivalTime() >= normalizedEarliestDepartureTime()
);
}

@Override
public boolean isStopTimesIncreasing(StopTime next) {
if (next instanceof RegularStopTime regularStopTime) {
return isAreaStopFollowedByRegularStopValid(regularStopTime);
}
return isAreaStopFollowedByAreaStopValid((FlexibleStopTime) next);
}

@Override
public int getStopTimeDiff(StopTime given) {
// TODO: This should be fixed. We need to take into account the type of given.
// Is it the same type as this, or not. See how we have done in
// isRegularStopFollowedByRegularStopValid, isAreaStopFollowedByAreaStopValid,
// isRegularStopFollowedByAreaStopValid, isAreaStopFollowedByRegularStopValid

if (given instanceof FlexibleStopTime) {
return isComplete()
? normalizedEarliestDepartureTime() - normalizedLatestArrivalTime()
: 0;
}
return (
given.normalizedEarliestDepartureTime() -
normalizedArrivalTimeOrElseDepartureTime()
);
}

@Override
public int normalizedEarliestDepartureTime() {
return elapsedTimeSinceMidnight(
earliestDepartureTime(),
earliestDepartureDayOffset()
);
}

@Override
public int normalizedLatestArrivalTime() {
return elapsedTimeSinceMidnight(
latestArrivalTime(),
latestArrivalDayOffset()
);
}

@Override
public int normalizedDepartureTimeOrElseArrivalTime() {
throw new UnsupportedOperationException();
}

@Override
public int normalizedArrivalTimeOrElseDepartureTime() {
throw new UnsupportedOperationException();
}

private boolean hasLatestArrivalTime() {
return latestArrivalTime() != null;
}

private boolean hasEarliestDepartureTime() {
return earliestDepartureTime() != null;
}

private boolean isAreaStopFollowedByAreaStopValid(FlexibleStopTime next) {
int earliestDepartureTime = normalizedEarliestDepartureTime();
int nextEarliestDepartureTime = next.normalizedEarliestDepartureTime();
int latestArrivalTime = normalizedLatestArrivalTime();
int nextLatestArrivalTime = next.normalizedLatestArrivalTime();

return (
earliestDepartureTime <= nextEarliestDepartureTime &&
latestArrivalTime <= nextLatestArrivalTime
);
}

@Override
public boolean isArrivalInMinutesResolution() {
return hasLatestArrivalTime()
? latestArrivalTime().getSecond() == 0
: earliestDepartureTime().getSecond() == 0;
}

@Override
public boolean isDepartureInMinutesResolution() {
return hasEarliestDepartureTime()
? earliestDepartureTime().getSecond() == 0
: latestArrivalTime().getSecond() == 0;
}
}
Loading