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

Nav 131 extend query config for raptor #100

Merged
merged 52 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c58f215
ENH: NAV-131 - Add more information requirements to ScheduleInformati…
clukas1 Aug 16, 2024
74c6a1b
REFACTOR: NAV-131 - Remove the time type dto enum and use service enu…
clukas1 Aug 16, 2024
e228bb0
ENH: NAV-131 - Add TravelMode Enum.
clukas1 Aug 16, 2024
445c59d
ENH: NAV-131 - Extend ConnectionQueryConfig with more query options.
clukas1 Aug 16, 2024
e00cf6e
ENH: NAV-131 - Include extended query options to routing controller.
clukas1 Aug 16, 2024
55f22b3
TEST: NAV-131 - Refactor routing controller test to use more parametr…
clukas1 Aug 16, 2024
0c3a60c
TEST: NAV-131 - Add tests for new query config parameter values in ro…
clukas1 Aug 16, 2024
f7ad46a
ENH: NAV-131 - Add router info endpoint.
clukas1 Aug 16, 2024
3f50d95
TEST: NAV-131 - Add test for router info endpoint.
clukas1 Aug 16, 2024
ee3418f
ENH: NAV-131 - Add TravelMode Enum on Raptor level.
clukas1 Aug 17, 2024
3d6cb0e
ENH: NAV-131 - Extend service mappers for service/raptor travelmodes …
clukas1 Aug 17, 2024
b41af84
ENH: NAV-131 - Extend raptor query config with more options.
clukas1 Aug 17, 2024
3f2e13e
ENH: NAV-131 - Pass QueryConfig to TripMaskProvider and allow caching…
clukas1 Aug 17, 2024
6d3a353
FIX: NAV-131 - Add default query config when preparing stop time arra…
clukas1 Aug 17, 2024
d65a4fe
FIX: NAV-131 - Handle cases correctly where travelmodes are null or e…
clukas1 Aug 17, 2024
216098f
ENH: NAV-131 - Add trip masking based on gtfs schedule and query config.
clukas1 Aug 17, 2024
8d9a3ae
FIX: NAV-131 - Define GTFS Service accessibility information with trips.
clukas1 Aug 17, 2024
d63c0b6
FIX: NAV-131 - Get route through trip instead (sub)route id in gtfs m…
clukas1 Aug 17, 2024
8f16328
TEST: NAV-131 - Add tests for GtfsTripMaskProvider.
clukas1 Aug 18, 2024
ae802f2
STYLE: NAV-131 - Format project and cosmetics
munterfi Aug 19, 2024
9da1a5a
ENH: NAV-131 - Add schedule validity to schedule info endpoint and re…
clukas1 Aug 21, 2024
bfb5e98
Merge remote-tracking branch 'origin/NAV-131-Extend-QueryConfig-for-R…
clukas1 Aug 21, 2024
06cbd7c
ENH: NAV-131 - Add getters to scheduleValidity.
clukas1 Aug 21, 2024
50bcbab
TEST: NAV-131 - Move schedule info test to scheduleControllerTest
clukas1 Aug 21, 2024
71b7779
ENH: NAV-131 - Reintroduce TimeType enum on DTO level to keep separat…
clukas1 Aug 21, 2024
d7c1475
DOC: NAV-131 - Better explain when travel mode masking has to be done.
clukas1 Aug 21, 2024
99962b7
REFACTOR: NAV-131 - Flatten getCacheKEyForStopTimes.
clukas1 Aug 21, 2024
dd7190b
ENH: NAV-131 - Make service use explicit implementation of raptor alg…
clukas1 Aug 22, 2024
90dc629
REFACTOR: NAV-131 - Remove prepareStopTimesForDate from RaptorAlgorit…
clukas1 Aug 22, 2024
688d4f8
REFACTOR: NAV-131 - Move logic whether travel mode filtering is neede…
clukas1 Aug 22, 2024
f4523c3
ENH: NAV-131 - Add validation of query configs before creating trip m…
clukas1 Aug 22, 2024
1e64db3
ENH: NAV-131 - Add SupportedRoutingFeatures.
clukas1 Aug 22, 2024
674107f
ENH: NAV-131 - Implement get supported routing features.
clukas1 Aug 22, 2024
8ec5d2d
REFACTOR: NAV-131 - Rename info booleans in schedule info.
clukas1 Aug 22, 2024
cf71146
ENH: NAV-131 - Add API endpoint for RoutingInfo
clukas1 Aug 22, 2024
ee20632
REFACTOR: NAV-131 - Ensure Router Info variables are consistently named.
clukas1 Aug 22, 2024
99976df
ENH: NAV-131 - Extend Routing Controller test.
clukas1 Aug 22, 2024
10c58c6
REFACTROR: NAV-131 - Remove accessors(fluent=true) in DTOs (does not …
clukas1 Aug 22, 2024
9e97b4f
ENH: NAV-131 - Add better validation based on routing capabilities in…
clukas1 Aug 22, 2024
19c55ee
TEST: NAV-141 - Add test case for routing request when target and sou…
clukas1 Aug 22, 2024
9f4bd0d
ENH: NAV-141 - Include check if source and target coordinates are ide…
clukas1 Aug 22, 2024
3302503
TEST: NAV-141 - Fix failing test because test case had same source an…
clukas1 Aug 22, 2024
4770d29
TEST: NAV-131 - Update expected error messages in tests
clukas1 Aug 22, 2024
748a531
TEST: NAV-131 - Add appropriate default values for routing features i…
clukas1 Aug 22, 2024
84c0614
FIX: NAV-131 - Fix logical error in checking if travel mode routing i…
clukas1 Aug 22, 2024
8db6d76
ENH: NAV-131 - Add TravelMode Enum as DTO.
clukas1 Aug 22, 2024
c98b1d0
ENH: NAV-148 - Add TravelMode to Route DTO in App and Accessibility a…
clukas1 Aug 22, 2024
5bcbf52
STYLE: NAV-131 - Format project
munterfi Aug 23, 2024
c693bd8
STYLE: NAV-131 - Remove "/" from schedule and routing info endpoints
munterfi Aug 23, 2024
b398ce1
STYLE: NAV-131 - Add assert to prevent IDE complaining.
clukas1 Aug 23, 2024
a51784b
REFACTOR: NAV-131 - Renamce SupportedRoutingFeatures to RoutingFeatures.
clukas1 Aug 23, 2024
4cbfc5b
STYLE: NAV-131 - Format
munterfi Aug 23, 2024
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
55 changes: 37 additions & 18 deletions src/main/java/ch/naviqore/app/controller/RoutingController.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package ch.naviqore.app.controller;

import ch.naviqore.app.dto.Connection;
import ch.naviqore.app.dto.RouterInfo;
import ch.naviqore.app.dto.StopConnection;
import ch.naviqore.app.dto.TimeType;
import ch.naviqore.service.PublicTransitService;
import ch.naviqore.service.ScheduleInformationService;
import ch.naviqore.service.Stop;
import ch.naviqore.service.*;
import ch.naviqore.service.config.ConnectionQueryConfig;
import ch.naviqore.service.exception.ConnectionRoutingException;
import ch.naviqore.utils.spatial.GeoCoordinate;
Expand All @@ -25,6 +23,7 @@
import org.springframework.web.server.ResponseStatusException;

import java.time.LocalDateTime;
import java.util.EnumSet;
import java.util.List;

import static ch.naviqore.app.dto.DtoMapper.map;
Expand All @@ -47,6 +46,14 @@ private static void handleConnectionRoutingException(ConnectionRoutingException
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
}

@Operation(summary = "Get information about the routing service", description = "Get information about the routing service, such as supported features.")
@ApiResponse(responseCode = "200", description = "A list of features supported or not supported by the routing service.")
@GetMapping("/")
public RouterInfo getRouterInfo() {
return new RouterInfo(service.hasAccessibilityInformation(), service.hasBikeInformation(),
service.hasTravelModeInformation());
}

@Operation(summary = "Request connections between two stops or locations", description = "Requests connections between two stops or locations at a given departure / arrival datetime.")
@ApiResponse(responseCode = "200", description = "A list of connections between the specified stops.")
@ApiResponse(responseCode = "400", description = "Invalid input parameters", content = @Content(schema = @Schema()))
Expand All @@ -63,8 +70,10 @@ public List<Connection> getConnections(@RequestParam(required = false) String so
@RequestParam(required = false) Integer maxWalkingDuration,
@RequestParam(required = false) Integer maxTransferNumber,
@RequestParam(required = false) Integer maxTravelTime,
@RequestParam(required = false, defaultValue = "0") int minTransferTime) {

@RequestParam(required = false, defaultValue = "0") int minTransferTime,
@RequestParam(required = false, defaultValue = "false") boolean wheelchairAccessible,
@RequestParam(required = false, defaultValue = "false") boolean bikeAllowed,
@RequestParam(required = false) EnumSet<TravelMode> travelModes) {
// get coordinates if available
GeoCoordinate sourceCoordinate = Utils.getCoordinateIfAvailable(sourceStopId, sourceLatitude, sourceLongitude,
GlobalValidator.StopType.SOURCE);
Expand All @@ -78,19 +87,19 @@ public List<Connection> getConnections(@RequestParam(required = false) String so
// configure routing request
dateTime = GlobalValidator.validateAndSetDefaultDateTime(dateTime, service);
ConnectionQueryConfig config = Utils.createConfig(maxWalkingDuration, maxTransferNumber, maxTravelTime,
minTransferTime);
minTransferTime, wheelchairAccessible, bikeAllowed, travelModes, service);

// determine routing case and get connections
try {
if (sourceStop != null && targetStop != null) {
RoutingRequestValidator.validateStops(sourceStopId, targetStopId);
return map(service.getConnections(sourceStop, targetStop, dateTime, map(timeType), config));
return map(service.getConnections(sourceStop, targetStop, dateTime, timeType, config));
} else if (sourceStop != null) {
return map(service.getConnections(sourceStop, targetCoordinate, dateTime, map(timeType), config));
return map(service.getConnections(sourceStop, targetCoordinate, dateTime, timeType, config));
} else if (targetStop != null) {
return map(service.getConnections(sourceCoordinate, targetStop, dateTime, map(timeType), config));
return map(service.getConnections(sourceCoordinate, targetStop, dateTime, timeType, config));
} else {
return map(service.getConnections(sourceCoordinate, targetCoordinate, dateTime, map(timeType), config));
return map(service.getConnections(sourceCoordinate, targetCoordinate, dateTime, timeType, config));
}
} catch (ConnectionRoutingException e) {
handleConnectionRoutingException(e);
Expand All @@ -112,6 +121,9 @@ public List<StopConnection> getIsolines(@RequestParam(required = false) String s
@RequestParam(required = false) Integer maxTransferNumber,
@RequestParam(required = false) Integer maxTravelTime,
@RequestParam(required = false, defaultValue = "0") int minTransferTime,
@RequestParam(required = false, defaultValue = "false") boolean wheelchairAccessible,
@RequestParam(required = false, defaultValue = "false") boolean bikeAllowed,
@RequestParam(required = false) EnumSet<TravelMode> travelModes,
@RequestParam(required = false, defaultValue = "false") boolean returnConnections) {

// get stops or coordinates if available
Expand All @@ -122,15 +134,14 @@ public List<StopConnection> getIsolines(@RequestParam(required = false) String s
// configure routing request
dateTime = GlobalValidator.validateAndSetDefaultDateTime(dateTime, service);
ConnectionQueryConfig config = Utils.createConfig(maxWalkingDuration, maxTransferNumber, maxTravelTime,
minTransferTime);
minTransferTime, wheelchairAccessible, bikeAllowed, travelModes, service);

// determine routing case and get isolines
try {
if (sourceStop != null) {
return map(service.getIsoLines(sourceStop, dateTime, map(timeType), config), timeType,
returnConnections);
return map(service.getIsoLines(sourceStop, dateTime, timeType, config), timeType, returnConnections);
} else {
return map(service.getIsoLines(sourceCoordinate, dateTime, map(timeType), config), timeType,
return map(service.getIsoLines(sourceCoordinate, dateTime, timeType, config), timeType,
returnConnections);
}
} catch (ConnectionRoutingException e) {
Expand All @@ -156,17 +167,25 @@ private static class Utils {

private static ConnectionQueryConfig createConfig(@Nullable Integer maxWalkingDuration,
@Nullable Integer maxTransferNumber,
@Nullable Integer maxTravelTime, int minTransferTime) {
@Nullable Integer maxTravelTime, int minTransferTime,
boolean wheelchairAccessible, boolean bikeAllowed,
@Nullable EnumSet<TravelMode> travelModes,
PublicTransitService service) {

// replace null values with integer max value
maxWalkingDuration = setToMaxIfNull(maxWalkingDuration);
maxTransferNumber = setToMaxIfNull(maxTransferNumber);
maxTravelTime = setToMaxIfNull(maxTravelTime);

if (travelModes == null || travelModes.isEmpty()) {
travelModes = EnumSet.allOf(TravelMode.class);
}

// validate and create config
RoutingRequestValidator.validateQueryParams(maxWalkingDuration, maxTransferNumber, maxTravelTime,
minTransferTime);
return new ConnectionQueryConfig(maxWalkingDuration, minTransferTime, maxTransferNumber, maxTravelTime);
minTransferTime, wheelchairAccessible, bikeAllowed, travelModes, service);
return new ConnectionQueryConfig(maxWalkingDuration, minTransferTime, maxTransferNumber, maxTravelTime,
wheelchairAccessible, bikeAllowed, travelModes);
}

private static int setToMaxIfNull(Integer value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package ch.naviqore.app.controller;

import ch.naviqore.service.PublicTransitService;
import ch.naviqore.service.TravelMode;
import ch.naviqore.utils.spatial.GeoCoordinate;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.Nullable;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

import java.util.EnumSet;

@NoArgsConstructor(access = AccessLevel.NONE)
final class RoutingRequestValidator {

Expand All @@ -20,7 +24,8 @@ public static GeoCoordinate validateCoordinate(double latitude, double longitude
}

public static void validateQueryParams(int maxWalkingDuration, int maxTransferNumber, int maxTravelTime,
int minTransferTime) {
int minTransferTime, boolean wheelchairAccessible, boolean bikeAllowed,
EnumSet<TravelMode> travelModes, PublicTransitService service) {
if (maxWalkingDuration < 0) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Max walking duration must be greater than or equal to 0.");
Expand All @@ -36,6 +41,22 @@ public static void validateQueryParams(int maxWalkingDuration, int maxTransferNu
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Min transfer time must be greater than or equal to 0.");
}

// If the service does not support accessibility information, bike information, or travel mode information,
// only default values are allowed (i.e., false for wheelchairAccessible, false for bikeAllowed,
// and all travel modes).
if (wheelchairAccessible && !service.hasAccessibilityInformation()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Accessibility information is not available for this service.");
}
if (bikeAllowed && !service.hasBikeInformation()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Bike information is not available for this service.");
}
if (!travelModes.containsAll(EnumSet.allOf(TravelMode.class)) && !service.hasTravelModeInformation()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Service does not support travel mode information.");
}
}

public static void validateStopParameters(@Nullable String stopId, @Nullable Double latitude,
Expand Down
10 changes: 1 addition & 9 deletions src/main/java/ch/naviqore/app/dto/DtoMapper.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ch.naviqore.app.dto;

import ch.naviqore.service.SearchType;
import ch.naviqore.service.TimeType;
import ch.naviqore.service.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -50,13 +49,6 @@ public static SearchType map(ch.naviqore.app.dto.SearchType searchType) {
};
}

public static TimeType map(ch.naviqore.app.dto.TimeType timeType) {
return switch (timeType) {
case DEPARTURE -> TimeType.DEPARTURE;
case ARRIVAL -> TimeType.ARRIVAL;
};
}

public static Connection map(ch.naviqore.service.Connection connection) {
List<Leg> legs = connection.getLegs().stream().map(leg -> leg.accept(new LegVisitorImpl())).toList();
return new Connection(legs);
Expand All @@ -67,7 +59,7 @@ public static List<Connection> map(List<ch.naviqore.service.Connection> connecti
}

public static List<StopConnection> map(Map<ch.naviqore.service.Stop, ch.naviqore.service.Connection> connections,
ch.naviqore.app.dto.TimeType timeType, boolean returnConnections) {
TimeType timeType, boolean returnConnections) {
List<StopConnection> arrivals = new ArrayList<>();
for (Map.Entry<ch.naviqore.service.Stop, ch.naviqore.service.Connection> entry : connections.entrySet()) {
arrivals.add(new StopConnection(entry.getKey(), entry.getValue(), timeType, returnConnections));
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/ch/naviqore/app/dto/RouterInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ch.naviqore.app.dto;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@RequiredArgsConstructor
@ToString
@Getter
public class RouterInfo {
clukas1 marked this conversation as resolved.
Show resolved Hide resolved
final boolean supportsAccessibility;
final boolean supportsBikes;
final boolean supportsTravelModes;
clukas1 marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions src/main/java/ch/naviqore/app/dto/StopConnection.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.naviqore.app.dto;

import ch.naviqore.service.TimeType;
import lombok.*;

import java.time.LocalDateTime;
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/ch/naviqore/app/dto/TimeType.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ public Validity getValidity() {
return delegate.getValidity();
}

@Override
public boolean hasAccessibilityInformation() {
return delegate.hasAccessibilityInformation();
}

@Override
public boolean hasBikeInformation() {
return delegate.hasBikeInformation();
}

@Override
public boolean hasTravelModeInformation() {
return delegate.hasTravelModeInformation();
}

@Override
public List<Stop> getStops(String like, SearchType searchType) {
return delegate.getStops(like, searchType);
Expand Down
16 changes: 15 additions & 1 deletion src/main/java/ch/naviqore/raptor/QueryConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.EnumSet;

/**
* Configuration to query connections or iso-lines. Default values are set to infinity or zero, which means that no
Expand All @@ -18,12 +21,23 @@ public class QueryConfig {
private int maximumTransferNumber = INFINITY;
private int maximumTravelTime = INFINITY;

@Setter
private boolean wheelchairAccessible = false;
@Setter
private boolean bikeAccessible = false;
@Setter
private EnumSet<TravelMode> allowedTravelModes = EnumSet.allOf(TravelMode.class);

public QueryConfig(int maximumWalkingDuration, int minimumTransferDuration, int maximumTransferNumber,
int maximumTravelTime) {
int maximumTravelTime, boolean wheelchairAccessible, boolean bikeAccessible,
EnumSet<TravelMode> allowedTravelModes) {
this.setMaximumWalkingDuration(maximumWalkingDuration);
this.setMinimumTransferDuration(minimumTransferDuration);
this.setMaximumTransferNumber(maximumTransferNumber);
this.setMaximumTravelTime(maximumTravelTime);
this.setWheelchairAccessible(wheelchairAccessible);
this.setBikeAccessible(bikeAccessible);
this.setAllowedTravelModes(allowedTravelModes);
}

public void setMaximumWalkingDuration(int maximumWalkingDuration) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/ch/naviqore/raptor/TravelMode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ch.naviqore.raptor;

public enum TravelMode {
BUS,
TRAM,
RAIL,
SHIP,
SUBWAY,
AERIAL_LIFT,
FUNICULAR,
}
2 changes: 1 addition & 1 deletion src/main/java/ch/naviqore/raptor/router/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Query {
// set up footpath relaxer and route scanner and inject stop labels and times
footpathRelaxer = new FootpathRelaxer(queryState, raptorData, config.getMinimumTransferDuration(),
config.getMaximumWalkingDuration(), timeType);
routeScanner = new RouteScanner(queryState, raptorData, config.getMinimumTransferDuration(), timeType,
routeScanner = new RouteScanner(queryState, raptorData, config, timeType,
referenceDate, raptorConfig.getDaysToScan());
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/ch/naviqore/raptor/router/RaptorConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.naviqore.raptor.router;

import ch.naviqore.raptor.QueryConfig;
import ch.naviqore.utils.cache.EvictionCache;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -80,7 +81,7 @@ public String getServiceIdForDate(LocalDate date) {
}

@Override
public DayTripMask getDayTripMask(LocalDate date) {
public DayTripMask getDayTripMask(LocalDate date, QueryConfig queryConfig) {
Map<String, RouteTripMask> tripMasks = new HashMap<>();
for (Map.Entry<String, String[]> entry : tripIds.entrySet()) {
String routeId = entry.getKey();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ch/naviqore/raptor/router/RaptorRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class RaptorRouter implements RaptorAlgorithm, RaptorData {

@Override
public void prepareStopTimesForDate(LocalDate date) {
stopTimeProvider.getStopTimesForDate(date);
stopTimeProvider.getStopTimesForDate(date, new QueryConfig());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ch.naviqore.raptor.router;

import ch.naviqore.raptor.QueryConfig;

import java.time.LocalDate;
import java.util.Map;

Expand Down Expand Up @@ -32,14 +34,15 @@ public interface RaptorTripMaskProvider {
String getServiceIdForDate(LocalDate date);

/**
* Get the trip mask for a given date.
* Get the trip mask for a given date and query config.
* <p>
* This method should return a map of route ids to trip masks for the given date.
* This method should return a map of route ids to trip masks for the given date and query config.
munterfi marked this conversation as resolved.
Show resolved Hide resolved
*
* @param date the date for which the trip mask should be returned.
* @param date the date for which the trip mask should be returned.
* @param queryConfig the query config for which the trip mask should be returned.
* @return the raptor day mask of the day.
*/
DayTripMask getDayTripMask(LocalDate date);
DayTripMask getDayTripMask(LocalDate date, QueryConfig queryConfig);

/**
* This represents a service day trip mask for a given day.
Expand Down
Loading