diff --git a/client-next/.env b/client-next/.env index 003970b4e1f..e8a9667bc23 100644 --- a/client-next/.env +++ b/client-next/.env @@ -1 +1,2 @@ -VITE_API_URL=/otp/routers/default/transmodel/index/graphql \ No newline at end of file +VITE_API_URL=/otp/routers/default/transmodel/index/graphql +VITE_DEBUG_STYLE_URL=/otp/routers/default/inspector/vectortile/style.json diff --git a/client-next/.env.development b/client-next/.env.development index e11b45c4411..b10ac31fdf9 100644 --- a/client-next/.env.development +++ b/client-next/.env.development @@ -1 +1,2 @@ -VITE_API_URL=http://localhost:8080/otp/routers/default/transmodel/index/graphql \ No newline at end of file +VITE_API_URL=http://localhost:8080/otp/routers/default/transmodel/index/graphql +VITE_DEBUG_STYLE_URL=http://localhost:8080/otp/routers/default/inspector/vectortile/style.json \ No newline at end of file diff --git a/client-next/.npmrc b/client-next/.npmrc new file mode 100644 index 00000000000..449691b70fd --- /dev/null +++ b/client-next/.npmrc @@ -0,0 +1 @@ +save-exact=true \ No newline at end of file diff --git a/client-next/package-lock.json b/client-next/package-lock.json index 85a29784489..19909ba109d 100644 --- a/client-next/package-lock.json +++ b/client-next/package-lock.json @@ -8,36 +8,36 @@ "name": "otp-debug-client-next", "version": "0.0.0", "dependencies": { - "@googlemaps/polyline-codec": "^1.0.28", - "bootstrap": "^5.3.1", - "graphql": "^16.8.0", - "graphql-request": "^6.1.0", - "maplibre-gl": "^3.3.0", - "react": "^18.2.0", - "react-bootstrap": "^2.8.0", - "react-dom": "^18.2.0", - "react-map-gl": "^7.1.5" + "@googlemaps/polyline-codec": "1.0.28", + "bootstrap": "5.3.1", + "graphql": "16.8.0", + "graphql-request": "6.1.0", + "maplibre-gl": "3.3.0", + "react": "18.2.0", + "react-bootstrap": "2.8.0", + "react-dom": "18.2.0", + "react-map-gl": "7.1.5" }, "devDependencies": { "@graphql-codegen/cli": "5.0.0", "@graphql-codegen/client-preset": "4.1.0", "@graphql-codegen/introspection": "4.0.0", - "@parcel/watcher": "^2.3.0", - "@types/react": "^18.2.15", - "@types/react-dom": "^18.2.7", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", - "@vitejs/plugin-react": "^4.0.3", - "eslint": "^8.45.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.3", - "prettier": "^3.0.3", - "typescript": "^5.2.2", - "vite": "^4.4.5" + "@parcel/watcher": "2.3.0", + "@types/react": "18.2.21", + "@types/react-dom": "18.2.7", + "@typescript-eslint/eslint-plugin": "6.5.0", + "@typescript-eslint/parser": "6.5.0", + "@vitejs/plugin-react": "4.0.4", + "eslint": "8.48.0", + "eslint-config-prettier": "9.0.0", + "eslint-plugin-import": "2.28.1", + "eslint-plugin-jsx-a11y": "6.7.1", + "eslint-plugin-react": "7.33.2", + "eslint-plugin-react-hooks": "4.6.0", + "eslint-plugin-react-refresh": "0.4.3", + "prettier": "3.0.3", + "typescript": "5.2.2", + "vite": "4.4.9" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/client-next/package.json b/client-next/package.json index 4d453ed37ca..79d2c7942f1 100644 --- a/client-next/package.json +++ b/client-next/package.json @@ -15,35 +15,35 @@ "codegen": "graphql-codegen --config codegen.ts" }, "dependencies": { - "@googlemaps/polyline-codec": "^1.0.28", - "bootstrap": "^5.3.1", - "graphql": "^16.8.0", - "graphql-request": "^6.1.0", - "maplibre-gl": "^3.3.0", - "react": "^18.2.0", - "react-bootstrap": "^2.8.0", - "react-dom": "^18.2.0", - "react-map-gl": "^7.1.5" + "@googlemaps/polyline-codec": "1.0.28", + "bootstrap": "5.3.1", + "graphql": "16.8.0", + "graphql-request": "6.1.0", + "maplibre-gl": "3.3.0", + "react": "18.2.0", + "react-bootstrap": "2.8.0", + "react-dom": "18.2.0", + "react-map-gl": "7.1.5" }, "devDependencies": { "@graphql-codegen/cli": "5.0.0", "@graphql-codegen/client-preset": "4.1.0", "@graphql-codegen/introspection": "4.0.0", - "@parcel/watcher": "^2.3.0", - "@types/react": "^18.2.15", - "@types/react-dom": "^18.2.7", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", - "@vitejs/plugin-react": "^4.0.3", - "eslint": "^8.45.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.3", - "prettier": "^3.0.3", - "typescript": "^5.2.2", - "vite": "^4.4.5" + "@parcel/watcher": "2.3.0", + "@types/react": "18.2.21", + "@types/react-dom": "18.2.7", + "@typescript-eslint/eslint-plugin": "6.5.0", + "@typescript-eslint/parser": "6.5.0", + "@vitejs/plugin-react": "4.0.4", + "eslint": "8.48.0", + "eslint-config-prettier": "9.0.0", + "eslint-plugin-import": "2.28.1", + "eslint-plugin-jsx-a11y": "6.7.1", + "eslint-plugin-react": "7.33.2", + "eslint-plugin-react-hooks": "4.6.0", + "eslint-plugin-react-refresh": "0.4.3", + "prettier": "3.0.3", + "typescript": "5.2.2", + "vite": "4.4.9" } } diff --git a/client-next/src/components/MapView/GeometryPropertyPopup.tsx b/client-next/src/components/MapView/GeometryPropertyPopup.tsx new file mode 100644 index 00000000000..d2b55689270 --- /dev/null +++ b/client-next/src/components/MapView/GeometryPropertyPopup.tsx @@ -0,0 +1,27 @@ +import { LngLat, Popup } from 'react-map-gl'; +import { Table } from 'react-bootstrap'; + +export function GeometryPropertyPopup({ + coordinates, + properties, + onClose, +}: { + coordinates: LngLat; + properties: { [s: string]: string }; + onClose: () => void; +}) { + return ( + onClose()}> + + + {Object.entries(properties).map(([key, value]) => ( + + + + + ))} + +
{key}{value}
+
+ ); +} diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 011d9408148..5b6223a5dee 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -1,12 +1,12 @@ -import { LngLat, Map, NavigationControl } from 'react-map-gl'; +import { LngLat, Map, MapboxGeoJSONFeature, NavigationControl } from 'react-map-gl'; import 'maplibre-gl/dist/maplibre-gl.css'; import { TripPattern, TripQuery, TripQueryVariables } from '../../gql/graphql.ts'; import { NavigationMarkers } from './NavigationMarkers.tsx'; import { LegLines } from './LegLines.tsx'; import { useMapDoubleClick } from './useMapDoubleClick.ts'; -import { mapStyle } from './mapStyle.ts'; import { useState } from 'react'; import { ContextMenuPopup } from './ContextMenuPopup.tsx'; +import { GeometryPropertyPopup } from './GeometryPropertyPopup.tsx'; // TODO: this should be configurable const initialViewState = { @@ -15,6 +15,10 @@ const initialViewState = { zoom: 4, }; +const styleUrl = import.meta.env.VITE_DEBUG_STYLE_URL; + +type PopupData = { coordinates: LngLat; feature: MapboxGeoJSONFeature }; + export function MapView({ tripQueryVariables, setTripQueryVariables, @@ -29,7 +33,21 @@ export function MapView({ loading: boolean; }) { const onMapDoubleClick = useMapDoubleClick({ tripQueryVariables, setTripQueryVariables }); - const [showPopup, setShowPopup] = useState(null); + const [showContextPopup, setShowContextPopup] = useState(null); + const [showPropsPopup, setShowPropsPopup] = useState(null); + const showFeaturePropPopup = ( + e: mapboxgl.MapMouseEvent & { + features?: mapboxgl.MapboxGeoJSONFeature[] | undefined; + }, + ) => { + if (e.features) { + // if you click on a cluster of map features it's possible that there are multiple + // to select from. we are using the first one instead of presenting a selection UI. + // you can always zoom in closer if you want to make a more specific click. + const feature = e.features[0]; + setShowPropsPopup({ coordinates: e.lngLat, feature: feature }); + } + }; return (
@@ -37,12 +55,19 @@ export function MapView({ // @ts-ignore mapLib={import('maplibre-gl')} // @ts-ignore - mapStyle={mapStyle} + mapStyle={styleUrl} initialViewState={initialViewState} onDblClick={onMapDoubleClick} onContextMenu={(e) => { - setShowPopup(e.lngLat); + setShowContextPopup(e.lngLat); }} + interactiveLayerIds={['regular-stop']} + onClick={showFeaturePropPopup} + // put lat/long in URL and pan to it on page reload + hash={true} + // disable pitching and rotating the map + touchPitch={false} + dragRotate={false} > )} - {showPopup && ( + {showContextPopup && ( setShowPopup(null)} + coordinates={showContextPopup} + onClose={() => setShowContextPopup(null)} + /> + )} + {showPropsPopup?.feature?.properties && ( + setShowPropsPopup(null)} /> )} diff --git a/client-next/src/components/MapView/mapStyle.ts b/client-next/src/components/MapView/mapStyle.ts deleted file mode 100644 index ecaa88c0354..00000000000 --- a/client-next/src/components/MapView/mapStyle.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const mapStyle = { - version: 8, - sources: { - osm: { - type: 'raster', - tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'], - tileSize: 256, - attribution: '© OpenStreetMap Contributors', - maxzoom: 19, - }, - }, - layers: [ - { - id: 'osm', - type: 'raster', - source: 'osm', // This must match the source key above - }, - ], -}; diff --git a/doc-templates/UpdaterConfig.md b/doc-templates/UpdaterConfig.md index 90c699fcf28..57152671ec7 100644 --- a/doc-templates/UpdaterConfig.md +++ b/doc-templates/UpdaterConfig.md @@ -8,8 +8,8 @@ # Updater configuration -This section covers all options that can be set in the *router-config.json* in the -[updaters](RouterConfiguration.md) section. +This section covers options that can be set in the updaters section of `router-config.json`. +See the parameter summary and examples in the router configuration documentation Real-time data are those that are not added to OTP during the graph build phase but during runtime. @@ -44,18 +44,15 @@ The information is downloaded in a single HTTP request and polled regularly. +### Streaming TripUpdates via MQTT -### TripUpdates via WebSocket +This updater connects to an MQTT broker and processes TripUpdates in a streaming fashion. This means +that they will be applied individually in near-realtime rather than in batches at a certain interval. -This updater doesn't poll a data source but opens a persistent connection to the GTFS-RT provider, -which then sends incremental updates immediately as they become available. - -The [OneBusAway GTFS-realtime exporter project](https://github.com/OneBusAway/onebusaway-gtfs-realtime-exporter) -provides this kind of streaming, incremental updates over a websocket rather than a single large -file. - - +This system powers the realtime updates in Helsinki and more information can be found +[on Github](https://github.com/HSLdevcom/transitdata). + ### Vehicle Positions diff --git a/docs/Changelog.md b/docs/Changelog.md index 9f755bd8f8f..50846c3fce7 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -70,6 +70,10 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Consider escalator edges in island pruning [#5591](https://github.com/opentripplanner/OpenTripPlanner/pull/5591) - Create own rental preferences for bike and car in the internal model [#5562](https://github.com/opentripplanner/OpenTripPlanner/pull/5562) - Adding situation-version to TransmodelGraphQL API [#5592](https://github.com/opentripplanner/OpenTripPlanner/pull/5592) +- Move REST API into sandbox [#5580](https://github.com/opentripplanner/OpenTripPlanner/pull/5580) +- Fix high walk reluctance leading to zero egress results for rental searches [#5605](https://github.com/opentripplanner/OpenTripPlanner/pull/5605) +- Remove GTFS-RT websocket updater [#5604](https://github.com/opentripplanner/OpenTripPlanner/pull/5604) +- Add stop layer to new Debug UI [#5602](https://github.com/opentripplanner/OpenTripPlanner/pull/5602) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.4.0 (2023-09-13) diff --git a/docs/Configuration.md b/docs/Configuration.md index d4803da0a56..d43ff150926 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -219,38 +219,38 @@ Here is a list of all features which can be toggled on/off and their default val -| Feature | Description | Enabled by default | Sandbox | -|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------:|:-------:| -| `APIBikeRental` | Enable the bike rental endpoint. | ✓️ | | -| `APIServerInfo` | Enable the server info endpoint. | ✓️ | | -| `APIGraphInspectorTile` | Enable the inspector endpoint for graph information for inspection/debugging purpose. | ✓️ | | -| `APIUpdaterStatus` | Enable endpoint for graph updaters status. | ✓️ | | -| `ConsiderPatternsForDirectTransfers` | Enable limiting transfers so that there is only a single transfer to each pattern. | ✓️ | | -| `DebugClient` | Enable the debug web client located at the root of the web server. | ✓️ | | -| `FloatingBike` | Enable floating bike routing. | ✓️ | | -| `GtfsGraphQlApi` | Enable GTFS GraphQL API. | ✓️ | | -| `GtfsGraphQlApiRentalStationFuzzyMatching` | Does vehicleRentalStation query also allow ids that are not feed scoped. | | | -| `MinimumTransferTimeIsDefinitive` | If the minimum transfer time is a lower bound (default) or the definitive time for the transfer. Set this to `true` if you want to set a transfer time lower than what OTP derives from OSM data. | | | -| `OptimizeTransfers` | OTP will inspect all itineraries found and optimize where (which stops) the transfer will happen. Waiting time, priority and guaranteed transfers are taken into account. | ✓️ | | -| `ParallelRouting` | Enable performing parts of the trip planning in parallel. | | | -| `TransferConstraints` | Enforce transfers to happen according to the _transfers.txt_ (GTFS) and Interchanges (NeTEx). Turning this _off_ will increase the routing performance a little. | ✓️ | | -| `TransmodelGraphQlApi` | Enable Transmodel (NeTEx) GraphQL API. | ✓️ | ✓️ | -| `ActuatorAPI` | Endpoint for actuators (service health status). | | ✓️ | -| `AsyncGraphQLFetchers` | Whether the @async annotation in the GraphQL schema should lead to the fetch being executed asynchronously. This allows batch or alias queries to run in parallel at the cost of consuming extra threads. | | | -| `Co2Emissions` | Enable the emissions sandbox module. | | ✓️ | -| `DataOverlay` | Enable usage of data overlay when calculating costs for the street network. | | ✓️ | -| `FaresV2` | Enable import of GTFS-Fares v2 data. | | ✓️ | -| `FlexRouting` | Enable FLEX routing. | | ✓️ | -| `GoogleCloudStorage` | Enable Google Cloud Storage integration. | | ✓️ | -| `RealtimeResolver` | When routing with ignoreRealtimeUpdates=true, add an extra step which populates results with real-time data | | ✓️ | -| `ReportApi` | Enable the report API. | | ✓️ | -| `RestAPIPassInDefaultConfigAsJson` | Enable a default RouteRequest to be passed in as JSON on the REST API - FOR DEBUGGING ONLY! | | | -| `SandboxAPIGeocoder` | Enable the Geocoder API. | | ✓️ | -| `SandboxAPIMapboxVectorTilesApi` | Enable Mapbox vector tiles API. | | ✓️ | -| `SandboxAPIParkAndRideApi` | Enable park-and-ride endpoint. | | ✓️ | -| `SandboxAPITravelTime` | Enable the isochrone/travel time surface API. | | ✓️ | -| `TransferAnalyzer` | Analyze transfers during graph build. | | ✓️ | -| `VehicleToStopHeuristics` | Enable improved heuristic for park-and-ride queries. | | ✓️ | +| Feature | Description | Enabled by default | Sandbox | +|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------:|:-------:| +| `APIBikeRental` | Enable the bike rental endpoint. | ✓️ | | +| `APIServerInfo` | Enable the server info endpoint. | ✓️ | | +| `APIUpdaterStatus` | Enable endpoint for graph updaters status. | ✓️ | | +| `ConsiderPatternsForDirectTransfers` | Enable limiting transfers so that there is only a single transfer to each pattern. | ✓️ | | +| `DebugUi` | Enable the debug GraphQL client and web UI and located at the root of the web server as well as the debug map tiles it uses. Be aware that the map tiles are not a stable API and can change without notice. Use the [vector tiles feature if](sandbox/MapboxVectorTilesApi.md) you want a stable map tiles API. | ✓️ | | +| `FloatingBike` | Enable floating bike routing. | ✓️ | | +| `GtfsGraphQlApi` | Enable the [GTFS GraphQL API](apis/GTFS-GraphQL-API.md). | ✓️ | | +| `GtfsGraphQlApiRentalStationFuzzyMatching` | Does vehicleRentalStation query also allow ids that are not feed scoped. | | | +| `MinimumTransferTimeIsDefinitive` | If the minimum transfer time is a lower bound (default) or the definitive time for the transfer. Set this to `true` if you want to set a transfer time lower than what OTP derives from OSM data. | | | +| `OptimizeTransfers` | OTP will inspect all itineraries found and optimize where (which stops) the transfer will happen. Waiting time, priority and guaranteed transfers are taken into account. | ✓️ | | +| `ParallelRouting` | Enable performing parts of the trip planning in parallel. | | | +| `TransferConstraints` | Enforce transfers to happen according to the _transfers.txt_ (GTFS) and Interchanges (NeTEx). Turning this _off_ will increase the routing performance a little. | ✓️ | | +| `TransmodelGraphQlApi` | Enable the [Transmodel (NeTEx) GraphQL API](apis/TransmodelApi.md). | ✓️ | ✓️ | +| `ActuatorAPI` | Endpoint for actuators (service health status). | | ✓️ | +| `AsyncGraphQLFetchers` | Whether the @async annotation in the GraphQL schema should lead to the fetch being executed asynchronously. This allows batch or alias queries to run in parallel at the cost of consuming extra threads. | | | +| `Co2Emissions` | Enable the emissions sandbox module. | | ✓️ | +| `DataOverlay` | Enable usage of data overlay when calculating costs for the street network. | | ✓️ | +| `FaresV2` | Enable import of GTFS-Fares v2 data. | | ✓️ | +| `FlexRouting` | Enable FLEX routing. | | ✓️ | +| `GoogleCloudStorage` | Enable Google Cloud Storage integration. | | ✓️ | +| `LegacyRestApi` | Enable legacy REST API. This API will be removed in the future. | ✓️ | ✓️ | +| `RealtimeResolver` | When routing with ignoreRealtimeUpdates=true, add an extra step which populates results with real-time data | | ✓️ | +| `ReportApi` | Enable the report API. | | ✓️ | +| `RestAPIPassInDefaultConfigAsJson` | Enable a default RouteRequest to be passed in as JSON on the REST API - FOR DEBUGGING ONLY! | | | +| `SandboxAPIGeocoder` | Enable the Geocoder API. | | ✓️ | +| `SandboxAPIMapboxVectorTilesApi` | Enable Mapbox vector tiles API. | | ✓️ | +| `SandboxAPIParkAndRideApi` | Enable park-and-ride endpoint. | | ✓️ | +| `SandboxAPITravelTime` | Enable the isochrone/travel time surface API. | | ✓️ | +| `TransferAnalyzer` | Analyze transfers during graph build. | | ✓️ | +| `VehicleToStopHeuristics` | Enable improved heuristic for park-and-ride queries. | | ✓️ | diff --git a/docs/Developers-Guide.md b/docs/Developers-Guide.md index e12d9cf6c1b..8a68f83f301 100644 --- a/docs/Developers-Guide.md +++ b/docs/Developers-Guide.md @@ -63,8 +63,8 @@ There are several ways to get involved: * Create pull requests citing the relevant issue. -* Join developer meetings hosted twice a week. Check the specific times - on [this calendar](https://calendar.google.com/calendar/u/0/embed?src=ormbltvsqb6adl80ejgudt0glc@group.calendar.google.com) +* Join developer meetings hosted twice a week. Check the specific times and URLs + on [this page](https://github.com/opentripplanner/OpenTripPlanner/blob/dev-2.x/CONTRIBUTING.md#developer-meetings) ### Branches and Branch Protection diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index 9e891cf732d..cef482eb781 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -57,7 +57,7 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe | numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | | [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | | [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | -| [relaxTransitPriorityGroup](#rd_relaxTransitPriorityGroup) | `string` | The relax function for transit-priority-groups | *Optional* | `"0s + 1.00 t"` | 2.5 | +| [relaxTransitGroupPriority](#rd_relaxTransitGroupPriority) | `string` | The relax function for transit-group-priority | *Optional* | `"0s + 1.00 t"` | 2.5 | | [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | | [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | | stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | @@ -108,7 +108,7 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe |    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | |    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | |    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | -| [transitPriorityGroups](#rd_transitPriorityGroups) | `object` | Transit priority groups configuration | *Optional* | | 2.5 | +| [transitGroupPriority](#rd_transitGroupPriority) | `object` | Group transit patterns and give each group a mutual advantage in the Raptor search. | *Optional* | | 2.5 | | [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | | [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | |    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | @@ -247,16 +247,16 @@ Penalty added for using every route that is not preferred if user set any route We return number of seconds that we are willing to wait for preferred route. -

relaxTransitPriorityGroup

+

relaxTransitGroupPriority

**Since version:** `2.5` ∙ **Type:** `string` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"0s + 1.00 t"` **Path:** /routingDefaults -The relax function for transit-priority-groups +The relax function for transit-group-priority -A path is considered optimal if the generalized-cost is less than the -generalized-cost of another path. If this parameter is set, the comparison is relaxed -further if they belong to different transit-priority-groups. +A path is considered optimal if the generalized-cost is less than the generalized-cost of +another path. If this parameter is set, the comparison is relaxed further if they belong +to different transit groups.

relaxTransitSearchGeneralizedCostAtDestination

@@ -812,22 +812,20 @@ This enables the transfer wait time optimization. If not enabled generalizedCost function is used to pick the optimal transfer point. -

transitPriorityGroups

+

transitGroupPriority

**Since version:** `2.5` ∙ **Type:** `object` ∙ **Cardinality:** `Optional` **Path:** /routingDefaults -Transit priority groups configuration +Group transit patterns and give each group a mutual advantage in the Raptor search. Use this to separate transit patterns into groups. Each group will be given a group-id. A path (multiple legs) will then have a set of group-ids based on the group-id from each leg. Hence, two paths with a different set of group-ids will BOTH be optimal unless the cost is -worse than the relaxation specified in the `relaxTransitPriorityGroup` parameter. This is +worse than the relaxation specified in the `relaxTransitGroupPriority` parameter. This is only available in the TransmodelAPI for now. -Unmatched patterns are put in the BASE priority-group (group id: 0). This group is special. -If a path only have legs in the base group, then that path dominates other paths, but other -paths must be better to make it. +Unmatched patterns are put in the BASE priority-group. **THIS IS STILL AN EXPERIMENTAL FEATURE - IT MAY CHANGE WITHOUT ANY NOTICE!** diff --git a/docs/RouterConfiguration.md b/docs/RouterConfiguration.md index 65f50260ee5..5ca87a2aefa 100644 --- a/docs/RouterConfiguration.md +++ b/docs/RouterConfiguration.md @@ -727,6 +727,13 @@ Used to group requests when monitoring OTP. "Authorization" : "A-Token" } }, + { + "type" : "mqtt-gtfs-rt-updater", + "url" : "tcp://pred.rt.hsl.fi", + "topic" : "gtfsrt/v2/fi/hsl/tu", + "feedId" : "HSL", + "fuzzyTripMatching" : true + }, { "type" : "vehicle-positions", "url" : "https://s3.amazonaws.com/kcm-alerts-realtime-prod/vehiclepositions.pb", @@ -740,10 +747,6 @@ Used to group requests when monitoring OTP. "position" ] }, - { - "type" : "websocket-gtfs-rt-updater", - "feedId" : "ov" - }, { "type" : "siri-et-updater", "url" : "https://example.com/some/path", diff --git a/docs/UpdaterConfig.md b/docs/UpdaterConfig.md index 6b744794642..a819a898240 100644 --- a/docs/UpdaterConfig.md +++ b/docs/UpdaterConfig.md @@ -8,8 +8,8 @@ # Updater configuration -This section covers all options that can be set in the *router-config.json* in the -[updaters](RouterConfiguration.md) section. +This section covers options that can be set in the updaters section of `router-config.json`. +See the parameter summary and examples in the router configuration documentation Real-time data are those that are not added to OTP during the graph build phase but during runtime. @@ -164,37 +164,51 @@ HTTP headers to add to the request. Any header key, value can be inserted. +### Streaming TripUpdates via MQTT -### TripUpdates via WebSocket +This updater connects to an MQTT broker and processes TripUpdates in a streaming fashion. This means +that they will be applied individually in near-realtime rather than in batches at a certain interval. -This updater doesn't poll a data source but opens a persistent connection to the GTFS-RT provider, -which then sends incremental updates immediately as they become available. +This system powers the realtime updates in Helsinki and more information can be found +[on Github](https://github.com/HSLdevcom/transitdata). -The [OneBusAway GTFS-realtime exporter project](https://github.com/OneBusAway/onebusaway-gtfs-realtime-exporter) -provides this kind of streaming, incremental updates over a websocket rather than a single large -file. - - + -| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | -|-----------------------------------------------------------------------|:---------:|--------------------------|:----------:|----------------------|:-----:| -| type = "websocket-gtfs-rt-updater" | `enum` | The type of the updater. | *Required* | | 1.5 | -| [backwardsDelayPropagationType](#u__7__backwardsDelayPropagationType) | `enum` | TODO | *Optional* | `"required-no-data"` | 1.5 | -| feedId | `string` | TODO | *Required* | | 1.5 | -| reconnectPeriodSec | `integer` | TODO | *Optional* | `60` | 1.5 | -| url | `string` | TODO | *Optional* | | 1.5 | +| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | +|-----------------------------------------------------------------------|:---------:|----------------------------------------------|:----------:|----------------------|:-----:| +| type = "mqtt-gtfs-rt-updater" | `enum` | The type of the updater. | *Required* | | 1.5 | +| [backwardsDelayPropagationType](#u__6__backwardsDelayPropagationType) | `enum` | How backwards propagation should be handled. | *Optional* | `"required-no-data"` | 2.2 | +| feedId | `string` | The feed id to apply the updates to. | *Required* | | 2.0 | +| fuzzyTripMatching | `boolean` | Whether to match trips fuzzily. | *Optional* | `false` | 2.0 | +| qos | `integer` | QOS level. | *Optional* | `0` | 2.0 | +| topic | `string` | The topic to subscribe to. | *Required* | | 2.0 | +| url | `string` | URL of the MQTT broker. | *Required* | | 2.0 | ##### Parameter details -

backwardsDelayPropagationType

+

backwardsDelayPropagationType

-**Since version:** `1.5` ∙ **Type:** `enum` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"required-no-data"` -**Path:** /updaters/[7] +**Since version:** `2.2` ∙ **Type:** `enum` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"required-no-data"` +**Path:** /updaters/[6] **Enum values:** `required-no-data` | `required` | `always` -TODO +How backwards propagation should be handled. + + REQUIRED_NO_DATA: + Default value. Only propagates delays backwards when it is required to ensure that the times + are increasing, and it sets the NO_DATA flag on the stops so these automatically updated times + are not exposed through APIs. + + REQUIRED: + Only propagates delays backwards when it is required to ensure that the times are increasing. + The updated times are exposed through APIs. + + ALWAYS: + Propagates delays backwards on stops with no estimates regardless if it's required or not. + The updated times are exposed through APIs. + @@ -205,15 +219,17 @@ TODO { "updaters" : [ { - "type" : "websocket-gtfs-rt-updater", - "feedId" : "ov" + "type" : "mqtt-gtfs-rt-updater", + "url" : "tcp://pred.rt.hsl.fi", + "topic" : "gtfsrt/v2/fi/hsl/tu", + "feedId" : "HSL", + "fuzzyTripMatching" : true } ] } ``` - - + ### Vehicle Positions @@ -231,24 +247,24 @@ The information is downloaded in a single HTTP request and polled regularly. | frequency | `duration` | How often the positions should be updated. | *Optional* | `"PT1M"` | 2.2 | | fuzzyTripMatching | `boolean` | Whether to match trips fuzzily. | *Optional* | `false` | 2.5 | | url | `uri` | The URL of GTFS-RT protobuf HTTP resource to download the positions from. | *Required* | | 2.2 | -| [features](#u__6__features) | `enum set` | Which features of GTFS RT vehicle positions should be loaded into OTP. | *Optional* | | 2.5 | -| [headers](#u__6__headers) | `map of string` | HTTP headers to add to the request. Any header key, value can be inserted. | *Optional* | | 2.3 | +| [features](#u__7__features) | `enum set` | Which features of GTFS RT vehicle positions should be loaded into OTP. | *Optional* | | 2.5 | +| [headers](#u__7__headers) | `map of string` | HTTP headers to add to the request. Any header key, value can be inserted. | *Optional* | | 2.3 | ##### Parameter details -

features

+

features

**Since version:** `2.5` ∙ **Type:** `enum set` ∙ **Cardinality:** `Optional` -**Path:** /updaters/[6] +**Path:** /updaters/[7] **Enum values:** `position` | `stop-position` | `occupancy` Which features of GTFS RT vehicle positions should be loaded into OTP. -

headers

+

headers

**Since version:** `2.3` ∙ **Type:** `map of string` ∙ **Cardinality:** `Optional` -**Path:** /updaters/[6] +**Path:** /updaters/[7] HTTP headers to add to the request. Any header key, value can be inserted. diff --git a/pom.xml b/pom.xml index d2fd4a0515c..e5f86fe5b66 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ - 135 + 136 30.1 2.50 @@ -282,7 +282,6 @@ --add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens java.base/jdk.internal.ref=ALL-UNNAMED --add-opens java.base/jdk.internal.util=ALL-UNNAMED - --add-opens java.base/jdk.internal.util.jar=ALL-UNNAMED --add-opens java.base/jdk.internal.module=ALL-UNNAMED --add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-opens java.base/sun.net.www.protocol.jar=ALL-UNNAMED @@ -551,20 +550,6 @@ import - - - io.netty - netty-bom - 4.1.100.Final - pom - import - - @@ -728,7 +713,7 @@ org.mockito mockito-core - 5.8.0 + 5.9.0 test @@ -842,13 +827,6 @@ protobuf-java - - - - org.asynchttpclient - async-http-client - 2.12.3 - org.onebusaway diff --git a/src/client/debug-client-preview/index.html b/src/client/debug-client-preview/index.html index dfb4915efcc..5f77418dbe6 100644 --- a/src/client/debug-client-preview/index.html +++ b/src/client/debug-client-preview/index.html @@ -5,8 +5,8 @@ OTP Debug Client - - + +
diff --git a/src/test/java/org/opentripplanner/api/mapping/EnumMapperTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/mapping/EnumMapperTest.java similarity index 91% rename from src/test/java/org/opentripplanner/api/mapping/EnumMapperTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/mapping/EnumMapperTest.java index 184e6b7e6d7..35cc368fec4 100644 --- a/src/test/java/org/opentripplanner/api/mapping/EnumMapperTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/mapping/EnumMapperTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -8,9 +8,9 @@ import java.util.Map; import java.util.function.Function; import org.junit.jupiter.api.Test; -import org.opentripplanner.api.model.ApiAbsoluteDirection; -import org.opentripplanner.api.model.ApiRelativeDirection; -import org.opentripplanner.api.model.ApiVertexType; +import org.opentripplanner.ext.restapi.model.ApiAbsoluteDirection; +import org.opentripplanner.ext.restapi.model.ApiRelativeDirection; +import org.opentripplanner.ext.restapi.model.ApiVertexType; import org.opentripplanner.model.plan.AbsoluteDirection; import org.opentripplanner.model.plan.RelativeDirection; import org.opentripplanner.model.plan.VertexType; diff --git a/src/test/java/org/opentripplanner/api/mapping/FareMapperTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/mapping/FareMapperTest.java similarity index 95% rename from src/test/java/org/opentripplanner/api/mapping/FareMapperTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/mapping/FareMapperTest.java index 44fb360efd2..bd1bd07aa43 100644 --- a/src/test/java/org/opentripplanner/api/mapping/FareMapperTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/mapping/FareMapperTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.opentripplanner.model.plan.TestItineraryBuilder.newItinerary; diff --git a/src/test/java/org/opentripplanner/api/model/ApiApiTravelOptionsMakerTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/model/ApiTravelOptionsMakerTest.java similarity index 98% rename from src/test/java/org/opentripplanner/api/model/ApiApiTravelOptionsMakerTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/model/ApiTravelOptionsMakerTest.java index 9429151a422..fdcd0a7fe20 100644 --- a/src/test/java/org/opentripplanner/api/model/ApiApiTravelOptionsMakerTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/model/ApiTravelOptionsMakerTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -11,7 +11,7 @@ /** * Created by mabu on 28.7.2015. */ -public class ApiApiTravelOptionsMakerTest { +public class ApiTravelOptionsMakerTest { @Test public void testMakeOptions() throws Exception { diff --git a/src/test/java/org/opentripplanner/api/model/ApiWalkStepTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/model/ApiWalkStepTest.java similarity index 93% rename from src/test/java/org/opentripplanner/api/model/ApiWalkStepTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/model/ApiWalkStepTest.java index 44be1348eee..7f6909bfc2c 100644 --- a/src/test/java/org/opentripplanner/api/model/ApiWalkStepTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/model/ApiWalkStepTest.java @@ -1,8 +1,7 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/opentripplanner/api/parameter/ApiRequestModeTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/parameter/ApiRequestModeTest.java similarity index 75% rename from src/test/java/org/opentripplanner/api/parameter/ApiRequestModeTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/parameter/ApiRequestModeTest.java index caf26510b2a..29cd6b5715c 100644 --- a/src/test/java/org/opentripplanner/api/parameter/ApiRequestModeTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/parameter/ApiRequestModeTest.java @@ -1,10 +1,11 @@ -package org.opentripplanner.api.parameter; +package org.opentripplanner.ext.restapi.parameter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.opentripplanner.transit.model.basic.TransitMode.CARPOOL; import java.util.List; import org.junit.jupiter.api.Test; +import org.opentripplanner.api.parameter.ApiRequestMode; class ApiRequestModeTest { diff --git a/src/test/java/org/opentripplanner/api/parameter/QualifiedModeSetTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/parameter/QualifiedModeSetTest.java similarity index 97% rename from src/test/java/org/opentripplanner/api/parameter/QualifiedModeSetTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/parameter/QualifiedModeSetTest.java index ba5a39abe89..ad344713a74 100644 --- a/src/test/java/org/opentripplanner/api/parameter/QualifiedModeSetTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/parameter/QualifiedModeSetTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.parameter; +package org.opentripplanner.ext.restapi.parameter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -26,6 +26,8 @@ import jakarta.ws.rs.BadRequestException; import java.util.Set; import org.junit.jupiter.api.Test; +import org.opentripplanner.api.parameter.QualifiedMode; +import org.opentripplanner.api.parameter.QualifiedModeSet; import org.opentripplanner.routing.api.request.RequestModes; import org.opentripplanner.transit.model.basic.TransitMode; diff --git a/src/test/java/org/opentripplanner/api/parameter/QualifiedModeTest.java b/src/ext-test/java/org/opentripplanner/ext/restapi/parameter/QualifiedModeTest.java similarity index 82% rename from src/test/java/org/opentripplanner/api/parameter/QualifiedModeTest.java rename to src/ext-test/java/org/opentripplanner/ext/restapi/parameter/QualifiedModeTest.java index e4c4c9448fc..3a682ba40c9 100644 --- a/src/test/java/org/opentripplanner/api/parameter/QualifiedModeTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/restapi/parameter/QualifiedModeTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.parameter; +package org.opentripplanner.ext.restapi.parameter; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -6,6 +6,9 @@ import java.util.Set; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; +import org.opentripplanner.api.parameter.ApiRequestMode; +import org.opentripplanner.api.parameter.QualifiedMode; +import org.opentripplanner.api.parameter.Qualifier; public class QualifiedModeTest { diff --git a/src/ext/java/org/opentripplanner/ext/geocoder/GeocoderResource.java b/src/ext/java/org/opentripplanner/ext/geocoder/GeocoderResource.java index d2eafc91e5c..39ed6da297c 100644 --- a/src/ext/java/org/opentripplanner/ext/geocoder/GeocoderResource.java +++ b/src/ext/java/org/opentripplanner/ext/geocoder/GeocoderResource.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -import org.opentripplanner.api.mapping.FeedScopedIdMapper; +import org.opentripplanner.ext.restapi.mapping.FeedScopedIdMapper; import org.opentripplanner.standalone.api.OtpServerRequestContext; import org.opentripplanner.transit.model.site.StopLocation; diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/InteractiveOtpMain.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/InteractiveOtpMain.java index 1f9227b3be6..43061ee2b62 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/InteractiveOtpMain.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/InteractiveOtpMain.java @@ -1,19 +1,20 @@ package org.opentripplanner.ext.interactivelauncher; -import static org.opentripplanner.ext.interactivelauncher.DebugLoggingSupport.configureDebugLogging; - -import org.opentripplanner.ext.interactivelauncher.views.MainView; +import org.opentripplanner.ext.interactivelauncher.configuration.InteractiveLauncherModule; +import org.opentripplanner.ext.interactivelauncher.debug.OtpDebugController; +import org.opentripplanner.ext.interactivelauncher.startup.MainView; import org.opentripplanner.standalone.OTPMain; /** - * This class provide a main method to start a GUI which can start OTPMain. + * This class provides a main method to start a GUI which can start OTPMain. *

- * The UI allow the user to select a OTP configuration data set. The list of data location is - * created by searching the a root data source directory. + * The UI allows the user to select the OTP configuration dataset. The list of data locations is + * created by searching the root data source directory. *

- * The user then select what he/she want OTP to do. The settings are stored in the - * .interactive_otp_main.json file in the folder InteractiveOtpMain is started. The - * settings from the last run is loaded next time InteractiveOtpMain is started. + * The user then selects what he/she wants OTP to do. + * The settings are stored in the + * .interactive_otp_main.json file in the folder InteractiveOtpMain is started. + * The settings from the last run are loaded the next time InteractiveOtpMain is started. */ public class InteractiveOtpMain { @@ -25,16 +26,19 @@ public static void main(String[] args) { private void run() { this.model = Model.load(); - MainView frame = new MainView(new Thread(this::startOtp)::start, model); + MainView frame = new MainView(new Thread(this::startOtp)::start, model.getStartupModel()); frame.start(); } private void startOtp() { - model.save(); - - configureDebugLogging(model.getDebugLogging()); + startDebugControllerAndSetupRequestInterceptor(); System.out.println("Start OTP: " + model + "\n"); - OTPMain.main(model.asOtpArgs()); + OTPMain.main(model.getStartupModel().asOtpArgs()); + } + + private void startDebugControllerAndSetupRequestInterceptor() { + new OtpDebugController(model).start(); + InteractiveLauncherModule.setRequestInterceptor(model.getRaptorDebugModel()); } } diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/Model.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/Model.java index ee2dde3e684..59682082b90 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/Model.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/Model.java @@ -1,245 +1,81 @@ package org.opentripplanner.ext.interactivelauncher; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import java.io.File; import java.io.IOException; import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Consumer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opentripplanner.ext.interactivelauncher.debug.logging.LogModel; +import org.opentripplanner.ext.interactivelauncher.debug.raptor.RaptorDebugModel; +import org.opentripplanner.ext.interactivelauncher.startup.StartupModel; public class Model implements Serializable { - private static final Logger LOG = LoggerFactory.getLogger(Model.class); - private static final File MODEL_FILE = new File("interactive_otp_main.json"); - private final Map debugLogging = new HashMap<>(); - - @JsonIgnore - private transient Consumer commandLineChange; + private StartupModel startupModel; + private LogModel logModel; + private RaptorDebugModel raptorDebugModel; - private String rootDirectory = null; - private String dataSource = null; - private boolean buildStreet = false; - private boolean buildTransit = true; - private boolean saveGraph = false; - private boolean serveGraph = true; - private boolean visualizer = false; - - public Model() { - setupListOfDebugLoggers(); - } + public Model() {} public static Model load() { - return MODEL_FILE.exists() ? readFromFile() : new Model(); - } - - public void subscribeCmdLineUpdates(Consumer commandLineChange) { - this.commandLineChange = commandLineChange; - } - - @SuppressWarnings("AccessOfSystemProperties") - public String getRootDirectory() { - return rootDirectory == null ? System.getProperty("user.dir") : rootDirectory; - } - - public void setRootDirectory(String rootDirectory) { - // If the persisted JSON do not contain the rootDirectory, then avoid setting it - if (rootDirectory != null) { - this.rootDirectory = rootDirectory; - } - notifyChangeListener(); - } - - public String getDataSource() { - return dataSource; - } - - public void setDataSource(String dataSource) { - this.dataSource = dataSource; - notifyChangeListener(); - } - - @JsonIgnore - public List getDataSourceOptions() { - List dataSourceOptions = new ArrayList<>(); - File rootDir = new File(getRootDirectory()); - List dirs = SearchForOtpConfig.search(rootDir); - // Add 1 char for the path-separator-character - int length = rootDir.getAbsolutePath().length() + 1; - - for (File dir : dirs) { - var path = dir.getAbsolutePath(); - if (path.length() <= length) { - LOG.warn( - "The root directory contains a config file, choose " + - "the parent directory or delete the config file." - ); - continue; - } - dataSourceOptions.add(path.substring(length)); - } - return dataSourceOptions; - } - - public boolean isBuildStreet() { - return buildStreet; - } - - public void setBuildStreet(boolean buildStreet) { - this.buildStreet = buildStreet; - notifyChangeListener(); - } - - public boolean isBuildTransit() { - return buildTransit; - } - - public void setBuildTransit(boolean buildTransit) { - this.buildTransit = buildTransit; - notifyChangeListener(); - } - - public boolean isSaveGraph() { - return saveGraph; - } - - public void setSaveGraph(boolean saveGraph) { - this.saveGraph = saveGraph; - notifyChangeListener(); - } - - public boolean isServeGraph() { - return serveGraph; - } - - public void setServeGraph(boolean serveGraph) { - this.serveGraph = serveGraph; - notifyChangeListener(); - } - - public boolean isVisualizer() { - return visualizer; + return MODEL_FILE.exists() ? readFromFile() : createNew(); } - public void setVisualizer(boolean visualizer) { - this.visualizer = visualizer; - notifyChangeListener(); + public StartupModel getStartupModel() { + return startupModel; } - public Map getDebugLogging() { - return debugLogging; + public LogModel getLogModel() { + return logModel; } - public void setDebugLogging(Map map) { - for (Entry e : map.entrySet()) { - // Only keep entries that exist in the log config - if (debugLogging.containsKey(e.getKey())) { - debugLogging.put(e.getKey(), e.getValue()); - } - } - } - - @Override - public String toString() { - return ( - "(" + - "data-source-dir: " + - getDataSourceDirectory() + - (buildStreet ? ", buildStreet" : "") + - (buildTransit ? ", buildTransit" : "") + - (saveGraph ? ", saveGraph" : "") + - (serveGraph ? ", serveGraph" : "") + - (visualizer ? ", visualizer" : "") + - ')' - ); - } - - public String toCliString() { - return String.join(" ", asOtpArgs()); - } - - public void save() { - try { - new ObjectMapper().writeValue(MODEL_FILE, this); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @JsonIgnore - String getDataSourceDirectory() { - if (dataSource == null) { - return "DATA_SOURCE_NOT_SET"; - } - return rootDirectory + File.separatorChar + dataSource; + public RaptorDebugModel getRaptorDebugModel() { + return raptorDebugModel; } - String[] asOtpArgs() { - List args = new ArrayList<>(); - - if (buildAll()) { - args.add("--build"); - } else if (buildStreet) { - args.add("--buildStreet"); - } else if (buildTransit) { - args.add("--loadStreet"); - } else { - args.add("--load"); - } - - if (saveGraph && (buildTransit || buildStreet)) { - args.add("--save"); - } - if (serveGraph && !buildStreetOnly()) { - args.add("--serve"); - } - if (serveGraph && !buildStreetOnly() && visualizer) { - args.add("--visualize"); - } - - args.add(getDataSourceDirectory()); - - return args.toArray(new String[0]); + private static Model createNew() { + return new Model().initSubModels(); } private static Model readFromFile() { try { - return new ObjectMapper().readValue(MODEL_FILE, Model.class); + var mapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper.readValue(MODEL_FILE, Model.class).initSubModels(); } catch (IOException e) { System.err.println( "Unable to read the InteractiveOtpMain state cache. If the model changed this " + "is expected, and it will work next time. Cause: " + e.getMessage() ); - return new Model(); + return createNew(); } } - private void notifyChangeListener() { - if (commandLineChange != null) { - commandLineChange.accept(toCliString()); + private void save() { + try { + var mapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true); + mapper.writeValue(MODEL_FILE, this); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); } } - private boolean buildAll() { - return buildStreet && buildTransit; - } - - private boolean buildStreetOnly() { - return buildStreet && !buildTransit; - } - - private void setupListOfDebugLoggers() { - for (String log : DebugLoggingSupport.getLogs()) { - debugLogging.put(log, Boolean.FALSE); + private Model initSubModels() { + if (startupModel == null) { + startupModel = new StartupModel(); + } + if (logModel == null) { + logModel = LogModel.createFromConfig(); + } + if (raptorDebugModel == null) { + raptorDebugModel = new RaptorDebugModel(); } + logModel.init(this::save); + raptorDebugModel.init(this::save); + return this; } } diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/SetupResult.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/SetupResult.java deleted file mode 100644 index a6ecf5e7229..00000000000 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/SetupResult.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.opentripplanner.ext.interactivelauncher; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -public class SetupResult { - - private final File configDataDir; - private final boolean buildStreet; - private final boolean buildTransit; - private final boolean saveGraph; - private final boolean serveGraph; - - public SetupResult( - File configDataDir, - boolean buildStreet, - boolean buildTransit, - boolean saveGraph, - boolean serveGraph - ) { - this.configDataDir = configDataDir; - this.buildStreet = buildStreet; - this.buildTransit = buildTransit; - this.saveGraph = saveGraph; - this.serveGraph = serveGraph; - } - - @Override - public String toString() { - return ( - "SetupResult{" + - "configDataDir=" + - configDataDir.getAbsolutePath() + - (buildStreet ? ", buildStreet" : "") + - (buildTransit ? ", buildTransit" : "") + - (saveGraph ? ", saveGraph" : "") + - (serveGraph ? ", serveGraph" : "") + - '}' - ); - } - - public String toCliString() { - return String.join(" ", asOtpArgs()); - } - - File configDataDir() { - return configDataDir; - } - - boolean buildStreet() { - return buildStreet; - } - - boolean buildTransit() { - return buildTransit; - } - - boolean buildAll() { - return buildStreet && buildTransit; - } - - boolean buildStreetOnly() { - return buildStreet && !buildTransit; - } - - boolean saveGraph() { - return saveGraph; - } - - boolean serveGraph() { - return serveGraph; - } - - String[] asOtpArgs() { - List args = new ArrayList<>(); - - if (buildAll()) { - args.add("--build"); - } else if (buildStreet) { - args.add("--buildStreet"); - } else if (buildTransit) { - args.add("--loadStreet"); - } else { - args.add("--load"); - } - - if (saveGraph && (buildTransit || buildStreet)) { - args.add("--save"); - } - if (serveGraph && !buildStreetOnly()) { - args.add("--serve"); - } - - args.add(configDataDir.getAbsolutePath()); - - return args.toArray(new String[0]); - } -} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/api/LauncherRequestDecorator.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/api/LauncherRequestDecorator.java new file mode 100644 index 00000000000..99c28bad260 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/api/LauncherRequestDecorator.java @@ -0,0 +1,15 @@ +package org.opentripplanner.ext.interactivelauncher.api; + +import org.opentripplanner.routing.api.request.RouteRequest; + +/** + * Allow the interactive launcher intercept planing requests. + */ +public interface LauncherRequestDecorator { + /** + * The launcher may use this method to change the default plan request. Note! It is the DEFAULT + * request witch is passed in here, then the request-specific values are applied on top + * of that. + */ + RouteRequest intercept(RouteRequest defaultRequest); +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/configuration/InteractiveLauncherModule.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/configuration/InteractiveLauncherModule.java new file mode 100644 index 00000000000..9acd0298122 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/configuration/InteractiveLauncherModule.java @@ -0,0 +1,20 @@ +package org.opentripplanner.ext.interactivelauncher.configuration; + +import dagger.Module; +import dagger.Provides; +import org.opentripplanner.ext.interactivelauncher.api.LauncherRequestDecorator; + +@Module +public class InteractiveLauncherModule { + + static LauncherRequestDecorator decorator = request -> request; + + public static void setRequestInterceptor(LauncherRequestDecorator decorator) { + InteractiveLauncherModule.decorator = decorator; + } + + @Provides + LauncherRequestDecorator requestDecorator() { + return decorator; + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/OtpDebugController.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/OtpDebugController.java new file mode 100644 index 00000000000..9e41fe3412d --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/OtpDebugController.java @@ -0,0 +1,37 @@ +package org.opentripplanner.ext.interactivelauncher.debug; + +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.BACKGROUND; + +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import org.opentripplanner.ext.interactivelauncher.Model; +import org.opentripplanner.ext.interactivelauncher.debug.logging.LogView; +import org.opentripplanner.ext.interactivelauncher.debug.raptor.RaptorDebugView; + +/** + * This controller/UI allows changing the debug loggers and setting the raptor + * debug parameters for incoming rute requests. + */ +public class OtpDebugController { + + private final JFrame debugFrame = new JFrame("OTP Debug Controller"); + + public OtpDebugController(Model model) { + debugFrame.add(createTabbedPane(model)); + debugFrame.getContentPane().setBackground(BACKGROUND); + } + + public void start() { + debugFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + debugFrame.pack(); + debugFrame.setLocationRelativeTo(null); + debugFrame.setVisible(true); + } + + private static JTabbedPane createTabbedPane(Model model) { + var tabPanel = new JTabbedPane(); + tabPanel.addTab("Logging", new LogView(model.getLogModel()).panel()); + tabPanel.addTab("Raptor", new RaptorDebugView(model.getRaptorDebugModel()).panel()); + return tabPanel; + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/DebugLoggers.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/DebugLoggers.java new file mode 100644 index 00000000000..48f87abf2ab --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/DebugLoggers.java @@ -0,0 +1,26 @@ +package org.opentripplanner.ext.interactivelauncher.debug.logging; + +import java.util.List; + +class DebugLoggers { + + static List list() { + return List.of( + of("Data import issues", "DATA_IMPORT_ISSUES"), + of("All OTP debuggers", "org.opentripplanner"), + of("OTP request/response", "org.opentripplanner.routing.service.DefaultRoutingService"), + of("Raptor request/response", "org.opentripplanner.raptor.RaptorService"), + of("Transfer Optimization", "org.opentripplanner.routing.algorithm.transferoptimization") + ); + } + + static List listLoggers() { + return list().stream().map(Entry::logger).toList(); + } + + private static Entry of(String label, String logger) { + return new Entry(label, logger); + } + + record Entry(String label, String logger) {} +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/DebugLoggingSupport.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/DebugLoggingSupport.java similarity index 60% rename from src/ext/java/org/opentripplanner/ext/interactivelauncher/DebugLoggingSupport.java rename to src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/DebugLoggingSupport.java index e0b07a8c79e..09eddcfdf78 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/DebugLoggingSupport.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/DebugLoggingSupport.java @@ -1,22 +1,21 @@ -package org.opentripplanner.ext.interactivelauncher; +package org.opentripplanner.ext.interactivelauncher.debug.logging; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.regex.Pattern; import org.slf4j.LoggerFactory; /** - * Responsible for integration with the OTP Debug log configuraton, reading loggers from the slf4j + * Responsible for integration with the OTP Debug log configuration, reading loggers from the slf4j * context and setting DEBUG level on selected loggers back. *

- * The log names are transformed to be more human readable: + * The log names are transformed to be more human-readable: *

org.opentripplanner.routing.algorithm  -->  o.o.routing.algorithm
*/ -public class DebugLoggingSupport { +class DebugLoggingSupport { private static final String OTP = Pattern.quote("org.opentripplanner.") + ".*"; private static final String GRAPHQL = Pattern.quote("fea"); @@ -26,29 +25,26 @@ public class DebugLoggingSupport { "(" + OTP + "|" + GRAPHQL + "|" + NAMED_LOGGERS + ")" ); - public static List getLogs() { + static List listConfiguredDebugLoggers() { List result = new ArrayList<>(); LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); for (Logger log : context.getLoggerList()) { var name = log.getName(); - if (!name.equals("ROOT") && LOG_MATCHER_PATTERN.matcher(name).matches()) { - result.add(logDisplayName(name)); + if (name.equals("ROOT") || log.getLevel() == null) { + continue; + } + if (log.getLevel().toInt() <= Level.DEBUG.toInt()) { + if (LOG_MATCHER_PATTERN.matcher(name).matches()) { + result.add(name); + } } } return result; } - public static void configureDebugLogging(Map loggers) { + static void configureDebugLogging(String logger, boolean debug) { LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - for (Logger log : context.getLoggerList()) { - var name = logDisplayName(log.getName()); - if (loggers.getOrDefault(name, false)) { - log.setLevel(Level.DEBUG); - } - } - } - - private static String logDisplayName(String name) { - return name.replace("org.opentripplanner.", "o.o."); + var log = context.getLogger(logger); + log.setLevel(debug ? Level.DEBUG : Level.INFO); } } diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/LogModel.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/LogModel.java new file mode 100644 index 00000000000..df59ccaa968 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/LogModel.java @@ -0,0 +1,82 @@ +package org.opentripplanner.ext.interactivelauncher.debug.logging; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Responsible for storing the selected loggers to debug. This is + * serialized to store the user preferences between runs. + */ +public class LogModel implements Serializable { + + private final Set activeLoggers = new HashSet<>(); + + @JsonIgnore + private Runnable saveCallback; + + public LogModel() {} + + public static LogModel createFromConfig() { + var model = new LogModel(); + model.initFromConfig(); + return model; + } + + /** Need to set this manually to support JSON serialization. */ + public void init(Runnable saveCallback) { + this.saveCallback = saveCallback; + } + + /** Used by JSON serialization. */ + public Collection getActiveLoggers() { + return List.copyOf(activeLoggers); + } + + /** Used by JSON deserialization. */ + public void setActiveLoggers(Collection loggers) { + this.activeLoggers.clear(); + this.activeLoggers.addAll(loggers); + for (var logger : activeLoggers) { + DebugLoggingSupport.configureDebugLogging(logger, true); + } + } + + boolean isLoggerEnabled(String name) { + return activeLoggers.contains(name); + } + + void turnLoggerOnOff(String name, boolean enable) { + if (enable) { + if (!activeLoggers.contains(name)) { + activeLoggers.add(name); + DebugLoggingSupport.configureDebugLogging(name, enable); + save(); + } + } else { + if (activeLoggers.contains(name)) { + activeLoggers.remove(name); + DebugLoggingSupport.configureDebugLogging(name, enable); + save(); + } + } + } + + private void initFromConfig() { + var debugLoggers = DebugLoggers.listLoggers(); + for (var logger : DebugLoggingSupport.listConfiguredDebugLoggers()) { + if (debugLoggers.contains(logger)) { + activeLoggers.add(logger); + } + } + } + + private void save() { + if (saveCallback != null) { + saveCallback.run(); + } + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/LogView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/LogView.java new file mode 100644 index 00000000000..ae8be59b07d --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/logging/LogView.java @@ -0,0 +1,35 @@ +package org.opentripplanner.ext.interactivelauncher.debug.logging; + +import javax.swing.Box; +import javax.swing.JCheckBox; +import javax.swing.JComponent; + +/** + * Display a list of loggers to turn on/off. + */ +public class LogView { + + private final Box panel = Box.createVerticalBox(); + private final LogModel model; + + public LogView(LogModel model) { + this.model = model; + DebugLoggers.list().forEach(this::add); + } + + public JComponent panel() { + return panel; + } + + private void add(DebugLoggers.Entry entry) { + var box = new JCheckBox(entry.label()); + box.setToolTipText("Logger: " + entry.logger()); + box.setSelected(model.isLoggerEnabled(entry.logger())); + box.addActionListener(e -> selectLogger(entry.logger(), box.isSelected())); + panel.add(box); + } + + private void selectLogger(String logger, boolean selected) { + model.turnLoggerOnOff(logger, selected); + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/raptor/RaptorDebugModel.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/raptor/RaptorDebugModel.java new file mode 100644 index 00000000000..41d6ed6be1a --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/raptor/RaptorDebugModel.java @@ -0,0 +1,97 @@ +package org.opentripplanner.ext.interactivelauncher.debug.raptor; + +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Objects; +import java.util.Set; +import javax.annotation.Nullable; +import org.opentripplanner.ext.interactivelauncher.api.LauncherRequestDecorator; +import org.opentripplanner.framework.lang.StringUtils; +import org.opentripplanner.routing.api.request.DebugEventType; +import org.opentripplanner.routing.api.request.RouteRequest; + +public class RaptorDebugModel implements LauncherRequestDecorator { + + private final Set eventTypes = EnumSet.noneOf(DebugEventType.class); + private String stops = null; + private String path = null; + private Runnable saveCallback; + + public RaptorDebugModel() {} + + public void init(Runnable saveCallback) { + this.saveCallback = saveCallback; + } + + /** Used by JSON serialization */ + public Set getEventTypes() { + return Collections.unmodifiableSet(eventTypes); + } + + /** Used by JSON serialization */ + public void setEventTypes(Collection eventTypes) { + this.eventTypes.clear(); + this.eventTypes.addAll(eventTypes); + } + + public void enableEventTypes(DebugEventType eventType, boolean enable) { + if (enable) { + if (!isEventTypeSet(eventType)) { + this.eventTypes.add(eventType); + save(); + } + } else { + if (isEventTypeSet(eventType)) { + this.eventTypes.remove(eventType); + save(); + } + } + } + + @Nullable + public String getStops() { + return stops; + } + + public void setStops(@Nullable String stops) { + stops = StringUtils.hasValue(stops) ? stops : null; + if (!Objects.equals(this.stops, stops)) { + this.stops = stops; + save(); + } + } + + @Nullable + public String getPath() { + return path; + } + + public void setPath(@Nullable String path) { + path = StringUtils.hasValue(path) ? path : null; + if (!Objects.equals(this.path, path)) { + this.path = path; + save(); + } + } + + public boolean isEventTypeSet(DebugEventType eventType) { + return eventTypes.contains(eventType); + } + + @Override + public RouteRequest intercept(RouteRequest defaultRequest) { + var newRequest = defaultRequest.clone(); + var debug = newRequest.journey().transit().raptorDebugging(); + debug.withEventTypes(eventTypes); + debug.withStops(stops); + debug.withPath(path); + return newRequest; + } + + private void save() { + if (saveCallback != null) { + saveCallback.run(); + } + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/raptor/RaptorDebugView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/raptor/RaptorDebugView.java new file mode 100644 index 00000000000..186b8d14837 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/debug/raptor/RaptorDebugView.java @@ -0,0 +1,87 @@ +package org.opentripplanner.ext.interactivelauncher.debug.raptor; + +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addComp; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addLabel; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addVerticalSectionSpace; +import static org.opentripplanner.routing.api.request.DebugEventType.DESTINATION_ARRIVALS; +import static org.opentripplanner.routing.api.request.DebugEventType.PATTERN_RIDES; +import static org.opentripplanner.routing.api.request.DebugEventType.STOP_ARRIVALS; + +import java.awt.Component; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.util.function.Consumer; +import javax.swing.Box; +import javax.swing.JCheckBox; +import javax.swing.JTextField; +import org.opentripplanner.routing.api.request.DebugEventType; + +/** + * This UI is used to set Raptor debug parameters, instrument the Raptor + * search, and log event at decision points during routing. + */ +public class RaptorDebugView { + + private final RaptorDebugModel model; + private final Box panel = Box.createVerticalBox(); + private final JCheckBox logStopArrivalsChk = new JCheckBox("Stop arrivals"); + private final JCheckBox logPatternRidesChk = new JCheckBox("Pattern rides"); + private final JCheckBox logDestinationArrivalsChk = new JCheckBox("Destination arrivals"); + private final JTextField stopsTxt = new JTextField(40); + private final JTextField pathTxt = new JTextField(40); + + public RaptorDebugView(RaptorDebugModel model) { + this.model = model; + + addLabel("Log Raptor events for", panel); + addComp(logStopArrivalsChk, panel); + addComp(logPatternRidesChk, panel); + addComp(logDestinationArrivalsChk, panel); + addVerticalSectionSpace(panel); + + addLabel("A list of stops to debug", panel); + addComp(stopsTxt, panel); + addVerticalSectionSpace(panel); + addLabel("A a path (as a list of stops) to debug", panel); + addComp(pathTxt, panel); + addVerticalSectionSpace(panel); + + initValues(); + setupActionListeners(); + } + + private void initValues() { + logStopArrivalsChk.setSelected(model.isEventTypeSet(STOP_ARRIVALS)); + logPatternRidesChk.setSelected(model.isEventTypeSet(PATTERN_RIDES)); + logDestinationArrivalsChk.setSelected(model.isEventTypeSet(DESTINATION_ARRIVALS)); + stopsTxt.setText(model.getStops()); + pathTxt.setText(model.getPath()); + } + + private void setupActionListeners() { + setupActionListenerChkBox(logStopArrivalsChk, STOP_ARRIVALS); + setupActionListenerChkBox(logPatternRidesChk, PATTERN_RIDES); + setupActionListenerChkBox(logDestinationArrivalsChk, DESTINATION_ARRIVALS); + setupActionListenerTextField(stopsTxt, model::setStops); + setupActionListenerTextField(pathTxt, model::setPath); + } + + public Component panel() { + return panel; + } + + private void setupActionListenerChkBox(JCheckBox box, DebugEventType type) { + box.addActionListener(l -> model.enableEventTypes(type, box.isSelected())); + } + + private static void setupActionListenerTextField(JTextField txtField, Consumer model) { + txtField.addFocusListener( + new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + model.accept(txtField.getText()); + } + } + ); + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/SearchDirectoryView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/DataSourceRootView.java similarity index 80% rename from src/ext/java/org/opentripplanner/ext/interactivelauncher/views/SearchDirectoryView.java rename to src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/DataSourceRootView.java index ef054e2c879..e5ba9136e9d 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/SearchDirectoryView.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/DataSourceRootView.java @@ -1,7 +1,7 @@ -package org.opentripplanner.ext.interactivelauncher.views; +package org.opentripplanner.ext.interactivelauncher.startup; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.BG_STATUS_BAR; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.FG_STATUS_BAR; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.BG_STATUS_BAR; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.FG_STATUS_BAR; import java.awt.Component; import java.awt.Dimension; @@ -9,18 +9,20 @@ import java.util.function.Consumer; import javax.swing.Box; import javax.swing.JButton; +import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JTextField; +import org.opentripplanner.ext.interactivelauncher.support.ViewUtils; -public class SearchDirectoryView { +class DataSourceRootView { private final Box panel; private final JTextField fileTxt = new JTextField(); private final JButton searchBtn = new JButton("Open"); private final Consumer rootDirChangedListener; - public SearchDirectoryView(String dir, Consumer rootDirChangedListener) { + DataSourceRootView(String dir, Consumer rootDirChangedListener) { this.fileTxt.setText(dir); this.rootDirChangedListener = rootDirChangedListener; @@ -35,9 +37,6 @@ public SearchDirectoryView(String dir, Consumer rootDirChangedListener) fileTxt.setEditable(false); fileTxt.setBackground(BG_STATUS_BAR); fileTxt.setForeground(FG_STATUS_BAR); - //var d = minWidth(fileTxt.getPreferredSize(), 460); - //fileTxt.setMinimumSize(d); - //fileTxt.setPreferredSize(d); // Add text field and open button Box box = Box.createHorizontalBox(); @@ -48,7 +47,7 @@ public SearchDirectoryView(String dir, Consumer rootDirChangedListener) panel.add(box); } - public Box panel() { + public JComponent panel() { return panel; } diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/DataSourcesView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/DataSourcesView.java new file mode 100644 index 00000000000..e7b1814faa2 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/DataSourcesView.java @@ -0,0 +1,131 @@ +package org.opentripplanner.ext.interactivelauncher.startup; + +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addComp; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addHorizontalGlue; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addLabel; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addVerticalSectionSpace; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.util.List; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JRadioButton; +import org.opentripplanner.ext.interactivelauncher.support.ViewUtils; + +class DataSourcesView { + + /* + |-----------------------------------------------| + | Label | + |-----------------------------------------------| + | ( ) List 1 | ( ) List 2 | ( ) List 3 | + | ( ) List 1 | ( ) List 2 | ( ) List 3 | + |-----------------------------------------------| + */ + + private final Box mainPanel = Box.createVerticalBox(); + private final Box listPanel = Box.createHorizontalBox(); + private final StartupModel model; + + public DataSourcesView(StartupModel model) { + this.model = model; + setupDataSources(); + + addLabel("Select data source", mainPanel); + addVerticalSectionSpace(mainPanel); + + listPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + addComp(listPanel, mainPanel); + } + + public JComponent panel() { + return mainPanel; + } + + public void onRootDirChange() { + model.setDataSource(null); + listPanel.removeAll(); + setupDataSources(); + listPanel.repaint(); + } + + public void onDataSourceChange(ActionEvent e) { + model.setDataSource(e.getActionCommand()); + } + + private void setupDataSources() { + final List values = model.getDataSourceOptions(); + + if (values.isEmpty()) { + model.setDataSource(null); + var label = new JLabel(""); + label.setBackground(ViewUtils.BG_STATUS_BAR); + label.setForeground(ViewUtils.FG_STATUS_BAR); + addComp(label, listPanel); + return; + } + + String selectedValue = model.getDataSource(); + + if (selectedValue == null) { + selectedValue = values.get(0); + model.setDataSource(selectedValue); + } + + ButtonGroup selectDataSourceRadioGroup = new ButtonGroup(); + + List valuesSorted = values.stream().sorted().toList(); + int size = valuesSorted.size(); + + // Split the list of configuration in one, two or three columns depending on the + // number of configurations found. + if (size <= 10) { + addListPanel(valuesSorted, selectedValue, selectDataSourceRadioGroup); + } else if (size <= 20) { + int half = size / 2; + addListPanel(valuesSorted.subList(0, half), selectedValue, selectDataSourceRadioGroup); + addHorizontalGlue(listPanel); + addListPanel(valuesSorted.subList(half, size), selectedValue, selectDataSourceRadioGroup); + } else { + int third = size / 3; + addListPanel(valuesSorted.subList(0, third), selectedValue, selectDataSourceRadioGroup); + addHorizontalGlue(listPanel); + addListPanel( + valuesSorted.subList(third, third * 2), + selectedValue, + selectDataSourceRadioGroup + ); + addHorizontalGlue(listPanel); + addListPanel( + valuesSorted.subList(third * 2, size), + selectedValue, + selectDataSourceRadioGroup + ); + } + } + + private void addListPanel( + List values, + String selectedValue, + ButtonGroup selectDataSourceRadioGroup + ) { + Box column = Box.createVerticalBox(); + + for (String name : values) { + boolean selected = selectedValue.equals(name); + JRadioButton radioBtn = newRadioBtn(selectDataSourceRadioGroup, name, selected); + radioBtn.addActionListener(this::onDataSourceChange); + addComp(radioBtn, column); + } + addComp(column, listPanel); + } + + private static JRadioButton newRadioBtn(ButtonGroup group, String name, boolean selected) { + JRadioButton radioButton = new JRadioButton(name, selected); + group.add(radioButton); + return radioButton; + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/MainView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/MainView.java similarity index 51% rename from src/ext/java/org/opentripplanner/ext/interactivelauncher/views/MainView.java rename to src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/MainView.java index 44ede02e3eb..6db2508196c 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/MainView.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/MainView.java @@ -1,11 +1,9 @@ -package org.opentripplanner.ext.interactivelauncher.views; +package org.opentripplanner.ext.interactivelauncher.startup; -import static java.awt.GridBagConstraints.BOTH; import static java.awt.GridBagConstraints.CENTER; -import static java.awt.GridBagConstraints.NONE; -import static java.awt.GridBagConstraints.NORTH; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.BACKGROUND; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.debugLayout; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.BACKGROUND; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.debugLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -14,105 +12,35 @@ import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; -import org.opentripplanner.ext.interactivelauncher.Model; public class MainView { - /** Margins between components (IN) */ private static final int M_IN = 10; - - /** Margins around frame boarder (OUT) */ private static final int M_OUT = 2 * M_IN; + private static final Insets DEFAULT_INSETS = new Insets(M_OUT, M_OUT, M_IN, M_OUT); + private static final Insets SMALL_INSETS = new Insets(M_OUT, M_OUT, M_IN, M_OUT); + private static int Y = 0; /* - The application have the following 4 panels: + The application have the following panels: + +-----------------------------------+ + | Root dir [Open] | + +-----------------------------------+ + | Config Dirs Panel | + +-----------------------------------+ + | Options Panel | +-----------------------------------+ - | Root dir [Open] | - +-------------------+---------------+ - | | | - | Config Dirs Panel | Options Panel | - | | | - +-------------------+---------------+ - | Start OTP Main Panel | + | [ Start OTP ] | +-----------------------------------+ | Status Bar | +-----------------------------------+ */ - // Root dir view - private static final GridBagConstraints CONFIG_SOURCE_DIR_PANEL_CONSTRAINTS = new GridBagConstraints( - 0, - 0, - 2, - 1, - 1.0, - 0.0, - NORTH, - BOTH, - new Insets(M_OUT, M_OUT, M_IN, M_IN), - 0, - 0 - ); - - // List of locations - private static final GridBagConstraints CONFIG_DIRS_PANEL_CONSTRAINTS = new GridBagConstraints( - 0, - 1, - 1, - 1, - 1.0, - 1.0, - NORTH, - NONE, - new Insets(M_OUT, M_OUT, M_IN, M_IN), - 0, - 0 - ); - - // Options panel - private static final GridBagConstraints OPTIONS_PANEL_CONSTRAINTS = new GridBagConstraints( - 1, - 1, - 1, - 1, - 1.0, - 1.0, - NORTH, - NONE, - new Insets(M_OUT, M_IN, M_IN, M_OUT), - 0, - 0 - ); - - // Run btn and status - private static final GridBagConstraints START_OTP_BUTTON_PANEL_CONSTRAINTS = new GridBagConstraints( - 0, - 2, - 2, - 1, - 1.0, - 1.0, - CENTER, - BOTH, - new Insets(M_IN, M_OUT, M_IN, M_OUT), - 0, - 0 - ); - - // Run btn and status - private static final GridBagConstraints STATUS_BAR_CONSTRAINTS = new GridBagConstraints( - 0, - 3, - 2, - 1, - 1.0, - 0.0, - CENTER, - BOTH, - new Insets(M_IN, 0, 0, 0), - 40, - 0 - ); + private static final GridBagConstraints DATA_SOURCE_ROOT_PANEL_CONSTRAINTS = gbc(0f); + private static final GridBagConstraints DATA_SOURCE_LIST_PANEL_CONSTRAINTS = gbc(1f); + private static final GridBagConstraints OPTIONS_PANEL_CONSTRAINTS = gbc(1f); + private static final GridBagConstraints START_BUTTON_PANEL_CONSTRAINTS = gbc(0f); + private static final GridBagConstraints STATUS_BAR_CONSTRAINTS = gbc(0f, SMALL_INSETS, 40); private final JFrame mainFrame = new JFrame("Setup and Run OTP Main"); @@ -120,9 +48,9 @@ public class MainView { private final OptionsView optionsView; private final StartOtpButtonView startOtpButtonView; private final Runnable otpStarter; - private final Model model; + private final StartupModel model; - public MainView(Runnable otpStarter, Model model) throws HeadlessException { + public MainView(Runnable otpStarter, StartupModel model) throws HeadlessException { var innerPanel = new JPanel(); var statusBarTxt = new StatusBar(); @@ -134,7 +62,7 @@ public MainView(Runnable otpStarter, Model model) throws HeadlessException { innerPanel.setLayout(layout); innerPanel.setBackground(BACKGROUND); - var sourceDirectoryView = new SearchDirectoryView( + var sourceDirectoryView = new DataSourceRootView( model.getRootDirectory(), this::onRootDirChanged ); @@ -142,16 +70,17 @@ public MainView(Runnable otpStarter, Model model) throws HeadlessException { this.optionsView = new OptionsView(model); this.startOtpButtonView = new StartOtpButtonView(); - innerPanel.add(sourceDirectoryView.panel(), CONFIG_SOURCE_DIR_PANEL_CONSTRAINTS); - innerPanel.add(dataSourcesView.panel(), CONFIG_DIRS_PANEL_CONSTRAINTS); + innerPanel.add(sourceDirectoryView.panel(), DATA_SOURCE_ROOT_PANEL_CONSTRAINTS); + innerPanel.add(dataSourcesView.panel(), DATA_SOURCE_LIST_PANEL_CONSTRAINTS); innerPanel.add(optionsView.panel(), OPTIONS_PANEL_CONSTRAINTS); - innerPanel.add(startOtpButtonView.panel(), START_OTP_BUTTON_PANEL_CONSTRAINTS); + innerPanel.add(startOtpButtonView.panel(), START_BUTTON_PANEL_CONSTRAINTS); innerPanel.add(statusBarTxt, STATUS_BAR_CONSTRAINTS); // Setup action listeners startOtpButtonView.addActionListener(e -> startOtp()); debugLayout( + sourceDirectoryView.panel(), dataSourcesView.panel(), optionsView.panel(), startOtpButtonView.panel(), @@ -186,4 +115,12 @@ private void startOtp() { mainFrame.dispose(); otpStarter.run(); } + + private static GridBagConstraints gbc(float weighty) { + return gbc(weighty, DEFAULT_INSETS, 0); + } + + private static GridBagConstraints gbc(float weighty, Insets insets, int ipadx) { + return new GridBagConstraints(0, Y++, 1, 1, 1.0, weighty, CENTER, HORIZONTAL, insets, ipadx, 0); + } } diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/OptionsView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/OptionsView.java similarity index 59% rename from src/ext/java/org/opentripplanner/ext/interactivelauncher/views/OptionsView.java rename to src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/OptionsView.java index 08923f3af88..08907346a76 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/OptionsView.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/OptionsView.java @@ -1,28 +1,25 @@ -package org.opentripplanner.ext.interactivelauncher.views; +package org.opentripplanner.ext.interactivelauncher.startup; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.addComp; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.addSectionDoubleSpace; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.addSectionSpace; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addComp; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addLabel; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.addVerticalSectionSpace; -import java.util.List; import java.util.function.Consumer; -import java.util.stream.Collectors; import javax.swing.Box; import javax.swing.JCheckBox; -import javax.swing.JLabel; -import org.opentripplanner.ext.interactivelauncher.Model; +import javax.swing.JComponent; class OptionsView { - private final Box panel = Box.createVerticalBox(); + private final Box panel = Box.createHorizontalBox(); private final JCheckBox buildStreetGraphChk; private final JCheckBox buildTransitGraphChk; private final JCheckBox saveGraphChk; private final JCheckBox startOptServerChk; private final JCheckBox startOptVisualizerChk; - private final Model model; + private final StartupModel model; - OptionsView(Model model) { + OptionsView(StartupModel model) { this.model = model; this.buildStreetGraphChk = new JCheckBox("Street graph", model.isBuildStreet()); this.buildTransitGraphChk = new JCheckBox("Transit graph", model.isBuildTransit()); @@ -30,28 +27,41 @@ class OptionsView { this.startOptServerChk = new JCheckBox("Serve graph", model.isServeGraph()); this.startOptVisualizerChk = new JCheckBox("Visualizer", model.isVisualizer()); - addComp(new JLabel("Build graph"), panel); - addSectionSpace(panel); - addComp(buildStreetGraphChk, panel); - addComp(buildTransitGraphChk, panel); - addSectionDoubleSpace(panel); + panel.add(Box.createGlue()); + addComp(createBuildBox(), panel); + panel.add(Box.createGlue()); + addComp(createActionBox(), panel); + panel.add(Box.createGlue()); // Toggle [ ] save on/off buildStreetGraphChk.addActionListener(e -> onBuildGraphChkChanged()); buildTransitGraphChk.addActionListener(e -> onBuildGraphChkChanged()); startOptServerChk.addActionListener(e -> onStartOptServerChkChanged()); - addComp(new JLabel("Actions"), panel); - addSectionSpace(panel); - addComp(saveGraphChk, panel); - addComp(startOptServerChk, panel); - addComp(startOptVisualizerChk, panel); - - addDebugCheckBoxes(model); - addSectionDoubleSpace(panel); + //addSectionDoubleSpace(panel); bindCheckBoxesToModel(); } + private JComponent createBuildBox() { + var buildBox = Box.createVerticalBox(); + addLabel("Build graph", buildBox); + addVerticalSectionSpace(buildBox); + addComp(buildStreetGraphChk, buildBox); + addComp(buildTransitGraphChk, buildBox); + buildBox.add(Box.createVerticalGlue()); + return buildBox; + } + + private JComponent createActionBox() { + var actionBox = Box.createVerticalBox(); + addLabel("Actions", actionBox); + addVerticalSectionSpace(actionBox); + addComp(saveGraphChk, actionBox); + addComp(startOptServerChk, actionBox); + addComp(startOptVisualizerChk, actionBox); + return actionBox; + } + Box panel() { return panel; } @@ -64,19 +74,6 @@ void bind(JCheckBox box, Consumer modelUpdate) { box.addActionListener(l -> modelUpdate.accept(box.isSelected() && box.isEnabled())); } - private void addDebugCheckBoxes(Model model) { - addSectionSpace(panel); - addComp(new JLabel("Debug logging"), panel); - addSectionSpace(panel); - var entries = model.getDebugLogging(); - List keys = entries.keySet().stream().sorted().collect(Collectors.toList()); - for (String name : keys) { - JCheckBox box = new JCheckBox(name, entries.get(name)); - box.addActionListener(l -> model.getDebugLogging().put(name, box.isSelected())); - addComp(box, panel); - } - } - private void bindCheckBoxesToModel() { bind(buildStreetGraphChk, model::setBuildStreet); bind(buildTransitGraphChk, model::setBuildTransit); diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/StartOtpButtonView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StartOtpButtonView.java similarity index 82% rename from src/ext/java/org/opentripplanner/ext/interactivelauncher/views/StartOtpButtonView.java rename to src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StartOtpButtonView.java index 5c0c1e7a621..3050b7c5c62 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/StartOtpButtonView.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StartOtpButtonView.java @@ -1,6 +1,6 @@ -package org.opentripplanner.ext.interactivelauncher.views; +package org.opentripplanner.ext.interactivelauncher.startup; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.adjustSize; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.adjustSize; import java.awt.event.ActionListener; import javax.swing.Box; diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StartupModel.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StartupModel.java new file mode 100644 index 00000000000..5b803b2318c --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StartupModel.java @@ -0,0 +1,178 @@ +package org.opentripplanner.ext.interactivelauncher.startup; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import org.opentripplanner.ext.interactivelauncher.support.SearchForOtpConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StartupModel { + + private static final Logger LOG = LoggerFactory.getLogger(StartupModel.class); + + @JsonIgnore + private transient Consumer commandLineChange; + + private String rootDirectory = null; + private String dataSource = null; + private boolean buildStreet = false; + private boolean buildTransit = true; + private boolean saveGraph = false; + private boolean serveGraph = true; + private boolean visualizer = false; + + public void subscribeCmdLineUpdates(Consumer commandLineChange) { + this.commandLineChange = commandLineChange; + } + + @SuppressWarnings("AccessOfSystemProperties") + public String getRootDirectory() { + return rootDirectory == null ? System.getProperty("user.dir") : rootDirectory; + } + + public void setRootDirectory(String rootDirectory) { + // If the persisted JSON do not contain the rootDirectory, then avoid setting it + if (rootDirectory != null) { + this.rootDirectory = rootDirectory; + } + notifyChangeListener(); + } + + public String getDataSource() { + return dataSource; + } + + public void setDataSource(String dataSource) { + this.dataSource = dataSource; + notifyChangeListener(); + } + + @JsonIgnore + public List getDataSourceOptions() { + List dataSourceOptions = new ArrayList<>(); + File rootDir = new File(getRootDirectory()); + List dirs = SearchForOtpConfig.search(rootDir); + // Add 1 char for the path-separator-character + int length = rootDir.getAbsolutePath().length() + 1; + + for (File dir : dirs) { + var path = dir.getAbsolutePath(); + if (path.length() <= length) { + LOG.warn( + "The root directory contains a config file, choose " + + "the parent directory or delete the config file." + ); + continue; + } + dataSourceOptions.add(path.substring(length)); + } + return dataSourceOptions; + } + + public boolean isBuildStreet() { + return buildStreet; + } + + public void setBuildStreet(boolean buildStreet) { + this.buildStreet = buildStreet; + notifyChangeListener(); + } + + public boolean isBuildTransit() { + return buildTransit; + } + + public void setBuildTransit(boolean buildTransit) { + this.buildTransit = buildTransit; + notifyChangeListener(); + } + + public boolean isSaveGraph() { + return saveGraph; + } + + public void setSaveGraph(boolean saveGraph) { + this.saveGraph = saveGraph; + notifyChangeListener(); + } + + public boolean isServeGraph() { + return serveGraph; + } + + public void setServeGraph(boolean serveGraph) { + this.serveGraph = serveGraph; + notifyChangeListener(); + } + + public boolean isVisualizer() { + return visualizer; + } + + public void setVisualizer(boolean visualizer) { + this.visualizer = visualizer; + notifyChangeListener(); + } + + @Override + public String toString() { + return String.join("", asOtpArgs()); + } + + public String toCliString() { + return String.join(" ", asOtpArgs()); + } + + private void notifyChangeListener() { + if (commandLineChange != null) { + commandLineChange.accept(toCliString()); + } + } + + @JsonIgnore + String getDataSourceDirectory() { + if (dataSource == null) { + return "DATA_SOURCE_NOT_SET"; + } + return getRootDirectory() + File.separatorChar + dataSource; + } + + public String[] asOtpArgs() { + List args = new ArrayList<>(); + + if (buildAll()) { + args.add("--build"); + } else if (buildStreet) { + args.add("--buildStreet"); + } else if (buildTransit) { + args.add("--loadStreet"); + } else { + args.add("--load"); + } + + if (saveGraph && (buildTransit || buildStreet)) { + args.add("--save"); + } + if (serveGraph && !buildStreetOnly()) { + args.add("--serve"); + } + if (serveGraph && !buildStreetOnly() && visualizer) { + args.add("--visualize"); + } + + args.add(getDataSourceDirectory()); + + return args.toArray(new String[0]); + } + + private boolean buildAll() { + return buildStreet && buildTransit; + } + + private boolean buildStreetOnly() { + return buildStreet && !buildTransit; + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StatusBar.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StatusBar.java new file mode 100644 index 00000000000..f88c77c9f75 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/startup/StatusBar.java @@ -0,0 +1,15 @@ +package org.opentripplanner.ext.interactivelauncher.startup; + +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.BG_STATUS_BAR; +import static org.opentripplanner.ext.interactivelauncher.support.ViewUtils.FG_STATUS_BAR; + +import javax.swing.JTextField; + +class StatusBar extends JTextField { + + public StatusBar() { + setEditable(false); + setBackground(BG_STATUS_BAR); + setForeground(FG_STATUS_BAR); + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/SearchForOtpConfig.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/support/SearchForOtpConfig.java similarity index 85% rename from src/ext/java/org/opentripplanner/ext/interactivelauncher/SearchForOtpConfig.java rename to src/ext/java/org/opentripplanner/ext/interactivelauncher/support/SearchForOtpConfig.java index ccf6be72e20..6b0574f0fdf 100644 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/SearchForOtpConfig.java +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/support/SearchForOtpConfig.java @@ -1,4 +1,4 @@ -package org.opentripplanner.ext.interactivelauncher; +package org.opentripplanner.ext.interactivelauncher.support; import java.io.File; import java.util.Arrays; @@ -10,17 +10,17 @@ /** * Search for directories containing OTP configuration files. The search is recursive and searches - * sub-directories 10 levels deep. + * subdirectories 10 levels deep. */ -class SearchForOtpConfig { +public class SearchForOtpConfig { private static final int DEPTH_LIMIT = 10; private static final Pattern EXCLUDE_DIR = Pattern.compile( "(otp1|archive|\\..*|te?mp|target|docs?|src|source|resource)" ); - static List search(File rootDir) { - return recursiveSearch(rootDir, DEPTH_LIMIT).collect(Collectors.toUnmodifiableList()); + public static List search(File rootDir) { + return recursiveSearch(rootDir, DEPTH_LIMIT).toList(); } @SuppressWarnings("ConstantConditions") diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/support/ViewUtils.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/support/ViewUtils.java new file mode 100644 index 00000000000..f906f063058 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/interactivelauncher/support/ViewUtils.java @@ -0,0 +1,53 @@ +package org.opentripplanner.ext.interactivelauncher.support; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JComponent; +import javax.swing.JLabel; + +public final class ViewUtils { + + private static final boolean DEBUG_LAYOUT = false; + static final int SECTION_SPACE = 10; + public static final Color BACKGROUND = new Color(0xe0, 0xf0, 0xff); + public static final Color BG_STATUS_BAR = new Color(0xd0, 0xe0, 0xf0); + public static final Color FG_STATUS_BAR = new Color(0, 0, 0x80); + + public static void addVerticalSectionSpace(Box panel) { + panel.add(Box.createVerticalStrut(SECTION_SPACE)); + } + + public static void addHorizontalGlue(Box box) { + box.add(Box.createHorizontalGlue()); + } + + public static void addLabel(String label, Container panel) { + addComp(new JLabel(label), panel); + } + + public static void addComp(JComponent c, Container panel) { + if (DEBUG_LAYOUT) { + c.setBorder(BorderFactory.createLineBorder(Color.green)); + } + panel.add(c); + } + + public static void debugLayout(JComponent... components) { + if (DEBUG_LAYOUT) { + for (JComponent c : components) { + c.setBorder(BorderFactory.createLineBorder(Color.red)); + } + } + } + + public static void adjustSize(JComponent c, int dWidth, int dHeight) { + Dimension d0 = c.getPreferredSize(); + Dimension d = new Dimension(d0.width + dWidth, d0.height + dHeight); + c.setMinimumSize(d); + c.setPreferredSize(d); + c.setMaximumSize(d); + } +} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/DataSourcesView.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/DataSourcesView.java deleted file mode 100644 index c7faa43779d..00000000000 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/DataSourcesView.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.opentripplanner.ext.interactivelauncher.views; - -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.addComp; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.addSectionDoubleSpace; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.addSectionSpace; - -import java.awt.event.ActionEvent; -import java.util.List; -import java.util.stream.Collectors; -import javax.swing.Box; -import javax.swing.ButtonGroup; -import javax.swing.JLabel; -import javax.swing.JRadioButton; -import org.opentripplanner.ext.interactivelauncher.Model; - -class DataSourcesView { - - private final Box panel = Box.createVerticalBox(); - private final Box dataSourceSelectionPanel = Box.createVerticalBox(); - private final Model model; - - public DataSourcesView(Model model) { - this.model = model; - - setupDataSources(); - - addComp(new JLabel("Select data source"), panel); - addSectionSpace(panel); - addComp(dataSourceSelectionPanel, panel); - addSectionDoubleSpace(panel); - } - - public Box panel() { - return panel; - } - - public void onRootDirChange() { - model.setDataSource(null); - dataSourceSelectionPanel.removeAll(); - setupDataSources(); - panel.repaint(); - } - - public void onDataSourceChange(ActionEvent e) { - model.setDataSource(e.getActionCommand()); - } - - private static JRadioButton newRadioBtn(ButtonGroup group, String name, boolean selected) { - JRadioButton radioButton = new JRadioButton(name, selected); - group.add(radioButton); - return radioButton; - } - - private void setupDataSources() { - final List values = model.getDataSourceOptions(); - - if (values.isEmpty()) { - model.setDataSource(null); - JLabel label = new JLabel(""); - label.setBackground(ViewUtils.BG_STATUS_BAR); - label.setForeground(ViewUtils.FG_STATUS_BAR); - addComp(label, dataSourceSelectionPanel); - return; - } - - String selectedValue = model.getDataSource(); - - if (selectedValue == null) { - selectedValue = values.get(0); - model.setDataSource(selectedValue); - } - - ButtonGroup selectDataSourceRadioGroup = new ButtonGroup(); - - List valuesSorted = values.stream().sorted().collect(Collectors.toList()); - - for (String name : valuesSorted) { - boolean selected = selectedValue.equals(name); - JRadioButton radioBtn = newRadioBtn(selectDataSourceRadioGroup, name, selected); - radioBtn.addActionListener(this::onDataSourceChange); - addComp(radioBtn, dataSourceSelectionPanel); - } - } -} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/StatusBar.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/StatusBar.java deleted file mode 100644 index faffa9d87d2..00000000000 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/StatusBar.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.opentripplanner.ext.interactivelauncher.views; - -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.BG_STATUS_BAR; -import static org.opentripplanner.ext.interactivelauncher.views.ViewUtils.FG_STATUS_BAR; - -import javax.swing.JTextField; - -public class StatusBar extends JTextField { - - public StatusBar() { - setEditable(false); - setBackground(BG_STATUS_BAR); - setForeground(FG_STATUS_BAR); - } -} diff --git a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/ViewUtils.java b/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/ViewUtils.java deleted file mode 100644 index 14f6f589109..00000000000 --- a/src/ext/java/org/opentripplanner/ext/interactivelauncher/views/ViewUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.opentripplanner.ext.interactivelauncher.views; - -import java.awt.Color; -import java.awt.Dimension; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.JComponent; - -final class ViewUtils { - - private static final boolean DEBUG_LAYOUT = false; - static final int SECTION_SPACE = 10; - static final Color BACKGROUND = new Color(0xe0, 0xf0, 0xff); - static final Color BG_STATUS_BAR = new Color(0xd0, 0xe0, 0xf0); - static final Color FG_STATUS_BAR = new Color(0, 0, 0x80); - - static void addSectionSpace(Box panel) { - panel.add(Box.createVerticalStrut(SECTION_SPACE)); - } - - static void addSectionDoubleSpace(Box panel) { - panel.add(Box.createVerticalStrut(2 * SECTION_SPACE)); - } - - static void addComp(JComponent c, Box panel) { - if (DEBUG_LAYOUT) { - c.setBorder(BorderFactory.createLineBorder(Color.green)); - } - panel.add(c); - } - - static void debugLayout(JComponent... components) { - if (DEBUG_LAYOUT) { - for (JComponent c : components) { - c.setBorder(BorderFactory.createLineBorder(Color.red)); - } - } - } - - static void adjustSize(JComponent c, int dWidth, int dHeight) { - Dimension d0 = c.getPreferredSize(); - Dimension d = new Dimension(d0.width + dWidth, d0.height + dHeight); - c.setMinimumSize(d); - c.setPreferredSize(d); - c.setMaximumSize(d); - } -} diff --git a/src/main/java/org/opentripplanner/api/mapping/AbsoluteDirectionMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/AbsoluteDirectionMapper.java similarity index 88% rename from src/main/java/org/opentripplanner/api/mapping/AbsoluteDirectionMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/AbsoluteDirectionMapper.java index 59bb0d77955..8500323c032 100644 --- a/src/main/java/org/opentripplanner/api/mapping/AbsoluteDirectionMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/AbsoluteDirectionMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiAbsoluteDirection; +import org.opentripplanner.ext.restapi.model.ApiAbsoluteDirection; import org.opentripplanner.model.plan.AbsoluteDirection; public class AbsoluteDirectionMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/AgencyMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/AgencyMapper.java similarity index 89% rename from src/main/java/org/opentripplanner/api/mapping/AgencyMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/AgencyMapper.java index 9600400d373..4ea3ebb5209 100644 --- a/src/main/java/org/opentripplanner/api/mapping/AgencyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/AgencyMapper.java @@ -1,9 +1,9 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiAgency; +import org.opentripplanner.ext.restapi.model.ApiAgency; import org.opentripplanner.transit.model.organization.Agency; public class AgencyMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/AlertMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/AlertMapper.java similarity index 92% rename from src/main/java/org/opentripplanner/api/mapping/AlertMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/AlertMapper.java index e01961a5dca..8fbfa71111f 100644 --- a/src/main/java/org/opentripplanner/api/mapping/AlertMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/AlertMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.time.Instant; import java.util.Collection; @@ -7,7 +7,7 @@ import java.util.Locale; import java.util.Optional; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiAlert; +import org.opentripplanner.ext.restapi.model.ApiAlert; import org.opentripplanner.routing.alertpatch.TransitAlert; public class AlertMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/BikeAccessMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BikeAccessMapper.java similarity index 86% rename from src/main/java/org/opentripplanner/api/mapping/BikeAccessMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/BikeAccessMapper.java index 43c00ef8227..3ceb86b4459 100644 --- a/src/main/java/org/opentripplanner/api/mapping/BikeAccessMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BikeAccessMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import org.opentripplanner.transit.model.network.BikeAccess; diff --git a/src/main/java/org/opentripplanner/api/mapping/BookingInfoMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingInfoMapper.java similarity index 88% rename from src/main/java/org/opentripplanner/api/mapping/BookingInfoMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingInfoMapper.java index 4f1eb0c6249..4aa8b4a46b1 100644 --- a/src/main/java/org/opentripplanner/api/mapping/BookingInfoMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingInfoMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiBookingInfo; +import org.opentripplanner.ext.restapi.model.ApiBookingInfo; import org.opentripplanner.model.BookingInfo; public class BookingInfoMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/BookingMethodMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingMethodMapper.java similarity index 94% rename from src/main/java/org/opentripplanner/api/mapping/BookingMethodMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingMethodMapper.java index b938c1813d2..9b61ff39543 100644 --- a/src/main/java/org/opentripplanner/api/mapping/BookingMethodMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingMethodMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.EnumSet; import java.util.Set; diff --git a/src/main/java/org/opentripplanner/api/mapping/BookingTimeMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingTimeMapper.java similarity index 71% rename from src/main/java/org/opentripplanner/api/mapping/BookingTimeMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingTimeMapper.java index 3a779cbeed4..e40309e9137 100644 --- a/src/main/java/org/opentripplanner/api/mapping/BookingTimeMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/BookingTimeMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiBookingTime; +import org.opentripplanner.ext.restapi.model.ApiBookingTime; import org.opentripplanner.model.BookingTime; public class BookingTimeMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/ContactInfoMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ContactInfoMapper.java similarity index 80% rename from src/main/java/org/opentripplanner/api/mapping/ContactInfoMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/ContactInfoMapper.java index d12a06f8e30..452e15a0cb5 100644 --- a/src/main/java/org/opentripplanner/api/mapping/ContactInfoMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ContactInfoMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiContactInfo; +import org.opentripplanner.ext.restapi.model.ApiContactInfo; import org.opentripplanner.transit.model.organization.ContactInfo; public class ContactInfoMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/DirectionMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/DirectionMapper.java similarity index 83% rename from src/main/java/org/opentripplanner/api/mapping/DirectionMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/DirectionMapper.java index 22decc21f81..ea510b1fdc7 100644 --- a/src/main/java/org/opentripplanner/api/mapping/DirectionMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/DirectionMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import org.opentripplanner.transit.model.timetable.Direction; diff --git a/src/main/java/org/opentripplanner/api/mapping/ElevationMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ElevationMapper.java similarity index 92% rename from src/main/java/org/opentripplanner/api/mapping/ElevationMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/ElevationMapper.java index de5c9f46fdb..192848f04d6 100644 --- a/src/main/java/org/opentripplanner/api/mapping/ElevationMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ElevationMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import org.opentripplanner.model.plan.ElevationProfile; diff --git a/src/main/java/org/opentripplanner/api/mapping/FareMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/FareMapper.java similarity index 89% rename from src/main/java/org/opentripplanner/api/mapping/FareMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/FareMapper.java index 4d682a1d32c..a6020c6bf37 100644 --- a/src/main/java/org/opentripplanner/api/mapping/FareMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/FareMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import com.google.common.collect.Multimap; import java.util.AbstractMap.SimpleEntry; @@ -10,13 +10,13 @@ import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.Nullable; -import org.opentripplanner.api.model.ApiCurrency; -import org.opentripplanner.api.model.ApiFareComponent; -import org.opentripplanner.api.model.ApiFareProduct; -import org.opentripplanner.api.model.ApiFareQualifier; -import org.opentripplanner.api.model.ApiItineraryFares; -import org.opentripplanner.api.model.ApiLegProducts; -import org.opentripplanner.api.model.ApiMoney; +import org.opentripplanner.ext.restapi.model.ApiCurrency; +import org.opentripplanner.ext.restapi.model.ApiFareComponent; +import org.opentripplanner.ext.restapi.model.ApiFareProduct; +import org.opentripplanner.ext.restapi.model.ApiFareQualifier; +import org.opentripplanner.ext.restapi.model.ApiItineraryFares; +import org.opentripplanner.ext.restapi.model.ApiLegProducts; +import org.opentripplanner.ext.restapi.model.ApiMoney; import org.opentripplanner.model.fare.FareMedium; import org.opentripplanner.model.fare.FareProduct; import org.opentripplanner.model.fare.FareProductUse; diff --git a/src/main/java/org/opentripplanner/api/mapping/FeedInfoMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/FeedInfoMapper.java similarity index 84% rename from src/main/java/org/opentripplanner/api/mapping/FeedInfoMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/FeedInfoMapper.java index b8262d726fe..203ade5749e 100644 --- a/src/main/java/org/opentripplanner/api/mapping/FeedInfoMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/FeedInfoMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiFeedInfo; +import org.opentripplanner.ext.restapi.model.ApiFeedInfo; import org.opentripplanner.model.FeedInfo; public class FeedInfoMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/FeedScopedIdMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/FeedScopedIdMapper.java similarity index 95% rename from src/main/java/org/opentripplanner/api/mapping/FeedScopedIdMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/FeedScopedIdMapper.java index d33d7c53bc1..619c306fbbc 100644 --- a/src/main/java/org/opentripplanner/api/mapping/FeedScopedIdMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/FeedScopedIdMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import jakarta.ws.rs.BadRequestException; import org.opentripplanner.transit.model.framework.AbstractTransitEntity; diff --git a/src/main/java/org/opentripplanner/api/mapping/ItineraryMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ItineraryMapper.java similarity index 94% rename from src/main/java/org/opentripplanner/api/mapping/ItineraryMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/ItineraryMapper.java index cf14eda73dd..d87cf33d71c 100644 --- a/src/main/java/org/opentripplanner/api/mapping/ItineraryMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ItineraryMapper.java @@ -1,11 +1,11 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiItinerary; +import org.opentripplanner.ext.restapi.model.ApiItinerary; import org.opentripplanner.model.plan.Itinerary; public class ItineraryMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/LegMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java similarity index 92% rename from src/main/java/org/opentripplanner/api/mapping/LegMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java index cc139e5180d..766262bca89 100644 --- a/src/main/java/org/opentripplanner/api/mapping/LegMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java @@ -1,15 +1,17 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import static org.opentripplanner.api.mapping.ElevationMapper.mapElevation; +import static org.opentripplanner.ext.restapi.mapping.ElevationMapper.mapElevation; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; -import org.opentripplanner.api.model.ApiAlert; -import org.opentripplanner.api.model.ApiLeg; +import org.opentripplanner.apis.support.mapping.StreetNoteMapper; +import org.opentripplanner.ext.restapi.model.ApiAlert; +import org.opentripplanner.ext.restapi.model.ApiLeg; import org.opentripplanner.framework.geometry.EncodedPolyline; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.model.PickDrop; import org.opentripplanner.model.plan.Leg; import org.opentripplanner.model.plan.StreetLeg; @@ -18,7 +20,7 @@ public class LegMapper { private final WalkStepMapper walkStepMapper; - private final StreetNoteMaperMapper streetNoteMaperMapper; + private final StreetNoteMapper streetNoteMaperMapper; private final AlertMapper alertMapper; private final PlaceMapper placeMapper; private final boolean addIntermediateStops; @@ -27,7 +29,7 @@ public class LegMapper { public LegMapper(Locale locale, boolean addIntermediateStops) { this.walkStepMapper = new WalkStepMapper(locale); - this.streetNoteMaperMapper = new StreetNoteMaperMapper(locale); + this.streetNoteMaperMapper = new StreetNoteMapper(locale); this.alertMapper = new AlertMapper(locale); this.placeMapper = new PlaceMapper(locale); this.addIntermediateStops = addIntermediateStops; diff --git a/src/main/java/org/opentripplanner/api/mapping/LocalDateMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LocalDateMapper.java similarity index 89% rename from src/main/java/org/opentripplanner/api/mapping/LocalDateMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/LocalDateMapper.java index 334efa8c6e8..940bcc13d54 100644 --- a/src/main/java/org/opentripplanner/api/mapping/LocalDateMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LocalDateMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.time.LocalDate; import org.opentripplanner.framework.time.ServiceDateUtils; diff --git a/src/main/java/org/opentripplanner/api/mapping/ModeMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ModeMapper.java similarity index 97% rename from src/main/java/org/opentripplanner/api/mapping/ModeMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/ModeMapper.java index 3276de080c3..49bd2619149 100644 --- a/src/main/java/org/opentripplanner/api/mapping/ModeMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/ModeMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.List; import java.util.Set; diff --git a/src/main/java/org/opentripplanner/api/mapping/PlaceMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/PlaceMapper.java similarity index 93% rename from src/main/java/org/opentripplanner/api/mapping/PlaceMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/PlaceMapper.java index e806c5615d2..b1eb3410af8 100644 --- a/src/main/java/org/opentripplanner/api/mapping/PlaceMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/PlaceMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.time.ZonedDateTime; import java.util.ArrayList; @@ -8,9 +8,10 @@ import java.util.Locale; import java.util.Optional; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiPlace; -import org.opentripplanner.api.model.ApiVehicleParkingSpaces; -import org.opentripplanner.api.model.ApiVehicleParkingWithEntrance; +import org.opentripplanner.ext.restapi.model.ApiPlace; +import org.opentripplanner.ext.restapi.model.ApiVehicleParkingSpaces; +import org.opentripplanner.ext.restapi.model.ApiVehicleParkingWithEntrance; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.VehicleParkingWithEntrance; diff --git a/src/main/java/org/opentripplanner/api/mapping/RelativeDirectionMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/RelativeDirectionMapper.java similarity index 91% rename from src/main/java/org/opentripplanner/api/mapping/RelativeDirectionMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/RelativeDirectionMapper.java index 78c4495292c..a1bdd145a55 100644 --- a/src/main/java/org/opentripplanner/api/mapping/RelativeDirectionMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/RelativeDirectionMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiRelativeDirection; +import org.opentripplanner.ext.restapi.model.ApiRelativeDirection; import org.opentripplanner.model.plan.RelativeDirection; public class RelativeDirectionMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/RouteMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/RouteMapper.java similarity index 90% rename from src/main/java/org/opentripplanner/api/mapping/RouteMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/RouteMapper.java index f64a350092c..decee369a17 100644 --- a/src/main/java/org/opentripplanner/api/mapping/RouteMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/RouteMapper.java @@ -1,10 +1,11 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiRoute; -import org.opentripplanner.api.model.ApiRouteShort; +import org.opentripplanner.ext.restapi.model.ApiRoute; +import org.opentripplanner.ext.restapi.model.ApiRouteShort; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.organization.Branding; diff --git a/src/main/java/org/opentripplanner/api/mapping/RouteTypeMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/RouteTypeMapper.java similarity index 92% rename from src/main/java/org/opentripplanner/api/mapping/RouteTypeMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/RouteTypeMapper.java index af300b1d39a..9dede395e80 100644 --- a/src/main/java/org/opentripplanner/api/mapping/RouteTypeMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/RouteTypeMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import org.opentripplanner.transit.model.basic.TransitMode; diff --git a/src/main/java/org/opentripplanner/api/mapping/StopMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/StopMapper.java similarity index 93% rename from src/main/java/org/opentripplanner/api/mapping/StopMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/StopMapper.java index 954584fd76f..9e3c8b04262 100644 --- a/src/main/java/org/opentripplanner/api/mapping/StopMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/StopMapper.java @@ -1,10 +1,11 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiStop; -import org.opentripplanner.api.model.ApiStopShort; +import org.opentripplanner.ext.restapi.model.ApiStop; +import org.opentripplanner.ext.restapi.model.ApiStopShort; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.transit.model.site.StopLocation; public class StopMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/StopTimesInPatternMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/StopTimesInPatternMapper.java similarity index 86% rename from src/main/java/org/opentripplanner/api/mapping/StopTimesInPatternMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/StopTimesInPatternMapper.java index 66da0071959..d917bac9203 100644 --- a/src/main/java/org/opentripplanner/api/mapping/StopTimesInPatternMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/StopTimesInPatternMapper.java @@ -1,9 +1,9 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiStopTimesInPattern; +import org.opentripplanner.ext.restapi.model.ApiStopTimesInPattern; import org.opentripplanner.model.StopTimesInPattern; public class StopTimesInPatternMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/SystemNoticeMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/SystemNoticeMapper.java similarity index 87% rename from src/main/java/org/opentripplanner/api/mapping/SystemNoticeMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/SystemNoticeMapper.java index f30a62d2d97..1c79a4a7074 100644 --- a/src/main/java/org/opentripplanner/api/mapping/SystemNoticeMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/SystemNoticeMapper.java @@ -1,9 +1,9 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiSystemNotice; +import org.opentripplanner.ext.restapi.model.ApiSystemNotice; import org.opentripplanner.model.SystemNotice; public final class SystemNoticeMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/TransferMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TransferMapper.java similarity index 77% rename from src/main/java/org/opentripplanner/api/mapping/TransferMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/TransferMapper.java index 3004d86aa44..49b87f25779 100644 --- a/src/main/java/org/opentripplanner/api/mapping/TransferMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TransferMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiTransfer; +import org.opentripplanner.ext.restapi.model.ApiTransfer; import org.opentripplanner.model.PathTransfer; public class TransferMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/TripMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripMapper.java similarity index 90% rename from src/main/java/org/opentripplanner/api/mapping/TripMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/TripMapper.java index 33df525a9a7..f4894a4a7a3 100644 --- a/src/main/java/org/opentripplanner/api/mapping/TripMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripMapper.java @@ -1,10 +1,11 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.opentripplanner.api.model.ApiTrip; -import org.opentripplanner.api.model.ApiTripShort; +import org.opentripplanner.ext.restapi.model.ApiTrip; +import org.opentripplanner.ext.restapi.model.ApiTripShort; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.timetable.Trip; diff --git a/src/main/java/org/opentripplanner/api/mapping/TripPatternMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripPatternMapper.java similarity index 88% rename from src/main/java/org/opentripplanner/api/mapping/TripPatternMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/TripPatternMapper.java index 439d2b5fe2f..ba68979c73f 100644 --- a/src/main/java/org/opentripplanner/api/mapping/TripPatternMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripPatternMapper.java @@ -1,11 +1,11 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiPatternDetail; -import org.opentripplanner.api.model.ApiPatternShort; +import org.opentripplanner.ext.restapi.model.ApiPatternDetail; +import org.opentripplanner.ext.restapi.model.ApiPatternShort; import org.opentripplanner.transit.model.network.TripPattern; public class TripPatternMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/TripPlanMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripPlanMapper.java similarity index 89% rename from src/main/java/org/opentripplanner/api/mapping/TripPlanMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/TripPlanMapper.java index 8c5459af8ed..891afcf9542 100644 --- a/src/main/java/org/opentripplanner/api/mapping/TripPlanMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripPlanMapper.java @@ -1,8 +1,8 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Date; import java.util.Locale; -import org.opentripplanner.api.model.ApiTripPlan; +import org.opentripplanner.ext.restapi.model.ApiTripPlan; import org.opentripplanner.model.plan.TripPlan; public class TripPlanMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/TripSearchMetadataMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripSearchMetadataMapper.java similarity index 85% rename from src/main/java/org/opentripplanner/api/mapping/TripSearchMetadataMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/TripSearchMetadataMapper.java index 0a3b46bb118..db92e821493 100644 --- a/src/main/java/org/opentripplanner/api/mapping/TripSearchMetadataMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripSearchMetadataMapper.java @@ -1,7 +1,7 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.time.Instant; -import org.opentripplanner.api.model.ApiTripSearchMetadata; +import org.opentripplanner.ext.restapi.model.ApiTripSearchMetadata; import org.opentripplanner.routing.api.response.TripSearchMetadata; public class TripSearchMetadataMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/TripTimeMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripTimeMapper.java similarity index 86% rename from src/main/java/org/opentripplanner/api/mapping/TripTimeMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/TripTimeMapper.java index 2f5bfe91026..f1f37e6d8b4 100644 --- a/src/main/java/org/opentripplanner/api/mapping/TripTimeMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/TripTimeMapper.java @@ -1,10 +1,11 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiRealTimeState; -import org.opentripplanner.api.model.ApiTripTimeShort; +import org.opentripplanner.ext.restapi.model.ApiRealTimeState; +import org.opentripplanner.ext.restapi.model.ApiTripTimeShort; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.model.TripTimeOnDate; public class TripTimeMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/VehicleRentalStationMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/VehicleRentalStationMapper.java similarity index 88% rename from src/main/java/org/opentripplanner/api/mapping/VehicleRentalStationMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/VehicleRentalStationMapper.java index 482a966dec0..2f68448fdf4 100644 --- a/src/main/java/org/opentripplanner/api/mapping/VehicleRentalStationMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/VehicleRentalStationMapper.java @@ -1,8 +1,8 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import java.util.List; import java.util.Locale; -import org.opentripplanner.api.model.ApiVehicleRentalStation; +import org.opentripplanner.ext.restapi.model.ApiVehicleRentalStation; import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; public class VehicleRentalStationMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/VertexTypeMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/VertexTypeMapper.java similarity index 83% rename from src/main/java/org/opentripplanner/api/mapping/VertexTypeMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/VertexTypeMapper.java index 340be3d60fd..5f59ea4fd57 100644 --- a/src/main/java/org/opentripplanner/api/mapping/VertexTypeMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/VertexTypeMapper.java @@ -1,6 +1,6 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import org.opentripplanner.api.model.ApiVertexType; +import org.opentripplanner.ext.restapi.model.ApiVertexType; import org.opentripplanner.model.plan.VertexType; public class VertexTypeMapper { diff --git a/src/main/java/org/opentripplanner/api/mapping/WalkStepMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java similarity index 76% rename from src/main/java/org/opentripplanner/api/mapping/WalkStepMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java index 5d633079e4a..c5c59e4dc37 100644 --- a/src/main/java/org/opentripplanner/api/mapping/WalkStepMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java @@ -1,23 +1,24 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; -import static org.opentripplanner.api.mapping.ElevationMapper.mapElevation; -import static org.opentripplanner.api.mapping.RelativeDirectionMapper.mapRelativeDirection; +import static org.opentripplanner.ext.restapi.mapping.ElevationMapper.mapElevation; +import static org.opentripplanner.ext.restapi.mapping.RelativeDirectionMapper.mapRelativeDirection; import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiWalkStep; +import org.opentripplanner.apis.support.mapping.StreetNoteMapper; +import org.opentripplanner.ext.restapi.model.ApiWalkStep; import org.opentripplanner.model.plan.WalkStep; public class WalkStepMapper { - private final StreetNoteMaperMapper alertsMapper; + private final StreetNoteMapper alertsMapper; private final Locale locale; public WalkStepMapper(Locale locale) { this.locale = locale; - this.alertsMapper = new StreetNoteMaperMapper(locale); + this.alertsMapper = new StreetNoteMapper(locale); } public List mapWalkSteps(Collection domain) { diff --git a/src/main/java/org/opentripplanner/api/mapping/WheelchairAccessibilityMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/WheelchairAccessibilityMapper.java similarity index 87% rename from src/main/java/org/opentripplanner/api/mapping/WheelchairAccessibilityMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/mapping/WheelchairAccessibilityMapper.java index 05d8cc97959..e0aafeaee05 100644 --- a/src/main/java/org/opentripplanner/api/mapping/WheelchairAccessibilityMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/WheelchairAccessibilityMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.ext.restapi.mapping; import org.opentripplanner.transit.model.basic.Accessibility; diff --git a/src/main/java/org/opentripplanner/api/model/ApiAbsoluteDirection.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiAbsoluteDirection.java similarity index 79% rename from src/main/java/org/opentripplanner/api/model/ApiAbsoluteDirection.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiAbsoluteDirection.java index 48d93618bf7..ffa00cbc54e 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiAbsoluteDirection.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiAbsoluteDirection.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** * An absolute cardinal or intermediate direction. diff --git a/src/main/java/org/opentripplanner/api/model/ApiAgency.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiAgency.java similarity index 93% rename from src/main/java/org/opentripplanner/api/model/ApiAgency.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiAgency.java index e895ea655cd..ada6739a795 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiAgency.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiAgency.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import java.util.Objects; diff --git a/src/main/java/org/opentripplanner/api/model/ApiAlert.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiAlert.java similarity index 83% rename from src/main/java/org/opentripplanner/api/model/ApiAlert.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiAlert.java index 3c4d77c6129..a503a7d18e2 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiAlert.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiAlert.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.Date; diff --git a/src/main/java/org/opentripplanner/api/model/ApiBookingInfo.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiBookingInfo.java similarity index 98% rename from src/main/java/org/opentripplanner/api/model/ApiBookingInfo.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiBookingInfo.java index f3a553fc1f1..c89d6429caa 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiBookingInfo.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiBookingInfo.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import java.time.Duration; diff --git a/src/main/java/org/opentripplanner/api/model/ApiBookingTime.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiBookingTime.java similarity index 94% rename from src/main/java/org/opentripplanner/api/model/ApiBookingTime.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiBookingTime.java index e0c140f8ee1..08eee69a3cf 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiBookingTime.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiBookingTime.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import org.opentripplanner.framework.tostring.ToStringBuilder; diff --git a/src/main/java/org/opentripplanner/api/model/ApiContactInfo.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiContactInfo.java similarity index 97% rename from src/main/java/org/opentripplanner/api/model/ApiContactInfo.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiContactInfo.java index 06c1fc8d198..b7c2ec90166 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiContactInfo.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiContactInfo.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import org.opentripplanner.framework.tostring.ToStringBuilder; diff --git a/src/main/java/org/opentripplanner/api/model/ApiCurrency.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiCurrency.java similarity index 71% rename from src/main/java/org/opentripplanner/api/model/ApiCurrency.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiCurrency.java index 3835f7986ca..b3cff1eaa93 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiCurrency.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiCurrency.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; public record ApiCurrency( String currency, diff --git a/src/main/java/org/opentripplanner/api/model/ApiFareComponent.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareComponent.java similarity index 76% rename from src/main/java/org/opentripplanner/api/model/ApiFareComponent.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareComponent.java index 8d6038c487a..e26f859c4f2 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiFareComponent.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareComponent.java @@ -1,7 +1,6 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.List; -import java.util.Optional; import org.opentripplanner.transit.model.framework.FeedScopedId; public record ApiFareComponent( diff --git a/src/main/java/org/opentripplanner/api/model/ApiFareProduct.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareProduct.java similarity index 91% rename from src/main/java/org/opentripplanner/api/model/ApiFareProduct.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareProduct.java index 2beb991855d..af8561b73cb 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiFareProduct.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareProduct.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** * A Fares V2 product. This is a type of ticket or monthly pass that customers can buy. diff --git a/src/main/java/org/opentripplanner/api/model/ApiFareQualifier.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareQualifier.java similarity index 83% rename from src/main/java/org/opentripplanner/api/model/ApiFareQualifier.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareQualifier.java index 702caca7a0f..94a3731863a 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiFareQualifier.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFareQualifier.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** * Qualifiers for Fares V2 fare products. Qualifiers can be rider categories (youth, senior, veteran) or diff --git a/src/main/java/org/opentripplanner/api/model/ApiFeedInfo.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFeedInfo.java similarity index 93% rename from src/main/java/org/opentripplanner/api/model/ApiFeedInfo.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiFeedInfo.java index a1614ba6391..1b96ee0759d 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiFeedInfo.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiFeedInfo.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import java.util.Objects; diff --git a/src/main/java/org/opentripplanner/api/model/ApiItinerary.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiItinerary.java similarity index 98% rename from src/main/java/org/opentripplanner/api/model/ApiItinerary.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiItinerary.java index e2d205de13e..0bce9426fd8 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiItinerary.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiItinerary.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.ArrayList; import java.util.Calendar; diff --git a/src/main/java/org/opentripplanner/api/model/ApiItineraryFares.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiItineraryFares.java similarity index 92% rename from src/main/java/org/opentripplanner/api/model/ApiItineraryFares.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiItineraryFares.java index e908a81b452..a7140e59d4d 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiItineraryFares.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiItineraryFares.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.List; import java.util.Map; diff --git a/src/main/java/org/opentripplanner/api/model/ApiLeg.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiLeg.java similarity index 99% rename from src/main/java/org/opentripplanner/api/model/ApiLeg.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiLeg.java index 87be725615d..7bbd83f7c2d 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiLeg.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiLeg.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.Calendar; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiLegProducts.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiLegProducts.java similarity index 88% rename from src/main/java/org/opentripplanner/api/model/ApiLegProducts.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiLegProducts.java index ef7d95a3abf..abd4643100b 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiLegProducts.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiLegProducts.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.Collection; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiMoney.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiMoney.java similarity index 56% rename from src/main/java/org/opentripplanner/api/model/ApiMoney.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiMoney.java index a9a27e828ae..a5f3f840bf6 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiMoney.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiMoney.java @@ -1,3 +1,3 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; public record ApiMoney(int cents, ApiCurrency currency) {} diff --git a/src/main/java/org/opentripplanner/api/model/ApiPatternDetail.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiPatternDetail.java similarity index 87% rename from src/main/java/org/opentripplanner/api/model/ApiPatternDetail.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiPatternDetail.java index 1acb3acb6d5..d24f7f35c12 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiPatternDetail.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiPatternDetail.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.ArrayList; import java.util.Collection; diff --git a/src/main/java/org/opentripplanner/api/model/ApiPatternShort.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiPatternShort.java similarity index 68% rename from src/main/java/org/opentripplanner/api/model/ApiPatternShort.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiPatternShort.java index 0adcb6c2f18..d2acd234f47 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiPatternShort.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiPatternShort.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; public class ApiPatternShort { diff --git a/src/main/java/org/opentripplanner/api/model/ApiPlace.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiPlace.java similarity index 97% rename from src/main/java/org/opentripplanner/api/model/ApiPlace.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiPlace.java index 3ac922059ee..7cfe3bc7c22 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiPlace.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiPlace.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.Calendar; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiRealTimeState.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRealTimeState.java similarity index 96% rename from src/main/java/org/opentripplanner/api/model/ApiRealTimeState.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiRealTimeState.java index df307007157..d9a068349ec 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiRealTimeState.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRealTimeState.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import org.opentripplanner.transit.model.timetable.RealTimeState; diff --git a/src/main/java/org/opentripplanner/api/model/ApiRelativeDirection.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRelativeDirection.java similarity index 90% rename from src/main/java/org/opentripplanner/api/model/ApiRelativeDirection.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiRelativeDirection.java index e8e1553d51f..02a530f06de 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiRelativeDirection.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRelativeDirection.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** * Represents a turn direction, relative to the current heading. diff --git a/src/main/java/org/opentripplanner/api/model/ApiRoute.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRoute.java similarity index 95% rename from src/main/java/org/opentripplanner/api/model/ApiRoute.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiRoute.java index 1826091f210..d4ce90d9b23 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiRoute.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRoute.java @@ -1,5 +1,5 @@ /* This file is based on code copied from project OneBusAway, see the LICENSE file for further information. */ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import java.util.Objects; diff --git a/src/main/java/org/opentripplanner/api/model/ApiRouteShort.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouteShort.java similarity index 85% rename from src/main/java/org/opentripplanner/api/model/ApiRouteShort.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouteShort.java index db74e2514cc..a62dcc4bdb6 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiRouteShort.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouteShort.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; public class ApiRouteShort { diff --git a/src/main/java/org/opentripplanner/api/model/ApiRouterInfo.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouterInfo.java similarity index 97% rename from src/main/java/org/opentripplanner/api/model/ApiRouterInfo.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouterInfo.java index 3c08defcba5..a0bbb1116b3 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiRouterInfo.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouterInfo.java @@ -1,9 +1,9 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.Date; import java.util.List; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.ModeMapper; +import org.opentripplanner.ext.restapi.mapping.ModeMapper; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.vehicle_parking.VehicleParkingService; import org.opentripplanner.service.vehiclerental.VehicleRentalService; diff --git a/src/main/java/org/opentripplanner/api/model/ApiRouterList.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouterList.java similarity index 75% rename from src/main/java/org/opentripplanner/api/model/ApiRouterList.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouterList.java index ec412716202..dd7ef3544af 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiRouterList.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiRouterList.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiStop.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiStop.java similarity index 96% rename from src/main/java/org/opentripplanner/api/model/ApiStop.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiStop.java index b2604268f76..abe4adb623a 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiStop.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiStop.java @@ -1,5 +1,5 @@ /* This file is based on code copied from project OneBusAway, see the LICENSE file for further information. */ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import java.util.Objects; diff --git a/src/main/java/org/opentripplanner/api/model/ApiStopShort.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiStopShort.java similarity index 92% rename from src/main/java/org/opentripplanner/api/model/ApiStopShort.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiStopShort.java index 3fe4daf7c4c..1eafd760248 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiStopShort.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiStopShort.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/src/main/java/org/opentripplanner/api/model/ApiStopTimesInPattern.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiStopTimesInPattern.java similarity index 74% rename from src/main/java/org/opentripplanner/api/model/ApiStopTimesInPattern.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiStopTimesInPattern.java index c0069c1662a..405c200651b 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiStopTimesInPattern.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiStopTimesInPattern.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiSystemNotice.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiSystemNotice.java similarity index 95% rename from src/main/java/org/opentripplanner/api/model/ApiSystemNotice.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiSystemNotice.java index ab95bc2034d..dc7eb51177e 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiSystemNotice.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiSystemNotice.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import org.opentripplanner.routing.alertpatch.TransitAlert; import org.opentripplanner.transit.model.basic.Notice; diff --git a/src/main/java/org/opentripplanner/api/model/ApiTransfer.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTransfer.java similarity index 82% rename from src/main/java/org/opentripplanner/api/model/ApiTransfer.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTransfer.java index a9d45aac4c1..38cede8c1f1 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTransfer.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTransfer.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** Represents a transfer from a stop */ public class ApiTransfer { diff --git a/src/main/java/org/opentripplanner/api/model/ApiTravelOption.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTravelOption.java similarity index 97% rename from src/main/java/org/opentripplanner/api/model/ApiTravelOption.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTravelOption.java index 06b186969b0..d09de672d91 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTravelOption.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTravelOption.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.HashSet; import java.util.Objects; diff --git a/src/main/java/org/opentripplanner/api/model/ApiTravelOptionsMaker.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTravelOptionsMaker.java similarity index 98% rename from src/main/java/org/opentripplanner/api/model/ApiTravelOptionsMaker.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTravelOptionsMaker.java index 5c0109f8baf..cf424392d70 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTravelOptionsMaker.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTravelOptionsMaker.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiTrip.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTrip.java similarity index 96% rename from src/main/java/org/opentripplanner/api/model/ApiTrip.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTrip.java index 947991ac392..3ff0626c9a8 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTrip.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTrip.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; import java.util.Objects; diff --git a/src/main/java/org/opentripplanner/api/model/ApiTripPlan.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripPlan.java similarity index 90% rename from src/main/java/org/opentripplanner/api/model/ApiTripPlan.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripPlan.java index 7c62b6cdd66..bfb812b69c3 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTripPlan.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripPlan.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.ArrayList; import java.util.Date; diff --git a/src/main/java/org/opentripplanner/api/model/ApiTripSearchMetadata.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripSearchMetadata.java similarity index 98% rename from src/main/java/org/opentripplanner/api/model/ApiTripSearchMetadata.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripSearchMetadata.java index 486118883f9..abe5a74337f 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTripSearchMetadata.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripSearchMetadata.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** * Meta-data about the trip search performed. diff --git a/src/main/java/org/opentripplanner/api/model/ApiTripShort.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripShort.java similarity index 77% rename from src/main/java/org/opentripplanner/api/model/ApiTripShort.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripShort.java index 17560af64ce..cedfa471d4a 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTripShort.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripShort.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; public class ApiTripShort { diff --git a/src/main/java/org/opentripplanner/api/model/ApiTripTimeShort.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripTimeShort.java similarity index 93% rename from src/main/java/org/opentripplanner/api/model/ApiTripTimeShort.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripTimeShort.java index 0a340d4a812..21c6010c5a2 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiTripTimeShort.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiTripTimeShort.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.io.Serializable; diff --git a/src/main/java/org/opentripplanner/api/model/ApiVehicleParkingSpaces.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleParkingSpaces.java similarity index 97% rename from src/main/java/org/opentripplanner/api/model/ApiVehicleParkingSpaces.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleParkingSpaces.java index 8c4ab4b8fee..bcb10e70f0f 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiVehicleParkingSpaces.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleParkingSpaces.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; public class ApiVehicleParkingSpaces { diff --git a/src/main/java/org/opentripplanner/api/model/ApiVehicleParkingWithEntrance.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleParkingWithEntrance.java similarity index 99% rename from src/main/java/org/opentripplanner/api/model/ApiVehicleParkingWithEntrance.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleParkingWithEntrance.java index 8cac78f6c9e..68a9f37dfe4 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiVehicleParkingWithEntrance.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleParkingWithEntrance.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiVehicleRentalStation.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleRentalStation.java similarity index 95% rename from src/main/java/org/opentripplanner/api/model/ApiVehicleRentalStation.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleRentalStation.java index 354961bae16..8431ac5c387 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiVehicleRentalStation.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleRentalStation.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.List; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; diff --git a/src/main/java/org/opentripplanner/api/model/ApiVehicleRentalStationList.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleRentalStationList.java similarity index 78% rename from src/main/java/org/opentripplanner/api/model/ApiVehicleRentalStationList.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleRentalStationList.java index ed74f8a7ab7..c97a18c337e 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiVehicleRentalStationList.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVehicleRentalStationList.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/model/ApiVertexType.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVertexType.java similarity index 81% rename from src/main/java/org/opentripplanner/api/model/ApiVertexType.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiVertexType.java index 3bcc4034272..595f0628e0a 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiVertexType.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiVertexType.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; /** * Represent type of vertex, used in Place aka from, to in API for easier client side localization diff --git a/src/main/java/org/opentripplanner/api/model/ApiWalkStep.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiWalkStep.java similarity index 98% rename from src/main/java/org/opentripplanner/api/model/ApiWalkStep.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ApiWalkStep.java index 5e810d98602..363a01cb7b5 100644 --- a/src/main/java/org/opentripplanner/api/model/ApiWalkStep.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ApiWalkStep.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.ext.restapi.model; import java.util.List; diff --git a/src/main/java/org/opentripplanner/api/resource/ElevationMetadata.java b/src/ext/java/org/opentripplanner/ext/restapi/model/ElevationMetadata.java similarity index 83% rename from src/main/java/org/opentripplanner/api/resource/ElevationMetadata.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/ElevationMetadata.java index 7b11f5fa736..b885883b17e 100644 --- a/src/main/java/org/opentripplanner/api/resource/ElevationMetadata.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/ElevationMetadata.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.ext.restapi.model; /** * Contains elevation-specific metadata to be included in the response diff --git a/src/main/java/org/opentripplanner/api/resource/TripPlannerResponse.java b/src/ext/java/org/opentripplanner/ext/restapi/model/TripPlannerResponse.java similarity index 94% rename from src/main/java/org/opentripplanner/api/resource/TripPlannerResponse.java rename to src/ext/java/org/opentripplanner/ext/restapi/model/TripPlannerResponse.java index 970acad5ac2..28cce2dd669 100644 --- a/src/main/java/org/opentripplanner/api/resource/TripPlannerResponse.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/model/TripPlannerResponse.java @@ -1,12 +1,11 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.ext.restapi.model; import jakarta.ws.rs.core.UriInfo; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; -import org.opentripplanner.api.model.ApiTripPlan; -import org.opentripplanner.api.model.ApiTripSearchMetadata; -import org.opentripplanner.api.model.error.PlannerError; +import org.opentripplanner.api.error.PlannerError; +import org.opentripplanner.api.resource.DebugOutput; /** Represents a trip planner response, will be serialized into XML or JSON by Jersey */ public class TripPlannerResponse { diff --git a/src/main/java/org/opentripplanner/api/resource/BikeRental.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/BikeRental.java similarity index 91% rename from src/main/java/org/opentripplanner/api/resource/BikeRental.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/BikeRental.java index fdac9b39023..0da598f8a3f 100644 --- a/src/main/java/org/opentripplanner/api/resource/BikeRental.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/BikeRental.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.ext.restapi.resources; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -12,9 +12,9 @@ import java.util.List; import java.util.Locale; import org.locationtech.jts.geom.Envelope; -import org.opentripplanner.api.mapping.VehicleRentalStationMapper; -import org.opentripplanner.api.model.ApiVehicleRentalStation; -import org.opentripplanner.api.model.ApiVehicleRentalStationList; +import org.opentripplanner.ext.restapi.mapping.VehicleRentalStationMapper; +import org.opentripplanner.ext.restapi.model.ApiVehicleRentalStation; +import org.opentripplanner.ext.restapi.model.ApiVehicleRentalStationList; import org.opentripplanner.service.vehiclerental.VehicleRentalService; import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; import org.opentripplanner.standalone.api.OtpServerRequestContext; diff --git a/src/main/java/org/opentripplanner/index/IndexAPI.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/IndexAPI.java similarity index 93% rename from src/main/java/org/opentripplanner/index/IndexAPI.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/IndexAPI.java index 74eba3a60b8..5bdda8a57a2 100644 --- a/src/main/java/org/opentripplanner/index/IndexAPI.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/IndexAPI.java @@ -1,4 +1,4 @@ -package org.opentripplanner.index; +package org.opentripplanner.ext.restapi.resources; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.DefaultValue; @@ -25,31 +25,31 @@ import java.util.stream.Collectors; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; -import org.opentripplanner.api.mapping.AgencyMapper; -import org.opentripplanner.api.mapping.AlertMapper; -import org.opentripplanner.api.mapping.FeedInfoMapper; -import org.opentripplanner.api.mapping.FeedScopedIdMapper; -import org.opentripplanner.api.mapping.RouteMapper; -import org.opentripplanner.api.mapping.StopMapper; -import org.opentripplanner.api.mapping.StopTimesInPatternMapper; -import org.opentripplanner.api.mapping.TransferMapper; -import org.opentripplanner.api.mapping.TripMapper; -import org.opentripplanner.api.mapping.TripPatternMapper; -import org.opentripplanner.api.mapping.TripTimeMapper; -import org.opentripplanner.api.model.ApiAgency; -import org.opentripplanner.api.model.ApiAlert; -import org.opentripplanner.api.model.ApiFeedInfo; -import org.opentripplanner.api.model.ApiPatternShort; -import org.opentripplanner.api.model.ApiRoute; -import org.opentripplanner.api.model.ApiRouteShort; -import org.opentripplanner.api.model.ApiStop; -import org.opentripplanner.api.model.ApiStopShort; -import org.opentripplanner.api.model.ApiStopTimesInPattern; -import org.opentripplanner.api.model.ApiTransfer; -import org.opentripplanner.api.model.ApiTrip; -import org.opentripplanner.api.model.ApiTripShort; -import org.opentripplanner.api.model.ApiTripTimeShort; -import org.opentripplanner.api.support.SemanticHash; +import org.opentripplanner.apis.support.SemanticHash; +import org.opentripplanner.ext.restapi.mapping.AgencyMapper; +import org.opentripplanner.ext.restapi.mapping.AlertMapper; +import org.opentripplanner.ext.restapi.mapping.FeedInfoMapper; +import org.opentripplanner.ext.restapi.mapping.FeedScopedIdMapper; +import org.opentripplanner.ext.restapi.mapping.RouteMapper; +import org.opentripplanner.ext.restapi.mapping.StopMapper; +import org.opentripplanner.ext.restapi.mapping.StopTimesInPatternMapper; +import org.opentripplanner.ext.restapi.mapping.TransferMapper; +import org.opentripplanner.ext.restapi.mapping.TripMapper; +import org.opentripplanner.ext.restapi.mapping.TripPatternMapper; +import org.opentripplanner.ext.restapi.mapping.TripTimeMapper; +import org.opentripplanner.ext.restapi.model.ApiAgency; +import org.opentripplanner.ext.restapi.model.ApiAlert; +import org.opentripplanner.ext.restapi.model.ApiFeedInfo; +import org.opentripplanner.ext.restapi.model.ApiPatternShort; +import org.opentripplanner.ext.restapi.model.ApiRoute; +import org.opentripplanner.ext.restapi.model.ApiRouteShort; +import org.opentripplanner.ext.restapi.model.ApiStop; +import org.opentripplanner.ext.restapi.model.ApiStopShort; +import org.opentripplanner.ext.restapi.model.ApiStopTimesInPattern; +import org.opentripplanner.ext.restapi.model.ApiTransfer; +import org.opentripplanner.ext.restapi.model.ApiTrip; +import org.opentripplanner.ext.restapi.model.ApiTripShort; +import org.opentripplanner.ext.restapi.model.ApiTripTimeShort; import org.opentripplanner.framework.geometry.EncodedPolyline; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.StopTimesInPattern; diff --git a/src/main/java/org/opentripplanner/api/resource/PlannerResource.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/PlannerResource.java similarity index 92% rename from src/main/java/org/opentripplanner/api/resource/PlannerResource.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/PlannerResource.java index bb2b4f1020a..38c70851b76 100644 --- a/src/main/java/org/opentripplanner/api/resource/PlannerResource.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/PlannerResource.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.ext.restapi.resources; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -10,11 +10,12 @@ import jakarta.ws.rs.core.UriInfo; import org.glassfish.grizzly.http.server.Request; import org.opentripplanner.api.common.Message; -import org.opentripplanner.api.common.RoutingResource; -import org.opentripplanner.api.mapping.PlannerErrorMapper; -import org.opentripplanner.api.mapping.TripPlanMapper; -import org.opentripplanner.api.mapping.TripSearchMetadataMapper; -import org.opentripplanner.api.model.error.PlannerError; +import org.opentripplanner.api.error.PlannerError; +import org.opentripplanner.apis.support.mapping.PlannerErrorMapper; +import org.opentripplanner.ext.restapi.mapping.TripPlanMapper; +import org.opentripplanner.ext.restapi.mapping.TripSearchMetadataMapper; +import org.opentripplanner.ext.restapi.model.ElevationMetadata; +import org.opentripplanner.ext.restapi.model.TripPlannerResponse; import org.opentripplanner.framework.application.OTPRequestTimeoutException; import org.opentripplanner.routing.api.request.RouteRequest; import org.opentripplanner.routing.api.response.RoutingResponse; diff --git a/src/main/java/org/opentripplanner/api/common/RequestToPreferencesMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java similarity index 97% rename from src/main/java/org/opentripplanner/api/common/RequestToPreferencesMapper.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java index 6ccc8d3ca47..d09645832cb 100644 --- a/src/main/java/org/opentripplanner/api/common/RequestToPreferencesMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/RequestToPreferencesMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.common; +package org.opentripplanner.ext.restapi.resources; import jakarta.validation.constraints.NotNull; import java.util.function.Consumer; @@ -97,10 +97,8 @@ private BoardAndAlightSlack mapTransit() { setIfNotNull(req.otherThanPreferredRoutesPenalty, tr::setOtherThanPreferredRoutesPenalty); setIfNotNull(req.ignoreRealtimeUpdates, tr::setIgnoreRealtimeUpdates); - if (req.relaxTransitPriorityGroup != null) { - tr.withTransitGroupPriorityGeneralizedCostSlack( - CostLinearFunction.of(req.relaxTransitPriorityGroup) - ); + if (req.relaxTransitGroupPriority != null) { + tr.withRelaxTransitGroupPriority(CostLinearFunction.of(req.relaxTransitGroupPriority)); } else { setIfNotNull( req.relaxTransitSearchGeneralizedCostAtDestination, diff --git a/src/main/java/org/opentripplanner/api/resource/Routers.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/Routers.java similarity index 93% rename from src/main/java/org/opentripplanner/api/resource/Routers.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/Routers.java index 63ed28fbea3..9cfab49017c 100644 --- a/src/main/java/org/opentripplanner/api/resource/Routers.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/Routers.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.ext.restapi.resources; import jakarta.annotation.security.PermitAll; import jakarta.ws.rs.GET; @@ -7,8 +7,8 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; -import org.opentripplanner.api.model.ApiRouterInfo; -import org.opentripplanner.api.model.ApiRouterList; +import org.opentripplanner.ext.restapi.model.ApiRouterInfo; +import org.opentripplanner.ext.restapi.model.ApiRouterList; import org.opentripplanner.routing.error.GraphNotFoundException; import org.opentripplanner.standalone.api.OtpServerRequestContext; diff --git a/src/main/java/org/opentripplanner/api/common/RoutingResource.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java similarity index 99% rename from src/main/java/org/opentripplanner/api/common/RoutingResource.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java index 8e7501c77fd..5746317039e 100644 --- a/src/main/java/org/opentripplanner/api/common/RoutingResource.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/RoutingResource.java @@ -1,7 +1,7 @@ -package org.opentripplanner.api.common; +package org.opentripplanner.ext.restapi.resources; import static org.opentripplanner.api.common.LocationStringParser.fromOldStyleString; -import static org.opentripplanner.api.common.RequestToPreferencesMapper.setIfNotNull; +import static org.opentripplanner.ext.restapi.resources.RequestToPreferencesMapper.setIfNotNull; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.QueryParam; @@ -658,8 +658,8 @@ public abstract class RoutingResource { @QueryParam("useVehicleParkingAvailabilityInformation") protected Boolean useVehicleParkingAvailabilityInformation; - @QueryParam("relaxTransitPriorityGroup") - protected String relaxTransitPriorityGroup; + @QueryParam("relaxTransitGroupPriority") + protected String relaxTransitGroupPriority; /** * Whether non-optimal transit paths at the destination should be returned. diff --git a/src/main/java/org/opentripplanner/index/ValidateParameters.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/ValidateParameters.java similarity index 96% rename from src/main/java/org/opentripplanner/index/ValidateParameters.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/ValidateParameters.java index 41149ac31e3..5a94ca318f7 100644 --- a/src/main/java/org/opentripplanner/index/ValidateParameters.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/ValidateParameters.java @@ -1,4 +1,4 @@ -package org.opentripplanner.index; +package org.opentripplanner.ext.restapi.resources; import jakarta.ws.rs.BadRequestException; import java.util.HashSet; diff --git a/src/main/java/org/opentripplanner/api/resource/package-info.java b/src/ext/java/org/opentripplanner/ext/restapi/resources/package-info.java similarity index 74% rename from src/main/java/org/opentripplanner/api/resource/package-info.java rename to src/ext/java/org/opentripplanner/ext/restapi/resources/package-info.java index 4d67f4b2100..7b66666ee5d 100644 --- a/src/main/java/org/opentripplanner/api/resource/package-info.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/resources/package-info.java @@ -2,4 +2,4 @@ * This package contains the JAX-RS-annotated REST resource classes for the OpenTripPlanner public * API, i.e. the Jersey REST endpoints. */ -package org.opentripplanner.api.resource; +package org.opentripplanner.ext.restapi.resources; diff --git a/src/main/java/org/opentripplanner/api/json/FeedScopedIdDeserializer.java b/src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdDeserializer.java similarity index 94% rename from src/main/java/org/opentripplanner/api/json/FeedScopedIdDeserializer.java rename to src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdDeserializer.java index aaccc900c1c..75b1b58bfee 100644 --- a/src/main/java/org/opentripplanner/api/json/FeedScopedIdDeserializer.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdDeserializer.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.json; +package org.opentripplanner.ext.restapi.serialization; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/src/main/java/org/opentripplanner/api/json/FeedScopedIdKeyDeserializer.java b/src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdKeyDeserializer.java similarity index 91% rename from src/main/java/org/opentripplanner/api/json/FeedScopedIdKeyDeserializer.java rename to src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdKeyDeserializer.java index a59f46e1052..75270e9dd0b 100644 --- a/src/main/java/org/opentripplanner/api/json/FeedScopedIdKeyDeserializer.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdKeyDeserializer.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.json; +package org.opentripplanner.ext.restapi.serialization; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.KeyDeserializer; diff --git a/src/main/java/org/opentripplanner/api/json/FeedScopedIdSerializer.java b/src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdSerializer.java similarity index 96% rename from src/main/java/org/opentripplanner/api/json/FeedScopedIdSerializer.java rename to src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdSerializer.java index 1e357f642b1..c9c67e675c4 100644 --- a/src/main/java/org/opentripplanner/api/json/FeedScopedIdSerializer.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/serialization/FeedScopedIdSerializer.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.json; +package org.opentripplanner.ext.restapi.serialization; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/src/main/java/org/opentripplanner/api/json/JSONObjectMapperProvider.java b/src/ext/java/org/opentripplanner/ext/restapi/serialization/JSONObjectMapperProvider.java similarity index 98% rename from src/main/java/org/opentripplanner/api/json/JSONObjectMapperProvider.java rename to src/ext/java/org/opentripplanner/ext/restapi/serialization/JSONObjectMapperProvider.java index d4138563fc7..e271e945ca1 100644 --- a/src/main/java/org/opentripplanner/api/json/JSONObjectMapperProvider.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/serialization/JSONObjectMapperProvider.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.json; +package org.opentripplanner.ext.restapi.serialization; import com.bedatadriven.jackson.datatype.jts.JtsModule; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/VectorTilesResource.java b/src/ext/java/org/opentripplanner/ext/vectortiles/VectorTilesResource.java index f22145d261d..af2715d6928 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/VectorTilesResource.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/VectorTilesResource.java @@ -17,7 +17,7 @@ import java.util.Objects; import java.util.function.Predicate; import org.glassfish.grizzly.http.server.Request; -import org.opentripplanner.api.model.TileJson; +import org.opentripplanner.apis.support.TileJson; import org.opentripplanner.ext.vectortiles.layers.stations.StationsLayerBuilder; import org.opentripplanner.ext.vectortiles.layers.stops.StopsLayerBuilder; import org.opentripplanner.ext.vectortiles.layers.vehicleparkings.VehicleParkingGroupsLayerBuilder; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/DigitransitStationPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/DigitransitStationPropertyMapper.java index b706a0ae8c3..a828cd37a7c 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/DigitransitStationPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/DigitransitStationPropertyMapper.java @@ -6,8 +6,8 @@ import java.util.Map; import java.util.stream.Collectors; import org.json.simple.JSONArray; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.site.Station; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/StationsLayerBuilder.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/StationsLayerBuilder.java index 56e8be7b3e4..449a1489d89 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/StationsLayerBuilder.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stations/StationsLayerBuilder.java @@ -9,7 +9,7 @@ import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.ext.vectortiles.VectorTilesResource; import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.inspector.vector.LayerBuilder; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/DigitransitStopPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/DigitransitStopPropertyMapper.java index 502adc7899f..2c5a4519e96 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/DigitransitStopPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/DigitransitStopPropertyMapper.java @@ -8,8 +8,8 @@ import java.util.stream.Collectors; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.site.RegularStop; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/StopsLayerBuilder.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/StopsLayerBuilder.java index b6558f3cbe5..6d15816669e 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/StopsLayerBuilder.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/stops/StopsLayerBuilder.java @@ -7,7 +7,7 @@ import java.util.stream.Collectors; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.ext.vectortiles.VectorTilesResource; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingGroupPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingGroupPropertyMapper.java index a5bb4ae2c8b..33f415c157a 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingGroupPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingGroupPropertyMapper.java @@ -5,8 +5,8 @@ import java.util.Locale; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; public class DigitransitVehicleParkingGroupPropertyMapper diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingPropertyMapper.java index 993675dcf06..892d4907395 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/DigitransitVehicleParkingPropertyMapper.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Locale; import javax.annotation.Nonnull; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.routing.vehicle_parking.VehicleParking; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/StadtnaviVehicleParkingPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/StadtnaviVehicleParkingPropertyMapper.java index 0e7c5cd90e8..c938f9736fd 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/StadtnaviVehicleParkingPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/StadtnaviVehicleParkingPropertyMapper.java @@ -4,8 +4,8 @@ import java.util.List; import java.util.Locale; import org.json.simple.JSONObject; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.model.calendar.openinghours.OsmOpeningHoursSupport; import org.opentripplanner.routing.vehicle_parking.VehicleParking; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingGroupsLayerBuilder.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingGroupsLayerBuilder.java index f39d042ad6e..0cd1d84868b 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingGroupsLayerBuilder.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingGroupsLayerBuilder.java @@ -8,7 +8,7 @@ import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.ext.vectortiles.VectorTilesResource; import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.inspector.vector.LayerBuilder; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingsLayerBuilder.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingsLayerBuilder.java index 66dde2e4258..95326172415 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingsLayerBuilder.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehicleparkings/VehicleParkingsLayerBuilder.java @@ -11,7 +11,7 @@ import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.ext.vectortiles.VectorTilesResource; import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.inspector.vector.LayerBuilder; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/VehicleRentalLayerBuilder.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/VehicleRentalLayerBuilder.java index 4e181ed4fa1..0869aeb2ba8 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/VehicleRentalLayerBuilder.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/VehicleRentalLayerBuilder.java @@ -7,7 +7,7 @@ import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.ext.vectortiles.VectorTilesResource; import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.inspector.vector.LayerBuilder; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRealtimeVehicleRentalStationPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRealtimeVehicleRentalStationPropertyMapper.java index a6f2aa63fd4..4ceb7124d52 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRealtimeVehicleRentalStationPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRealtimeVehicleRentalStationPropertyMapper.java @@ -7,8 +7,8 @@ import java.util.Collection; import java.util.List; import java.util.Locale; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRentalVehiclePropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRentalVehiclePropertyMapper.java index e1093467d4d..33e661866bc 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRentalVehiclePropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitRentalVehiclePropertyMapper.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Collection; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalPropertyMapper.java index 1839edf8905..3114b072934 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalPropertyMapper.java @@ -3,8 +3,8 @@ import java.util.Collection; import java.util.List; import java.util.Locale; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; diff --git a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalStationPropertyMapper.java b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalStationPropertyMapper.java index 962c1db4b04..67fb00efa85 100644 --- a/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalStationPropertyMapper.java +++ b/src/ext/java/org/opentripplanner/ext/vectortiles/layers/vehiclerental/mapper/DigitransitVehicleRentalStationPropertyMapper.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Locale; import java.util.stream.Collectors; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation; diff --git a/src/main/java/org/opentripplanner/api/model/error/PlannerError.java b/src/main/java/org/opentripplanner/api/error/PlannerError.java similarity index 94% rename from src/main/java/org/opentripplanner/api/model/error/PlannerError.java rename to src/main/java/org/opentripplanner/api/error/PlannerError.java index a41a3f6148a..1a35275a7cd 100644 --- a/src/main/java/org/opentripplanner/api/model/error/PlannerError.java +++ b/src/main/java/org/opentripplanner/api/error/PlannerError.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model.error; +package org.opentripplanner.api.error; import java.util.List; import org.opentripplanner.api.common.Message; diff --git a/src/main/java/org/opentripplanner/api/package.md b/src/main/java/org/opentripplanner/api/package.md deleted file mode 100644 index 5498b2e4c47..00000000000 --- a/src/main/java/org/opentripplanner/api/package.md +++ /dev/null @@ -1,8 +0,0 @@ -# OTP REST API - -This package contains the code which exposes OpenTripPlanner services to the outside world as a REST -API. This includes Jersey REST resource classes (in the "resource" subpackage, picked up by Jersey's -package scanning process), and the classes modeling the structure of the response (in the "model" -subpackage). We provide OTP with the REST API as a embedded standalone Grizzly-based command-line -server. - diff --git a/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java b/src/main/java/org/opentripplanner/apis/APIEndpoints.java similarity index 83% rename from src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java rename to src/main/java/org/opentripplanner/apis/APIEndpoints.java index b0d38aa00cd..32d893618cc 100644 --- a/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java +++ b/src/main/java/org/opentripplanner/apis/APIEndpoints.java @@ -1,11 +1,12 @@ -package org.opentripplanner.api.configuration; +package org.opentripplanner.apis; import static org.opentripplanner.framework.application.OTPFeature.APIBikeRental; -import static org.opentripplanner.framework.application.OTPFeature.APIGraphInspectorTile; import static org.opentripplanner.framework.application.OTPFeature.APIServerInfo; import static org.opentripplanner.framework.application.OTPFeature.APIUpdaterStatus; import static org.opentripplanner.framework.application.OTPFeature.ActuatorAPI; +import static org.opentripplanner.framework.application.OTPFeature.DebugUi; import static org.opentripplanner.framework.application.OTPFeature.GtfsGraphQlApi; +import static org.opentripplanner.framework.application.OTPFeature.LegacyRestApi; import static org.opentripplanner.framework.application.OTPFeature.ReportApi; import static org.opentripplanner.framework.application.OTPFeature.SandboxAPIGeocoder; import static org.opentripplanner.framework.application.OTPFeature.SandboxAPIMapboxVectorTilesApi; @@ -17,23 +18,23 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import org.opentripplanner.api.resource.BikeRental; import org.opentripplanner.api.resource.GraphInspectorTileResource; -import org.opentripplanner.api.resource.GraphInspectorVectorTileResource; -import org.opentripplanner.api.resource.PlannerResource; -import org.opentripplanner.api.resource.Routers; import org.opentripplanner.api.resource.ServerInfo; import org.opentripplanner.api.resource.UpdaterStatusResource; import org.opentripplanner.apis.gtfs.GtfsGraphQLAPI; import org.opentripplanner.apis.transmodel.TransmodelAPI; +import org.opentripplanner.apis.vectortiles.GraphInspectorVectorTileResource; import org.opentripplanner.ext.actuator.ActuatorAPI; import org.opentripplanner.ext.geocoder.GeocoderResource; import org.opentripplanner.ext.parkAndRideApi.ParkAndRideResource; import org.opentripplanner.ext.reportapi.resource.ReportResource; +import org.opentripplanner.ext.restapi.resources.BikeRental; +import org.opentripplanner.ext.restapi.resources.IndexAPI; +import org.opentripplanner.ext.restapi.resources.PlannerResource; +import org.opentripplanner.ext.restapi.resources.Routers; import org.opentripplanner.ext.traveltime.TravelTimeResource; import org.opentripplanner.ext.vectortiles.VectorTilesResource; import org.opentripplanner.framework.application.OTPFeature; -import org.opentripplanner.index.IndexAPI; /** * Configure API resource endpoints. @@ -43,18 +44,12 @@ public class APIEndpoints { private final List> resources = new ArrayList<>(); private APIEndpoints() { - // Add mandatory APIs - add(Routers.class); - add(PlannerResource.class); - add(IndexAPI.class); - // Add feature enabled APIs, these can be enabled by default, some is not. // See the OTPFeature enum for details. - addIfEnabled(APIBikeRental, BikeRental.class); - addIfEnabled(APIGraphInspectorTile, GraphInspectorTileResource.class); - addIfEnabled(APIGraphInspectorTile, GraphInspectorVectorTileResource.class); addIfEnabled(APIServerInfo, ServerInfo.class); addIfEnabled(APIUpdaterStatus, UpdaterStatusResource.class); + addIfEnabled(DebugUi, GraphInspectorTileResource.class); + addIfEnabled(DebugUi, GraphInspectorVectorTileResource.class); addIfEnabled(GtfsGraphQlApi, GtfsGraphQLAPI.class); addIfEnabled(TransmodelGraphQlApi, TransmodelAPI.class); @@ -65,6 +60,12 @@ private APIEndpoints() { addIfEnabled(SandboxAPIParkAndRideApi, ParkAndRideResource.class); addIfEnabled(SandboxAPIGeocoder, GeocoderResource.class); addIfEnabled(SandboxAPITravelTime, TravelTimeResource.class); + + // scheduled to be removed + addIfEnabled(APIBikeRental, BikeRental.class); + addIfEnabled(LegacyRestApi, Routers.class); + addIfEnabled(LegacyRestApi, PlannerResource.class); + addIfEnabled(LegacyRestApi, IndexAPI.class); } /** diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLAPI.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLAPI.java index 20d15b1cfe8..b9b93190816 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLAPI.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLAPI.java @@ -21,7 +21,7 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Future; -import org.opentripplanner.api.json.GraphQLResponseSerializer; +import org.opentripplanner.framework.graphql.GraphQLResponseSerializer; import org.opentripplanner.standalone.api.OtpServerRequestContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index c70836a581f..b50bbaa9b9e 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -26,7 +26,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.opentripplanner.api.json.GraphQLResponseSerializer; import org.opentripplanner.apis.gtfs.datafetchers.AgencyImpl; import org.opentripplanner.apis.gtfs.datafetchers.AlertEntityTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.AlertImpl; @@ -88,6 +87,7 @@ import org.opentripplanner.ext.actuator.MicrometerGraphQLInstrumentation; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.framework.concurrent.OtpRequestThreadFactory; +import org.opentripplanner.framework.graphql.GraphQLResponseSerializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java index b13f6123d4d..639cb95bf28 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java @@ -6,11 +6,11 @@ import java.util.Objects; import java.util.stream.Collectors; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.LocalDateMapper; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; import org.opentripplanner.apis.gtfs.mapping.NumberMapper; +import org.opentripplanner.ext.restapi.mapping.LocalDateMapper; import org.opentripplanner.ext.ridehailing.model.RideEstimate; import org.opentripplanner.ext.ridehailing.model.RideHailingLeg; import org.opentripplanner.framework.graphql.GraphQLUtils; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PatternImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PatternImpl.java index 241434c664f..88db00c3c4e 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PatternImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PatternImpl.java @@ -13,10 +13,10 @@ import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; -import org.opentripplanner.api.support.SemanticHash; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; +import org.opentripplanner.apis.support.SemanticHash; import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.routing.alertpatch.EntitySelector; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlanImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlanImpl.java index 9ae58be1334..b9bdfde9cbc 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlanImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlanImpl.java @@ -3,9 +3,9 @@ import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import java.util.stream.Collectors; -import org.opentripplanner.api.mapping.PlannerErrorMapper; import org.opentripplanner.api.resource.DebugOutput; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.apis.support.mapping.PlannerErrorMapper; import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.paging.cursor.PageCursor; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RoutingErrorImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RoutingErrorImpl.java index 7c516930888..5c4bd7099c6 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RoutingErrorImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RoutingErrorImpl.java @@ -4,9 +4,9 @@ import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; -import org.opentripplanner.api.mapping.PlannerErrorMapper; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; +import org.opentripplanner.apis.support.mapping.PlannerErrorMapper; import org.opentripplanner.routing.api.response.RoutingError; public class RoutingErrorImpl implements GraphQLDataFetchers.GraphQLRoutingError { diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java index 2502d2b9539..21bff637976 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripImpl.java @@ -15,7 +15,6 @@ import java.util.stream.Collectors; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; -import org.opentripplanner.api.support.SemanticHash; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.GraphQLUtils; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; @@ -23,6 +22,7 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLBikesAllowed; import org.opentripplanner.apis.gtfs.mapping.BikesAllowedMapper; import org.opentripplanner.apis.gtfs.model.TripOccupancy; +import org.opentripplanner.apis.support.SemanticHash; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.Timetable; import org.opentripplanner.model.TripTimeOnDate; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/mapping/StreetNoteMapper.java b/src/main/java/org/opentripplanner/apis/gtfs/mapping/StreetNoteMapper.java index baa601c7448..563200dbba0 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/mapping/StreetNoteMapper.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/mapping/StreetNoteMapper.java @@ -1,6 +1,5 @@ package org.opentripplanner.apis.gtfs.mapping; -import org.opentripplanner.api.mapping.StreetNoteMaperMapper; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.routing.alertpatch.TimePeriod; import org.opentripplanner.routing.alertpatch.TransitAlert; @@ -11,7 +10,7 @@ public class StreetNoteMapper { /** - * Similar to {@link StreetNoteMaperMapper ::mapToApi}. + * Similar to {@link org.opentripplanner.apis.support.mapping.StreetNoteMapper ::mapToApi}. */ public static TransitAlert mapStreetNoteToAlert(StreetNote note) { // TODO: The ID is used only in the mapping, we should instead have two mappers for the fields diff --git a/src/main/java/org/opentripplanner/api/support/SemanticHash.java b/src/main/java/org/opentripplanner/apis/support/SemanticHash.java similarity index 99% rename from src/main/java/org/opentripplanner/api/support/SemanticHash.java rename to src/main/java/org/opentripplanner/apis/support/SemanticHash.java index bf7e8da8b01..2d1f35977fa 100644 --- a/src/main/java/org/opentripplanner/api/support/SemanticHash.java +++ b/src/main/java/org/opentripplanner/apis/support/SemanticHash.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.support; +package org.opentripplanner.apis.support; import com.google.common.hash.HashCode; import com.google.common.hash.HashFunction; diff --git a/src/main/java/org/opentripplanner/api/model/TileJson.java b/src/main/java/org/opentripplanner/apis/support/TileJson.java similarity index 97% rename from src/main/java/org/opentripplanner/api/model/TileJson.java rename to src/main/java/org/opentripplanner/apis/support/TileJson.java index d012241d892..2259d72d828 100644 --- a/src/main/java/org/opentripplanner/api/model/TileJson.java +++ b/src/main/java/org/opentripplanner/apis/support/TileJson.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.model; +package org.opentripplanner.apis.support; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.UriInfo; diff --git a/src/main/java/org/opentripplanner/api/mapping/PlannerErrorMapper.java b/src/main/java/org/opentripplanner/apis/support/mapping/PlannerErrorMapper.java similarity index 94% rename from src/main/java/org/opentripplanner/api/mapping/PlannerErrorMapper.java rename to src/main/java/org/opentripplanner/apis/support/mapping/PlannerErrorMapper.java index 204495110c1..9ec662f51e0 100644 --- a/src/main/java/org/opentripplanner/api/mapping/PlannerErrorMapper.java +++ b/src/main/java/org/opentripplanner/apis/support/mapping/PlannerErrorMapper.java @@ -1,8 +1,8 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.apis.support.mapping; import java.util.List; import org.opentripplanner.api.common.Message; -import org.opentripplanner.api.model.error.PlannerError; +import org.opentripplanner.api.error.PlannerError; import org.opentripplanner.routing.api.response.InputField; import org.opentripplanner.routing.api.response.RoutingError; diff --git a/src/main/java/org/opentripplanner/api/mapping/PropertyMapper.java b/src/main/java/org/opentripplanner/apis/support/mapping/PropertyMapper.java similarity index 96% rename from src/main/java/org/opentripplanner/api/mapping/PropertyMapper.java rename to src/main/java/org/opentripplanner/apis/support/mapping/PropertyMapper.java index 88f102a2b06..dfb7def85c7 100644 --- a/src/main/java/org/opentripplanner/api/mapping/PropertyMapper.java +++ b/src/main/java/org/opentripplanner/apis/support/mapping/PropertyMapper.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.apis.support.mapping; import edu.colorado.cires.cmg.mvt.VectorTile; import edu.colorado.cires.cmg.mvt.adapt.jts.IUserDataConverter; diff --git a/src/main/java/org/opentripplanner/api/mapping/StreetNoteMaperMapper.java b/src/main/java/org/opentripplanner/apis/support/mapping/StreetNoteMapper.java similarity index 85% rename from src/main/java/org/opentripplanner/api/mapping/StreetNoteMaperMapper.java rename to src/main/java/org/opentripplanner/apis/support/mapping/StreetNoteMapper.java index 9ee44d102bb..9cde403c2ed 100644 --- a/src/main/java/org/opentripplanner/api/mapping/StreetNoteMaperMapper.java +++ b/src/main/java/org/opentripplanner/apis/support/mapping/StreetNoteMapper.java @@ -1,17 +1,17 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.apis.support.mapping; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; -import org.opentripplanner.api.model.ApiAlert; +import org.opentripplanner.ext.restapi.model.ApiAlert; import org.opentripplanner.street.model.note.StreetNote; -public class StreetNoteMaperMapper { +public class StreetNoteMapper { private final Locale locale; - public StreetNoteMaperMapper(Locale locale) { + public StreetNoteMapper(Locale locale) { this.locale = locale; } diff --git a/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/TransitPreferencesMapper.java b/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/TransitPreferencesMapper.java index caa8ebf7715..28643bf8199 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/TransitPreferencesMapper.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/mapping/preferences/TransitPreferencesMapper.java @@ -1,8 +1,11 @@ package org.opentripplanner.apis.transmodel.mapping.preferences; import graphql.schema.DataFetchingEnvironment; +import java.util.Map; import org.opentripplanner.apis.transmodel.model.TransportModeSlack; +import org.opentripplanner.apis.transmodel.model.plan.RelaxCostType; import org.opentripplanner.apis.transmodel.support.DataFetcherDecorator; +import org.opentripplanner.routing.api.request.framework.CostLinearFunction; import org.opentripplanner.routing.api.request.preference.TransitPreferences; public class TransitPreferencesMapper { @@ -34,8 +37,11 @@ public static void mapTransitPreferences( callWith.argument("includePlannedCancellations", transit::setIncludePlannedCancellations); callWith.argument("includeRealtimeCancellations", transit::setIncludeRealtimeCancellations); callWith.argument( - "relaxTransitPriorityGroup", - transit::withTransitGroupPriorityGeneralizedCostSlack + "relaxTransitGroupPriority", + it -> + transit.withRelaxTransitGroupPriority( + RelaxCostType.mapToDomain((Map) it, CostLinearFunction.NORMAL) + ) ); callWith.argument( "relaxTransitSearchGeneralizedCostAtDestination", diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostType.java b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostType.java index 3bd3ed129ef..41435c83a2f 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostType.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostType.java @@ -2,13 +2,15 @@ import graphql.Scalars; import graphql.language.FloatValue; -import graphql.language.IntValue; import graphql.language.ObjectField; import graphql.language.ObjectValue; +import graphql.language.StringValue; import graphql.schema.GraphQLInputObjectField; import graphql.schema.GraphQLInputObjectType; -import graphql.schema.GraphQLList; -import graphql.schema.GraphQLNonNull; +import java.util.Map; +import org.opentripplanner.framework.graphql.scalar.CostScalarFactory; +import org.opentripplanner.framework.model.Cost; +import org.opentripplanner.framework.time.DurationUtils; import org.opentripplanner.routing.api.request.framework.CostLinearFunction; public class RelaxCostType { @@ -26,8 +28,8 @@ public class RelaxCostType { with twice as high cost as another one, is accepted. A `constant=$300` means a "fixed" constant is added to the limit. A `{ratio=1.0, constant=0}` is said to be the NORMAL relaxed cost - the limit is the same as the cost used to calculate the limit. The NORMAL is usually - the default. We can express the RelaxCost as a function `f(x) = constant + ratio * x`. - `f(x)=x` is the NORMAL function. + the default. We can express the RelaxCost as a function `f(t) = constant + ratio * t`. + `f(t)=t` is the NORMAL function. """ ) .field( @@ -44,11 +46,12 @@ public class RelaxCostType { .newInputObjectField() .name(CONSTANT) .description( - "The constant value to add to the limit. Must be a positive number. The unit" + - " is cost-seconds." + "The constant value to add to the limit. Must be a positive number. The value is " + + "equivalent to transit-cost-seconds. Integers are treated as seconds, but you may use " + + "the duration format. Example: '3665 = 'DT1h1m5s' = '1h1m5s'." ) - .defaultValueLiteral(IntValue.of(0)) - .type(new GraphQLList(new GraphQLNonNull(Scalars.GraphQLID))) + .defaultValueProgrammatic("0s") + .type(CostScalarFactory.costScalar()) .build() ) .build(); @@ -63,9 +66,31 @@ public static ObjectValue valueOf(CostLinearFunction value) { ObjectField .newObjectField() .name(CONSTANT) - .value(IntValue.of(value.constant().toSeconds())) + // We only use this to display the default value (this is an input type), so using + // the lenient OTP version of duration is ok - it is slightly more readable. + .value(StringValue.of(DurationUtils.durationToStr(value.constant().asDuration()))) .build() ) .build(); } + + public static CostLinearFunction mapToDomain( + Map input, + CostLinearFunction defaultValue + ) { + if (input == null || input.isEmpty()) { + return defaultValue; + } + + double ratio = 1.0; + Cost constant = Cost.ZERO; + + if (input.containsKey(RATIO)) { + ratio = (Double) input.get(RATIO); + } + if (input.containsKey(CONSTANT)) { + constant = (Cost) input.get(CONSTANT); + } + return CostLinearFunction.of(constant, ratio); + } } diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RoutingErrorType.java b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RoutingErrorType.java index 79052f17b69..215e1983ca0 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RoutingErrorType.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/RoutingErrorType.java @@ -7,7 +7,7 @@ import graphql.schema.GraphQLFieldDefinition; import graphql.schema.GraphQLNonNull; import graphql.schema.GraphQLObjectType; -import org.opentripplanner.api.mapping.PlannerErrorMapper; +import org.opentripplanner.apis.support.mapping.PlannerErrorMapper; public class RoutingErrorType { diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripQuery.java b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripQuery.java index 243ebdc1692..abeeb187342 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripQuery.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripQuery.java @@ -277,30 +277,30 @@ public static GraphQLFieldDefinition create( .argument( GraphQLArgument .newArgument() - .name("relaxTransitPriorityGroup") + .name("relaxTransitGroupPriority") .description( """ Relax generalized-cost when comparing trips with a different set of - transit-priority-groups. The groups are set server side for service-journey and + transit-group-priorities. The groups are set server side for service-journey and can not be configured in the API. This mainly helps to return competition neutral - services. Long distance authorities are put in different transit-priority-groups. + services. Long distance authorities are put in different transit-groups. This relaxes the comparison inside the routing engine for each stop-arrival. If two - paths have a different set of transit-priority-groups, then the generalized-cost + paths have a different set of transit-group-priorities, then the generalized-cost comparison is relaxed. The final set of paths are filtered through the normal itinerary-filters. - The `ratio` must be greater or equal to 1.0 and less then 1.2. - - The `slack` must be greater or equal to 0 and less then 3600. + - The `constant` must be greater or equal to '0s' and less then '1h'. THIS IS STILL AN EXPERIMENTAL FEATURE - IT MAY CHANGE WITHOUT ANY NOTICE! """.stripIndent() ) .type(RelaxCostType.INPUT_TYPE) .defaultValueLiteral( - preferences.transit().relaxTransitPriorityGroup().isNormal() + preferences.transit().relaxTransitGroupPriority().isNormal() ? NullValue.of() - : RelaxCostType.valueOf(preferences.transit().relaxTransitPriorityGroup()) + : RelaxCostType.valueOf(preferences.transit().relaxTransitGroupPriority()) ) .build() ) @@ -523,7 +523,7 @@ public static GraphQLFieldDefinition create( GraphQLArgument .newArgument() .name("relaxTransitSearchGeneralizedCostAtDestination") - .deprecate("This is replaced by 'relaxTransitPriorityGroup'.") + .deprecate("This is replaced by 'relaxTransitGroupPriority'.") .description( """ Whether non-optimal transit paths at the destination should be returned. Let c be the diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripType.java b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripType.java index d9c3c0caa02..053b261c08e 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripType.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/TripType.java @@ -8,7 +8,7 @@ import graphql.schema.GraphQLNonNull; import graphql.schema.GraphQLObjectType; import java.util.stream.Collectors; -import org.opentripplanner.api.mapping.PlannerErrorMapper; +import org.opentripplanner.apis.support.mapping.PlannerErrorMapper; import org.opentripplanner.apis.transmodel.model.PlanResponse; import org.opentripplanner.apis.transmodel.support.GqlUtil; import org.opentripplanner.framework.graphql.GraphQLUtils; diff --git a/src/main/java/org/opentripplanner/apis/transmodel/support/ExecutionResultMapper.java b/src/main/java/org/opentripplanner/apis/transmodel/support/ExecutionResultMapper.java index ecb5a38ef01..d0ccb198e16 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/support/ExecutionResultMapper.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/support/ExecutionResultMapper.java @@ -4,8 +4,8 @@ import graphql.ExecutionResult; import graphql.GraphQLError; import jakarta.ws.rs.core.Response; -import org.opentripplanner.api.json.GraphQLResponseSerializer; import org.opentripplanner.framework.application.OTPRequestTimeoutException; +import org.opentripplanner.framework.graphql.GraphQLResponseSerializer; import org.opentripplanner.framework.http.OtpHttpStatus; /** diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java new file mode 100644 index 00000000000..ff933901cf8 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java @@ -0,0 +1,48 @@ +package org.opentripplanner.apis.vectortiles; + +import java.util.List; +import org.opentripplanner.apis.vectortiles.model.LayerStyleBuilder; +import org.opentripplanner.apis.vectortiles.model.StyleSpec; +import org.opentripplanner.apis.vectortiles.model.TileSource; +import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; + +/** + * A Mapbox/Mapblibre style specification for rendering debug information about transit and + * street data. + */ +public class DebugStyleSpec { + + private static final RasterSource BACKGROUND_SOURCE = new RasterSource( + "background", + List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), + 256, + "© OpenStreetMap Contributors" + ); + + public record VectorSourceLayer(VectorSource vectorSource, String vectorLayer) {} + + static StyleSpec build(VectorSource debugSource, VectorSourceLayer regularStops) { + List sources = List.of(BACKGROUND_SOURCE, debugSource); + return new StyleSpec( + "OTP Debug Tiles", + sources, + List.of( + LayerStyleBuilder + .ofId("background") + .typeRaster() + .source(BACKGROUND_SOURCE) + .minZoom(0) + .maxZoom(22), + LayerStyleBuilder + .ofId("regular-stop") + .typeCircle() + .vectorSourceLayer(regularStops) + .circleStroke("#140d0e", 2) + .circleColor("#fcf9fa") + .minZoom(13) + .maxZoom(22) + ) + ); + } +} diff --git a/src/main/java/org/opentripplanner/api/resource/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java similarity index 62% rename from src/main/java/org/opentripplanner/api/resource/GraphInspectorVectorTileResource.java rename to src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 2c21e0396ce..67f92f01ee3 100644 --- a/src/main/java/org/opentripplanner/api/resource/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.apis.vectortiles; import static org.opentripplanner.framework.io.HttpUtils.APPLICATION_X_PROTOBUF; @@ -16,13 +16,20 @@ import java.util.Locale; import java.util.Objects; import java.util.function.Predicate; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; import org.glassfish.grizzly.http.server.Request; -import org.opentripplanner.api.model.TileJson; -import org.opentripplanner.inspector.vector.AreaStopsLayerBuilder; +import org.opentripplanner.apis.support.TileJson; +import org.opentripplanner.apis.vectortiles.model.LayerParams; +import org.opentripplanner.apis.vectortiles.model.LayerType; +import org.opentripplanner.apis.vectortiles.model.StyleSpec; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; +import org.opentripplanner.framework.io.HttpUtils; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; import org.opentripplanner.inspector.vector.VectorTileResponseFactory; import org.opentripplanner.inspector.vector.geofencing.GeofencingZonesLayerBuilder; +import org.opentripplanner.inspector.vector.stop.StopLayerBuilder; import org.opentripplanner.model.FeedInfo; import org.opentripplanner.standalone.api.OtpServerRequestContext; @@ -33,9 +40,19 @@ @Path("/routers/{ignoreRouterId}/inspector/vectortile") public class GraphInspectorVectorTileResource { + private static final LayerParams REGULAR_STOPS = new LayerParams( + "regularStops", + LayerType.RegularStop + ); + private static final LayerParams AREA_STOPS = new LayerParams("areaStops", LayerType.AreaStop); + private static final LayerParams GEOFENCING_ZONES = new LayerParams( + "geofencingZones", + LayerType.GeofencingZones + ); private static final List> DEBUG_LAYERS = List.of( - new LayerParams("areaStops", LayerType.AreaStop), - new LayerParams("geofencingZones", LayerType.GeofencingZones) + REGULAR_STOPS, + AREA_STOPS, + GEOFENCING_ZONES ); private final OtpServerRequestContext serverContext; @@ -84,13 +101,7 @@ public TileJson getTileJson( @PathParam("layers") String requestedLayers ) { var envelope = serverContext.worldEnvelopeService().envelope().orElseThrow(); - List feedInfos = serverContext - .transitService() - .getFeedIds() - .stream() - .map(serverContext.transitService()::getFeedInfo) - .filter(Predicate.not(Objects::isNull)) - .toList(); + List feedInfos = feedInfos(); return new TileJson( uri, @@ -103,26 +114,54 @@ public TileJson getTileJson( ); } + @GET + @Path("/style.json") + @Produces(MediaType.APPLICATION_JSON) + public StyleSpec getTileJson(@Context UriInfo uri, @Context HttpHeaders headers) { + var base = HttpUtils.getBaseAddress(uri, headers); + final String allLayers = DEBUG_LAYERS + .stream() + .map(LayerParameters::name) + .collect(Collectors.joining(",")); + var url = + "%s/otp/routers/%s/inspector/vectortile/%s/tilejson.json".formatted( + base, + ignoreRouterId, + allLayers + ); + + var vectorSource = new VectorSource("debug", url); + return DebugStyleSpec.build(vectorSource, REGULAR_STOPS.toVectorSourceLayer(vectorSource)); + } + + @Nonnull + private List feedInfos() { + return serverContext + .transitService() + .getFeedIds() + .stream() + .map(serverContext.transitService()::getFeedInfo) + .filter(Predicate.not(Objects::isNull)) + .toList(); + } + private static LayerBuilder createLayerBuilder( LayerParameters layerParameters, Locale locale, OtpServerRequestContext context ) { return switch (layerParameters.type()) { - case AreaStop -> new AreaStopsLayerBuilder(context.transitService(), layerParameters, locale); + case RegularStop -> new StopLayerBuilder<>( + layerParameters, + locale, + e -> context.transitService().findRegularStop(e) + ); + case AreaStop -> new StopLayerBuilder<>( + layerParameters, + locale, + e -> context.transitService().findAreaStops(e) + ); case GeofencingZones -> new GeofencingZonesLayerBuilder(context.graph(), layerParameters); }; } - - private enum LayerType { - AreaStop, - GeofencingZones, - } - - private record LayerParams(String name, LayerType type) implements LayerParameters { - @Override - public String mapper() { - return "DebugClient"; - } - } } diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java new file mode 100644 index 00000000000..7365e8972da --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java @@ -0,0 +1,20 @@ +package org.opentripplanner.apis.vectortiles.model; + +import org.opentripplanner.apis.vectortiles.DebugStyleSpec.VectorSourceLayer; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; +import org.opentripplanner.inspector.vector.LayerParameters; + +public record LayerParams(String name, LayerType type) implements LayerParameters { + @Override + public String mapper() { + return "DebugClient"; + } + + /** + * Convert these params to a vector source layer so that it can be used in the style for rendering + * in the frontend. + */ + public VectorSourceLayer toVectorSourceLayer(VectorSource source) { + return new VectorSourceLayer(source, name); + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java new file mode 100644 index 00000000000..41144611f92 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java @@ -0,0 +1,116 @@ +package org.opentripplanner.apis.vectortiles.model; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; +import org.opentripplanner.apis.vectortiles.DebugStyleSpec.VectorSourceLayer; +import org.opentripplanner.framework.json.ObjectMappers; + +/** + * Builds a Maplibre/Mapbox vector tile + * layer style. + */ +public class LayerStyleBuilder { + + private static final ObjectMapper OBJECT_MAPPER = ObjectMappers.ignoringExtraFields(); + private static final String TYPE = "type"; + private static final String SOURCE_LAYER = "source-layer"; + private final Map props = new HashMap<>(); + private final Map paint = new HashMap<>(); + + public static LayerStyleBuilder ofId(String id) { + return new LayerStyleBuilder(id); + } + + public LayerStyleBuilder vectorSourceLayer(VectorSourceLayer source) { + source(source.vectorSource()); + return sourceLayer(source.vectorLayer()); + } + + public enum LayerType { + Circle, + Raster, + } + + private LayerStyleBuilder(String id) { + props.put("id", id); + } + + public LayerStyleBuilder minZoom(int i) { + props.put("minzoom", i); + return this; + } + + public LayerStyleBuilder maxZoom(int i) { + props.put("maxzoom", i); + return this; + } + + /** + * Which vector tile source this should apply to. + */ + public LayerStyleBuilder source(TileSource source) { + props.put("source", source.id()); + return this; + } + + /** + * For vector tile sources, specify which source layer in the tile the styles should apply to. + * There is an unfortunate collision in the name "layer" as it can both refer to a styling layer + * and the layer inside the vector tile. + */ + public LayerStyleBuilder sourceLayer(String source) { + props.put(SOURCE_LAYER, source); + return this; + } + + public LayerStyleBuilder typeRaster() { + return type(LayerType.Raster); + } + + public LayerStyleBuilder typeCircle() { + return type(LayerType.Circle); + } + + private LayerStyleBuilder type(LayerType type) { + props.put(TYPE, type.name().toLowerCase()); + return this; + } + + public LayerStyleBuilder circleColor(String color) { + paint.put("circle-color", validateColor(color)); + return this; + } + + public LayerStyleBuilder circleStroke(String color, int width) { + paint.put("circle-stroke-color", validateColor(color)); + paint.put("circle-stroke-width", width); + return this; + } + + public JsonNode toJson() { + validate(); + + var copy = new HashMap<>(props); + if (!paint.isEmpty()) { + copy.put("paint", paint); + } + return OBJECT_MAPPER.valueToTree(copy); + } + + private String validateColor(String color) { + if (!color.startsWith("#")) { + throw new IllegalArgumentException("Colors must start with '#'"); + } + return color; + } + + private void validate() { + Stream + .of(TYPE) + .forEach(p -> Objects.requireNonNull(props.get(p), "%s must be set".formatted(p))); + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java new file mode 100644 index 00000000000..f4cb7a636fa --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java @@ -0,0 +1,7 @@ +package org.opentripplanner.apis.vectortiles.model; + +public enum LayerType { + RegularStop, + AreaStop, + GeofencingZones, +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java new file mode 100644 index 00000000000..84e19f25364 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java @@ -0,0 +1,48 @@ +package org.opentripplanner.apis.vectortiles.model; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a style specification for Maplibre/Mapbox vector tile layers. + * https://maplibre.org/maplibre-style-spec/root/ + *

+ * Maplibre uses these to render vector maps in the browser. + */ +public final class StyleSpec { + + private final String name; + private final List sources; + private final List layers; + + public StyleSpec(String name, List sources, List layers) { + this.name = name; + this.sources = sources; + this.layers = layers.stream().map(LayerStyleBuilder::toJson).toList(); + } + + @JsonSerialize + public int version() { + return 8; + } + + @JsonSerialize + public String name() { + return name; + } + + @JsonSerialize + public Map sources() { + var output = new HashMap(); + sources.forEach(s -> output.put(s.id(), s)); + return output; + } + + @JsonSerialize + public List layers() { + return layers; + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java new file mode 100644 index 00000000000..06af294a4f0 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java @@ -0,0 +1,36 @@ +package org.opentripplanner.apis.vectortiles.model; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.util.List; + +/** + * Represent a data source where Maplibre can fetch data for rendering directly in the browser. + */ +public sealed interface TileSource { + @JsonSerialize + String type(); + + String id(); + + /** + * Represents a vector tile source which is rendered into a map in the browser. + */ + record VectorSource(String id, String url) implements TileSource { + @Override + public String type() { + return "vector"; + } + } + + /** + * Represents a raster-based source for map tiles. These are used mainly for background + * map layers with vector data being rendered on top of it. + */ + record RasterSource(String id, List tiles, int tileSize, String attribution) + implements TileSource { + @Override + public String type() { + return "raster"; + } + } +} diff --git a/src/main/java/org/opentripplanner/astar/model/BinHeap.java b/src/main/java/org/opentripplanner/astar/model/BinHeap.java index 9bc2b0762a8..1e9b540a77a 100644 --- a/src/main/java/org/opentripplanner/astar/model/BinHeap.java +++ b/src/main/java/org/opentripplanner/astar/model/BinHeap.java @@ -79,14 +79,6 @@ public void rekey(T e, double p) { prio[i] = p; } - public void dump() { - for (int i = 0; i <= capacity; i++) { - String topMarker = (i > size) ? "(UNUSED)" : ""; - System.out.printf("%d\t%f\t%s\t%s\n", i, prio[i], elem[i], topMarker); - } - System.out.printf("-----------------------\n"); - } - public void reset() { // empties the queue in one operation size = 0; @@ -135,8 +127,4 @@ public void resize(int capacity) { prio = Arrays.copyOf(prio, capacity + 1); elem = Arrays.copyOf(elem, capacity + 1); } - - public int getCapacity() { - return capacity; - } } diff --git a/src/main/java/org/opentripplanner/astar/model/ShortestPathTree.java b/src/main/java/org/opentripplanner/astar/model/ShortestPathTree.java index e373f9c785e..a6d7123cdfe 100644 --- a/src/main/java/org/opentripplanner/astar/model/ShortestPathTree.java +++ b/src/main/java/org/opentripplanner/astar/model/ShortestPathTree.java @@ -244,10 +244,6 @@ public void setAborted() { aborted = true; } - public boolean isAborted() { - return aborted; - } - public String toString() { return "ShortestPathTree(" + this.stateSets.size() + " vertices)"; } diff --git a/src/main/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategy.java b/src/main/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategy.java index bcae9dcdb86..0369e3e29db 100644 --- a/src/main/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategy.java +++ b/src/main/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategy.java @@ -1,12 +1,12 @@ package org.opentripplanner.astar.strategy; -import java.util.function.Function; +import java.util.function.Predicate; import org.opentripplanner.astar.spi.AStarEdge; import org.opentripplanner.astar.spi.AStarState; import org.opentripplanner.astar.spi.SkipEdgeStrategy; /** - * Skips edges when the specified number of desired vertices have been visited + * Skips edges when the specified number of desired vertices have been visited. */ public class MaxCountSkipEdgeStrategy< State extends AStarState, Edge extends AStarEdge @@ -14,11 +14,11 @@ public class MaxCountSkipEdgeStrategy< implements SkipEdgeStrategy { private final int maxCount; - private final Function shouldIncreaseCount; + private final Predicate shouldIncreaseCount; private int visited; - public MaxCountSkipEdgeStrategy(int count, Function shouldIncreaseCount) { + public MaxCountSkipEdgeStrategy(int count, Predicate shouldIncreaseCount) { this.maxCount = count; this.shouldIncreaseCount = shouldIncreaseCount; this.visited = 0; @@ -26,7 +26,7 @@ public MaxCountSkipEdgeStrategy(int count, Function shouldIncrea @Override public boolean shouldSkipEdge(State current, Edge edge) { - if (this.shouldIncreaseCount.apply(current)) { + if (shouldIncreaseCount.test(current)) { visited++; } return visited > maxCount; diff --git a/src/main/java/org/opentripplanner/framework/application/OTPFeature.java b/src/main/java/org/opentripplanner/framework/application/OTPFeature.java index 05d1284a883..4847b204077 100644 --- a/src/main/java/org/opentripplanner/framework/application/OTPFeature.java +++ b/src/main/java/org/opentripplanner/framework/application/OTPFeature.java @@ -16,20 +16,23 @@ public enum OTPFeature { APIBikeRental(true, false, "Enable the bike rental endpoint."), APIServerInfo(true, false, "Enable the server info endpoint."), - APIGraphInspectorTile( - true, - false, - "Enable the inspector endpoint for graph information for inspection/debugging purpose." - ), APIUpdaterStatus(true, false, "Enable endpoint for graph updaters status."), ConsiderPatternsForDirectTransfers( true, false, "Enable limiting transfers so that there is only a single transfer to each pattern." ), - DebugClient(true, false, "Enable the debug web client located at the root of the web server."), + DebugUi( + true, + false, + """ + Enable the debug GraphQL client and web UI and located at the root of the web server as well as the debug map tiles it uses. + Be aware that the map tiles are not a stable API and can change without notice. + Use the [vector tiles feature if](sandbox/MapboxVectorTilesApi.md) you want a stable map tiles API. + """ + ), FloatingBike(true, false, "Enable floating bike routing."), - GtfsGraphQlApi(true, false, "Enable GTFS GraphQL API."), + GtfsGraphQlApi(true, false, "Enable the [GTFS GraphQL API](apis/GTFS-GraphQL-API.md)."), GtfsGraphQlApiRentalStationFuzzyMatching( false, false, @@ -63,7 +66,11 @@ public enum OTPFeature { false, "Enforce transfers to happen according to the _transfers.txt_ (GTFS) and Interchanges (NeTEx). Turning this _off_ will increase the routing performance a little." ), - TransmodelGraphQlApi(true, true, "Enable Transmodel (NeTEx) GraphQL API."), + TransmodelGraphQlApi( + true, + true, + "Enable the [Transmodel (NeTEx) GraphQL API](apis/TransmodelApi.md)." + ), /* Sandbox extension features - Must be turned OFF by default */ @@ -82,6 +89,7 @@ public enum OTPFeature { FaresV2(false, true, "Enable import of GTFS-Fares v2 data."), FlexRouting(false, true, "Enable FLEX routing."), GoogleCloudStorage(false, true, "Enable Google Cloud Storage integration."), + LegacyRestApi(true, true, "Enable legacy REST API. This API will be removed in the future."), RealtimeResolver( false, true, diff --git a/src/main/java/org/opentripplanner/api/json/GraphQLResponseSerializer.java b/src/main/java/org/opentripplanner/framework/graphql/GraphQLResponseSerializer.java similarity index 94% rename from src/main/java/org/opentripplanner/api/json/GraphQLResponseSerializer.java rename to src/main/java/org/opentripplanner/framework/graphql/GraphQLResponseSerializer.java index caba621294c..cb3b146a113 100644 --- a/src/main/java/org/opentripplanner/api/json/GraphQLResponseSerializer.java +++ b/src/main/java/org/opentripplanner/framework/graphql/GraphQLResponseSerializer.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.json; +package org.opentripplanner.framework.graphql; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -10,6 +10,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import org.opentripplanner.ext.restapi.serialization.JSONObjectMapperProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/opentripplanner/framework/graphql/scalar/CostScalarFactory.java b/src/main/java/org/opentripplanner/framework/graphql/scalar/CostScalarFactory.java new file mode 100644 index 00000000000..6f710328174 --- /dev/null +++ b/src/main/java/org/opentripplanner/framework/graphql/scalar/CostScalarFactory.java @@ -0,0 +1,83 @@ +package org.opentripplanner.framework.graphql.scalar; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; +import graphql.language.StringValue; +import graphql.language.Value; +import graphql.schema.Coercing; +import graphql.schema.CoercingParseLiteralException; +import graphql.schema.CoercingParseValueException; +import graphql.schema.GraphQLScalarType; +import java.util.Locale; +import java.util.NoSuchElementException; +import javax.annotation.Nonnull; +import org.opentripplanner.framework.model.Cost; +import org.opentripplanner.framework.time.DurationUtils; + +public class CostScalarFactory { + + private static final String TYPENAME = "Cost"; + + private static final String DOCUMENTATION = + "A cost value, normally a value of 1 is equivalent to riding transit for 1 second, " + + "but it might not depending on the use-case. Format: 3665 = DT1h1m5s = 1h1m5s"; + + private static final GraphQLScalarType SCALAR_INSTANCE = createCostScalar(); + + private CostScalarFactory() {} + + public static GraphQLScalarType costScalar() { + return SCALAR_INSTANCE; + } + + private static GraphQLScalarType createCostScalar() { + return GraphQLScalarType + .newScalar() + .name(TYPENAME) + .description(DOCUMENTATION) + .coercing(createCoercing()) + .build(); + } + + private static String serializeCost(Cost cost) { + return cost.asDuration().toString(); + } + + private static Cost parseCost(String input) throws CoercingParseValueException { + try { + return Cost.fromDuration(DurationUtils.parseSecondsOrDuration(input).orElseThrow()); + } catch (IllegalArgumentException | NoSuchElementException e) { + throw new CoercingParseValueException(e.getMessage(), e); + } + } + + private static Coercing createCoercing() { + return new Coercing<>() { + @Override + public String serialize(@Nonnull Object result, GraphQLContext c, Locale l) { + return serializeCost((Cost) result); + } + + @Override + public Cost parseValue(Object input, GraphQLContext c, Locale l) + throws CoercingParseValueException { + return parseCost((String) input); + } + + @Override + public Cost parseLiteral(Value input, CoercedVariables v, GraphQLContext c, Locale l) + throws CoercingParseLiteralException { + if (input instanceof StringValue stringValue) { + return parseCost(stringValue.getValue()); + } + return null; + } + + @Override + @Nonnull + public Value valueToLiteral(Object input, GraphQLContext c, Locale l) { + return StringValue.of((String) input); + } + }; + } +} diff --git a/src/main/java/org/opentripplanner/api/mapping/I18NStringMapper.java b/src/main/java/org/opentripplanner/framework/i18n/I18NStringMapper.java similarity index 77% rename from src/main/java/org/opentripplanner/api/mapping/I18NStringMapper.java rename to src/main/java/org/opentripplanner/framework/i18n/I18NStringMapper.java index 6b40a07b953..acdb30b301f 100644 --- a/src/main/java/org/opentripplanner/api/mapping/I18NStringMapper.java +++ b/src/main/java/org/opentripplanner/framework/i18n/I18NStringMapper.java @@ -1,9 +1,8 @@ -package org.opentripplanner.api.mapping; +package org.opentripplanner.framework.i18n; import java.util.Locale; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.opentripplanner.framework.i18n.I18NString; public class I18NStringMapper { @@ -24,7 +23,7 @@ public String mapNonnullToApi(I18NString string) { } @Nullable - static String mapToApi(I18NString string, Locale locale) { + public static String mapToApi(I18NString string, Locale locale) { return string == null ? null : string.toString(locale); } } diff --git a/src/main/java/org/opentripplanner/framework/io/HttpUtils.java b/src/main/java/org/opentripplanner/framework/io/HttpUtils.java index 3450cf0786c..4981a8ab91b 100644 --- a/src/main/java/org/opentripplanner/framework/io/HttpUtils.java +++ b/src/main/java/org/opentripplanner/framework/io/HttpUtils.java @@ -24,16 +24,16 @@ private HttpUtils() {} public static String getBaseAddress(UriInfo uri, HttpHeaders headers) { String protocol; if (headers.getRequestHeader(HEADER_X_FORWARDED_PROTO) != null) { - protocol = headers.getRequestHeader(HEADER_X_FORWARDED_PROTO).get(0); + protocol = headers.getRequestHeader(HEADER_X_FORWARDED_PROTO).getFirst(); } else { protocol = uri.getRequestUri().getScheme(); } String host; if (headers.getRequestHeader(HEADER_X_FORWARDED_HOST) != null) { - host = headers.getRequestHeader(HEADER_X_FORWARDED_HOST).get(0); + host = headers.getRequestHeader(HEADER_X_FORWARDED_HOST).getFirst(); } else if (headers.getRequestHeader(HEADER_HOST) != null) { - host = headers.getRequestHeader(HEADER_HOST).get(0); + host = headers.getRequestHeader(HEADER_HOST).getFirst(); } else { host = uri.getBaseUri().getHost() + ":" + uri.getBaseUri().getPort(); } diff --git a/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java b/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java index ba776ac5243..360cdaee363 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java @@ -47,14 +47,8 @@ import org.opentripplanner.transit.service.TransitService; /** - * These library functions are used by the streetless and streetful stop linkers, and in profile - * transfer generation. - * TODO OTP2 Fold these into org.opentripplanner.routing.graphfinder.StreetGraphFinder - * These are not library functions, this is instantiated as an object. Define lifecycle of the object (reuse?). - * Because AStar instances should only be used once, NearbyStopFinder should only be used once. - * Ideally they could also be used in long distance mode and profile routing for the street segments. - * For each stop, it finds the closest stops on all other patterns. This reduces the number of transfer edges - * significantly compared to simple radius-constrained all-to-all stop linkage. + * This class contains code for finding nearby stops from a given vertex. It is being used by access + * and egress searches as well as transfer generation. */ public class NearbyStopFinder { @@ -100,6 +94,8 @@ public NearbyStopFinder( * that the result will include the origin vertex if it is an instance of StopVertex. This is * intentional: we don't want to return the next stop down the line for trip patterns that pass * through the origin vertex. + * Taking the patterns into account reduces the number of transfers significantly compared to + * simple traverse-duration-constrained all-to-all stop linkage. */ public Set findNearbyStopsConsideringPatterns( Vertex vertex, @@ -227,15 +223,12 @@ public List findNearbyStopsViaStreets( for (State state : spt.getAllStates()) { Vertex targetVertex = state.getVertex(); if (originVertices.contains(targetVertex)) continue; - if (targetVertex instanceof TransitStopVertex && state.isFinal()) { - stopsFound.add( - NearbyStop.nearbyStopForState(state, ((TransitStopVertex) targetVertex).getStop()) - ); + if (targetVertex instanceof TransitStopVertex tsv && state.isFinal()) { + stopsFound.add(NearbyStop.nearbyStopForState(state, tsv.getStop())); } if ( OTPFeature.FlexRouting.isOn() && - targetVertex instanceof StreetVertex && - !((StreetVertex) targetVertex).areaStops().isEmpty() + targetVertex instanceof StreetVertex streetVertex && !streetVertex.areaStops().isEmpty() ) { for (AreaStop areaStop : ((StreetVertex) targetVertex).areaStops()) { // This is for a simplification, so that we only return one vertex from each @@ -314,7 +307,7 @@ private SkipEdgeStrategy getSkipEdgeStrategy( if (maxStopCount > 0) { var strategy = new MaxCountSkipEdgeStrategy<>( maxStopCount, - NearbyStopFinder::isTransitVertex + NearbyStopFinder::hasReachedStop ); return new ComposingSkipEdgeStrategy<>(strategy, durationSkipEdgeStrategy); } @@ -360,15 +353,23 @@ private boolean canBoardFlex(State state, boolean reverse) { return edges .stream() - .anyMatch(e -> - e instanceof StreetEdge && ((StreetEdge) e).getPermission().allows(TraverseMode.CAR) - ); + .anyMatch(e -> e instanceof StreetEdge se && se.getPermission().allows(TraverseMode.CAR)); } /** - * Checks if the {@code state} as at a transit vertex. + * Checks if the {@code state} is at a transit vertex and if it's final, which means that the state + * can actually board a vehicle. + *

+ * This is important because there can be cases where states that cannot actually board the vehicle + * can dominate those that can thereby leading to zero found stops when this predicate is used with + * the {@link MaxCountSkipEdgeStrategy}. + *

+ * An example of this would be an egress/reverse search with a very high walk reluctance where + * the states that speculatively rent a vehicle move the walk states down the A* priority queue + * until the required number of stops are reached to abort the search, leading to zero egress + * results. */ - public static boolean isTransitVertex(State state) { - return state.getVertex() instanceof TransitStopVertex; + public static boolean hasReachedStop(State state) { + return state.getVertex() instanceof TransitStopVertex && state.isFinal(); } } diff --git a/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java deleted file mode 100644 index 1604cf7d8d1..00000000000 --- a/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.opentripplanner.inspector.vector; - -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.function.Function; -import org.locationtech.jts.geom.Envelope; -import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.PropertyMapper; -import org.opentripplanner.transit.model.site.AreaStop; -import org.opentripplanner.transit.service.TransitService; - -/** - * A vector tile layer containing all {@link AreaStop}s inside the vector tile bounds. - */ -public class AreaStopsLayerBuilder extends LayerBuilder { - - private static final Map mappers = Map.of( - MapperType.DebugClient, - DebugClientAreaStopPropertyMapper::create - ); - private final Function> findAreaStops; - - public AreaStopsLayerBuilder( - TransitService transitService, - LayerParameters layerParameters, - Locale locale - ) { - super( - mappers.get(MapperType.valueOf(layerParameters.mapper())).build(transitService, locale), - layerParameters.name(), - layerParameters.expansionFactor() - ); - this.findAreaStops = transitService::findAreaStops; - } - - @Override - protected List getGeometries(Envelope query) { - return findAreaStops - .apply(query) - .stream() - .map(areaStop -> { - Geometry geometry = areaStop.getGeometry().copy(); - - geometry.setUserData(areaStop); - - return geometry; - }) - .toList(); - } - - enum MapperType { - DebugClient, - } - - @FunctionalInterface - private interface MapperFactory { - PropertyMapper build(TransitService transitService, Locale locale); - } -} diff --git a/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java deleted file mode 100644 index 88f7a17385b..00000000000 --- a/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.opentripplanner.inspector.vector; - -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; -import org.opentripplanner.transit.model.site.AreaStop; -import org.opentripplanner.transit.service.TransitService; - -/** - * A {@link PropertyMapper} for the {@link AreaStopsLayerBuilder} for the OTP debug client. - */ -public class DebugClientAreaStopPropertyMapper extends PropertyMapper { - - private final I18NStringMapper i18NStringMapper; - - public DebugClientAreaStopPropertyMapper(TransitService transitService, Locale locale) { - this.i18NStringMapper = new I18NStringMapper(locale); - } - - public static PropertyMapper create(TransitService transitService, Locale locale) { - return new DebugClientAreaStopPropertyMapper(transitService, locale); - } - - @Override - protected Collection map(AreaStop input) { - return List.of( - new KeyValue("id", input.getId().toString()), - new KeyValue("name", i18NStringMapper.mapNonnullToApi(input.getName())) - ); - } -} diff --git a/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java b/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java index d57afd3429e..6c8b0f3aa4e 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java +++ b/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java @@ -1,3 +1,7 @@ package org.opentripplanner.inspector.vector; -public record KeyValue(String key, Object value) {} +public record KeyValue(String key, Object value) { + public static KeyValue kv(String key, Object value) { + return new KeyValue(key, value); + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/LayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/LayerBuilder.java index 3e796487271..949bbef0a94 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/LayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/LayerBuilder.java @@ -10,7 +10,7 @@ import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.framework.geometry.GeometryUtils; /** diff --git a/src/main/java/org/opentripplanner/inspector/vector/LayerParameters.java b/src/main/java/org/opentripplanner/inspector/vector/LayerParameters.java index 2718c649797..ca4a6a64c76 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/LayerParameters.java +++ b/src/main/java/org/opentripplanner/inspector/vector/LayerParameters.java @@ -1,6 +1,6 @@ package org.opentripplanner.inspector.vector; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; /** * Configuration options for a single vector tile layer. diff --git a/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java index 8a77b8502ea..24be8d202a8 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java @@ -1,10 +1,8 @@ package org.opentripplanner.inspector.vector.geofencing; import java.util.List; -import java.util.Map; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.PropertyMapper; import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; @@ -19,15 +17,11 @@ */ public class GeofencingZonesLayerBuilder extends LayerBuilder { - private static final Map mappers = Map.of( - MapperType.DebugClient, - transitService -> new GeofencingZonesPropertyMapper() - ); private final StreetIndex streetIndex; public GeofencingZonesLayerBuilder(Graph graph, LayerParameters layerParameters) { super( - mappers.get(MapperType.valueOf(layerParameters.mapper())).build(graph), + new GeofencingZonesPropertyMapper(), layerParameters.name(), layerParameters.expansionFactor() ); @@ -47,13 +41,4 @@ protected List getGeometries(Envelope query) { }) .toList(); } - - enum MapperType { - DebugClient, - } - - @FunctionalInterface - private interface MapperFactory { - PropertyMapper build(Graph transitService); - } } diff --git a/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesPropertyMapper.java index 0d0f7b44fe9..98c9cf23eca 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesPropertyMapper.java +++ b/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesPropertyMapper.java @@ -6,7 +6,7 @@ import java.util.Collection; import java.util.List; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.street.model.vertex.Vertex; diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java new file mode 100644 index 00000000000..70ce6a58735 --- /dev/null +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java @@ -0,0 +1,49 @@ +package org.opentripplanner.inspector.vector.stop; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.function.Function; +import org.locationtech.jts.geom.Envelope; +import org.locationtech.jts.geom.Geometry; +import org.opentripplanner.inspector.vector.LayerBuilder; +import org.opentripplanner.inspector.vector.LayerParameters; +import org.opentripplanner.transit.model.site.AreaStop; +import org.opentripplanner.transit.model.site.RegularStop; +import org.opentripplanner.transit.model.site.StopLocation; + +/** + * A vector tile layer for {@link StopLocation}s inside the vector tile bounds. These can be further + * filtered to get only a subset of stop implementations like {@link RegularStop} + * or {@link AreaStop}. + */ +public class StopLayerBuilder extends LayerBuilder { + + private final Function> findStops; + + public StopLayerBuilder( + LayerParameters layerParameters, + Locale locale, + Function> findStops + ) { + super( + new StopLocationPropertyMapper(locale), + layerParameters.name(), + layerParameters.expansionFactor() + ); + this.findStops = findStops; + } + + @Override + protected List getGeometries(Envelope query) { + return findStops + .apply(query) + .stream() + .map(stop -> { + Geometry geometry = stop.getGeometry().copy(); + geometry.setUserData(stop); + return geometry; + }) + .toList(); + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java new file mode 100644 index 00000000000..ab9685dd0f6 --- /dev/null +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java @@ -0,0 +1,32 @@ +package org.opentripplanner.inspector.vector.stop; + +import static org.opentripplanner.inspector.vector.KeyValue.kv; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; +import org.opentripplanner.inspector.vector.KeyValue; +import org.opentripplanner.transit.model.site.StopLocation; + +/** + * A {@link PropertyMapper} for the {@link StopLocationPropertyMapper} for the OTP debug client. + */ +public class StopLocationPropertyMapper extends PropertyMapper { + + private final I18NStringMapper i18NStringMapper; + + public StopLocationPropertyMapper(Locale locale) { + this.i18NStringMapper = new I18NStringMapper(locale); + } + + @Override + protected Collection map(StopLocation stop) { + return List.of( + kv("name", i18NStringMapper.mapToApi(stop.getName())), + kv("id", stop.getId().toString()), + kv("parentId", stop.isPartOfStation() ? stop.getParentStation().getId().toString() : null) + ); + } +} diff --git a/src/main/java/org/opentripplanner/netex/mapping/NetexMapper.java b/src/main/java/org/opentripplanner/netex/mapping/NetexMapper.java index 8fc30ae166a..30bd04eea73 100644 --- a/src/main/java/org/opentripplanner/netex/mapping/NetexMapper.java +++ b/src/main/java/org/opentripplanner/netex/mapping/NetexMapper.java @@ -11,7 +11,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.calendar.ServiceCalendar; diff --git a/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapper.java b/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapper.java index f0d06b8871d..765a9b5c47f 100644 --- a/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapper.java +++ b/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapper.java @@ -26,7 +26,6 @@ import org.opentripplanner.transit.model.framework.ImmutableEntityById; import org.opentripplanner.transit.model.network.StopPattern; import org.opentripplanner.transit.model.network.TripPattern; -import org.opentripplanner.transit.model.network.TripPatternBuilder; import org.opentripplanner.transit.model.organization.Operator; import org.opentripplanner.transit.model.site.AreaStop; import org.opentripplanner.transit.model.site.GroupStop; diff --git a/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapperResult.java b/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapperResult.java index f2f75cd2561..370c24a7a41 100644 --- a/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapperResult.java +++ b/src/main/java/org/opentripplanner/netex/mapping/TripPatternMapperResult.java @@ -1,13 +1,10 @@ package org.opentripplanner.netex.mapping; import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.opentripplanner.model.StopTime; -import org.opentripplanner.transit.model.network.StopPattern; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; diff --git a/src/main/java/org/opentripplanner/raptor/api/model/RaptorTripPattern.java b/src/main/java/org/opentripplanner/raptor/api/model/RaptorTripPattern.java index 98a2533486b..e5be1cab0d5 100644 --- a/src/main/java/org/opentripplanner/raptor/api/model/RaptorTripPattern.java +++ b/src/main/java/org/opentripplanner/raptor/api/model/RaptorTripPattern.java @@ -46,7 +46,7 @@ public interface RaptorTripPattern { int slackIndex(); /** - * A pattern may belong to a transit-priority-group. Each group is given an advantage during + * A pattern may belong to a transit-group-priority. Each group is given an advantage during * the multi-criteria search, so the best alternative for each group is found. */ int priorityGroupId(); diff --git a/src/main/java/org/opentripplanner/raptor/api/request/MultiCriteriaRequest.java b/src/main/java/org/opentripplanner/raptor/api/request/MultiCriteriaRequest.java index 64cd9dae1a5..368b4660922 100644 --- a/src/main/java/org/opentripplanner/raptor/api/request/MultiCriteriaRequest.java +++ b/src/main/java/org/opentripplanner/raptor/api/request/MultiCriteriaRequest.java @@ -18,7 +18,7 @@ public class MultiCriteriaRequest { private final RelaxFunction relaxC1; @Nullable - private final RaptorTransitPriorityGroupCalculator transitPriorityCalculator; + private final RaptorTransitGroupCalculator transitPriorityCalculator; private final List passThroughPoints; @@ -63,7 +63,7 @@ public RelaxFunction relaxC1() { return relaxC1; } - public Optional transitPriorityCalculator() { + public Optional transitPriorityCalculator() { return Optional.ofNullable(transitPriorityCalculator); } @@ -140,7 +140,7 @@ public static class Builder { private final MultiCriteriaRequest original; private RelaxFunction relaxC1; - private RaptorTransitPriorityGroupCalculator transitPriorityCalculator; + private RaptorTransitGroupCalculator transitPriorityCalculator; private List passThroughPoints; private Double relaxCostAtDestination; @@ -163,11 +163,11 @@ public Builder withRelaxC1(RelaxFunction relaxC1) { } @Nullable - public RaptorTransitPriorityGroupCalculator transitPriorityCalculator() { + public RaptorTransitGroupCalculator transitPriorityCalculator() { return transitPriorityCalculator; } - public Builder withTransitPriorityCalculator(RaptorTransitPriorityGroupCalculator value) { + public Builder withTransitPriorityCalculator(RaptorTransitGroupCalculator value) { transitPriorityCalculator = value; return this; } diff --git a/src/main/java/org/opentripplanner/raptor/api/request/RaptorTransitPriorityGroupCalculator.java b/src/main/java/org/opentripplanner/raptor/api/request/RaptorTransitGroupCalculator.java similarity index 71% rename from src/main/java/org/opentripplanner/raptor/api/request/RaptorTransitPriorityGroupCalculator.java rename to src/main/java/org/opentripplanner/raptor/api/request/RaptorTransitGroupCalculator.java index c3890fa47b3..b5f0598415e 100644 --- a/src/main/java/org/opentripplanner/raptor/api/request/RaptorTransitPriorityGroupCalculator.java +++ b/src/main/java/org/opentripplanner/raptor/api/request/RaptorTransitGroupCalculator.java @@ -2,19 +2,19 @@ import org.opentripplanner.raptor.api.model.DominanceFunction; -public interface RaptorTransitPriorityGroupCalculator { +public interface RaptorTransitGroupCalculator { /** - * Merge in the trip transit priority group id with an existing set. Note! Both the set + * Merge in the transit group id with an existing set. Note! Both the set * and the group id type is {@code int}. * * @param currentGroupIds the set of groupIds for all legs in a path. * @param boardingGroupId the transit group id to add to the given set. * @return the new computed set of groupIds */ - int mergeTransitPriorityGroupIds(int currentGroupIds, int boardingGroupId); + int mergeGroupIds(int currentGroupIds, int boardingGroupId); /** - * This is the dominance function to use for comparing transit-priority-groupIds. + * This is the dominance function to use for comparing transit-groups. * It is critical that the implementation is "static" so it can be inlined, since it * is run in the innermost loop of Raptor. */ diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/SystemErrDebugLogger.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/SystemErrDebugLogger.java index 060d3a2e018..951721f81a7 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/SystemErrDebugLogger.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/SystemErrDebugLogger.java @@ -43,14 +43,14 @@ public class SystemErrDebugLogger implements DebugLogger { private final Table arrivalTable = Table .of() .withAlights(Center, Center, Right, Right, Right, Right, Left, Left) - .withHeaders("ARRIVAL", "LEG", "RND", "STOP", "ARRIVE", "COST", "TRIP", "DETAILS") + .withHeaders("ARRIVAL", "LEG", "RND", "STOP", "ARRIVE", "C₁", "TRIP", "DETAILS") .withMinWidths(9, 7, 3, 5, 8, 9, 24, 0) .build(); private final Table pathTable = Table .of() .withAlights(Center, Center, Right, Right, Right, Right, Right, Right, Left) - .withHeaders(">>> PATH", "TR", "FROM", "TO", "START", "END", "DURATION", "COST", "DETAILS") - .withMinWidths(9, 2, 5, 5, 8, 8, 8, 6, 0) + .withHeaders(">>> PATH", "TR", "FROM", "TO", "START", "END", "DURATION", "C₁", "DETAILS") + .withMinWidths(9, 2, 5, 5, 8, 8, 8, 9, 0) .build(); private boolean forwardSearch = true; private int lastIterationTime = NOT_SET; @@ -112,6 +112,7 @@ public void pathFilteringListener(DebugEvent> e) { RaptorPath p = e.element(); var aLeg = p.accessLeg(); var eLeg = p.egressLeg(); + println( pathTable.rowAsText( e.action().toString(), diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/internalapi/PassThroughPointsService.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/internalapi/PassThroughPointsService.java index 69899b55688..4932d9c46fe 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/internalapi/PassThroughPointsService.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/internalapi/PassThroughPointsService.java @@ -54,7 +54,7 @@ default boolean isNoop() { void updateC2Value(int currentPathC2, IntConsumer update); /** - * This is the dominance function to use for comparing transit-priority-groupIds. + * This is the dominance function to use for comparing transit-group-priorityIds. * It is critical that the implementation is "static" so it can be inlined, since it * is run in the innermost loop of Raptor. */ diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/configure/McRangeRaptorConfig.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/configure/McRangeRaptorConfig.java index e7aa07fb914..8eef90950dd 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/configure/McRangeRaptorConfig.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/configure/McRangeRaptorConfig.java @@ -6,7 +6,7 @@ import org.opentripplanner.raptor.api.model.DominanceFunction; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; import org.opentripplanner.raptor.api.request.MultiCriteriaRequest; -import org.opentripplanner.raptor.api.request.RaptorTransitPriorityGroupCalculator; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; import org.opentripplanner.raptor.rangeraptor.context.SearchContext; import org.opentripplanner.raptor.rangeraptor.internalapi.Heuristics; import org.opentripplanner.raptor.rangeraptor.internalapi.ParetoSetCost; @@ -29,7 +29,7 @@ import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.c1.PatternRideC1; import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.c2.PassThroughRideFactory; import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.c2.PatternRideC2; -import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.c2.TransitPriorityGroupRideFactory; +import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.c2.TransitGroupPriorityRideFactory; import org.opentripplanner.raptor.rangeraptor.path.DestinationArrivalPaths; import org.opentripplanner.raptor.rangeraptor.path.configure.PathConfig; import org.opentripplanner.raptor.util.paretoset.ParetoComparator; @@ -173,7 +173,8 @@ private MultiCriteriaRequest mcRequest() { } /** - * Currently "transit-priority-groups" is the only feature using two multi-criteria(c2). + * Use c2 in the search, this is use-case specific. For example the pass-through or + * transit-group-priority features uses the c2 value. */ private boolean includeC2() { return mcRequest().includeC2(); @@ -184,7 +185,7 @@ private PatternRideFactory> createPatternRideC2Factory() { return new PassThroughRideFactory<>(passThroughPointsService); } if (isTransitPriority()) { - return new TransitPriorityGroupRideFactory<>(getTransitPriorityGroupCalculator()); + return new TransitGroupPriorityRideFactory<>(getTransitGroupPriorityCalculator()); } throw new IllegalStateException("Only pass-through and transit-priority uses c2."); } @@ -195,12 +196,12 @@ private DominanceFunction dominanceFunctionC2() { return passThroughPointsService.dominanceFunction(); } if (isTransitPriority()) { - return getTransitPriorityGroupCalculator().dominanceFunction(); + return getTransitGroupPriorityCalculator().dominanceFunction(); } return null; } - private RaptorTransitPriorityGroupCalculator getTransitPriorityGroupCalculator() { + private RaptorTransitGroupCalculator getTransitGroupPriorityCalculator() { return mcRequest().transitPriorityCalculator().orElseThrow(); } diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/ride/c2/TransitPriorityGroupRideFactory.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/ride/c2/TransitGroupPriorityRideFactory.java similarity index 67% rename from src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/ride/c2/TransitPriorityGroupRideFactory.java rename to src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/ride/c2/TransitGroupPriorityRideFactory.java index eca049233b9..5d65c40d021 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/ride/c2/TransitPriorityGroupRideFactory.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/multicriteria/ride/c2/TransitGroupPriorityRideFactory.java @@ -2,25 +2,25 @@ import org.opentripplanner.raptor.api.model.RaptorTripPattern; import org.opentripplanner.raptor.api.model.RaptorTripSchedule; -import org.opentripplanner.raptor.api.request.RaptorTransitPriorityGroupCalculator; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; import org.opentripplanner.raptor.rangeraptor.multicriteria.arrivals.McStopArrival; import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.PatternRide; import org.opentripplanner.raptor.rangeraptor.multicriteria.ride.PatternRideFactory; /** - * This factory creates new {@link PatternRide}s and merge in transit-priority-group ids + * This factory creates new {@link PatternRide}s and merge in transit-group-priority ids * into c2. */ -public class TransitPriorityGroupRideFactory +public class TransitGroupPriorityRideFactory implements PatternRideFactory> { private int currentPatternGroupPriority; - private final RaptorTransitPriorityGroupCalculator transitPriorityGroupCalculator; + private final RaptorTransitGroupCalculator transitGroupPriorityCalculator; - public TransitPriorityGroupRideFactory( - RaptorTransitPriorityGroupCalculator transitPriorityGroupCalculator + public TransitGroupPriorityRideFactory( + RaptorTransitGroupCalculator transitGroupPriorityCalculator ) { - this.transitPriorityGroupCalculator = transitPriorityGroupCalculator; + this.transitGroupPriorityCalculator = transitGroupPriorityCalculator; } @Override @@ -52,12 +52,9 @@ public void prepareForTransitWith(RaptorTripPattern pattern) { } /** - * Currently transit-priority-group is the only usage of c2 + * Currently transit-group-priority is the only usage of c2 */ private int calculateC2(int c2) { - return transitPriorityGroupCalculator.mergeTransitPriorityGroupIds( - c2, - currentPatternGroupPriority - ); + return transitGroupPriorityCalculator.mergeGroupIds(c2, currentPatternGroupPriority); } } diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctions.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctions.java index 5059be84312..1ab737ae907 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctions.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctions.java @@ -5,12 +5,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.function.Predicate; import java.util.function.ToIntFunction; import java.util.stream.Collectors; import org.opentripplanner.raptor.api.model.RaptorAccessEgress; import org.opentripplanner.raptor.util.paretoset.ParetoComparator; import org.opentripplanner.raptor.util.paretoset.ParetoSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This class contains functions used by the {@link AccessPaths} and {@link EgressPaths} classes. @@ -23,8 +26,10 @@ */ public final class AccessEgressFunctions { + private static final Logger LOG = LoggerFactory.getLogger(AccessEgressFunctions.class); + /** - * Filter standard(not multi-criteria) Raptor access and egress paths. A path is pareto optimal + * Filter standard (not multi-criteria) Raptor access and egress paths. A path is pareto optimal * for a given stop if *

    *
  1. @@ -47,32 +52,57 @@ public final class AccessEgressFunctions { *
*/ private static final ParetoComparator STANDARD_COMPARATOR = (l, r) -> - (l.stopReachedOnBoard() && !r.stopReachedOnBoard()) || - r.hasOpeningHours() || - (l.numberOfRides() < r.numberOfRides()) || - (l.durationInSeconds() < r.durationInSeconds()); + ( + (l.stopReachedOnBoard() && !r.stopReachedOnBoard()) || + r.hasOpeningHours() || + l.numberOfRides() < r.numberOfRides() || + l.durationInSeconds() < r.durationInSeconds() + ); + + /** + * Filter Multi-criteria Raptor access and egress paths. This can be used to wash + * access/egress paths - paths that are not optimal using this should not be passed into + * Raptor - it is a bug. + */ + private static final ParetoComparator MC_COMPARATOR = (l, r) -> + STANDARD_COMPARATOR.leftDominanceExist(l, r) || l.c1() < r.c1(); /** private constructor to prevent instantiation of utils class. */ private AccessEgressFunctions() {} - static Collection removeNoneOptimalPathsForStandardRaptor( + /** + * Filter non-optimal paths away for the standard search. This method does not + * look at the c1 value. + */ + static Collection removeNonOptimalPathsForStandardRaptor( Collection paths ) { - // To avoid too many items in the pareto set we first group the paths by stop, - // for each stop we filter it down to the optimal pareto set. We could do this - // for multi-criteria as well, but it is likely not so important. The focus for - // the mc-set should be that the list of access/egress created in OTP should not - // contain to many non-optimal paths. - var mapByStop = groupByStop(paths); - var set = new ParetoSet<>(STANDARD_COMPARATOR); - Collection result = new ArrayList<>(); + return removeNonOptimalPaths(paths, STANDARD_COMPARATOR); + } - mapByStop.forEachValue(list -> { - set.clear(); - set.addAll(list); - result.addAll(set); - return true; - }); + /** + * Filter non-optimal paths away for the multi-criteria search. This method should in theory + * not remove any paths since the caller should not pass in duplicates, but it turns out that + * this happens, so we do it. + */ + static Collection removeNonOptimalPathsForMcRaptor( + Collection paths + ) { + var result = removeNonOptimalPaths(paths, MC_COMPARATOR); + if (LOG.isDebugEnabled() && result.size() < paths.size()) { + var duplicates = new ArrayList<>(paths); + duplicates.removeAll(result); + // Note! This does not provide enough information to solve/debug this problem, but this is + // not a problem in Raptor, so we do not want to add more specific logging here - this does + // however document that the problem exist. Turn on debug logging and move the start/end + // coordinate around until you see this message. + // + // See https://github.com/opentripplanner/OpenTripPlanner/issues/5601 + LOG.warn( + "Duplicate access/egress paths passed into raptor:\n\t" + + duplicates.stream().map(Objects::toString).collect(Collectors.joining("\n\t")) + ); + } return result; } @@ -96,6 +126,27 @@ static TIntObjectMap> groupByStop(Collection removeNonOptimalPaths( + Collection paths, + ParetoComparator comparator + ) { + var mapByStop = groupByStop(paths); + var set = new ParetoSet<>(comparator); + var result = new ArrayList(); + + for (int stop : mapByStop.keys()) { + var list = mapByStop.get(stop); + set.clear(); + set.addAll(list); + result.addAll(set); + } + return result; + } + private static List getOrCreate( int key, TIntObjectMap> map diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessPaths.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessPaths.java index 940937f82db..5c26a10db23 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessPaths.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/AccessPaths.java @@ -1,7 +1,8 @@ package org.opentripplanner.raptor.rangeraptor.transit; import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.groupByRound; -import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNoneOptimalPathsForStandardRaptor; +import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNonOptimalPathsForMcRaptor; +import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNonOptimalPathsForStandardRaptor; import gnu.trove.map.TIntObjectMap; import java.util.Arrays; @@ -57,8 +58,10 @@ public int calculateMaxNumberOfRides() { * This method is static and package local to enable unit-testing. */ public static AccessPaths create(Collection paths, RaptorProfile profile) { - if (!profile.is(RaptorProfile.MULTI_CRITERIA)) { - paths = removeNoneOptimalPathsForStandardRaptor(paths); + if (profile.is(RaptorProfile.MULTI_CRITERIA)) { + paths = removeNonOptimalPathsForMcRaptor(paths); + } else { + paths = removeNonOptimalPathsForStandardRaptor(paths); } return new AccessPaths( groupByRound(paths, RaptorAccessEgress::stopReachedByWalking), diff --git a/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPaths.java b/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPaths.java index 2038ab543df..374fc050782 100644 --- a/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPaths.java +++ b/src/main/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPaths.java @@ -2,7 +2,8 @@ import static org.opentripplanner.raptor.api.request.RaptorProfile.MULTI_CRITERIA; import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.groupByStop; -import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNoneOptimalPathsForStandardRaptor; +import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNonOptimalPathsForMcRaptor; +import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNonOptimalPathsForStandardRaptor; import gnu.trove.map.TIntObjectMap; import java.util.Collection; @@ -31,8 +32,10 @@ private EgressPaths(TIntObjectMap> pathsByStop) { * This method is static and package local to enable unit-testing. */ public static EgressPaths create(Collection paths, RaptorProfile profile) { - if (!MULTI_CRITERIA.is(profile)) { - paths = removeNoneOptimalPathsForStandardRaptor(paths); + if (MULTI_CRITERIA.is(profile)) { + paths = removeNonOptimalPathsForMcRaptor(paths); + } else { + paths = removeNonOptimalPathsForStandardRaptor(paths); } return new EgressPaths(groupByStop(paths)); } diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitPriorityGroup32n.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitGroupPriority32n.java similarity index 76% rename from src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitPriorityGroup32n.java rename to src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitGroupPriority32n.java index 9b744932b8b..feb3f6f7b3a 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitPriorityGroup32n.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitGroupPriority32n.java @@ -1,33 +1,33 @@ package org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.grouppriority; import org.opentripplanner.raptor.api.model.DominanceFunction; -import org.opentripplanner.raptor.api.request.RaptorTransitPriorityGroupCalculator; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; /** * This is a "BitSet" implementation for groupId. It can store upto 32 groups, * a set with few elements does NOT dominate a set with more elements. */ -public class TransitPriorityGroup32n { +public class TransitGroupPriority32n { private static final int GROUP_ZERO = 0; private static final int MIN_SEQ_NO = 0; private static final int MAX_SEQ_NO = 32; - public static RaptorTransitPriorityGroupCalculator priorityCalculator() { - return new RaptorTransitPriorityGroupCalculator() { + public static RaptorTransitGroupCalculator priorityCalculator() { + return new RaptorTransitGroupCalculator() { @Override - public int mergeTransitPriorityGroupIds(int currentGroupIds, int boardingGroupId) { + public int mergeGroupIds(int currentGroupIds, int boardingGroupId) { return mergeInGroupId(currentGroupIds, boardingGroupId); } @Override public DominanceFunction dominanceFunction() { - return TransitPriorityGroup32n::dominate; + return TransitGroupPriority32n::dominate; } @Override public String toString() { - return "TransitPriorityGroup32nCalculator{}"; + return "TransitGroupPriority32nCalculator{}"; } }; } @@ -42,7 +42,7 @@ public static boolean dominate(int left, int right) { @Override public String toString() { - return "TransitPriorityGroup32n{}"; + return "TransitGroupPriority32n{}"; } /** @@ -64,12 +64,12 @@ public static int mergeInGroupId(final int currentSetOfGroupIds, final int newGr private static void assertValidGroupSeqNo(int priorityGroupIndex) { if (priorityGroupIndex < MIN_SEQ_NO) { throw new IllegalArgumentException( - "Transit priority group can not be a negative number: " + priorityGroupIndex + "Transit group priority can not be a negative number: " + priorityGroupIndex ); } if (priorityGroupIndex > MAX_SEQ_NO) { throw new IllegalArgumentException( - "Transit priority group exceeds max number of groups: " + + "Transit group priority exceeds max number of groups: " + priorityGroupIndex + " (MAX=" + MAX_SEQ_NO + diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/RaptorRequestMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/RaptorRequestMapper.java index 75c1bcf7214..5f3b4b13746 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/RaptorRequestMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/RaptorRequestMapper.java @@ -13,6 +13,7 @@ import org.opentripplanner.raptor.api.model.RaptorAccessEgress; import org.opentripplanner.raptor.api.model.RaptorConstants; import org.opentripplanner.raptor.api.model.RelaxFunction; +import org.opentripplanner.raptor.api.request.DebugRequestBuilder; import org.opentripplanner.raptor.api.request.Optimization; import org.opentripplanner.raptor.api.request.PassThroughPoint; import org.opentripplanner.raptor.api.request.RaptorRequest; @@ -21,7 +22,8 @@ import org.opentripplanner.routing.algorithm.raptoradapter.router.performance.PerformanceTimersForRaptor; import org.opentripplanner.routing.algorithm.raptoradapter.transit.TripSchedule; import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.RaptorCostConverter; -import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.grouppriority.TransitPriorityGroup32n; +import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.grouppriority.TransitGroupPriority32n; +import org.opentripplanner.routing.api.request.DebugEventType; import org.opentripplanner.routing.api.request.RouteRequest; import org.opentripplanner.routing.api.request.framework.CostLinearFunction; import org.opentripplanner.transit.model.site.StopLocation; @@ -117,9 +119,9 @@ private RaptorRequest doMap() { builder.withMultiCriteria(mcBuilder -> { var pt = preferences.transit(); var r = pt.raptor(); - if (!pt.relaxTransitPriorityGroup().isNormal()) { - mcBuilder.withTransitPriorityCalculator(TransitPriorityGroup32n.priorityCalculator()); - mcBuilder.withRelaxC1(mapRelaxCost(pt.relaxTransitPriorityGroup())); + if (!pt.relaxTransitGroupPriority().isNormal()) { + mcBuilder.withTransitPriorityCalculator(TransitGroupPriority32n.priorityCalculator()); + mcBuilder.withRelaxC1(mapRelaxCost(pt.relaxTransitGroupPriority())); } else { mcBuilder.withPassThroughPoints(mapPassThroughPoints()); r.relaxGeneralizedCostAtDestination().ifPresent(mcBuilder::withRelaxCostAtDestination); @@ -156,10 +158,11 @@ private RaptorRequest doMap() { .addStops(raptorDebugging.stops()) .setPath(raptorDebugging.path()) .debugPathFromStopIndex(raptorDebugging.debugPathFromStopIndex()) - .stopArrivalListener(debugLogger::stopArrivalLister) - .patternRideDebugListener(debugLogger::patternRideLister) - .pathFilteringListener(debugLogger::pathFilteringListener) .logger(debugLogger); + + for (var type : raptorDebugging.eventTypes()) { + addLogListenerForEachEventTypeRequested(debug, type, debugLogger); + } } if (!request.timetableView() && request.arriveBy()) { @@ -209,4 +212,16 @@ private int relativeTime(Instant time) { } return (int) (time.getEpochSecond() - transitSearchTimeZeroEpocSecond); } + + private static void addLogListenerForEachEventTypeRequested( + DebugRequestBuilder target, + DebugEventType type, + SystemErrDebugLogger logger + ) { + switch (type) { + case STOP_ARRIVALS -> target.stopArrivalListener(logger::stopArrivalLister); + case PATTERN_RIDES -> target.patternRideDebugListener(logger::patternRideLister); + case DESTINATION_ARRIVALS -> target.pathFilteringListener(logger::pathFilteringListener); + } + } } diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java index 25006af49d8..826b9c09a13 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfigurator.java @@ -8,14 +8,14 @@ import java.util.List; import java.util.stream.Stream; import org.opentripplanner.framework.lang.ArrayUtils; -import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.grouppriority.TransitPriorityGroup32n; -import org.opentripplanner.routing.api.request.request.filter.TransitPriorityGroupSelect; +import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.grouppriority.TransitGroupPriority32n; +import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.network.RoutingTripPattern; /** * This class dynamically builds an index of transit-group-ids from the - * provided {@link TransitPriorityGroupSelect}s while serving the caller with + * provided {@link TransitGroupSelect}s while serving the caller with * group-ids for each requested pattern. It is made for optimal * performance, since it is used in request scope. *

@@ -44,7 +44,7 @@ public class PriorityGroupConfigurator { */ private static final int GROUP_INDEX_COUNTER_START = 1; - private final int baseGroupId = TransitPriorityGroup32n.groupId(GROUP_INDEX_COUNTER_START); + private final int baseGroupId = TransitGroupPriority32n.groupId(GROUP_INDEX_COUNTER_START); private int groupIndexCounter = GROUP_INDEX_COUNTER_START; private final boolean enabled; private final PriorityGroupMatcher[] agencyMatchers; @@ -63,8 +63,8 @@ private PriorityGroupConfigurator() { } private PriorityGroupConfigurator( - Collection byAgency, - Collection global + Collection byAgency, + Collection global ) { this.agencyMatchers = PriorityGroupMatcher.of(byAgency); this.globalMatchers = PriorityGroupMatcher.of(global); @@ -80,8 +80,8 @@ public static PriorityGroupConfigurator empty() { } public static PriorityGroupConfigurator of( - Collection byAgency, - Collection global + Collection byAgency, + Collection global ) { if (Stream.of(byAgency, global).allMatch(Collection::isEmpty)) { return empty(); @@ -94,7 +94,7 @@ public static PriorityGroupConfigurator of( *

* @throws IllegalArgumentException if more than 32 group-ids are requested. */ - public int lookupTransitPriorityGroupId(RoutingTripPattern tripPattern) { + public int lookupTransitGroupPriorityId(RoutingTripPattern tripPattern) { if (!enabled || tripPattern == null) { return baseGroupId; } @@ -128,7 +128,7 @@ public int baseGroupId() { } private int nextGroupId() { - return TransitPriorityGroup32n.groupId(++groupIndexCounter); + return TransitGroupPriority32n.groupId(++groupIndexCounter); } /** Pair of matcher and groupId. Used only inside this class. */ diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcher.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcher.java index 4d8a0475239..c017f2862ab 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcher.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcher.java @@ -15,13 +15,13 @@ import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; -import org.opentripplanner.routing.api.request.request.filter.TransitPriorityGroupSelect; +import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect; import org.opentripplanner.transit.model.basic.TransitMode; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.network.TripPattern; /** - * This class turns a {@link TransitPriorityGroupSelect} into a matcher. + * This class turns a {@link TransitGroupSelect} into a matcher. *

* Design: It uses the composite design pattern. A matcher is created for each * value in the "select", then the list of non-empty matchers is merged into @@ -42,7 +42,7 @@ boolean isEmpty() { } }; - public static PriorityGroupMatcher of(TransitPriorityGroupSelect select) { + public static PriorityGroupMatcher of(TransitGroupSelect select) { if (select.isEmpty()) { return NOOP; } @@ -65,7 +65,7 @@ public static PriorityGroupMatcher of(TransitPriorityGroupSelect select) { return andOf(list); } - static PriorityGroupMatcher[] of(Collection selectors) { + static PriorityGroupMatcher[] of(Collection selectors) { return selectors .stream() .map(PriorityGroupMatcher::of) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java index f1212b2f545..4338593d59d 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java @@ -92,7 +92,7 @@ public RaptorRoutingRequestTransitData( additionalPastSearchDays, additionalFutureSearchDays, filter, - createTransitPriorityGroupConfigurator(request) + createTransitGroupPriorityConfigurator(request) ); this.patternIndex = transitDataCreator.createPatternIndex(tripPatterns); this.activeTripPatternsPerStop = transitDataCreator.createTripPatternsPerStop(tripPatterns); @@ -243,8 +243,8 @@ public RaptorConstrainedBoardingSearch transferConstraintsReverseS return new ConstrainedBoardingSearch(false, toStopTransfers, fromStopTransfers); } - private PriorityGroupConfigurator createTransitPriorityGroupConfigurator(RouteRequest request) { - if (request.preferences().transit().relaxTransitPriorityGroup().isNormal()) { + private PriorityGroupConfigurator createTransitGroupPriorityConfigurator(RouteRequest request) { + if (request.preferences().transit().relaxTransitGroupPriority().isNormal()) { return PriorityGroupConfigurator.empty(); } var transitRequest = request.journey().transit(); diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java index 0cb155facd5..b8f915d6eb4 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitDataCreator.java @@ -147,7 +147,7 @@ static List merge( tripPattern.getAlightingPossible(), BoardAlight.ALIGHT ), - priorityGroupConfigurator.lookupTransitPriorityGroupId(tripPattern) + priorityGroupConfigurator.lookupTransitGroupPriorityId(tripPattern) ) ); } diff --git a/src/main/java/org/opentripplanner/routing/api/request/DebugEventType.java b/src/main/java/org/opentripplanner/routing/api/request/DebugEventType.java new file mode 100644 index 00000000000..09f9dbbe732 --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/api/request/DebugEventType.java @@ -0,0 +1,11 @@ +package org.opentripplanner.routing.api.request; + +/** + * Raptor check paths in 3 different places. The debugger can print events + * for each of these. + */ +public enum DebugEventType { + STOP_ARRIVALS, + PATTERN_RIDES, + DESTINATION_ARRIVALS, +} diff --git a/src/main/java/org/opentripplanner/routing/api/request/DebugRaptor.java b/src/main/java/org/opentripplanner/routing/api/request/DebugRaptor.java index 7d6c1472eee..0b9ff4f0c30 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/DebugRaptor.java +++ b/src/main/java/org/opentripplanner/routing/api/request/DebugRaptor.java @@ -3,7 +3,11 @@ import java.io.Serial; import java.io.Serializable; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.regex.Pattern; import org.opentripplanner.framework.tostring.ToStringBuilder; import org.slf4j.Logger; @@ -46,14 +50,16 @@ public class DebugRaptor implements Serializable { private List stops = List.of(); private List path = List.of(); private int debugPathFromStopIndex = 0; + private Set eventTypes = EnumSet.noneOf(DebugEventType.class); public DebugRaptor() {} - /** Avoid using clone(), use copy-constructor instead(Josh Bloch). */ + /** Avoid using clone(), use copy-constructor instead (Josh Bloch). */ public DebugRaptor(DebugRaptor other) { this.stops = List.copyOf(other.stops); this.path = List.copyOf(other.path); this.debugPathFromStopIndex = other.debugPathFromStopIndex; + this.eventTypes = EnumSet.copyOf(other.eventTypes); } public boolean isEnabled() { @@ -90,12 +96,23 @@ public int debugPathFromStopIndex() { return debugPathFromStopIndex; } + public Set eventTypes() { + return Collections.unmodifiableSet(eventTypes); + } + + public DebugRaptor withEventTypes(Collection eventTypes) { + this.eventTypes.clear(); + this.eventTypes.addAll(eventTypes); + return this; + } + @Override public String toString() { return ToStringBuilder .of(DebugRaptor.class) .addObj("stops", toString(stops, FIRST_STOP_INDEX)) .addObj("path", toString(path, debugPathFromStopIndex)) + .addCol("eventType", eventTypes) .toString(); } diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/TransitPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/TransitPreferences.java index 1ad6e8ddacd..78f30277e72 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/TransitPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/TransitPreferences.java @@ -26,7 +26,7 @@ public final class TransitPreferences implements Serializable { private final Map reluctanceForMode; private final Cost otherThanPreferredRoutesPenalty; private final CostLinearFunction unpreferredCost; - private final CostLinearFunction relaxTransitPriorityGroup; + private final CostLinearFunction relaxTransitGroupPriority; private final boolean ignoreRealtimeUpdates; private final boolean includePlannedCancellations; private final boolean includeRealtimeCancellations; @@ -37,7 +37,7 @@ private TransitPreferences() { this.reluctanceForMode = Map.of(); this.otherThanPreferredRoutesPenalty = Cost.costOfMinutes(5); this.unpreferredCost = CostLinearFunction.NORMAL; - this.relaxTransitPriorityGroup = CostLinearFunction.NORMAL; + this.relaxTransitGroupPriority = CostLinearFunction.NORMAL; this.ignoreRealtimeUpdates = false; this.includePlannedCancellations = false; this.includeRealtimeCancellations = false; @@ -50,7 +50,7 @@ private TransitPreferences(Builder builder) { this.reluctanceForMode = Map.copyOf(requireNonNull(builder.reluctanceForMode)); this.otherThanPreferredRoutesPenalty = builder.otherThanPreferredRoutesPenalty; this.unpreferredCost = requireNonNull(builder.unpreferredCost); - this.relaxTransitPriorityGroup = Objects.requireNonNull(builder.relaxTransitPriorityGroup); + this.relaxTransitGroupPriority = Objects.requireNonNull(builder.relaxTransitGroupPriority); this.ignoreRealtimeUpdates = builder.ignoreRealtimeUpdates; this.includePlannedCancellations = builder.includePlannedCancellations; this.includeRealtimeCancellations = builder.includeRealtimeCancellations; @@ -128,13 +128,13 @@ public CostLinearFunction unpreferredCost() { } /** - * This is used to relax the cost when comparing transit-priority-groups. The default is the - * NORMAL function({@code f(x) = x}. This is the same as not using priority-groups. The + * This is used to relax the cost when comparing transit-groups. The default is the + * NORMAL function({@code f(t) = t}. This is the same as not using priority-groups. The * coefficient must be in range {@code [1.0 to 4.0]} and the constant must be in range * {@code [$0 to $1440(4h)]}. */ - public CostLinearFunction relaxTransitPriorityGroup() { - return relaxTransitPriorityGroup; + public CostLinearFunction relaxTransitGroupPriority() { + return relaxTransitGroupPriority; } /** @@ -176,7 +176,7 @@ public boolean equals(Object o) { reluctanceForMode.equals(that.reluctanceForMode) && Objects.equals(otherThanPreferredRoutesPenalty, that.otherThanPreferredRoutesPenalty) && unpreferredCost.equals(that.unpreferredCost) && - Objects.equals(relaxTransitPriorityGroup, that.relaxTransitPriorityGroup) && + Objects.equals(relaxTransitGroupPriority, that.relaxTransitGroupPriority) && ignoreRealtimeUpdates == that.ignoreRealtimeUpdates && includePlannedCancellations == that.includePlannedCancellations && includeRealtimeCancellations == that.includeRealtimeCancellations && @@ -192,7 +192,7 @@ public int hashCode() { reluctanceForMode, otherThanPreferredRoutesPenalty, unpreferredCost, - relaxTransitPriorityGroup, + relaxTransitGroupPriority, ignoreRealtimeUpdates, includePlannedCancellations, includeRealtimeCancellations, @@ -213,7 +213,7 @@ public String toString() { DEFAULT.otherThanPreferredRoutesPenalty ) .addObj("unpreferredCost", unpreferredCost, DEFAULT.unpreferredCost) - .addObj("relaxTransitPriorityGroup", relaxTransitPriorityGroup, CostLinearFunction.NORMAL) + .addObj("relaxTransitGroupPriority", relaxTransitGroupPriority, CostLinearFunction.NORMAL) .addBoolIfTrue( "ignoreRealtimeUpdates", ignoreRealtimeUpdates != DEFAULT.ignoreRealtimeUpdates @@ -240,7 +240,7 @@ public static class Builder { private Map reluctanceForMode; private Cost otherThanPreferredRoutesPenalty; private CostLinearFunction unpreferredCost; - private CostLinearFunction relaxTransitPriorityGroup; + private CostLinearFunction relaxTransitGroupPriority; private boolean ignoreRealtimeUpdates; private boolean includePlannedCancellations; private boolean includeRealtimeCancellations; @@ -253,7 +253,7 @@ public Builder(TransitPreferences original) { this.reluctanceForMode = original.reluctanceForMode; this.otherThanPreferredRoutesPenalty = original.otherThanPreferredRoutesPenalty; this.unpreferredCost = original.unpreferredCost; - this.relaxTransitPriorityGroup = original.relaxTransitPriorityGroup; + this.relaxTransitGroupPriority = original.relaxTransitGroupPriority; this.ignoreRealtimeUpdates = original.ignoreRealtimeUpdates; this.includePlannedCancellations = original.includePlannedCancellations; this.includeRealtimeCancellations = original.includeRealtimeCancellations; @@ -302,8 +302,8 @@ public Builder setUnpreferredCostString(String constFunction) { return setUnpreferredCost(CostLinearFunction.of(constFunction)); } - public Builder withTransitGroupPriorityGeneralizedCostSlack(CostLinearFunction value) { - this.relaxTransitPriorityGroup = value; + public Builder withRelaxTransitGroupPriority(CostLinearFunction value) { + this.relaxTransitGroupPriority = value; return this; } diff --git a/src/main/java/org/opentripplanner/routing/api/request/request/TransitRequest.java b/src/main/java/org/opentripplanner/routing/api/request/request/TransitRequest.java index 67a56249328..b5626c479a0 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/request/TransitRequest.java +++ b/src/main/java/org/opentripplanner/routing/api/request/request/TransitRequest.java @@ -8,7 +8,7 @@ import org.opentripplanner.routing.api.request.DebugRaptor; import org.opentripplanner.routing.api.request.request.filter.AllowAllTransitFilter; import org.opentripplanner.routing.api.request.request.filter.TransitFilter; -import org.opentripplanner.routing.api.request.request.filter.TransitPriorityGroupSelect; +import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect; import org.opentripplanner.transit.model.framework.FeedScopedId; // TODO VIA: Javadoc @@ -31,8 +31,8 @@ public class TransitRequest implements Cloneable, Serializable { private List unpreferredRoutes = List.of(); - private List priorityGroupsByAgency = new ArrayList<>(); - private List priorityGroupsGlobal = new ArrayList<>(); + private List priorityGroupsByAgency = new ArrayList<>(); + private List priorityGroupsGlobal = new ArrayList<>(); private DebugRaptor raptorDebugging = new DebugRaptor(); public void setBannedTripsFromString(String ids) { @@ -64,16 +64,14 @@ public void setFilters(List filters) { *

* Note! Entities that are not matched are put in the BASE-GROUP with id 0. */ - public List priorityGroupsByAgency() { + public List priorityGroupsByAgency() { return priorityGroupsByAgency; } /** * All patterns matching the same select will be assigned the same group-id. */ - public void addPriorityGroupsByAgency( - Collection priorityGroupsByAgency - ) { + public void addPriorityGroupsByAgency(Collection priorityGroupsByAgency) { this.priorityGroupsByAgency.addAll(priorityGroupsByAgency); } @@ -82,11 +80,11 @@ public void addPriorityGroupsByAgency( *

* Note! Entities that are not matched are put in the BASE-GROUP with id 0. */ - public List priorityGroupsGlobal() { + public List priorityGroupsGlobal() { return priorityGroupsGlobal; } - public void addPriorityGroupsGlobal(Collection priorityGroupsGlobal) { + public void addPriorityGroupsGlobal(Collection priorityGroupsGlobal) { this.priorityGroupsGlobal.addAll(priorityGroupsGlobal); } diff --git a/src/main/java/org/opentripplanner/routing/api/request/request/filter/TransitPriorityGroupSelect.java b/src/main/java/org/opentripplanner/routing/api/request/request/filter/TransitGroupSelect.java similarity index 87% rename from src/main/java/org/opentripplanner/routing/api/request/request/filter/TransitPriorityGroupSelect.java rename to src/main/java/org/opentripplanner/routing/api/request/request/filter/TransitGroupSelect.java index 6d763e9c3bc..dfa5daa0e31 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/request/filter/TransitPriorityGroupSelect.java +++ b/src/main/java/org/opentripplanner/routing/api/request/request/filter/TransitGroupSelect.java @@ -21,23 +21,23 @@ *

  • {@code Entity(mode:SUBWAY, agency:A3)}
  • * */ -public class TransitPriorityGroupSelect { +public class TransitGroupSelect { - private static final TransitPriorityGroupSelect DEFAULT = new TransitPriorityGroupSelect(); + private static final TransitGroupSelect DEFAULT = new TransitGroupSelect(); private final List modes; private final List subModeRegexp; private final List agencyIds; private final List routeIds; - public TransitPriorityGroupSelect() { + public TransitGroupSelect() { this.modes = List.of(); this.subModeRegexp = List.of(); this.agencyIds = List.of(); this.routeIds = List.of(); } - private TransitPriorityGroupSelect(Builder builder) { + private TransitGroupSelect(Builder builder) { // Sort and keep only unique entries, this make this // implementation consistent for eq/hc/toString. this.modes = @@ -77,7 +77,7 @@ public boolean isEmpty() { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - TransitPriorityGroupSelect that = (TransitPriorityGroupSelect) o; + TransitGroupSelect that = (TransitGroupSelect) o; return ( Objects.equals(modes, that.modes) && Objects.equals(subModeRegexp, that.subModeRegexp) && @@ -96,7 +96,7 @@ public String toString() { return isEmpty() ? "TransitGroupSelect{ EMPTY }" : ToStringBuilder - .of(TransitPriorityGroupSelect.class) + .of(TransitGroupSelect.class) .addCol("modes", modes) .addCol("subModeRegexp", subModeRegexp) .addCol("agencyIds", agencyIds) @@ -106,13 +106,13 @@ public String toString() { public static class Builder { - private final TransitPriorityGroupSelect original; + private final TransitGroupSelect original; private final List modes; private final List subModeRegexp; private final List agencyIds; private final List routeIds; - public Builder(TransitPriorityGroupSelect original) { + public Builder(TransitGroupSelect original) { this.original = original; this.modes = new ArrayList<>(original.modes); this.subModeRegexp = new ArrayList<>(original.subModeRegexp); @@ -140,8 +140,8 @@ public Builder addRouteIds(Collection routeIds) { return this; } - public TransitPriorityGroupSelect build() { - var obj = new TransitPriorityGroupSelect(this); + public TransitGroupSelect build() { + var obj = new TransitGroupSelect(this); return original.equals(obj) ? original : obj; } } diff --git a/src/main/java/org/opentripplanner/routing/error/PathNotFoundException.java b/src/main/java/org/opentripplanner/routing/error/PathNotFoundException.java index 18d94d23038..a4071f9911e 100644 --- a/src/main/java/org/opentripplanner/routing/error/PathNotFoundException.java +++ b/src/main/java/org/opentripplanner/routing/error/PathNotFoundException.java @@ -4,6 +4,5 @@ * Indicates that the call to org.opentripplanner.routing.services.PathService returned either null * or ZERO paths. * - * @see org.opentripplanner.api.resource.PlannerResource for where this is (locally) thrown. */ public class PathNotFoundException extends RuntimeException {} diff --git a/src/main/java/org/opentripplanner/standalone/config/routerconfig/UpdatersConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerconfig/UpdatersConfig.java index 0f61fa4f7a2..08371660b8a 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerconfig/UpdatersConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerconfig/UpdatersConfig.java @@ -14,7 +14,6 @@ import static org.opentripplanner.standalone.config.routerconfig.UpdatersConfig.Type.VEHICLE_PARKING; import static org.opentripplanner.standalone.config.routerconfig.UpdatersConfig.Type.VEHICLE_POSITIONS; import static org.opentripplanner.standalone.config.routerconfig.UpdatersConfig.Type.VEHICLE_RENTAL; -import static org.opentripplanner.standalone.config.routerconfig.UpdatersConfig.Type.WEBSOCKET_GTFS_RT_UPDATER; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -39,7 +38,6 @@ import org.opentripplanner.standalone.config.routerconfig.updaters.VehicleParkingUpdaterConfig; import org.opentripplanner.standalone.config.routerconfig.updaters.VehiclePositionsUpdaterConfig; import org.opentripplanner.standalone.config.routerconfig.updaters.VehicleRentalUpdaterConfig; -import org.opentripplanner.standalone.config.routerconfig.updaters.WebsocketGtfsRealtimeUpdaterConfig; import org.opentripplanner.standalone.config.routerconfig.updaters.azure.SiriAzureETUpdaterConfig; import org.opentripplanner.standalone.config.routerconfig.updaters.azure.SiriAzureSXUpdaterConfig; import org.opentripplanner.standalone.config.sandbox.VehicleRentalServiceDirectoryFetcherConfig; @@ -48,7 +46,6 @@ import org.opentripplanner.updater.alert.GtfsRealtimeAlertsUpdaterParameters; import org.opentripplanner.updater.trip.MqttGtfsRealtimeUpdaterParameters; import org.opentripplanner.updater.trip.PollingTripUpdaterParameters; -import org.opentripplanner.updater.trip.WebsocketGtfsRealtimeUpdaterParameters; import org.opentripplanner.updater.vehicle_parking.VehicleParkingUpdaterParameters; import org.opentripplanner.updater.vehicle_position.VehiclePositionsUpdaterParameters; import org.opentripplanner.updater.vehicle_rental.VehicleRentalUpdaterParameters; @@ -185,11 +182,6 @@ public List getSiriSXUpdaterParameters() { return getParameters(SIRI_SX_UPDATER); } - @Override - public List getWebsocketGtfsRealtimeUpdaterParameters() { - return getParameters(WEBSOCKET_GTFS_RT_UPDATER); - } - @Override public List getMqttGtfsRealtimeUpdaterParameters() { return getParameters(MQTT_GTFS_RT_UPDATER); @@ -222,7 +214,6 @@ public enum Type { BIKE_RENTAL(VehicleRentalUpdaterConfig::create), VEHICLE_RENTAL(VehicleRentalUpdaterConfig::create), STOP_TIME_UPDATER(PollingTripUpdaterConfig::create), - WEBSOCKET_GTFS_RT_UPDATER(WebsocketGtfsRealtimeUpdaterConfig::create), MQTT_GTFS_RT_UPDATER(MqttGtfsRealtimeUpdaterConfig::create), REAL_TIME_ALERTS(GtfsRealtimeAlertsUpdaterConfig::create), VEHICLE_POSITIONS(VehiclePositionsUpdaterConfig::create), diff --git a/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/MqttGtfsRealtimeUpdaterConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/MqttGtfsRealtimeUpdaterConfig.java index 372bd36227e..ccc4ca5e80f 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/MqttGtfsRealtimeUpdaterConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/MqttGtfsRealtimeUpdaterConfig.java @@ -1,6 +1,6 @@ package org.opentripplanner.standalone.config.routerconfig.updaters; -import static org.opentripplanner.standalone.config.framework.json.OtpVersion.NA; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_0; import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_2; import org.opentripplanner.standalone.config.framework.json.NodeAdapter; @@ -12,13 +12,13 @@ public class MqttGtfsRealtimeUpdaterConfig { public static MqttGtfsRealtimeUpdaterParameters create(String configRef, NodeAdapter c) { return new MqttGtfsRealtimeUpdaterParameters( configRef, - c.of("feedId").since(NA).summary("The feed id to apply the updates to.").asString(), - c.of("url").since(NA).summary("URL of the MQTT broker.").asString(), - c.of("topic").since(NA).summary("The topic to subscribe to.").asString(), - c.of("qos").since(NA).summary("QOS level.").asInt(0), + c.of("feedId").since(V2_0).summary("The feed id to apply the updates to.").asString(), + c.of("url").since(V2_0).summary("URL of the MQTT broker.").asString(), + c.of("topic").since(V2_0).summary("The topic to subscribe to.").asString(), + c.of("qos").since(V2_0).summary("QOS level.").asInt(0), c .of("fuzzyTripMatching") - .since(NA) + .since(V2_0) .summary("Whether to match trips fuzzily.") .asBoolean(false), c diff --git a/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/WebsocketGtfsRealtimeUpdaterConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/WebsocketGtfsRealtimeUpdaterConfig.java deleted file mode 100644 index 5f1c203ca43..00000000000 --- a/src/main/java/org/opentripplanner/standalone/config/routerconfig/updaters/WebsocketGtfsRealtimeUpdaterConfig.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.opentripplanner.standalone.config.routerconfig.updaters; - -import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V1_5; - -import org.opentripplanner.standalone.config.framework.json.NodeAdapter; -import org.opentripplanner.updater.trip.BackwardsDelayPropagationType; -import org.opentripplanner.updater.trip.WebsocketGtfsRealtimeUpdaterParameters; - -public class WebsocketGtfsRealtimeUpdaterConfig { - - public static WebsocketGtfsRealtimeUpdaterParameters create(String configRef, NodeAdapter c) { - return new WebsocketGtfsRealtimeUpdaterParameters( - configRef, - c.of("feedId").since(V1_5).summary("TODO").asString(), - c.of("url").since(V1_5).summary("TODO").asString(null), - c.of("reconnectPeriodSec").since(V1_5).summary("TODO").asInt(60), - c - .of("backwardsDelayPropagationType") - .since(V1_5) - .summary("TODO") - .asEnum(BackwardsDelayPropagationType.REQUIRED_NO_DATA) - ); - } -} diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java index e600f1f8f12..b733b2c7d8d 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java @@ -167,7 +167,7 @@ cost function. The cost function (`unpreferredCost`) is defined as a linear func .asFeedScopedIds(request.journey().transit().unpreferredAgencies()) ); - TransitPriorityGroupConfig.mapTransitRequest(c, request.journey().transit()); + TransitGroupPriorityConfig.mapTransitRequest(c, request.journey().transit()); // Map preferences request.withPreferences(preferences -> mapPreferences(c, preferences)); @@ -292,25 +292,24 @@ The board time is added to the time when going from the stop (offboard) to onboa .asCostLinearFunction(dft.unpreferredCost()) ); - String relaxTransitPriorityGroupValue = c - .of("relaxTransitPriorityGroup") + String relaxTransitGroupPriorityValue = c + .of("relaxTransitGroupPriority") .since(V2_5) - .summary("The relax function for transit-priority-groups") + .summary("The relax function for transit-group-priority") .description( """ - A path is considered optimal if the generalized-cost is less than the - generalized-cost of another path. If this parameter is set, the comparison is relaxed - further if they belong to different transit-priority-groups. + A path is considered optimal if the generalized-cost is less than the generalized-cost of + another path. If this parameter is set, the comparison is relaxed further if they belong + to different transit groups. """ ) - .asString(dft.relaxTransitPriorityGroup().toString()); + .asString(dft.relaxTransitGroupPriority().toString()); - if (relaxTransitPriorityGroupValue != null) { - builder.withTransitGroupPriorityGeneralizedCostSlack( - CostLinearFunction.of(relaxTransitPriorityGroupValue) - ); + if (relaxTransitGroupPriorityValue != null) { + builder.withRelaxTransitGroupPriority(CostLinearFunction.of(relaxTransitGroupPriorityValue)); } + // TODO REMOVE THIS builder.withRaptor(it -> c .of("relaxTransitSearchGeneralizedCostAtDestination") diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/TransitPriorityGroupConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/TransitGroupPriorityConfig.java similarity index 76% rename from src/main/java/org/opentripplanner/standalone/config/routerequest/TransitPriorityGroupConfig.java rename to src/main/java/org/opentripplanner/standalone/config/routerequest/TransitGroupPriorityConfig.java index 51faafc7cbf..e5f1ccd784a 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/TransitPriorityGroupConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/TransitGroupPriorityConfig.java @@ -6,36 +6,36 @@ import java.util.Collection; import java.util.List; import org.opentripplanner.routing.api.request.request.TransitRequest; -import org.opentripplanner.routing.api.request.request.filter.TransitPriorityGroupSelect; +import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect; import org.opentripplanner.standalone.config.framework.json.NodeAdapter; import org.opentripplanner.standalone.config.framework.json.OtpVersion; import org.opentripplanner.transit.model.basic.TransitMode; -public class TransitPriorityGroupConfig { +public class TransitGroupPriorityConfig { public static void mapTransitRequest(NodeAdapter root, TransitRequest transit) { var c = root - .of("transitPriorityGroups") + .of("transitGroupPriority") .since(OtpVersion.V2_5) - .summary("Transit priority groups configuration") + .summary( + "Group transit patterns and give each group a mutual advantage in the Raptor search." + ) .description( """ Use this to separate transit patterns into groups. Each group will be given a group-id. A path (multiple legs) will then have a set of group-ids based on the group-id from each leg. Hence, two paths with a different set of group-ids will BOTH be optimal unless the cost is - worse than the relaxation specified in the `relaxTransitPriorityGroup` parameter. This is + worse than the relaxation specified in the `relaxTransitGroupPriority` parameter. This is only available in the TransmodelAPI for now. - Unmatched patterns are put in the BASE priority-group (group id: 0). This group is special. - If a path only have legs in the base group, then that path dominates other paths, but other - paths must be better to make it. + Unmatched patterns are put in the BASE priority-group. """ ) .experimentalFeature() .asObject(); transit.addPriorityGroupsByAgency( - TransitPriorityGroupConfig.mapList( + TransitGroupPriorityConfig.mapList( c, "byAgency", "All groups here are split by agency. For example if you list mode " + @@ -44,7 +44,7 @@ public static void mapTransitRequest(NodeAdapter root, TransitRequest transit) { ) ); transit.addPriorityGroupsGlobal( - TransitPriorityGroupConfig.mapList( + TransitGroupPriorityConfig.mapList( c, "global", "All services matching a 'global' group will get the same group-id. Use this " + @@ -53,7 +53,7 @@ public static void mapTransitRequest(NodeAdapter root, TransitRequest transit) { ); } - private static Collection mapList( + private static Collection mapList( NodeAdapter root, String parameterName, String description @@ -61,13 +61,13 @@ private static Collection mapList( return root .of(parameterName) .since(V2_5) - .summary("Configuration for transit priority groups.") + .summary("List of transit groups.") .description(description + " The max total number of group-ids are 32, so be careful.") - .asObjects(TransitPriorityGroupConfig::mapTransitGroupSelect); + .asObjects(TransitGroupPriorityConfig::mapTransitGroupSelect); } - private static TransitPriorityGroupSelect mapTransitGroupSelect(NodeAdapter c) { - return TransitPriorityGroupSelect + private static TransitGroupSelect mapTransitGroupSelect(NodeAdapter c) { + return TransitGroupSelect .of() .addModes( c diff --git a/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationFactory.java b/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationFactory.java index 097fcfb4f7a..a4f0ee49652 100644 --- a/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationFactory.java +++ b/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationFactory.java @@ -6,6 +6,7 @@ import javax.annotation.Nullable; import org.opentripplanner.ext.emissions.EmissionsDataModel; import org.opentripplanner.ext.emissions.EmissionsServiceModule; +import org.opentripplanner.ext.interactivelauncher.configuration.InteractiveLauncherModule; import org.opentripplanner.ext.ridehailing.configure.RideHailingServicesModule; import org.opentripplanner.ext.stopconsolidation.StopConsolidationRepository; import org.opentripplanner.ext.stopconsolidation.configure.StopConsolidationServiceModule; @@ -50,6 +51,7 @@ RideHailingServicesModule.class, EmissionsServiceModule.class, StopConsolidationServiceModule.class, + InteractiveLauncherModule.class, } ) public interface ConstructApplicationFactory { diff --git a/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationModule.java b/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationModule.java index 2ff6de29b3d..c9d7253b0be 100644 --- a/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationModule.java +++ b/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationModule.java @@ -7,6 +7,7 @@ import javax.annotation.Nullable; import org.opentripplanner.astar.spi.TraverseVisitor; import org.opentripplanner.ext.emissions.EmissionsService; +import org.opentripplanner.ext.interactivelauncher.api.LauncherRequestDecorator; import org.opentripplanner.ext.ridehailing.RideHailingService; import org.opentripplanner.ext.stopconsolidation.StopConsolidationService; import org.opentripplanner.raptor.configure.RaptorConfig; @@ -36,11 +37,14 @@ OtpServerRequestContext providesServerContext( List rideHailingServices, @Nullable StopConsolidationService stopConsolidationService, @Nullable TraverseVisitor traverseVisitor, - EmissionsService emissionsService + EmissionsService emissionsService, + LauncherRequestDecorator launcherRequestDecorator ) { + var defaultRequest = launcherRequestDecorator.intercept(routerConfig.routingRequestDefaults()); + return DefaultServerRequestContext.create( routerConfig.transitTuningConfig(), - routerConfig.routingRequestDefaults(), + defaultRequest, raptorConfig, graph, transitService, diff --git a/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java b/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java index c422e9c24f3..7dc7c87f735 100644 --- a/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java +++ b/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java @@ -102,7 +102,7 @@ public void run() { httpServer.getServerConfiguration().addHttpHandler(dynamicHandler, "/otp/"); /* 2. A static content handler to serve the client JS apps etc. from the classpath. */ - if (OTPFeature.DebugClient.isOn()) { + if (OTPFeature.DebugUi.isOn()) { CLStaticHttpHandler staticHandler = new CLStaticHttpHandler( GrizzlyServer.class.getClassLoader(), "/client/" diff --git a/src/main/java/org/opentripplanner/standalone/server/OTPWebApplication.java b/src/main/java/org/opentripplanner/standalone/server/OTPWebApplication.java index 56aaa2d1361..b238a74c7d3 100644 --- a/src/main/java/org/opentripplanner/standalone/server/OTPWebApplication.java +++ b/src/main/java/org/opentripplanner/standalone/server/OTPWebApplication.java @@ -7,7 +7,6 @@ import io.micrometer.prometheus.PrometheusMeterRegistry; import jakarta.ws.rs.container.ContainerResponseFilter; import jakarta.ws.rs.core.Application; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -17,10 +16,9 @@ import org.glassfish.jersey.internal.inject.AbstractBinder; import org.glassfish.jersey.internal.inject.Binder; import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider; -import org.glassfish.jersey.server.ServerProperties; import org.opentripplanner.api.common.OTPExceptionMapper; -import org.opentripplanner.api.configuration.APIEndpoints; -import org.opentripplanner.api.json.JSONObjectMapperProvider; +import org.opentripplanner.apis.APIEndpoints; +import org.opentripplanner.ext.restapi.serialization.JSONObjectMapperProvider; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.standalone.api.OtpServerRequestContext; import org.slf4j.bridge.SLF4JBridgeHandler; diff --git a/src/main/java/org/opentripplanner/street/search/StreetSearchBuilder.java b/src/main/java/org/opentripplanner/street/search/StreetSearchBuilder.java index b4ac98674d0..079cd29706f 100644 --- a/src/main/java/org/opentripplanner/street/search/StreetSearchBuilder.java +++ b/src/main/java/org/opentripplanner/street/search/StreetSearchBuilder.java @@ -102,7 +102,7 @@ protected void prepareInitialStates(Collection initialStates) { @Override protected void initializeHeuristic( RemainingWeightHeuristic heuristic, - Set origin, + Set ignored, Set destination, boolean arriveBy ) { @@ -111,7 +111,6 @@ protected void initializeHeuristic( } else if (heuristic instanceof EuclideanRemainingWeightHeuristic euclideanHeuristic) { euclideanHeuristic.initialize( streetRequest.mode(), - origin, destination, arriveBy, routeRequest.preferences() diff --git a/src/main/java/org/opentripplanner/street/search/strategy/EuclideanRemainingWeightHeuristic.java b/src/main/java/org/opentripplanner/street/search/strategy/EuclideanRemainingWeightHeuristic.java index 36e4a57f8ec..e43278901d4 100644 --- a/src/main/java/org/opentripplanner/street/search/strategy/EuclideanRemainingWeightHeuristic.java +++ b/src/main/java/org/opentripplanner/street/search/strategy/EuclideanRemainingWeightHeuristic.java @@ -26,7 +26,6 @@ public class EuclideanRemainingWeightHeuristic implements RemainingWeightHeurist // not work correctly. public void initialize( StreetMode streetMode, - Set fromVertices, Set toVertices, boolean arriveBy, RoutingPreferences preferences diff --git a/src/main/java/org/opentripplanner/updater/UpdatersParameters.java b/src/main/java/org/opentripplanner/updater/UpdatersParameters.java index 8a7c422eb03..a955e757100 100644 --- a/src/main/java/org/opentripplanner/updater/UpdatersParameters.java +++ b/src/main/java/org/opentripplanner/updater/UpdatersParameters.java @@ -10,7 +10,6 @@ import org.opentripplanner.updater.alert.GtfsRealtimeAlertsUpdaterParameters; import org.opentripplanner.updater.trip.MqttGtfsRealtimeUpdaterParameters; import org.opentripplanner.updater.trip.PollingTripUpdaterParameters; -import org.opentripplanner.updater.trip.WebsocketGtfsRealtimeUpdaterParameters; import org.opentripplanner.updater.vehicle_parking.VehicleParkingUpdaterParameters; import org.opentripplanner.updater.vehicle_position.VehiclePositionsUpdaterParameters; import org.opentripplanner.updater.vehicle_rental.VehicleRentalUpdaterParameters; @@ -34,8 +33,6 @@ public interface UpdatersParameters { List getSiriSXUpdaterParameters(); - List getWebsocketGtfsRealtimeUpdaterParameters(); - List getMqttGtfsRealtimeUpdaterParameters(); List getVehicleParkingUpdaterParameters(); diff --git a/src/main/java/org/opentripplanner/updater/configure/UpdaterConfigurator.java b/src/main/java/org/opentripplanner/updater/configure/UpdaterConfigurator.java index 037bd080f47..c755578da41 100644 --- a/src/main/java/org/opentripplanner/updater/configure/UpdaterConfigurator.java +++ b/src/main/java/org/opentripplanner/updater/configure/UpdaterConfigurator.java @@ -23,14 +23,11 @@ import org.opentripplanner.updater.trip.MqttGtfsRealtimeUpdater; import org.opentripplanner.updater.trip.PollingTripUpdater; import org.opentripplanner.updater.trip.TimetableSnapshotSource; -import org.opentripplanner.updater.trip.WebsocketGtfsRealtimeUpdater; import org.opentripplanner.updater.vehicle_parking.VehicleParkingDataSourceFactory; import org.opentripplanner.updater.vehicle_parking.VehicleParkingUpdater; import org.opentripplanner.updater.vehicle_position.PollingVehiclePositionUpdater; import org.opentripplanner.updater.vehicle_rental.VehicleRentalUpdater; import org.opentripplanner.updater.vehicle_rental.datasources.VehicleRentalDataSourceFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Sets up and starts all the graph updaters. @@ -41,8 +38,6 @@ */ public class UpdaterConfigurator { - private static final Logger LOG = LoggerFactory.getLogger(UpdaterConfigurator.class); - private final Graph graph; private final TransitModel transitModel; private final UpdatersParameters updatersParameters; @@ -177,11 +172,6 @@ private List createUpdatersFromConfig() { for (var configItem : updatersParameters.getSiriSXUpdaterParameters()) { updaters.add(new SiriSXUpdater(configItem, transitModel)); } - for (var configItem : updatersParameters.getWebsocketGtfsRealtimeUpdaterParameters()) { - updaters.add( - new WebsocketGtfsRealtimeUpdater(configItem, provideGtfsTimetableSnapshot(), transitModel) - ); - } for (var configItem : updatersParameters.getMqttGtfsRealtimeUpdaterParameters()) { updaters.add( new MqttGtfsRealtimeUpdater(configItem, transitModel, provideGtfsTimetableSnapshot()) diff --git a/src/main/java/org/opentripplanner/updater/trip/WebsocketGtfsRealtimeUpdater.java b/src/main/java/org/opentripplanner/updater/trip/WebsocketGtfsRealtimeUpdater.java deleted file mode 100644 index 007c73d9b9b..00000000000 --- a/src/main/java/org/opentripplanner/updater/trip/WebsocketGtfsRealtimeUpdater.java +++ /dev/null @@ -1,211 +0,0 @@ -package org.opentripplanner.updater.trip; - -import static org.asynchttpclient.Dsl.asyncHttpClient; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.transit.realtime.GtfsRealtime; -import com.google.transit.realtime.GtfsRealtime.FeedEntity; -import com.google.transit.realtime.GtfsRealtime.FeedMessage; -import com.google.transit.realtime.GtfsRealtime.TripUpdate; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import org.asynchttpclient.AsyncHttpClient; -import org.asynchttpclient.ws.WebSocket; -import org.asynchttpclient.ws.WebSocketListener; -import org.asynchttpclient.ws.WebSocketUpgradeHandler; -import org.opentripplanner.transit.service.DefaultTransitService; -import org.opentripplanner.transit.service.TransitModel; -import org.opentripplanner.updater.GtfsRealtimeFuzzyTripMatcher; -import org.opentripplanner.updater.spi.GraphUpdater; -import org.opentripplanner.updater.spi.UpdateResult; -import org.opentripplanner.updater.spi.WriteToGraphCallback; -import org.opentripplanner.updater.trip.metrics.TripUpdateMetrics; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class starts an HTTP client which opens a websocket connection to a GTFS-RT data source. A - * callback is registered which handles incoming GTFS-RT messages as they stream in by placing a - * GTFS-RT decoder Runnable task in the single-threaded executor for handling. - * - *
    - * websocket.type = websocket-gtfs-rt-updater
    - * websocket.defaultAgencyId = agency
    - * websocket.url = ws://localhost:8088/tripUpdates
    - * 
    - */ -public class WebsocketGtfsRealtimeUpdater implements GraphUpdater { - - private static final Logger LOG = LoggerFactory.getLogger(WebsocketGtfsRealtimeUpdater.class); - - /** - * Number of seconds to wait before checking again whether we are still connected - */ - private static final int CHECK_CONNECTION_PERIOD_SEC = 1; - - /** - * Url of the websocket server - */ - private final String url; - - /** - * The ID for the static feed to which these TripUpdates are applied - */ - private final String feedId; - - /** - * The number of seconds to wait before reconnecting after a failed connection. - */ - private final int reconnectPeriodSec; - - private final String configRef; - - private final BackwardsDelayPropagationType backwardsDelayPropagationType; - - private final TimetableSnapshotSource snapshotSource; - - /** - * Parent update manager. Is used to execute graph writer runnables. - */ - private WriteToGraphCallback saveResultOnGraph; - - private GtfsRealtimeFuzzyTripMatcher fuzzyTripMatcher; - - private final Consumer recordMetrics; - - public WebsocketGtfsRealtimeUpdater( - WebsocketGtfsRealtimeUpdaterParameters parameters, - TimetableSnapshotSource snapshotSource, - TransitModel transitModel - ) { - this.configRef = parameters.configRef(); - this.url = parameters.url(); - this.feedId = parameters.feedId(); - this.reconnectPeriodSec = parameters.getReconnectPeriodSec(); - this.backwardsDelayPropagationType = parameters.getBackwardsDelayPropagationType(); - this.snapshotSource = snapshotSource; - this.fuzzyTripMatcher = - new GtfsRealtimeFuzzyTripMatcher(new DefaultTransitService(transitModel)); - this.recordMetrics = TripUpdateMetrics.streaming(parameters); - } - - @Override - public void setGraphUpdaterManager(WriteToGraphCallback saveResultOnGraph) { - this.saveResultOnGraph = saveResultOnGraph; - } - - @Override - public void run() throws InterruptedException, IOException { - while (true) { - AsyncHttpClient client = asyncHttpClient(); - WebSocketListener listener = new Listener(); - WebSocketUpgradeHandler handler = new WebSocketUpgradeHandler.Builder() - .addWebSocketListener(listener) - .build(); - WebSocket socket = null; - boolean connectionSuccessful = true; - // Try to create a websocket connection - try { - socket = client.prepareGet(url).execute(handler).get(); - LOG.info("Successfully connected to {}.", url); - } catch (ExecutionException e) { - LOG.error("Could not connect to {}: {}", url, e.getCause().getMessage()); - connectionSuccessful = false; - } catch (Exception e) { - LOG.error("Unknown exception when trying to connect to {}.", url, e); - connectionSuccessful = false; - } - - // If connection was unsuccessful, wait some time before trying again - if (!connectionSuccessful) { - Thread.sleep(reconnectPeriodSec * 1000); - } - - // Keep checking whether connection is still open - while (true) { - if (socket == null || !socket.isOpen()) { - // The connection is closed somehow, try to reconnect - if (connectionSuccessful) { - LOG.warn("Connection to {} was lost. Trying to reconnect...", url); - } - break; - } - Thread.sleep(CHECK_CONNECTION_PERIOD_SEC * 1000); - } - - client.close(); - } - } - - @Override - public String getConfigRef() { - return configRef; - } - - /** - * Auxiliary class to handle incoming messages via the websocket connection - */ - private class Listener implements WebSocketListener { - - @Override - public void onOpen(WebSocket websocket) {} - - @Override - public void onClose(WebSocket websocket, int code, String reason) {} - - @Override - public void onError(Throwable t) {} - - @Override - public void onBinaryFrame(byte[] message, boolean finalFragment, int rsv) { - FeedMessage feedMessage; - List feedEntityList; - List updates = null; - boolean fullDataset = true; - try { - // Decode message - feedMessage = FeedMessage.PARSER.parseFrom(message); - feedEntityList = feedMessage.getEntityList(); - - // Change fullDataset value if this is an incremental update - if ( - feedMessage.hasHeader() && - feedMessage.getHeader().hasIncrementality() && - feedMessage - .getHeader() - .getIncrementality() - .equals(GtfsRealtime.FeedHeader.Incrementality.DIFFERENTIAL) - ) { - fullDataset = false; - } - - // Create List of TripUpdates - updates = new ArrayList<>(feedEntityList.size()); - for (FeedEntity feedEntity : feedEntityList) { - if (feedEntity.hasTripUpdate()) { - updates.add(feedEntity.getTripUpdate()); - } - } - } catch (InvalidProtocolBufferException e) { - LOG.error("Could not decode gtfs-rt message:", e); - } - - if (updates != null) { - // Handle trip updates via graph writer runnable - TripUpdateGraphWriterRunnable runnable = new TripUpdateGraphWriterRunnable( - snapshotSource, - fuzzyTripMatcher, - backwardsDelayPropagationType, - fullDataset, - updates, - feedId, - recordMetrics - ); - saveResultOnGraph.execute(runnable); - } - } - } -} diff --git a/src/main/java/org/opentripplanner/updater/trip/WebsocketGtfsRealtimeUpdaterParameters.java b/src/main/java/org/opentripplanner/updater/trip/WebsocketGtfsRealtimeUpdaterParameters.java deleted file mode 100644 index d5eebd748af..00000000000 --- a/src/main/java/org/opentripplanner/updater/trip/WebsocketGtfsRealtimeUpdaterParameters.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.opentripplanner.updater.trip; - -public class WebsocketGtfsRealtimeUpdaterParameters implements UrlUpdaterParameters { - - private final String configRef; - private final String feedId; - private final String url; - private final int reconnectPeriodSec; - private final BackwardsDelayPropagationType backwardsDelayPropagationType; - - public WebsocketGtfsRealtimeUpdaterParameters( - String configRef, - String feedId, - String url, - int reconnectPeriodSec, - BackwardsDelayPropagationType backwardsDelayPropagationType - ) { - this.configRef = configRef; - this.feedId = feedId; - this.url = url; - this.reconnectPeriodSec = reconnectPeriodSec; - this.backwardsDelayPropagationType = backwardsDelayPropagationType; - } - - public String url() { - return url; - } - - public String feedId() { - return feedId; - } - - int getReconnectPeriodSec() { - return reconnectPeriodSec; - } - - /** The config name/type for the updater. Used to reference the configuration element. */ - public String configRef() { - return configRef; - } - - public BackwardsDelayPropagationType getBackwardsDelayPropagationType() { - return backwardsDelayPropagationType; - } -} diff --git a/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java b/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java index 73516b0348f..9f8bbffb22d 100644 --- a/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java +++ b/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java @@ -157,6 +157,10 @@ public DisplayVertex getElementAt(int index) { * TransitStops only, and allows a user to select stops, examine incoming and outgoing edges, and * examine trip patterns. It's meant mainly for debugging, so it's totally OK if it develops (say) a * bunch of weird buttons designed to debug specific cases. + *

    + * 2024-01-26: We talked about the visualizer in the developer meeting and while the code is a bit + * dusty, we decided that we want to keep the option open to build make the visualization of routing + * steps work again in the future and won't delete it. */ public class GraphVisualizer extends JFrame implements VertexSelectionListener { diff --git a/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql b/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql index 07067acdb28..9b49283c180 100644 --- a/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql +++ b/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql @@ -827,21 +827,21 @@ type QueryType { passThroughPoints: [PassThroughPoint!], """ Relax generalized-cost when comparing trips with a different set of - transit-priority-groups. The groups are set server side for service-journey and + transit-group-priorities. The groups are set server side for service-journey and can not be configured in the API. This mainly helps to return competition neutral - services. Long distance authorities are put in different transit-priority-groups. + services. Long distance authorities are put in different transit-groups. This relaxes the comparison inside the routing engine for each stop-arrival. If two - paths have a different set of transit-priority-groups, then the generalized-cost + paths have a different set of transit-group-priorities, then the generalized-cost comparison is relaxed. The final set of paths are filtered through the normal itinerary-filters. - The `ratio` must be greater or equal to 1.0 and less then 1.2. - - The `slack` must be greater or equal to 0 and less then 3600. + - The `constant` must be greater or equal to '0s' and less then '1h'. THIS IS STILL AN EXPERIMENTAL FEATURE - IT MAY CHANGE WITHOUT ANY NOTICE! """ - relaxTransitPriorityGroup: RelaxCostInput = null, + relaxTransitGroupPriority: RelaxCostInput = null, """ Whether non-optimal transit paths at the destination should be returned. Let c be the existing minimum pareto optimal generalized-cost to beat. Then a trip with cost c' is @@ -854,7 +854,7 @@ type QueryType { Values less than 1.0 is not allowed, and values greater than 2.0 are not supported, due to performance reasons. """ - relaxTransitSearchGeneralizedCostAtDestination: Float = null @deprecated(reason : "This is replaced by 'relaxTransitPriorityGroup'."), + relaxTransitSearchGeneralizedCostAtDestination: Float = null @deprecated(reason : "This is replaced by 'relaxTransitGroupPriority'."), """ The length of the search-window in minutes. This parameter is optional. @@ -1869,6 +1869,9 @@ enum WheelchairBoarding { "List of coordinates like: [[60.89, 11.12], [62.56, 12.10]]" scalar Coordinates +"A cost value, normally a value of 1 is equivalent to riding transit for 1 second, but it might not depending on the use-case. Format: 3665 = DT1h1m5s = 1h1m5s" +scalar Cost + "Local date using the ISO 8601 format: `YYYY-MM-DD`. Example: `2020-05-17`." scalar Date @@ -2030,12 +2033,12 @@ This is used to include more results into the result. A `ratio=2.0` means a path with twice as high cost as another one, is accepted. A `constant=$300` means a "fixed" constant is added to the limit. A `{ratio=1.0, constant=0}` is said to be the NORMAL relaxed cost - the limit is the same as the cost used to calculate the limit. The NORMAL is usually -the default. We can express the RelaxCost as a function `f(x) = constant + ratio * x`. -`f(x)=x` is the NORMAL function. +the default. We can express the RelaxCost as a function `f(t) = constant + ratio * t`. +`f(t)=t` is the NORMAL function. """ input RelaxCostInput { - "The constant value to add to the limit. Must be a positive number. The unit is cost-seconds." - constant: [ID!] = 0 + "The constant value to add to the limit. Must be a positive number. The value is equivalent to transit-cost-seconds. Integers are treated as seconds, but you may use the duration format. Example: '3665 = 'DT1h1m5s' = '1h1m5s'." + constant: Cost = "0s" "The factor to multiply with the 'other cost'. Minimum value is 1.0." ratio: Float = 1.0 } diff --git a/src/test/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostTypeTest.java b/src/test/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostTypeTest.java new file mode 100644 index 00000000000..6fa235cdf0b --- /dev/null +++ b/src/test/java/org/opentripplanner/apis/transmodel/model/plan/RelaxCostTypeTest.java @@ -0,0 +1,71 @@ +package org.opentripplanner.apis.transmodel.model.plan; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opentripplanner.apis.transmodel.model.plan.RelaxCostType.CONSTANT; +import static org.opentripplanner.apis.transmodel.model.plan.RelaxCostType.RATIO; + +import graphql.language.FloatValue; +import graphql.language.ObjectField; +import graphql.language.ObjectValue; +import graphql.language.StringValue; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.opentripplanner.framework.model.Cost; +import org.opentripplanner.routing.api.request.framework.CostLinearFunction; + +class RelaxCostTypeTest { + + @Test + void valueOf() { + assertEquals( + ObjectValue + .newObjectValue() + .objectField(ObjectField.newObjectField().name(RATIO).value(FloatValue.of(1.0)).build()) + .objectField( + ObjectField.newObjectField().name(CONSTANT).value(StringValue.of("0s")).build() + ) + .build() + .toString(), + RelaxCostType.valueOf(CostLinearFunction.NORMAL).toString() + ); + assertEquals( + ObjectValue + .newObjectValue() + .objectField(ObjectField.newObjectField().name(RATIO).value(FloatValue.of(1.3)).build()) + .objectField( + ObjectField.newObjectField().name(CONSTANT).value(StringValue.of("1m7s")).build() + ) + .build() + .toString(), + RelaxCostType.valueOf(CostLinearFunction.of(Cost.costOfSeconds(67), 1.3)).toString() + ); + } + + @Test + void mapToDomain() { + Map input; + + input = Map.of(RATIO, 1.0, CONSTANT, Cost.ZERO); + assertEquals( + CostLinearFunction.NORMAL, + RelaxCostType.mapToDomain(input, CostLinearFunction.ZERO) + ); + + input = Map.of(RATIO, 0.0, CONSTANT, Cost.ZERO); + assertEquals( + CostLinearFunction.ZERO, + RelaxCostType.mapToDomain(input, CostLinearFunction.ZERO) + ); + + input = Map.of(RATIO, 1.7, CONSTANT, Cost.costOfSeconds(3600 + 3 * 60 + 7)); + assertEquals( + CostLinearFunction.of("1h3m7s + 1.7t"), + RelaxCostType.mapToDomain(input, CostLinearFunction.ZERO) + ); + assertEquals( + CostLinearFunction.NORMAL, + RelaxCostType.mapToDomain(null, CostLinearFunction.NORMAL) + ); + assertEquals(CostLinearFunction.ZERO, RelaxCostType.mapToDomain(null, CostLinearFunction.ZERO)); + } +} diff --git a/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java b/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java new file mode 100644 index 00000000000..d685e07a2f2 --- /dev/null +++ b/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.vectortiles; + +import static org.opentripplanner.test.support.JsonAssertions.assertEqualJson; + +import org.junit.jupiter.api.Test; +import org.opentripplanner.apis.vectortiles.DebugStyleSpec.VectorSourceLayer; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; +import org.opentripplanner.framework.json.ObjectMappers; +import org.opentripplanner.test.support.ResourceLoader; + +class DebugStyleSpecTest { + + private final ResourceLoader RES = ResourceLoader.of(this); + + @Test + void spec() { + var vectorSource = new VectorSource("vectorSource", "https://example.com"); + var regularStops = new VectorSourceLayer(vectorSource, "regularStops"); + var spec = DebugStyleSpec.build(vectorSource, regularStops); + + var json = ObjectMappers.ignoringExtraFields().valueToTree(spec); + var expectation = RES.fileToString("style.json"); + assertEqualJson(expectation, json); + } +} diff --git a/src/test/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategyTest.java b/src/test/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategyTest.java index 04844d65da2..17dc26a4c5e 100644 --- a/src/test/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategyTest.java +++ b/src/test/java/org/opentripplanner/astar/strategy/MaxCountSkipEdgeStrategyTest.java @@ -12,7 +12,7 @@ class MaxCountSkipEdgeStrategyTest { @Test void countStops() { var state = TestStateBuilder.ofWalking().stop().build(); - var strategy = new MaxCountSkipEdgeStrategy<>(1, NearbyStopFinder::isTransitVertex); + var strategy = new MaxCountSkipEdgeStrategy<>(1, NearbyStopFinder::hasReachedStop); assertFalse(strategy.shouldSkipEdge(state, null)); assertTrue(strategy.shouldSkipEdge(state, null)); } @@ -20,9 +20,17 @@ void countStops() { @Test void doNotCountStop() { var state = TestStateBuilder.ofWalking().build(); - var strategy = new MaxCountSkipEdgeStrategy<>(1, NearbyStopFinder::isTransitVertex); + var strategy = new MaxCountSkipEdgeStrategy<>(1, NearbyStopFinder::hasReachedStop); assertFalse(strategy.shouldSkipEdge(state, null)); assertFalse(strategy.shouldSkipEdge(state, null)); assertFalse(strategy.shouldSkipEdge(state, null)); } + + @Test + void nonFinalState() { + var state = TestStateBuilder.ofScooterRentalArriveBy().stop().build(); + assertFalse(state.isFinal()); + var strategy = new MaxCountSkipEdgeStrategy<>(1, NearbyStopFinder::hasReachedStop); + assertFalse(strategy.shouldSkipEdge(state, null)); + } } diff --git a/src/test/java/org/opentripplanner/api/common/PlannerResourceTest.java b/src/test/java/org/opentripplanner/ext/restapi/resources/PlannerResourceTest.java similarity index 95% rename from src/test/java/org/opentripplanner/api/common/PlannerResourceTest.java rename to src/test/java/org/opentripplanner/ext/restapi/resources/PlannerResourceTest.java index 36e0650b081..a86e270a2af 100644 --- a/src/test/java/org/opentripplanner/api/common/PlannerResourceTest.java +++ b/src/test/java/org/opentripplanner/ext/restapi/resources/PlannerResourceTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.common; +package org.opentripplanner.ext.restapi.resources; import static graphql.Assert.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -12,7 +12,6 @@ import org.opentripplanner.TestServerContext; import org.opentripplanner._support.time.ZoneIds; import org.opentripplanner.api.parameter.QualifiedModeSet; -import org.opentripplanner.api.resource.PlannerResource; import org.opentripplanner.routing.api.request.RequestModes; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.standalone.api.OtpServerRequestContext; diff --git a/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java b/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java similarity index 50% rename from src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java rename to src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java index 09b64adcf75..a1c01ca2e99 100644 --- a/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java +++ b/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java @@ -1,51 +1,36 @@ -package org.opentripplanner.inspector.vector; +package org.opentripplanner.inspector.vector.stop; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Locale; import org.junit.jupiter.api.Test; -import org.locationtech.jts.geom.Coordinate; -import org.opentripplanner.framework.geometry.GeometryUtils; +import org.opentripplanner._support.geometry.Polygons; import org.opentripplanner.framework.i18n.I18NString; -import org.opentripplanner.framework.i18n.NonLocalizedString; +import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.site.AreaStop; -import org.opentripplanner.transit.service.DefaultTransitService; import org.opentripplanner.transit.service.StopModel; import org.opentripplanner.transit.service.StopModelBuilder; -import org.opentripplanner.transit.service.TransitModel; class AreaStopLayerBuilderTest { - private static final Coordinate[] COORDINATES = { - new Coordinate(0, 0), - new Coordinate(0, 1), - new Coordinate(1, 1), - new Coordinate(1, 0), - new Coordinate(0, 0), - }; private static final FeedScopedId ID = new FeedScopedId("FEED", "ID"); - private static final I18NString NAME = new NonLocalizedString("Test stop"); + private static final I18NString NAME = I18NString.of("Test stop"); private final StopModelBuilder stopModelBuilder = StopModel.of(); private final AreaStop areaStop = stopModelBuilder .areaStop(ID) .withName(NAME) - .withGeometry(GeometryUtils.getGeometryFactory().createPolygon(COORDINATES)) + .withGeometry(Polygons.BERLIN) .build(); @Test void map() { - var subject = new DebugClientAreaStopPropertyMapper( - new DefaultTransitService(new TransitModel()), - Locale.ENGLISH - ); + var subject = new StopLocationPropertyMapper(Locale.ENGLISH); var properties = subject.map(areaStop); - assertEquals(2, properties.size()); assertTrue(properties.contains(new KeyValue("id", ID.toString()))); assertTrue(properties.contains(new KeyValue("name", NAME.toString()))); } diff --git a/src/test/java/org/opentripplanner/raptor/moduletests/K01_TransitPriorityTest.java b/src/test/java/org/opentripplanner/raptor/moduletests/K01_TransitPriorityTest.java index c1db11be779..00b1d528e7e 100644 --- a/src/test/java/org/opentripplanner/raptor/moduletests/K01_TransitPriorityTest.java +++ b/src/test/java/org/opentripplanner/raptor/moduletests/K01_TransitPriorityTest.java @@ -1,8 +1,6 @@ package org.opentripplanner.raptor.moduletests; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_B; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_C; import static org.opentripplanner.raptor._data.RaptorTestConstants.T00_00; @@ -12,6 +10,9 @@ import static org.opentripplanner.raptor._data.transit.TestRoute.route; import static org.opentripplanner.raptor._data.transit.TestTripPattern.pattern; import static org.opentripplanner.raptor._data.transit.TestTripSchedule.schedule; +import static org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator.GROUP_A; +import static org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator.GROUP_B; +import static org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator.GROUP_C; import java.time.Duration; import org.junit.jupiter.api.BeforeEach; @@ -19,11 +20,11 @@ import org.opentripplanner.raptor.RaptorService; import org.opentripplanner.raptor._data.transit.TestTransitData; import org.opentripplanner.raptor._data.transit.TestTripSchedule; -import org.opentripplanner.raptor.api.model.DominanceFunction; import org.opentripplanner.raptor.api.request.RaptorProfile; import org.opentripplanner.raptor.api.request.RaptorRequestBuilder; -import org.opentripplanner.raptor.api.request.RaptorTransitPriorityGroupCalculator; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; import org.opentripplanner.raptor.configure.RaptorConfig; +import org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator; import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.RaptorCostConverter; /** @@ -33,32 +34,8 @@ */ public class K01_TransitPriorityTest { - private static final RaptorTransitPriorityGroupCalculator PRIORITY_GROUP_CALCULATOR = new RaptorTransitPriorityGroupCalculator() { - @Override - public int mergeTransitPriorityGroupIds(int currentGroupIds, int boardingGroupId) { - return currentGroupIds | boardingGroupId; - } - - /** - * Left dominate right, if right has at least one priority group not in left. - */ - @Override - public DominanceFunction dominanceFunction() { - return (l, r) -> ((l ^ r) & r) != 0; - } - }; - - private static final int GROUP_A = 0x01; - private static final int GROUP_B = 0x02; - private static final int GROUP_C = 0x04; - private static final int GROUP_AB = PRIORITY_GROUP_CALCULATOR.mergeTransitPriorityGroupIds( - GROUP_A, - GROUP_B - ); - private static final int GROUP_AC = PRIORITY_GROUP_CALCULATOR.mergeTransitPriorityGroupIds( - GROUP_A, - GROUP_C - ); + private static final RaptorTransitGroupCalculator PRIORITY_GROUP_CALCULATOR = + TestGroupPriorityCalculator.PRIORITY_CALCULATOR; private static final int C1_SLACK_90s = RaptorCostConverter.toRaptorCost(90); private final TestTransitData data = new TestTransitData(); @@ -108,7 +85,6 @@ private void prepareRequest() { ); // Add 1 second access/egress paths requestBuilder.searchParams().addAccessPaths(walk(STOP_B, 1)).addEgressPaths(walk(STOP_C, 1)); - assetGroupCalculatorIsSetupCorrect(); } @Test @@ -122,21 +98,4 @@ public void transitPriority() { pathsToString(raptorService.route(requestBuilder.build(), data)) ); } - - /** - * Make sure the calculator and group setup is done correct. - */ - void assetGroupCalculatorIsSetupCorrect() { - var d = PRIORITY_GROUP_CALCULATOR.dominanceFunction(); - - assertTrue(d.leftDominateRight(GROUP_A, GROUP_B)); - assertTrue(d.leftDominateRight(GROUP_B, GROUP_A)); - assertFalse(d.leftDominateRight(GROUP_A, GROUP_A)); - // 3 = 1&2, 5 = 1&4 - assertTrue(d.leftDominateRight(GROUP_A, GROUP_AB)); - assertFalse(d.leftDominateRight(GROUP_AB, GROUP_A)); - assertFalse(d.leftDominateRight(GROUP_AB, GROUP_AB)); - assertTrue(d.leftDominateRight(GROUP_AB, GROUP_AC)); - assertTrue(d.leftDominateRight(GROUP_AC, GROUP_AB)); - } } diff --git a/src/test/java/org/opentripplanner/raptor/moduletests/K02_TransitPriorityDestinationTest.java b/src/test/java/org/opentripplanner/raptor/moduletests/K02_TransitPriorityDestinationTest.java index c7b64cb5b9e..c6ab8e337ea 100644 --- a/src/test/java/org/opentripplanner/raptor/moduletests/K02_TransitPriorityDestinationTest.java +++ b/src/test/java/org/opentripplanner/raptor/moduletests/K02_TransitPriorityDestinationTest.java @@ -1,14 +1,11 @@ package org.opentripplanner.raptor.moduletests; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_B; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_C; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_D; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_E; import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_F; -import static org.opentripplanner.raptor._data.RaptorTestConstants.STOP_G; import static org.opentripplanner.raptor._data.RaptorTestConstants.T00_00; import static org.opentripplanner.raptor._data.RaptorTestConstants.T01_00; import static org.opentripplanner.raptor._data.api.PathUtils.pathsToString; @@ -16,6 +13,9 @@ import static org.opentripplanner.raptor._data.transit.TestRoute.route; import static org.opentripplanner.raptor._data.transit.TestTripPattern.pattern; import static org.opentripplanner.raptor._data.transit.TestTripSchedule.schedule; +import static org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator.GROUP_A; +import static org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator.GROUP_B; +import static org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator.GROUP_C; import java.time.Duration; import org.junit.jupiter.api.BeforeEach; @@ -23,11 +23,11 @@ import org.opentripplanner.raptor.RaptorService; import org.opentripplanner.raptor._data.transit.TestTransitData; import org.opentripplanner.raptor._data.transit.TestTripSchedule; -import org.opentripplanner.raptor.api.model.DominanceFunction; import org.opentripplanner.raptor.api.request.RaptorProfile; import org.opentripplanner.raptor.api.request.RaptorRequestBuilder; -import org.opentripplanner.raptor.api.request.RaptorTransitPriorityGroupCalculator; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; import org.opentripplanner.raptor.configure.RaptorConfig; +import org.opentripplanner.raptor.moduletests.support.TestGroupPriorityCalculator; import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.RaptorCostConverter; /** @@ -37,32 +37,8 @@ */ public class K02_TransitPriorityDestinationTest { - private static final RaptorTransitPriorityGroupCalculator PRIORITY_GROUP_CALCULATOR = new RaptorTransitPriorityGroupCalculator() { - @Override - public int mergeTransitPriorityGroupIds(int currentGroupIds, int boardingGroupId) { - return currentGroupIds | boardingGroupId; - } - - /** - * Left dominate right, if right has at least one priority group not in left. - */ - @Override - public DominanceFunction dominanceFunction() { - return (l, r) -> ((l ^ r) & r) != 0; - } - }; - - private static final int GROUP_A = 0x01; - private static final int GROUP_B = 0x02; - private static final int GROUP_C = 0x04; - private static final int GROUP_AB = PRIORITY_GROUP_CALCULATOR.mergeTransitPriorityGroupIds( - GROUP_A, - GROUP_B - ); - private static final int GROUP_AC = PRIORITY_GROUP_CALCULATOR.mergeTransitPriorityGroupIds( - GROUP_A, - GROUP_C - ); + private static final RaptorTransitGroupCalculator PRIORITY_GROUP_CALCULATOR = + TestGroupPriorityCalculator.PRIORITY_CALCULATOR; private static final int C1_SLACK_90s = RaptorCostConverter.toRaptorCost(90); private final TestTransitData data = new TestTransitData(); @@ -117,7 +93,6 @@ private void prepareRequest() { .addEgressPaths(walk(STOP_D, 1)) .addEgressPaths(walk(STOP_E, 1)) .addEgressPaths(walk(STOP_F, 1)); - assetGroupCalculatorIsSetupCorrect(); } @Test @@ -131,21 +106,4 @@ public void transitPriority() { pathsToString(raptorService.route(requestBuilder.build(), data)) ); } - - /** - * Make sure the calculator and group setup is done correct. - */ - void assetGroupCalculatorIsSetupCorrect() { - var d = PRIORITY_GROUP_CALCULATOR.dominanceFunction(); - - assertTrue(d.leftDominateRight(GROUP_A, GROUP_B)); - assertTrue(d.leftDominateRight(GROUP_B, GROUP_A)); - assertFalse(d.leftDominateRight(GROUP_A, GROUP_A)); - // 3 = 1&2, 5 = 1&4 - assertTrue(d.leftDominateRight(GROUP_A, GROUP_AB)); - assertFalse(d.leftDominateRight(GROUP_AB, GROUP_A)); - assertFalse(d.leftDominateRight(GROUP_AB, GROUP_AB)); - assertTrue(d.leftDominateRight(GROUP_AB, GROUP_AC)); - assertTrue(d.leftDominateRight(GROUP_AC, GROUP_AB)); - } } diff --git a/src/test/java/org/opentripplanner/raptor/moduletests/support/TestGroupPriorityCalculator.java b/src/test/java/org/opentripplanner/raptor/moduletests/support/TestGroupPriorityCalculator.java new file mode 100644 index 00000000000..cdbe82f18a6 --- /dev/null +++ b/src/test/java/org/opentripplanner/raptor/moduletests/support/TestGroupPriorityCalculator.java @@ -0,0 +1,51 @@ +package org.opentripplanner.raptor.moduletests.support; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.opentripplanner.raptor.api.model.DominanceFunction; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; + +public class TestGroupPriorityCalculator implements RaptorTransitGroupCalculator { + + public static final RaptorTransitGroupCalculator PRIORITY_CALCULATOR = new TestGroupPriorityCalculator(); + + public static final int GROUP_A = 0x01; + public static final int GROUP_B = 0x02; + public static final int GROUP_C = 0x04; + + private static final int GROUP_AB = PRIORITY_CALCULATOR.mergeGroupIds(GROUP_A, GROUP_B); + private static final int GROUP_AC = PRIORITY_CALCULATOR.mergeGroupIds(GROUP_A, GROUP_C); + + @Override + public int mergeGroupIds(int currentGroupIds, int boardingGroupId) { + return currentGroupIds | boardingGroupId; + } + + /** + * Left dominate right, if right has at least one priority group not in left. + */ + @Override + public DominanceFunction dominanceFunction() { + return (l, r) -> ((l ^ r) & r) != 0; + } + + /** + * Make sure the calculator and group setup is done correct. + */ + @Test + void assetGroupCalculatorIsSetupCorrect() { + var d = PRIORITY_CALCULATOR.dominanceFunction(); + + assertTrue(d.leftDominateRight(GROUP_A, GROUP_B)); + assertTrue(d.leftDominateRight(GROUP_B, GROUP_A)); + assertFalse(d.leftDominateRight(GROUP_A, GROUP_A)); + // 3 = 1&2, 5 = 1&4 + assertTrue(d.leftDominateRight(GROUP_A, GROUP_AB)); + assertFalse(d.leftDominateRight(GROUP_AB, GROUP_A)); + assertFalse(d.leftDominateRight(GROUP_AB, GROUP_AB)); + assertTrue(d.leftDominateRight(GROUP_AB, GROUP_AC)); + assertTrue(d.leftDominateRight(GROUP_AC, GROUP_AB)); + } +} diff --git a/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctionsTest.java b/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctionsTest.java index eab9ee418cf..1d4f90557b0 100644 --- a/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctionsTest.java +++ b/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/AccessEgressFunctionsTest.java @@ -6,7 +6,8 @@ import static org.opentripplanner.raptor._data.transit.TestAccessEgress.flexAndWalk; import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.groupByRound; import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.groupByStop; -import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNoneOptimalPathsForStandardRaptor; +import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNonOptimalPathsForMcRaptor; +import static org.opentripplanner.raptor.rangeraptor.transit.AccessEgressFunctions.removeNonOptimalPathsForStandardRaptor; import java.util.Arrays; import java.util.Collection; @@ -24,78 +25,150 @@ class AccessEgressFunctionsTest implements RaptorTestConstants { public static final int TRANSFER_SLACK = D1m; private static final int STOP = 8; - - private static final RaptorAccessEgress WALK_10m = TestAccessEgress.walk(STOP, D10m); - private static final RaptorAccessEgress WALK_8m = TestAccessEgress.walk(STOP, D8m); - private static final RaptorAccessEgress FLEX_1x_10m = flex(STOP, D10m, 1); - private static final RaptorAccessEgress FLEX_1x_8m = flex(STOP, D8m, 1); - private static final RaptorAccessEgress FLEX_2x_8m = flex(STOP, D8m, 2); - private static final RaptorAccessEgress FLEX_AND_WALK_1x_8m = flexAndWalk(STOP, D8m, 1); + private static final int C1 = 1000; + private static final int C1_LOW = 999; + + private static final RaptorAccessEgress WALK_10m = TestAccessEgress.walk(STOP, D10m, C1); + private static final RaptorAccessEgress WALK_10m_C1_LOW = TestAccessEgress.walk( + STOP, + D10m, + C1_LOW + ); + private static final RaptorAccessEgress WALK_8m = TestAccessEgress.walk(STOP, D8m, C1); + private static final RaptorAccessEgress FLEX_1x_10m = flex(STOP, D10m, 1, C1); + private static final RaptorAccessEgress FLEX_1x_8m = flex(STOP, D8m, 1, C1); + private static final RaptorAccessEgress FLEX_2x_8m = flex(STOP, D8m, 2, C1); + private static final RaptorAccessEgress FLEX_AND_WALK_1x_8m = flexAndWalk(STOP, D8m, 1, C1); private static final RaptorAccessEgress WALK_W_OPENING_HOURS_8m = TestAccessEgress - .walk(STOP, D8m) + .walk(STOP, D8m, C1) .openingHours(T00_00, T01_00); private static final RaptorAccessEgress WALK_W_OPENING_HOURS_8m_OTHER = TestAccessEgress - .walk(STOP, D8m) + .walk(STOP, D8m, C1) .openingHours(T00_10, T01_00); @Test - void removeNoneOptimalPathsForStandardRaptorTest() { + void removeNonOptimalPathsForStandardRaptorTest() { // Empty set - assertElements(List.of(), removeNoneOptimalPathsForStandardRaptor(List.of())); + assertElements(List.of(), removeNonOptimalPathsForStandardRaptor(List.of())); // One element - assertElements(List.of(WALK_8m), removeNoneOptimalPathsForStandardRaptor(List.of(WALK_8m))); + assertElements(List.of(WALK_8m), removeNonOptimalPathsForStandardRaptor(List.of(WALK_8m))); // Shortest duration assertElements( List.of(WALK_8m), - removeNoneOptimalPathsForStandardRaptor(List.of(WALK_8m, WALK_10m)) + removeNonOptimalPathsForStandardRaptor(List.of(WALK_8m, WALK_10m)) + ); + + // Fewest rides + assertElements( + List.of(FLEX_1x_8m), + removeNonOptimalPathsForStandardRaptor(List.of(FLEX_1x_8m, FLEX_2x_8m)) + ); + + // Arriving at the stop on-board, and by-foot. + // OnBoard is better because we can do a transfer walk to nearby stops. + assertElements( + List.of(FLEX_1x_8m), + removeNonOptimalPathsForStandardRaptor(List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_8m)) + ); + + // Flex+walk is faster, flex arrive on-board, both is optimal + assertElements( + List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_10m), + removeNonOptimalPathsForStandardRaptor(List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_10m)) + ); + + // Walk has few rides, and Flex is faster - both is optimal + assertElements( + List.of(WALK_10m, FLEX_1x_8m), + removeNonOptimalPathsForStandardRaptor(List.of(WALK_10m, FLEX_1x_8m)) + ); + + // Walk without opening hours is better than with, because it can be time-shifted without + // any constraints + assertElements( + List.of(WALK_8m), + removeNonOptimalPathsForStandardRaptor(List.of(WALK_8m, WALK_W_OPENING_HOURS_8m)) + ); + + // Walk with opening hours can NOT dominate another access/egress without - even if it is + // faster. The reason is that it may not be allowed to time-shift it to the desired time. + assertElements( + List.of(WALK_10m, WALK_W_OPENING_HOURS_8m), + removeNonOptimalPathsForStandardRaptor(List.of(WALK_10m, WALK_W_OPENING_HOURS_8m)) + ); + + // If two paths both have opening hours, both should be accepted. + assertElements( + List.of(WALK_W_OPENING_HOURS_8m, WALK_W_OPENING_HOURS_8m_OTHER), + removeNonOptimalPathsForStandardRaptor( + List.of(WALK_W_OPENING_HOURS_8m, WALK_W_OPENING_HOURS_8m_OTHER) + ) ); + } + + @Test + void removeNonOptimalPathsForMcRaptorTest() { + // Empty set + assertElements(List.of(), removeNonOptimalPathsForMcRaptor(List.of())); + + // One element + assertElements(List.of(WALK_8m), removeNonOptimalPathsForMcRaptor(List.of(WALK_8m))); + + // Lowest cost + assertElements( + List.of(WALK_10m_C1_LOW), + removeNonOptimalPathsForMcRaptor(List.of(WALK_10m, WALK_10m_C1_LOW)) + ); + + // Shortest duration + assertElements(List.of(WALK_8m), removeNonOptimalPathsForMcRaptor(List.of(WALK_8m, WALK_10m))); // Fewest rides assertElements( List.of(FLEX_1x_8m), - removeNoneOptimalPathsForStandardRaptor(List.of(FLEX_1x_8m, FLEX_2x_8m)) + removeNonOptimalPathsForMcRaptor(List.of(FLEX_1x_8m, FLEX_2x_8m)) ); // Arriving at the stop on-board, and by-foot. // OnBoard is better because we can do a transfer walk to nearby stops. assertElements( List.of(FLEX_1x_8m), - removeNoneOptimalPathsForStandardRaptor(List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_8m)) + removeNonOptimalPathsForMcRaptor(List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_8m)) ); // Flex+walk is faster, flex arrive on-board, both is optimal assertElements( List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_10m), - removeNoneOptimalPathsForStandardRaptor(List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_10m)) + removeNonOptimalPathsForStandardRaptor(List.of(FLEX_AND_WALK_1x_8m, FLEX_1x_10m)) ); // Walk has few rides, and Flex is faster - both is optimal assertElements( List.of(WALK_10m, FLEX_1x_8m), - removeNoneOptimalPathsForStandardRaptor(List.of(WALK_10m, FLEX_1x_8m)) + removeNonOptimalPathsForMcRaptor(List.of(WALK_10m, FLEX_1x_8m)) ); // Walk without opening hours is better than with, because it can be time-shifted without // any constraints assertElements( List.of(WALK_8m), - removeNoneOptimalPathsForStandardRaptor(List.of(WALK_8m, WALK_W_OPENING_HOURS_8m)) + removeNonOptimalPathsForMcRaptor(List.of(WALK_8m, WALK_W_OPENING_HOURS_8m)) ); // Walk with opening hours can NOT dominate another access/egress without - even if it is // faster. The reason is that it may not be allowed to time-shift it to the desired time. assertElements( List.of(WALK_10m, WALK_W_OPENING_HOURS_8m), - removeNoneOptimalPathsForStandardRaptor(List.of(WALK_10m, WALK_W_OPENING_HOURS_8m)) + removeNonOptimalPathsForMcRaptor(List.of(WALK_10m, WALK_W_OPENING_HOURS_8m)) ); // If two paths both have opening hours, both should be accepted. assertElements( List.of(WALK_W_OPENING_HOURS_8m, WALK_W_OPENING_HOURS_8m_OTHER), - removeNoneOptimalPathsForStandardRaptor( + removeNonOptimalPathsForMcRaptor( List.of(WALK_W_OPENING_HOURS_8m, WALK_W_OPENING_HOURS_8m_OTHER) ) ); diff --git a/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPathsTest.java b/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPathsTest.java index 6d3b25c1d31..144904fa3e6 100644 --- a/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPathsTest.java +++ b/src/test/java/org/opentripplanner/raptor/rangeraptor/transit/EgressPathsTest.java @@ -38,7 +38,7 @@ class EgressPathsTest { // Number of rides, smallest is better flex(STOP_D, D1m, 2), flex(STOP_D, D1m, 3), - // Opening Hours dominate each other(no check on overlapping) + // Opening Hours dominate each other (no check on overlapping) walk(STOP_E, D2m), walk(STOP_E, D1m).openingHours("10:00", "11:45"), walk(STOP_E, D1m).openingHours("11:30", "12:30"), @@ -83,18 +83,15 @@ void listAll() { """.strip(), subjectStd.listAll().stream().map(Object::toString).sorted().collect(Collectors.joining("\n")) ); + assertEquals( """ Flex 1m C₁120 1x ~ 3 Flex 1m C₁120 1x ~ 4 Flex 1m C₁120 2x ~ 5 - Flex 1m C₁120 3x ~ 5 - Flex 2m C₁240 1x ~ 3 - Flex+Walk 1m C₁120 1x ~ 4 Walk 1m C₁120 Open(10:00 11:45) ~ 6 Walk 1m C₁120 Open(11:30 12:30) ~ 6 Walk 1m C₁120 ~ 2 - Walk 2m C₁240 Open(14:00 14:00) ~ 6 Walk 2m C₁240 ~ 6 """.strip(), subjectMc.listAll().stream().map(Object::toString).sorted().collect(Collectors.joining("\n")) @@ -107,8 +104,10 @@ void walkToDestinationEgressStops() { toString(new int[] { STOP_A, STOP_E }), toString(subjectStd.egressesWitchStartByWalking()) ); + + //[2, 6] assertEquals( - toString(new int[] { STOP_A, STOP_C, STOP_E }), + toString(new int[] { STOP_A, STOP_E }), toString(subjectMc.egressesWitchStartByWalking()) ); } diff --git a/src/test/java/org/opentripplanner/routing/algorithm/mapping/SnapshotTestBase.java b/src/test/java/org/opentripplanner/routing/algorithm/mapping/SnapshotTestBase.java index bf0e62dbc19..8dbf5536ea2 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/mapping/SnapshotTestBase.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/mapping/SnapshotTestBase.java @@ -36,11 +36,11 @@ import org.opentripplanner.ConstantsForTests; import org.opentripplanner.TestOtpModel; import org.opentripplanner.TestServerContext; -import org.opentripplanner.api.mapping.ItineraryMapper; -import org.opentripplanner.api.model.ApiLeg; import org.opentripplanner.api.parameter.ApiRequestMode; import org.opentripplanner.api.parameter.QualifiedMode; import org.opentripplanner.api.parameter.Qualifier; +import org.opentripplanner.ext.restapi.mapping.ItineraryMapper; +import org.opentripplanner.ext.restapi.model.ApiLeg; import org.opentripplanner.framework.time.TimeUtils; import org.opentripplanner.model.GenericLocation; import org.opentripplanner.model.plan.Itinerary; diff --git a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitPriorityGroup32nTest.java b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitGroupPriority32nTest.java similarity index 51% rename from src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitPriorityGroup32nTest.java rename to src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitGroupPriority32nTest.java index 85083a3ee6a..2713a190dbf 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitPriorityGroup32nTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/cost/grouppriority/TransitGroupPriority32nTest.java @@ -6,9 +6,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; -import org.opentripplanner.raptor.api.request.RaptorTransitPriorityGroupCalculator; +import org.opentripplanner.raptor.api.request.RaptorTransitGroupCalculator; -class TransitPriorityGroup32nTest { +class TransitGroupPriority32nTest { private static final int GROUP_INDEX_0 = 0; private static final int GROUP_INDEX_1 = 1; @@ -16,35 +16,35 @@ class TransitPriorityGroup32nTest { private static final int GROUP_INDEX_30 = 30; private static final int GROUP_INDEX_31 = 31; - private static final int GROUP_0 = TransitPriorityGroup32n.groupId(GROUP_INDEX_0); - private static final int GROUP_1 = TransitPriorityGroup32n.groupId(GROUP_INDEX_1); - private static final int GROUP_2 = TransitPriorityGroup32n.groupId(GROUP_INDEX_2); - private static final int GROUP_30 = TransitPriorityGroup32n.groupId(GROUP_INDEX_30); - private static final int GROUP_31 = TransitPriorityGroup32n.groupId(GROUP_INDEX_31); - private static final RaptorTransitPriorityGroupCalculator subjct = TransitPriorityGroup32n.priorityCalculator(); + private static final int GROUP_0 = TransitGroupPriority32n.groupId(GROUP_INDEX_0); + private static final int GROUP_1 = TransitGroupPriority32n.groupId(GROUP_INDEX_1); + private static final int GROUP_2 = TransitGroupPriority32n.groupId(GROUP_INDEX_2); + private static final int GROUP_30 = TransitGroupPriority32n.groupId(GROUP_INDEX_30); + private static final int GROUP_31 = TransitGroupPriority32n.groupId(GROUP_INDEX_31); + private static final RaptorTransitGroupCalculator subjct = TransitGroupPriority32n.priorityCalculator(); @Test void groupId() { - assertEqualsHex(0x00_00_00_00, TransitPriorityGroup32n.groupId(0)); - assertEqualsHex(0x00_00_00_01, TransitPriorityGroup32n.groupId(1)); - assertEqualsHex(0x00_00_00_02, TransitPriorityGroup32n.groupId(2)); - assertEqualsHex(0x00_00_00_04, TransitPriorityGroup32n.groupId(3)); - assertEqualsHex(0x40_00_00_00, TransitPriorityGroup32n.groupId(31)); - assertEqualsHex(0x80_00_00_00, TransitPriorityGroup32n.groupId(32)); + assertEqualsHex(0x00_00_00_00, TransitGroupPriority32n.groupId(0)); + assertEqualsHex(0x00_00_00_01, TransitGroupPriority32n.groupId(1)); + assertEqualsHex(0x00_00_00_02, TransitGroupPriority32n.groupId(2)); + assertEqualsHex(0x00_00_00_04, TransitGroupPriority32n.groupId(3)); + assertEqualsHex(0x40_00_00_00, TransitGroupPriority32n.groupId(31)); + assertEqualsHex(0x80_00_00_00, TransitGroupPriority32n.groupId(32)); - assertThrows(IllegalArgumentException.class, () -> TransitPriorityGroup32n.groupId(-1)); - assertThrows(IllegalArgumentException.class, () -> TransitPriorityGroup32n.groupId(33)); + assertThrows(IllegalArgumentException.class, () -> TransitGroupPriority32n.groupId(-1)); + assertThrows(IllegalArgumentException.class, () -> TransitGroupPriority32n.groupId(33)); } @Test - void mergeTransitPriorityGroupIds() { - assertEqualsHex(GROUP_0, subjct.mergeTransitPriorityGroupIds(GROUP_0, GROUP_0)); - assertEqualsHex(GROUP_1, subjct.mergeTransitPriorityGroupIds(GROUP_1, GROUP_1)); - assertEqualsHex(GROUP_0 | GROUP_1, subjct.mergeTransitPriorityGroupIds(GROUP_0, GROUP_1)); - assertEqualsHex(GROUP_30 | GROUP_31, subjct.mergeTransitPriorityGroupIds(GROUP_30, GROUP_31)); + void mergeTransitGroupPriorityIds() { + assertEqualsHex(GROUP_0, subjct.mergeGroupIds(GROUP_0, GROUP_0)); + assertEqualsHex(GROUP_1, subjct.mergeGroupIds(GROUP_1, GROUP_1)); + assertEqualsHex(GROUP_0 | GROUP_1, subjct.mergeGroupIds(GROUP_0, GROUP_1)); + assertEqualsHex(GROUP_30 | GROUP_31, subjct.mergeGroupIds(GROUP_30, GROUP_31)); assertEqualsHex( GROUP_0 | GROUP_1 | GROUP_2 | GROUP_30 | GROUP_31, - subjct.mergeTransitPriorityGroupIds(GROUP_0 | GROUP_1 | GROUP_2 | GROUP_30, GROUP_31) + subjct.mergeGroupIds(GROUP_0 | GROUP_1 | GROUP_2 | GROUP_30, GROUP_31) ); } diff --git a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java index 777aee5352c..cc4bb09f01e 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupConfiguratorTest.java @@ -7,7 +7,7 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.opentripplanner.routing.api.request.request.filter.TransitPriorityGroupSelect; +import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect; import org.opentripplanner.transit.model.basic.TransitMode; import org.opentripplanner.transit.model.network.RoutingTripPattern; import org.opentripplanner.transit.model.site.RegularStop; @@ -69,14 +69,14 @@ class PriorityGroupConfiguratorTest { @Test void emptyConfigurationShouldReturnGroupZero() { var subject = PriorityGroupConfigurator.of(List.of(), List.of()); - assertEquals(subject.baseGroupId(), subject.lookupTransitPriorityGroupId(railR1)); - assertEquals(subject.baseGroupId(), subject.lookupTransitPriorityGroupId(busB2)); - assertEquals(subject.baseGroupId(), subject.lookupTransitPriorityGroupId(null)); + assertEquals(subject.baseGroupId(), subject.lookupTransitGroupPriorityId(railR1)); + assertEquals(subject.baseGroupId(), subject.lookupTransitGroupPriorityId(busB2)); + assertEquals(subject.baseGroupId(), subject.lookupTransitGroupPriorityId(null)); } @Test - void lookupTransitPriorityGroupIdByAgency() { - var select = TransitPriorityGroupSelect + void lookupTransitGroupIdByAgency() { + var select = TransitGroupSelect .of() .addModes(List.of(TransitMode.BUS, TransitMode.RAIL)) .build(); @@ -85,12 +85,12 @@ void lookupTransitPriorityGroupIdByAgency() { var subject = PriorityGroupConfigurator.of(List.of(select), List.of()); // Agency groups are indexed (group-id set) at request time - assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitPriorityGroupId(null)); - assertEquals(EXP_GROUP_1, subject.lookupTransitPriorityGroupId(busB2)); - assertEquals(EXP_GROUP_2, subject.lookupTransitPriorityGroupId(railR3)); - assertEquals(EXP_GROUP_3, subject.lookupTransitPriorityGroupId(railR1)); - assertEquals(EXP_GROUP_2, subject.lookupTransitPriorityGroupId(busB3)); - assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitPriorityGroupId(ferryF3)); + assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitGroupPriorityId(null)); + assertEquals(EXP_GROUP_1, subject.lookupTransitGroupPriorityId(busB2)); + assertEquals(EXP_GROUP_2, subject.lookupTransitGroupPriorityId(railR3)); + assertEquals(EXP_GROUP_3, subject.lookupTransitGroupPriorityId(railR1)); + assertEquals(EXP_GROUP_2, subject.lookupTransitGroupPriorityId(busB3)); + assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitGroupPriorityId(ferryF3)); } @Test @@ -99,17 +99,17 @@ void lookupTransitPriorityGroupIdByGlobalMode() { var subject = PriorityGroupConfigurator.of( List.of(), List.of( - TransitPriorityGroupSelect.of().addModes(List.of(TransitMode.BUS)).build(), - TransitPriorityGroupSelect.of().addModes(List.of(TransitMode.RAIL)).build() + TransitGroupSelect.of().addModes(List.of(TransitMode.BUS)).build(), + TransitGroupSelect.of().addModes(List.of(TransitMode.RAIL)).build() ) ); - assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitPriorityGroupId(null)); - assertEquals(EXP_GROUP_2, subject.lookupTransitPriorityGroupId(railR1)); - assertEquals(EXP_GROUP_1, subject.lookupTransitPriorityGroupId(busB2)); - assertEquals(EXP_GROUP_2, subject.lookupTransitPriorityGroupId(railR3)); - assertEquals(EXP_GROUP_1, subject.lookupTransitPriorityGroupId(busB3)); - assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitPriorityGroupId(ferryF3)); + assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitGroupPriorityId(null)); + assertEquals(EXP_GROUP_2, subject.lookupTransitGroupPriorityId(railR1)); + assertEquals(EXP_GROUP_1, subject.lookupTransitGroupPriorityId(busB2)); + assertEquals(EXP_GROUP_2, subject.lookupTransitGroupPriorityId(railR3)); + assertEquals(EXP_GROUP_1, subject.lookupTransitGroupPriorityId(busB3)); + assertEquals(EXP_GROUP_ID_BASE, subject.lookupTransitGroupPriorityId(ferryF3)); } private static TestRouteData route( diff --git a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcherTest.java b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcherTest.java index 880d8bc9b45..91d0142f9ef 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcherTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/PriorityGroupMatcherTest.java @@ -6,7 +6,7 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.opentripplanner.routing.api.request.request.filter.TransitPriorityGroupSelect; +import org.opentripplanner.routing.api.request.request.filter.TransitGroupSelect; import org.opentripplanner.transit.model.basic.TransitMode; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.network.TripPattern; @@ -35,7 +35,7 @@ class PriorityGroupMatcherTest { @Test void testMode() { var m = PriorityGroupMatcher.of( - TransitPriorityGroupSelect.of().addModes(List.of(TransitMode.BUS, TransitMode.TRAM)).build() + TransitGroupSelect.of().addModes(List.of(TransitMode.BUS, TransitMode.TRAM)).build() ); assertEquals("Mode(BUS | TRAM)", m.toString()); assertFalse(m.isEmpty()); @@ -47,10 +47,10 @@ void testMode() { @Test void testAgencyIds() { var m1 = PriorityGroupMatcher.of( - TransitPriorityGroupSelect.of().addAgencyIds(List.of(r1agencyId)).build() + TransitGroupSelect.of().addAgencyIds(List.of(r1agencyId)).build() ); var m2 = PriorityGroupMatcher.of( - TransitPriorityGroupSelect.of().addAgencyIds(List.of(r1agencyId, anyId)).build() + TransitGroupSelect.of().addAgencyIds(List.of(r1agencyId, anyId)).build() ); var matchers = List.of(m1, m2); @@ -68,10 +68,10 @@ void testAgencyIds() { @Test void routeIds() { var m1 = PriorityGroupMatcher.of( - TransitPriorityGroupSelect.of().addRouteIds(List.of(r1routeId)).build() + TransitGroupSelect.of().addRouteIds(List.of(r1routeId)).build() ); var m2 = PriorityGroupMatcher.of( - TransitPriorityGroupSelect.of().addRouteIds(List.of(r1routeId, anyId)).build() + TransitGroupSelect.of().addRouteIds(List.of(r1routeId, anyId)).build() ); var matchers = List.of(m1, m2); @@ -89,7 +89,7 @@ void routeIds() { @Test void testSubMode() { var subject = PriorityGroupMatcher.of( - TransitPriorityGroupSelect.of().addSubModeRegexp(List.of(".*local.*")).build() + TransitGroupSelect.of().addSubModeRegexp(List.of(".*local.*")).build() ); assertEquals("SubModeRegexp(.*local.*)", subject.toString()); @@ -103,7 +103,7 @@ void testSubMode() { @Test void testAnd() { var subject = PriorityGroupMatcher.of( - TransitPriorityGroupSelect + TransitGroupSelect .of() .addSubModeRegexp(List.of("express")) .addRouteIds(List.of(r1routeId)) @@ -125,7 +125,7 @@ void testAnd() { @Test void testToString() { var subject = PriorityGroupMatcher.of( - TransitPriorityGroupSelect + TransitGroupSelect .of() .addModes(List.of(TransitMode.BUS, TransitMode.TRAM)) .addAgencyIds(List.of(anyId, r1agencyId)) diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/TransitPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/TransitPreferencesTest.java index 811c4a70b29..b77a7d9085b 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/TransitPreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/TransitPreferencesTest.java @@ -42,7 +42,7 @@ class TransitPreferencesTest { .setUnpreferredCost(UNPREFERRED_COST) .withBoardSlack(b -> b.withDefault(D45s).with(TransitMode.AIRPLANE, D35m)) .withAlightSlack(b -> b.withDefault(D15s).with(TransitMode.AIRPLANE, D25m)) - .withTransitGroupPriorityGeneralizedCostSlack(TRANSIT_GROUP_PRIORITY_RELAX) + .withRelaxTransitGroupPriority(TRANSIT_GROUP_PRIORITY_RELAX) .setIgnoreRealtimeUpdates(IGNORE_REALTIME_UPDATES) .setIncludePlannedCancellations(INCLUDE_PLANNED_CANCELLATIONS) .setIncludeRealtimeCancellations(INCLUDE_REALTIME_CANCELLATIONS) @@ -77,8 +77,8 @@ void unpreferredCost() { } @Test - void relaxTransitPriorityGroup() { - assertEquals(TRANSIT_GROUP_PRIORITY_RELAX, subject.relaxTransitPriorityGroup()); + void relaxTransitGroupPriority() { + assertEquals(TRANSIT_GROUP_PRIORITY_RELAX, subject.relaxTransitGroupPriority()); } @Test @@ -125,7 +125,7 @@ void testToString() { "reluctanceForMode: {AIRPLANE=2.1}, " + "otherThanPreferredRoutesPenalty: $350, " + "unpreferredCost: 5m + 1.15 t, " + - "relaxTransitPriorityGroup: 5m + 1.50 t, " + + "relaxTransitGroupPriority: 5m + 1.50 t, " + "ignoreRealtimeUpdates, " + "includePlannedCancellations, " + "includeRealtimeCancellations, " + diff --git a/src/test/java/org/opentripplanner/street/search/state/TestStateBuilder.java b/src/test/java/org/opentripplanner/street/search/state/TestStateBuilder.java index 042ff5ba553..a4dbf76e55e 100644 --- a/src/test/java/org/opentripplanner/street/search/state/TestStateBuilder.java +++ b/src/test/java/org/opentripplanner/street/search/state/TestStateBuilder.java @@ -1,6 +1,7 @@ package org.opentripplanner.street.search.state; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.opentripplanner.routing.algorithm.raptoradapter.router.street.AccessEgressType.EGRESS; import static org.opentripplanner.transit.model.site.PathwayMode.WALKWAY; import java.time.Instant; @@ -10,6 +11,7 @@ import javax.annotation.Nonnull; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.framework.i18n.NonLocalizedString; +import org.opentripplanner.routing.algorithm.raptoradapter.router.street.AccessEgressType; import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.service.vehiclerental.model.TestFreeFloatingRentalVehicleBuilder; import org.opentripplanner.service.vehiclerental.model.TestVehicleRentalStationBuilder; @@ -20,6 +22,7 @@ import org.opentripplanner.street.model.RentalFormFactor; import org.opentripplanner.street.model.StreetTraversalPermission; import org.opentripplanner.street.model._data.StreetModelForTest; +import org.opentripplanner.street.model.edge.Edge; import org.opentripplanner.street.model.edge.ElevatorAlightEdge; import org.opentripplanner.street.model.edge.ElevatorBoardEdge; import org.opentripplanner.street.model.edge.ElevatorHopEdge; @@ -51,10 +54,19 @@ public class TestStateBuilder { private State currentState; private TestStateBuilder(StreetMode mode) { + this(mode, AccessEgressType.ACCESS); + } + + private TestStateBuilder(StreetMode mode, AccessEgressType type) { currentState = new State( StreetModelForTest.intersectionVertex(count, count), - StreetSearchRequest.of().withMode(mode).withStartTime(DEFAULT_START_TIME).build() + StreetSearchRequest + .of() + .withArriveBy(type.isEgress()) + .withMode(mode) + .withStartTime(DEFAULT_START_TIME) + .build() ); } @@ -80,6 +92,14 @@ public static TestStateBuilder ofScooterRental() { return new TestStateBuilder(StreetMode.SCOOTER_RENTAL); } + /** + * Creates a state that starts the scooter rental in arriveBy mode, so starting with + * a rental scooter and going backwards until it finds a rental vertex where to drop it. + */ + public static TestStateBuilder ofScooterRentalArriveBy() { + return new TestStateBuilder(StreetMode.SCOOTER_RENTAL, EGRESS); + } + public static TestStateBuilder ofBikeRental() { return new TestStateBuilder(StreetMode.BIKE_RENTAL); } @@ -248,7 +268,12 @@ private TestStateBuilder arriveAtStop(RegularStop stop) { var from = (StreetVertex) currentState.vertex; var to = new TransitStopVertexBuilder().withStop(stop).build(); - var edge = StreetTransitStopLink.createStreetTransitStopLink(from, to); + Edge edge; + if (currentState.getRequest().arriveBy()) { + edge = StreetTransitStopLink.createStreetTransitStopLink(to, from); + } else { + edge = StreetTransitStopLink.createStreetTransitStopLink(from, to); + } var states = edge.traverse(currentState); if (states.length != 1) { throw new IllegalStateException("Only single state transitions are supported."); diff --git a/src/test/java/org/opentripplanner/test/support/JsonAssertions.java b/src/test/java/org/opentripplanner/test/support/JsonAssertions.java index f3942c16f3b..2dab1e96190 100644 --- a/src/test/java/org/opentripplanner/test/support/JsonAssertions.java +++ b/src/test/java/org/opentripplanner/test/support/JsonAssertions.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.opentripplanner.standalone.config.framework.json.JsonSupport; @@ -15,9 +16,19 @@ public class JsonAssertions { */ public static void assertEqualJson(String expected, String actual) { try { - var act = MAPPER.readTree(actual); + assertEqualJson(expected, MAPPER.readTree(actual)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * @see JsonAssertions#assertEqualJson(String, String) + */ + public static void assertEqualJson(String expected, JsonNode actual) { + try { var exp = MAPPER.readTree(expected); - assertEquals(JsonSupport.prettyPrint(exp), JsonSupport.prettyPrint(act)); + assertEquals(JsonSupport.prettyPrint(exp), JsonSupport.prettyPrint(actual)); } catch (JsonProcessingException e) { throw new RuntimeException(e); } diff --git a/src/test/java/org/opentripplanner/test/support/ResourceLoader.java b/src/test/java/org/opentripplanner/test/support/ResourceLoader.java index 38fe02a8c74..5eb51cac55a 100644 --- a/src/test/java/org/opentripplanner/test/support/ResourceLoader.java +++ b/src/test/java/org/opentripplanner/test/support/ResourceLoader.java @@ -55,6 +55,17 @@ public File file(String path) { return file; } + /** + * Returns the string content of a file. + */ + public String fileToString(String p) { + try { + return Files.readString(file(p).toPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** * Return a URL for the given resource. */ diff --git a/src/test/resources/org/opentripplanner/apis/vectortiles/style.json b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json new file mode 100644 index 00000000000..f5bb18f6f6a --- /dev/null +++ b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json @@ -0,0 +1,42 @@ +{ + "name": "OTP Debug Tiles", + "sources": { + "background": { + "id": "background", + "tiles": [ + "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" + ], + "tileSize": 256, + "attribution" : "© OpenStreetMap Contributors", + "type": "raster" + }, + "vectorSource": { + "id": "vectorSource", + "url": "https://example.com", + "type": "vector" + } + }, + "layers": [ + { + "id": "background", + "source": "background", + "type": "raster", + "maxzoom": 22, + "minzoom": 0 + }, + { + "maxzoom": 22, + "paint": { + "circle-stroke-width": 2, + "circle-color": "#fcf9fa", + "circle-stroke-color": "#140d0e" + }, + "id": "regular-stop", + "source": "vectorSource", + "source-layer": "regularStops", + "type": "circle", + "minzoom": 13 + } + ], + "version": 8 +} diff --git a/src/test/resources/standalone/config/router-config.json b/src/test/resources/standalone/config/router-config.json index 69f859d784d..5abb5ef87a6 100644 --- a/src/test/resources/standalone/config/router-config.json +++ b/src/test/resources/standalone/config/router-config.json @@ -283,6 +283,14 @@ "Authorization": "A-Token" } }, + // Streaming GTFS-RT TripUpdates through an MQTT broker + { + "type": "mqtt-gtfs-rt-updater", + "url": "tcp://pred.rt.hsl.fi", + "topic": "gtfsrt/v2/fi/hsl/tu", + "feedId": "HSL", + "fuzzyTripMatching": true + }, // Polling for GTFS-RT Vehicle Positions - output can be fetched via trip pattern GraphQL API { "type": "vehicle-positions", @@ -295,11 +303,6 @@ "fuzzyTripMatching": false, "features": ["position"] }, - // Streaming differential GTFS-RT TripUpdates over websockets - { - "type": "websocket-gtfs-rt-updater", - "feedId": "ov" - }, // Siri-ET over HTTP { "type": "siri-et-updater",