Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -184,24 +184,19 @@ private static List<TripPatternForDate> filterActiveTripPatterns(
// and any previous day, while on subsequent search days we only want to add the
// TripPatternForDate objects that start on that particular day. This is to prevent duplicates.
// This was previously a stream, but was unrolled for improved performance.

Predicate<TripTimes> tripTimesWithSubmodesPredicate = tripTimes ->
filter.tripTimesPredicate(tripTimes, filter.hasSubModeFilters());
Predicate<TripTimes> tripTimesWithoutSubmodesPredicate = tripTimes ->
filter.tripTimesPredicate(tripTimes, false);
Collection<TripPatternForDate> tripPatternsForDate =
raptorTransitData.getTripPatternsForRunningDate(date);

List<TripPatternForDate> result = new ArrayList<>(tripPatternsForDate.size());
for (TripPatternForDate p : tripPatternsForDate) {
if (firstDay || p.getStartOfRunningPeriod().equals(date)) {
if (filter.tripPatternPredicate(p)) {
var tripTimesPredicate = p.getTripPattern().getPattern().getContainsMultipleModes()
? tripTimesWithSubmodesPredicate
: tripTimesWithoutSubmodesPredicate;
TripPatternForDate tripPatternForDate = p.newWithFilteredTripTimes(tripTimesPredicate);
if (tripPatternForDate != null) {
result.add(tripPatternForDate);
}
var tripTimesFilter = filter.getTripFilter(p.getTripPattern().getPattern());
if (tripTimesFilter == null) {
continue;
}
TripPatternForDate tripPatternForDate = p.newWithFilteredTripTimes(tripTimesFilter);
if (tripPatternForDate != null) {
result.add(tripPatternForDate);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import java.util.BitSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import org.opentripplanner.model.PickDrop;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TripPatternForDate;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.routing.api.request.preference.WheelchairPreferences;
Expand All @@ -14,6 +15,7 @@
import org.opentripplanner.transit.model.network.BikeAccess;
import org.opentripplanner.transit.model.network.CarAccess;
import org.opentripplanner.transit.model.network.RoutingTripPattern;
import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.timetable.Trip;
import org.opentripplanner.transit.model.timetable.TripTimes;

Expand Down Expand Up @@ -76,11 +78,6 @@ public RouteRequestTransitDataProviderFilter(
this.hasSubModeFilters = filters.stream().anyMatch(TransitFilter::isSubModePredicate);
}

@Override
public boolean hasSubModeFilters() {
return hasSubModeFilters;
}

public static BikeAccess bikeAccessForTrip(Trip trip) {
if (trip.getBikesAllowed() != BikeAccess.UNKNOWN) {
return trip.getBikesAllowed();
Expand All @@ -90,17 +87,18 @@ public static BikeAccess bikeAccessForTrip(Trip trip) {
}

@Override
public boolean tripPatternPredicate(TripPatternForDate tripPatternForDate) {
@Nullable
public Predicate<TripTimes> getTripFilter(TripPattern tripPattern) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming this to createTripFilter

for (TransitFilter filter : filters) {
if (filter.matchTripPattern(tripPatternForDate.getTripPattern().getPattern())) {
return true;
if (filter.matchTripPattern(tripPattern)) {
var withFilters = hasSubModeFilters && tripPattern.getContainsMultipleModes();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withFilters should probably have a better name. What about applyTripTimesFilters ? This apply to the tripTimesPredicate method argument as well.

return tripTimes -> this.tripTimesPredicate(tripTimes, withFilters);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return tripTimes -> this.tripTimesPredicate(tripTimes, withFilters);
return tripTimes ->tripTimesPredicate(tripTimes, withFilters);

Avoid using this. unless it is needed.

}
}
return false;
return null;
}

@Override
public boolean tripTimesPredicate(TripTimes tripTimes, boolean withFilters) {
private boolean tripTimesPredicate(TripTimes tripTimes, boolean withFilters) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming: withFilters see above

final Trip trip = tripTimes.getTrip();

if (requireBikesAllowed && bikeAccessForTrip(trip) != BikeAccess.ALLOWED) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
package org.opentripplanner.routing.algorithm.raptoradapter.transit.request;

import java.util.BitSet;
import java.util.Optional;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.RaptorTransitData;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TripPatternForDate;
import org.opentripplanner.transit.model.network.RoutingTripPattern;
import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.timetable.TripTimes;

/**
* Used to filter the elements in a {@link RaptorTransitData}
* when constructing a {@link RaptorRoutingRequestTransitData} for a request.
* <p>
* {@link TripPatternForDate} and {@link TripTimes} are filtered based on the request parameters to
* only included components which are allowed by the request. Such filters may included bike or
* only included components which are allowed by the request. Such filters may include bike or
* wheelchair accessibility, banned routes and transit modes.
*
* @see RouteRequestTransitDataProviderFilter
*/
public interface TransitDataProviderFilter {
boolean tripPatternPredicate(TripPatternForDate tripPatternForDate);

boolean hasSubModeFilters();

boolean tripTimesPredicate(TripTimes tripTimes, boolean withFilters);
/**
* For performance reasons filtering is done in a two-step process. First you apply the pattern. If it doesn't match you
* get a null value. If it does match you get a Predicate&lt;TripTimes&gt; that you use to match a TripTimes
* object.
*/
@Nullable
Predicate<TripTimes> getTripFilter(TripPattern tripPattern);

/**
* Check if boarding/alighting is possible at each stop. If the values differ from the default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,37 +38,19 @@ public SelectRequest(Builder builder) {
this.routes = builder.routes;
}

public boolean matches(TripPattern tripPattern) {
if (
// If the pattern contains multiple modes, we will do the filtering in
// SelectRequest.matches(TripTimes)
!tripPattern.getContainsMultipleModes() &&
this.transportModeFilter != null &&
!this.transportModeFilter.match(tripPattern.getMode(), tripPattern.getNetexSubmode())
) {
return false;
}

if (!agencies.isEmpty() && !agencies.contains(tripPattern.getRoute().getAgency().getId())) {
return false;
}

if (!routes.isEmpty() && !routes.contains(tripPattern.getRoute().getId())) {
return false;
}

if (!groupOfRoutes.isEmpty()) {
var ids = new ArrayList<FeedScopedId>();
for (var gor : tripPattern.getRoute().getGroupsOfRoutes()) {
ids.add(gor.getId());
}

if (Collections.disjoint(groupOfRoutes, ids)) {
return false;
}
}
/**
* Will return false if the pattern doesn't match the filter and true if it matches or needs to
* look at the Trip level to be sure decide.
*/
public boolean matchesPatternSelect(TripPattern tripPattern) {
return matchesPattern(tripPattern, true);
}

return true;
/**
* Will return true if the pattern matches the filter and false if it doesn't match or might not match.
*/
public boolean matchesPatternNot(TripPattern tripPattern) {
return matchesPattern(tripPattern, false);
}

/**
Expand Down Expand Up @@ -119,6 +101,40 @@ public List<FeedScopedId> routes() {
return routes;
}

private boolean matchesPattern(TripPattern tripPattern, boolean maybeValue) {
if (!agencies.isEmpty() && !agencies.contains(tripPattern.getRoute().getAgency().getId())) {
return false;
}

if (!routes.isEmpty() && !routes.contains(tripPattern.getRoute().getId())) {
return false;
}

if (!groupOfRoutes.isEmpty()) {
var ids = new ArrayList<FeedScopedId>();
for (var gor : tripPattern.getRoute().getGroupsOfRoutes()) {
ids.add(gor.getId());
}

if (Collections.disjoint(groupOfRoutes, ids)) {
return false;
}
}

if (this.transportModeFilter != null) {
// If the pattern contains multiple modes, we will do the filtering in
// SelectRequest.matches(TripTimes)
if (tripPattern.getContainsMultipleModes()) {
return maybeValue;
}
if (!this.transportModeFilter.match(tripPattern.getMode(), tripPattern.getNetexSubmode())) {
return false;
}
}

return true;
}

private String transportModesToString() {
if (transportModes == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public boolean matchTripPattern(TripPattern tripPattern) {
if (select.length != 0) {
var anyMatch = false;
for (SelectRequest s : select) {
if (s.matches(tripPattern)) {
if (s.matchesPatternSelect(tripPattern)) {
anyMatch = true;
break;
}
Expand All @@ -77,7 +77,7 @@ public boolean matchTripPattern(TripPattern tripPattern) {
}

for (SelectRequest s : not) {
if (s.matches(tripPattern)) {
if (s.matchesPatternNot(tripPattern)) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.opentripplanner._support.time.ZoneIds;
import org.opentripplanner.model.StopTime;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TripPatternForDate;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.transit.model._data.TimetableRepositoryForTest;
import org.opentripplanner.transit.model.basic.TransitMode;
import org.opentripplanner.transit.model.framework.FeedScopedId;
Expand Down Expand Up @@ -61,12 +62,14 @@ public void testMergeTripPatterns() {
tripPatternsForDates.add(new TripPatternForDate(tripPattern1, tripTimes, List.of(), third));
tripPatternsForDates.add(new TripPatternForDate(tripPattern3, tripTimes, List.of(), third));

var noOpFilter = new RouteRequestTransitDataProviderFilter(RouteRequest.defaultValue());

// Patterns containing trip schedules for all 3 days. Trip schedules for later days are offset
// in time when requested.
List<TripPatternForDates> combinedTripPatterns = RaptorRoutingRequestTransitDataCreator.merge(
startOfTime,
tripPatternsForDates,
new TestTransitDataProviderFilter(),
noOpFilter,
TransitGroupPriorityService.empty()
);

Expand Down Expand Up @@ -123,34 +126,4 @@ private static RoutingTripPattern createTripPattern(FeedScopedId id) {
.build()
.getRoutingTripPattern();
}

/**
* Utility class that does nothing, used just to avoid null value on filter
*/
private static class TestTransitDataProviderFilter implements TransitDataProviderFilter {

@Override
public boolean tripPatternPredicate(TripPatternForDate tripPatternForDate) {
return false;
}

@Override
public boolean tripTimesPredicate(TripTimes tripTimes, boolean withFilters) {
return false;
}

@Override
public boolean hasSubModeFilters() {
return false;
}

@Override
public BitSet filterAvailableStops(
RoutingTripPattern tripPattern,
BitSet boardingPossible,
BoardAlight boardAlight
) {
return boardingPossible;
}
}
}
Loading
Loading