diff --git a/src/ext-test/java/org/opentripplanner/ext/flex/FlexIntegrationTest.java b/src/ext-test/java/org/opentripplanner/ext/flex/FlexIntegrationTest.java new file mode 100644 index 00000000000..6d1fc95a51c --- /dev/null +++ b/src/ext-test/java/org/opentripplanner/ext/flex/FlexIntegrationTest.java @@ -0,0 +1,183 @@ +package org.opentripplanner.ext.flex; + +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.graph_builder.module.FakeGraph.getFileForResource; +import static org.opentripplanner.routing.api.request.StreetMode.FLEXIBLE; +import static org.opentripplanner.routing.core.TraverseMode.BUS; +import static org.opentripplanner.routing.core.TraverseMode.WALK; + +import java.io.File; +import java.net.URISyntaxException; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.opentripplanner.ConstantsForTests; +import org.opentripplanner.graph_builder.model.GtfsBundle; +import org.opentripplanner.graph_builder.module.DirectTransferGenerator; +import org.opentripplanner.graph_builder.module.GtfsModule; +import org.opentripplanner.graph_builder.module.StreetLinkerModule; +import org.opentripplanner.model.GenericLocation; +import org.opentripplanner.model.calendar.ServiceDateInterval; +import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.routing.RoutingService; +import org.opentripplanner.routing.api.request.RoutingRequest; +import org.opentripplanner.routing.core.TraverseMode; +import org.opentripplanner.routing.graph.Graph; +import org.opentripplanner.standalone.config.RouterConfig; +import org.opentripplanner.standalone.server.Router; +import org.opentripplanner.util.OTPFeature; + +/** + * This test checks the combination of transit and flex works. + */ +public class FlexIntegrationTest { + + static long dateTime = ZonedDateTime.parse("2021-12-02T12:00:00-05:00[America/New_York]") + .toInstant() + .getEpochSecond(); + + static Graph graph; + static RoutingService service; + static Router router; + + @BeforeAll + static void setup() { + OTPFeature.enableFeatures(Map.of(OTPFeature.FlexRouting, true)); + var osmPath = getAbsolutePath(FlexTest.COBB_OSM); + var cobblincGtfsPath = getAbsolutePath(FlexTest.COBB_BUS_30_GTFS); + var martaGtfsPath = getAbsolutePath(FlexTest.MARTA_BUS_856_GTFS); + var flexGtfsPath = getAbsolutePath(FlexTest.COBB_FLEX_GTFS); + + graph = ConstantsForTests.buildOsmGraph(osmPath); + addGtfsToGraph(graph, List.of(cobblincGtfsPath, martaGtfsPath, flexGtfsPath)); + router = new Router(graph, RouterConfig.DEFAULT); + router.startup(); + + service = new RoutingService(graph); + } + + private static String getAbsolutePath(String cobbOsm) { + try { + return getFileForResource(cobbOsm).getAbsolutePath(); + } + catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + @Test + public void shouldReturnARouteTransferringFromBusToFlex() { + var from = new GenericLocation(33.84329482265106, -84.583740234375); + var to = new GenericLocation(33.86701256815635, -84.61787939071655); + + var itin = getItinerary(from, to, 2); + + assertEquals(4, itin.legs.size()); + + var walkToBus = itin.legs.get(0); + assertEquals(TraverseMode.WALK, walkToBus.mode); + + var bus = itin.legs.get(1); + assertEquals(BUS, bus.mode); + assertEquals("30", bus.getRoute().getShortName()); + + var transfer = itin.legs.get(2); + assertEquals(TraverseMode.WALK, transfer.mode); + + var flex = itin.legs.get(3); + assertEquals(BUS, flex.mode); + assertEquals("Zone 2", flex.getRoute().getShortName()); + assertTrue(flex.flexibleTrip); + } + + @Test + public void shouldReturnARouteWithTwoTransfers() { + var from = GenericLocation.fromStopId("ALEX DR@ALEX WAY", "MARTA", "97266"); + var to = new GenericLocation(33.86701256815635, -84.61787939071655); + + var itin = getItinerary(from, to, 1); + + assertEquals(5, itin.legs.size()); + + var firstBus = itin.legs.get(0); + assertEquals(BUS, firstBus.mode); + assertEquals("856", firstBus.getRoute().getShortName()); + + var transferToSecondBus = itin.legs.get(1); + assertEquals(WALK, transferToSecondBus.mode); + + var secondBus = itin.legs.get(2); + assertEquals(BUS, secondBus.mode); + assertEquals("30", secondBus.getRoute().getShortName()); + + var transferToFlex = itin.legs.get(3); + assertEquals(WALK, transferToFlex.mode); + + var finalFlex = itin.legs.get(4); + assertEquals(BUS, finalFlex.mode); + assertEquals("Zone 2", finalFlex.getRoute().getShortName()); + assertTrue(finalFlex.flexibleTrip); + } + + private Itinerary getItinerary(GenericLocation from, GenericLocation to, int index) { + RoutingRequest request = new RoutingRequest(); + request.dateTime = dateTime; + request.from = from; + request.to = to; + request.numItineraries = 10; + request.searchWindow = Duration.ofHours(2); + request.modes.egressMode = FLEXIBLE; + + var result = service.route(request, router); + var itineraries = result.getTripPlan().itineraries; + + assertFalse(itineraries.isEmpty()); + + return itineraries.get(index); + } + + private static void addGtfsToGraph( + Graph graph, + List gtfsFiles + ) { + var extra = new HashMap, Object>(); + + // GTFS + var gtfsBundles = gtfsFiles.stream() + .map(f -> new GtfsBundle(new File(f))) + .collect(Collectors.toList()); + GtfsModule gtfsModule = new GtfsModule(gtfsBundles, ServiceDateInterval.unbounded()); + gtfsModule.buildGraph(graph, extra); + + // link stations to streets + StreetLinkerModule streetLinkerModule = new StreetLinkerModule(); + streetLinkerModule.buildGraph(graph, extra); + + // link flex locations to streets + var flexMapper = new FlexLocationsToStreetEdgesMapper(); + flexMapper.buildGraph(graph, new HashMap<>()); + + // generate direct transfers + var req = new RoutingRequest(); + + // we don't have a complete coverage of the entire area so use straight lines for transfers + var transfers = new DirectTransferGenerator(600, List.of(req)); + transfers.buildGraph(graph, extra); + + graph.index(); + } + + + @AfterAll + static void teardown() { + OTPFeature.enableFeatures(Map.of(OTPFeature.FlexRouting, false)); + } +} diff --git a/src/ext-test/java/org/opentripplanner/ext/flex/FlexTest.java b/src/ext-test/java/org/opentripplanner/ext/flex/FlexTest.java index a0da1a8e361..2171d378ac5 100644 --- a/src/ext-test/java/org/opentripplanner/ext/flex/FlexTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/flex/FlexTest.java @@ -3,6 +3,7 @@ import static graphql.Assert.assertFalse; import gnu.trove.set.hash.TIntHashSet; +import java.io.File; import java.net.URISyntaxException; import java.time.LocalTime; import java.util.HashMap; @@ -19,6 +20,13 @@ abstract public class FlexTest { + static final String ASPEN_GTFS = "/flex/aspen-flex-on-demand.gtfs.zip"; + static final String COBB_FLEX_GTFS = "/flex/cobblinc-scheduled-deviated-flex.gtfs.zip"; + static final String COBB_BUS_30_GTFS = "/flex/cobblinc-bus-30-only.gtfs.zip"; + static final String MARTA_BUS_856_GTFS = "/flex/marta-bus-856-only.gtfs.zip"; + static final String LINCOLN_COUNTY_GBFS = "/flex/lincoln-county-flex.gtfs.zip"; + static final String COBB_OSM = "/flex/cobb-county.filtered.osm.pbf"; + static final DirectFlexPathCalculator calculator = new DirectFlexPathCalculator(null); static final ServiceDate serviceDate = new ServiceDate(2021, 4, 11); static final int secondsSinceMidnight = LocalTime.of(10, 0).toSecondOfDay(); @@ -27,8 +35,14 @@ abstract public class FlexTest { static final FlexParameters params = new FlexParameters(300); - static Graph buildFlexGraph(String fileName) throws URISyntaxException { - var file = FakeGraph.getFileForResource(fileName); + static Graph buildFlexGraph(String fileName) { + File file = null; + try { + file = FakeGraph.getFileForResource(fileName); + } + catch (URISyntaxException e) { + throw new RuntimeException(e); + } var graph = new Graph(); GtfsBundle gtfsBundle = new GtfsBundle(file); diff --git a/src/ext-test/java/org/opentripplanner/ext/flex/ScheduledDeviatedTripTest.java b/src/ext-test/java/org/opentripplanner/ext/flex/ScheduledDeviatedTripTest.java index cb19f395444..0f45479b29f 100644 --- a/src/ext-test/java/org/opentripplanner/ext/flex/ScheduledDeviatedTripTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/flex/ScheduledDeviatedTripTest.java @@ -2,8 +2,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.opentripplanner.PolylineAssert.assertThatPolylinesAreEqual; -import java.net.URISyntaxException; import java.time.OffsetDateTime; import java.util.List; import java.util.Map; @@ -16,15 +17,23 @@ import org.opentripplanner.ext.flex.trip.ScheduledDeviatedTrip; import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.FlexStopLocation; +import org.opentripplanner.model.GenericLocation; +import org.opentripplanner.model.StopTime; +import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.routing.algorithm.raptor.router.TransitRouter; import org.opentripplanner.routing.api.request.RoutingRequest; import org.opentripplanner.routing.core.Fare.FareType; import org.opentripplanner.routing.core.Money; import org.opentripplanner.routing.core.State; import org.opentripplanner.routing.core.WrappedCurrency; +import org.opentripplanner.routing.framework.DebugTimingAggregator; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graphfinder.NearbyStop; import org.opentripplanner.routing.location.StreetLocation; +import org.opentripplanner.standalone.config.RouterConfig; +import org.opentripplanner.standalone.server.Router; import org.opentripplanner.util.OTPFeature; +import org.opentripplanner.util.TestUtils; /** * This tests that the feed for the Cobb County Flex service is processed correctly. This service @@ -35,10 +44,10 @@ */ public class ScheduledDeviatedTripTest extends FlexTest { - static final String COBB_COUNTY_GTFS = "/flex/cobblinc-scheduled-deviated-flex.gtfs.zip"; - static Graph graph; + float delta = 0.01f; + @Test public void parseCobbCountyAsScheduledDeviatedTrip() { var flexTrips = graph.flexTripsById.values(); @@ -50,6 +59,16 @@ public void parseCobbCountyAsScheduledDeviatedTrip() { flexTrips.stream().map(FlexTrip::getClass).collect( Collectors.toSet()) ); + + var trip = getFlexTrip(); + System.out.println(trip.getStops().stream().map(s -> s.getId().getId()).collect(Collectors.toList())); + var stop = trip.getStops().stream().filter(s -> s.getId().getId().equals("cujv")).findFirst().get(); + assertEquals(33.85465, stop.getLat(), delta); + assertEquals(-84.60039, stop.getLon(), delta); + + var flexZone = trip.getStops().stream().filter(s -> s.getId().getId().equals("zone_3")).findFirst().get(); + assertEquals(33.825846635310214, flexZone.getLat(), delta); + assertEquals(-84.63430143459385, flexZone.getLon(), delta); } @Test @@ -114,14 +133,108 @@ public void calculateDirectFare() { var itinerary = itineraries.iterator().next(); assertFalse(itinerary.fare.fare.isEmpty()); - assertEquals(new Money(new WrappedCurrency("USD"), 250), itinerary.fare.getFare(FareType.regular)); + assertEquals( + new Money(new WrappedCurrency("USD"), 250), + itinerary.fare.getFare(FareType.regular) + ); OTPFeature.enableFeatures(Map.of(OTPFeature.FlexRouting, false)); } + + /** + * Trips which consist of flex and fixed-schedule stops should work in transit mode. + *

+ * The flex stops will show up as intermediate stops (without a departure/arrival time) but you + * cannot board or alight. + */ + @Test + public void flexTripInTransitMode() { + var feedId = graph.getFeedIds().iterator().next(); + + var router = new Router(graph, RouterConfig.DEFAULT); + router.startup(); + + // from zone 3 to zone 2 + var from = GenericLocation.fromStopId( + "Transfer Point for Route 30", + feedId, + "cujv" + ); + var to = GenericLocation.fromStopId( + "Zone 1 - PUBLIX Super Market,Zone 1 Collection Point", + feedId, + "yz85" + ); + + var itineraries = getItineraries(from, to, router); + + assertEquals(1, itineraries.size()); + + var itin = itineraries.get(0); + var leg = itin.legs.get(0); + + assertEquals("cujv", leg.from.stop.getId().getId()); + assertEquals("yz85", leg.to.stop.getId().getId()); + + var intermediateStops = leg.intermediateStops; + assertEquals(1, intermediateStops.size()); + assertEquals("zone_1", intermediateStops.get(0).place.stop.getId().getId()); + + assertThatPolylinesAreEqual( + leg.legGeometry.getPoints(), + "kfsmEjojcOa@eBRKfBfHR|ALjBBhVArMG|OCrEGx@OhAKj@a@tAe@hA]l@MPgAnAgw@nr@cDxCm@t@c@t@c@x@_@~@]pAyAdIoAhG}@lE{AzHWhAtt@t~Aj@tAb@~AXdBHn@FlBC`CKnA_@nC{CjOa@dCOlAEz@E|BRtUCbCQ~CWjD??qBvXBl@kBvWOzAc@dDOx@sHv]aIG?q@@c@ZaB\\mA" + ); + + } + + /** + * We add flex trips, that can potentially not have a departure and arrival time, to the trip. + *

+ * Normally these trip times are interpolated/repaired during the graph build but for flex this + * is exactly what we don't want. Here we check that the interpolation process is skipped. + * + * @see org.opentripplanner.gtfs.RepairStopTimesForEachTripOperation#interpolateStopTimes(List) + */ + @Test + public void shouldNotInterpolateFlexTimes() { + var feedId = graph.getFeedIds().iterator().next(); + var pattern = graph.tripPatternForId.get(new FeedScopedId(feedId, "090z:0:01")); + + assertEquals(3, pattern.getStops().size()); + + var tripTimes = pattern.getScheduledTimetable().getTripTimes(0); + var arrivalTime = tripTimes.getArrivalTime(1); + + assertEquals(StopTime.MISSING_VALUE, arrivalTime); + } + + /** + * Checks that trips which have continuous pick up/drop off set are parsed correctly. + */ + @Test + public void parseContinuousPickup() { + var lincolnGraph = FlexTest.buildFlexGraph(LINCOLN_COUNTY_GBFS); + assertNotNull(lincolnGraph); + } + + private static List getItineraries( + GenericLocation from, + GenericLocation to, + Router router + ) { + RoutingRequest request = new RoutingRequest(); + request.dateTime = TestUtils.dateInSeconds("America/Atlanta", 2021, 11, 25, 12, 0, 0); + request.from = from; + request.to = to; + + var result = TransitRouter.route(request, router, new DebugTimingAggregator()); + return result.getItineraries(); + } + @BeforeAll - static void setup() throws URISyntaxException { - graph = FlexTest.buildFlexGraph(COBB_COUNTY_GTFS); + static void setup() { + graph = FlexTest.buildFlexGraph(COBB_FLEX_GTFS); } private static NearbyStop getNearbyStop(FlexTrip trip) { diff --git a/src/ext-test/java/org/opentripplanner/ext/flex/UnscheduledTripTest.java b/src/ext-test/java/org/opentripplanner/ext/flex/UnscheduledTripTest.java index 9206aa661ce..0873c0823e7 100644 --- a/src/ext-test/java/org/opentripplanner/ext/flex/UnscheduledTripTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/flex/UnscheduledTripTest.java @@ -25,8 +25,6 @@ */ public class UnscheduledTripTest extends FlexTest { - static final String ASPEN_GTFS = "/flex/aspen-flex-on-demand.gtfs.zip"; - static Graph graph; @Test @@ -85,7 +83,7 @@ public void calculateEgressTemplate() { } @BeforeAll - static void setup() throws URISyntaxException { + static void setup() { graph = FlexTest.buildFlexGraph(ASPEN_GTFS); } diff --git a/src/ext-test/java/org/opentripplanner/ext/legacygraphqlapi/GraphQLIndexTest.java b/src/ext-test/java/org/opentripplanner/ext/legacygraphqlapi/GraphQLIndexTest.java new file mode 100644 index 00000000000..69e98d49fbd --- /dev/null +++ b/src/ext-test/java/org/opentripplanner/ext/legacygraphqlapi/GraphQLIndexTest.java @@ -0,0 +1,18 @@ +package org.opentripplanner.ext.legacygraphqlapi; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +/** + * This graph does a quick sanity check that the GraphQL schema can be built. It's much + * quicker to run the test than to build a jar and start up OTP.` + */ +public class GraphQLIndexTest { + + @Test + public void testGraphQLIndex() { + var schema = LegacyGraphQLIndex.buildSchema(); + assertNotNull(schema); + } +} diff --git a/src/ext-test/resources/flex/cobb-county.filtered.osm.pbf b/src/ext-test/resources/flex/cobb-county.filtered.osm.pbf new file mode 100644 index 00000000000..52fc577860f Binary files /dev/null and b/src/ext-test/resources/flex/cobb-county.filtered.osm.pbf differ diff --git a/src/ext-test/resources/flex/cobblinc-bus-30-only.gtfs.zip b/src/ext-test/resources/flex/cobblinc-bus-30-only.gtfs.zip new file mode 100644 index 00000000000..37716690a40 Binary files /dev/null and b/src/ext-test/resources/flex/cobblinc-bus-30-only.gtfs.zip differ diff --git a/src/ext-test/resources/flex/lincoln-county-flex.gtfs.zip b/src/ext-test/resources/flex/lincoln-county-flex.gtfs.zip new file mode 100644 index 00000000000..f63a0bf736a Binary files /dev/null and b/src/ext-test/resources/flex/lincoln-county-flex.gtfs.zip differ diff --git a/src/ext-test/resources/flex/marta-bus-856-only.gtfs.zip b/src/ext-test/resources/flex/marta-bus-856-only.gtfs.zip new file mode 100644 index 00000000000..aecd1803183 Binary files /dev/null and b/src/ext-test/resources/flex/marta-bus-856-only.gtfs.zip differ diff --git a/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java b/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java index 10e892f33fc..b1b73c16582 100644 --- a/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java +++ b/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java @@ -28,7 +28,7 @@ public class FlexIndex { public Map routeById = new HashMap<>(); - public Map tripById = new HashMap<>(); + public Map tripById = new HashMap<>(); public FlexIndex(Graph graph) { for (PathTransfer transfer : graph.transfersByStop.values()) { @@ -36,7 +36,7 @@ public FlexIndex(Graph graph) { } for (FlexTrip flexTrip : graph.flexTripsById.values()) { routeById.put(flexTrip.getTrip().getRoute().getId(), flexTrip.getTrip().getRoute()); - tripById.put(flexTrip.getTrip().getId(), flexTrip.getTrip()); + tripById.put(flexTrip.getTrip().getId(), flexTrip); for (StopLocation stop : flexTrip.getStops()) { if (stop instanceof FlexLocationGroup) { for (StopLocation stopElement : ((FlexLocationGroup) stop).getLocations()) { diff --git a/src/ext/java/org/opentripplanner/ext/flex/FlexTripsMapper.java b/src/ext/java/org/opentripplanner/ext/flex/FlexTripsMapper.java index 1c826bbf14d..98bbeac6405 100644 --- a/src/ext/java/org/opentripplanner/ext/flex/FlexTripsMapper.java +++ b/src/ext/java/org/opentripplanner/ext/flex/FlexTripsMapper.java @@ -3,6 +3,7 @@ import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.ext.flex.trip.ScheduledDeviatedTrip; import org.opentripplanner.ext.flex.trip.UnscheduledTrip; +import org.opentripplanner.graph_builder.DataImportIssueStore; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.TripStopTimes; import org.opentripplanner.model.impl.OtpTransitServiceBuilder; @@ -19,7 +20,10 @@ public class FlexTripsMapper { private static final Logger LOG = LoggerFactory.getLogger(FlexTripsMapper.class); - static public List createFlexTrips(OtpTransitServiceBuilder builder) { + static public List createFlexTrips( + OtpTransitServiceBuilder builder, + DataImportIssueStore store + ) { List result = new ArrayList<>(); TripStopTimes stopTimesByTrip = builder.getStopTimesSortedByTrip(); @@ -38,7 +42,12 @@ static public List createFlexTrips(OtpTransitServiceBuilder builder) { result.add(new UnscheduledTrip(trip, stopTimes)); } else if (ScheduledDeviatedTrip.isScheduledFlexTrip(stopTimes)) { result.add(new ScheduledDeviatedTrip(trip, stopTimes)); - } else if (hasContinuousStops(stopTimes)) { + } else if (hasContinuousStops(stopTimes) && FlexTrip.containsFlexStops(stopTimes)) { + store.add( + "ContinuousFlexTrip", + "Trip %s contains both flex stops and continuous pick up/drop off. This is an invalid combination: https://github.com/MobilityData/gtfs-flex/issues/70", + trip.getId() + ); // result.add(new ContinuousPickupDropOffTrip(trip, stopTimes)); } diff --git a/src/ext/java/org/opentripplanner/ext/flex/trip/FlexTrip.java b/src/ext/java/org/opentripplanner/ext/flex/trip/FlexTrip.java index 5a6479e8f36..219b8bc025d 100644 --- a/src/ext/java/org/opentripplanner/ext/flex/trip/FlexTrip.java +++ b/src/ext/java/org/opentripplanner/ext/flex/trip/FlexTrip.java @@ -1,6 +1,8 @@ package org.opentripplanner.ext.flex.trip; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.opentripplanner.ext.flex.FlexParameters; import org.opentripplanner.ext.flex.FlexServiceDate; @@ -8,7 +10,10 @@ import org.opentripplanner.ext.flex.template.FlexAccessTemplate; import org.opentripplanner.ext.flex.template.FlexEgressTemplate; import org.opentripplanner.model.BookingInfo; +import org.opentripplanner.model.FlexLocationGroup; +import org.opentripplanner.model.FlexStopLocation; import org.opentripplanner.model.StopLocation; +import org.opentripplanner.model.StopTime; import org.opentripplanner.model.TransitEntity; import org.opentripplanner.model.Trip; import org.opentripplanner.routing.graphfinder.NearbyStop; @@ -60,4 +65,12 @@ public Trip getTrip() { public abstract boolean isBoardingPossible(NearbyStop stop); public abstract boolean isAlightingPossible(NearbyStop stop); + + public static boolean containsFlexStops(List stopTimes) { + return stopTimes.stream().map(StopTime::getStop).anyMatch(FlexTrip::isFlexStop); + } + + public static boolean isFlexStop(StopLocation stop) { + return stop instanceof FlexLocationGroup || stop instanceof FlexStopLocation; + } } diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLIndex.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLIndex.java index 8ed32c1b1e9..901c3339a33 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLIndex.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLIndex.java @@ -49,7 +49,7 @@ class LegacyGraphQLIndex { .setNameFormat("GraphQLExecutor-%d") .build()); - static private GraphQLSchema buildSchema() { + static protected GraphQLSchema buildSchema() { try { URL url = Resources.getResource("legacygraphqlapi/schema.graphqls"); String sdl = Resources.toString(url, Charsets.UTF_8); @@ -57,6 +57,7 @@ static private GraphQLSchema buildSchema() { RuntimeWiring runtimeWiring = RuntimeWiring .newRuntimeWiring() .scalar(LegacyGraphQLScalars.polylineScalar) + .scalar(LegacyGraphQLScalars.geoJsonScalar) .scalar(LegacyGraphQLScalars.graphQLIDScalar) .scalar(ExtendedScalars.GraphQLLong) .type("Node", type -> type.typeResolver(new LegacyGraphQLNodeTypeResolver())) @@ -101,6 +102,7 @@ static private GraphQLSchema buildSchema() { .type("AlertEntity", type -> type.typeResolver(new LegacyGraphQLAlertEntityTypeResolver())) .type(IntrospectionTypeWiring.build(LegacyGraphQLStopOnRouteImpl.class)) .type(IntrospectionTypeWiring.build(LegacyGraphQLStopOnTripImpl.class)) + .type(IntrospectionTypeWiring.build(LegacyGraphQLStopGeometriesImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLScalars.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLScalars.java index 7f71754893e..8bcb4fe8005 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLScalars.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/LegacyGraphQLScalars.java @@ -1,5 +1,7 @@ package org.opentripplanner.ext.legacygraphqlapi; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import graphql.language.StringValue; import graphql.relay.Relay; import graphql.schema.Coercing; @@ -7,10 +9,15 @@ import graphql.schema.CoercingParseValueException; import graphql.schema.CoercingSerializeException; import graphql.schema.GraphQLScalarType; +import org.locationtech.jts.geom.Geometry; +import org.opentripplanner.common.geometry.GeoJsonModule; public class LegacyGraphQLScalars { - public static GraphQLScalarType polylineScalar = GraphQLScalarType + private static final ObjectMapper geoJsonMapper = new ObjectMapper() + .registerModule(new GeoJsonModule()); + + public static GraphQLScalarType polylineScalar = GraphQLScalarType .newScalar() .name("Polyline") .description( @@ -34,7 +41,36 @@ public String parseLiteral(Object input) { }) .build(); - public static GraphQLScalarType graphQLIDScalar = GraphQLScalarType + public static GraphQLScalarType geoJsonScalar = GraphQLScalarType + .newScalar() + .name("GeoJson") + .description("Geographic data structures in JSON format. See: https://geojson.org/") + .coercing(new Coercing() { + @Override + public JsonNode serialize(Object dataFetcherResult) + throws CoercingSerializeException { + if (dataFetcherResult instanceof Geometry) { + var geom = (Geometry) dataFetcherResult; + return geoJsonMapper.valueToTree(geom); + } + return null; + } + + @Override + public Geometry parseValue(Object input) + throws CoercingParseValueException { + return null; + } + + @Override + public Geometry parseLiteral(Object input) + throws CoercingParseLiteralException { + return null; + } + }) + .build(); + + public static GraphQLScalarType graphQLIDScalar = GraphQLScalarType .newScalar() .name("ID") .coercing(new Coercing() { diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLAlertImpl.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLAlertImpl.java index 30be9621250..7839eba7d64 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLAlertImpl.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLAlertImpl.java @@ -15,6 +15,7 @@ import org.opentripplanner.model.Agency; import org.opentripplanner.model.Route; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.Trip; import org.opentripplanner.model.TripPattern; import org.opentripplanner.routing.RoutingService; @@ -206,13 +207,13 @@ public DataFetcher> entities() { } if (entitySelector instanceof EntitySelector.StopAndRoute) { StopAndRouteOrTripKey stopAndRouteKey = ((EntitySelector.StopAndRoute) entitySelector).stopAndRoute; - Stop stop = stopAndRouteKey == null ? null : getRoutingService(environment).getStopForId(stopAndRouteKey.stop); + StopLocation stop = stopAndRouteKey == null ? null : getRoutingService(environment).getStopForId(stopAndRouteKey.stop); Route route = stopAndRouteKey == null ? null : getRoutingService(environment).getRouteForId(stopAndRouteKey.routeOrTrip); return new LegacyGraphQLStopOnRoute(stop, route); } if (entitySelector instanceof EntitySelector.StopAndTrip) { StopAndRouteOrTripKey stopAndTripKey = ((EntitySelector.StopAndTrip) entitySelector).stopAndTrip; - Stop stop = stopAndTripKey == null ? null : getRoutingService(environment).getStopForId(stopAndTripKey.stop); + StopLocation stop = stopAndTripKey == null ? null : getRoutingService(environment).getStopForId(stopAndTripKey.stop); Trip trip = stopAndTripKey == null ? null : getRoutingService(environment).getTripForId().get(stopAndTripKey.routeOrTrip); return new LegacyGraphQLStopOnTrip(stop, trip); } diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLQueryTypeImpl.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLQueryTypeImpl.java index 65232dd82be..3b587ffe1d1 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLQueryTypeImpl.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLQueryTypeImpl.java @@ -134,7 +134,7 @@ public DataFetcher node() { return null; //TODO case "stopAtDistance": { String[] parts = id.split(";"); - Stop stop = routingService.getStopForId(FeedScopedId.parseId(parts[1])); + var stop = routingService.getStopForId(FeedScopedId.parseId(parts[1])); // TODO: Add geometry return new NearbyStop(stop, Integer.parseInt(parts[0]), null, null, null); @@ -142,7 +142,9 @@ public DataFetcher node() { case "TicketType": return null; //TODO case "Trip": - return routingService.getTripForId().get(FeedScopedId.parseId(id)); + var scopedId = FeedScopedId.parseId(id); + var trip = routingService.getTripForId().get(scopedId); + return trip; case "VehicleParking": var vehicleParkingId = FeedScopedId.parseId(id); return vehicleParkingService == null ? null : vehicleParkingService @@ -196,7 +198,7 @@ public DataFetcher> stops() { .collect(Collectors.toList()); } - Stream stopStream = routingService.getAllStops().stream(); + var stopStream = routingService.getAllStops().stream(); if (args.getLegacyGraphQLName() != null) { String name = args.getLegacyGraphQLName().toLowerCase(environment.getLocale()); diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopGeometriesImpl.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopGeometriesImpl.java new file mode 100644 index 00000000000..4062fb59cc7 --- /dev/null +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopGeometriesImpl.java @@ -0,0 +1,37 @@ +package org.opentripplanner.ext.legacygraphqlapi.datafetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.util.ArrayList; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; +import org.opentripplanner.ext.legacygraphqlapi.generated.LegacyGraphQLDataFetchers.LegacyGraphQLStopGeometries; +import org.opentripplanner.util.PolylineEncoder; +import org.opentripplanner.util.model.EncodedPolylineBean; + +public class LegacyGraphQLStopGeometriesImpl implements LegacyGraphQLStopGeometries { + + @Override + public DataFetcher geoJson() { + return this::getSource; + } + + @Override + public DataFetcher> googleEncoded() { + return env -> { + var geometries = getSource(env); + var polylines = new ArrayList(); + + for(int i = 0; i < geometries.getNumGeometries(); i++) { + var geom = geometries.getGeometryN(i); + var polyline = PolylineEncoder.createEncodings(geom); + polylines.add(polyline); + } + return polylines; + }; + } + + private Geometry getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopImpl.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopImpl.java index cb78bebb9df..1d3047108b8 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopImpl.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStopImpl.java @@ -20,6 +20,7 @@ import org.opentripplanner.model.Route; import org.opentripplanner.model.Station; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTimesInPattern; import org.opentripplanner.model.TripPattern; import org.opentripplanner.model.TripTimeOnDate; @@ -78,37 +79,37 @@ public DataFetcher gtfsId() { @Override public DataFetcher name() { - return environment -> getValue(environment, Stop::getName, Station::getName); + return environment -> getValue(environment, StopLocation::getName, Station::getName); } @Override public DataFetcher lat() { - return environment -> getValue(environment, Stop::getLat, Station::getLat); + return environment -> getValue(environment, StopLocation::getLat, Station::getLat); } @Override public DataFetcher lon() { - return environment -> getValue(environment, Stop::getLon, Station::getLon); + return environment -> getValue(environment, StopLocation::getLon, Station::getLon); } @Override public DataFetcher code() { - return environment -> getValue(environment, Stop::getCode, Station::getCode); + return environment -> getValue(environment, StopLocation::getCode, Station::getCode); } @Override public DataFetcher desc() { - return environment -> getValue(environment, Stop::getDescription, Station::getDescription); + return environment -> getValue(environment, StopLocation::getDescription, Station::getDescription); } @Override public DataFetcher zoneId() { - return environment -> getValue(environment, Stop::getFirstZoneAsString, station -> null); + return environment -> getValue(environment, StopLocation::getFirstZoneAsString, station -> null); } @Override public DataFetcher url() { - return environment -> getValue(environment, Stop::getUrl, Station::getUrl); + return environment -> getValue(environment, StopLocation::getUrl, Station::getUrl); } @Override @@ -118,12 +119,12 @@ public DataFetcher locationType() { @Override public DataFetcher parentStation() { - return environment -> getValue(environment, Stop::getParentStation, station -> null); + return environment -> getValue(environment, StopLocation::getParentStation, station -> null); } @Override public DataFetcher wheelchairBoarding() { - return environment -> getValue(environment, Stop::getWheelchairBoarding, station -> null); + return environment -> getValue(environment, StopLocation::getWheelchairBoarding, station -> null); } // TODO @@ -132,6 +133,11 @@ public DataFetcher direction() { return environment -> null; } + @Override + public DataFetcher geometries() { + return environment -> getValue(environment, StopLocation::getGeometry, Station::getGeometry); + } + @Override public DataFetcher timezone() { return environment -> getValue( @@ -184,7 +190,7 @@ public DataFetcher vehicleMode() { @Override public DataFetcher platformCode() { - return environment -> getValue(environment, Stop::getPlatformCode, station -> null); + return environment -> getValue(environment, StopLocation::getPlatformCode, station -> null); } @Override @@ -264,7 +270,7 @@ public DataFetcher> stoptimesForServiceDate() { // TODO: use args.getLegacyGraphQLOmitCanceled() - Function> stopTFunction = stop -> + Function> stopTFunction = stop -> routingService.getStopTimesForStop( stop, date, @@ -294,7 +300,7 @@ public DataFetcher> stoptimesForPatterns() { // TODO: use args.getLegacyGraphQLOmitCanceled() - Function> stopTFunction = stop -> + Function> stopTFunction = stop -> routingService.stopTimesForStop( stop, args.getLegacyGraphQLStartTime(), @@ -325,7 +331,7 @@ public DataFetcher> stoptimesWithoutPatterns() { // TODO: use args.getLegacyGraphQLOmitCanceled() - Function> stopTFunction = stop -> + Function> stopTFunction = stop -> routingService.stopTimesForStop( stop, args.getLegacyGraphQLStartTime(), @@ -363,12 +369,12 @@ private RoutingService getRoutingService(DataFetchingEnvironment environment) { private T getValue( DataFetchingEnvironment environment, - Function stopTFunction, + Function stopTFunction, Function stationTFunction ) { Object source = environment.getSource(); - if (source instanceof Stop) { - return stopTFunction.apply((Stop) source); + if (source instanceof StopLocation) { + return stopTFunction.apply((StopLocation) source); } else if (source instanceof Station) { return stationTFunction.apply((Station) source); diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStoptimeImpl.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStoptimeImpl.java index 779f10dad92..1632516477c 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStoptimeImpl.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLStoptimeImpl.java @@ -4,6 +4,7 @@ import graphql.schema.DataFetchingEnvironment; import org.opentripplanner.ext.legacygraphqlapi.LegacyGraphQLRequestContext; import org.opentripplanner.ext.legacygraphqlapi.generated.LegacyGraphQLDataFetchers; +import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Trip; import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.routing.RoutingService; @@ -17,27 +18,27 @@ public DataFetcher stop() { @Override public DataFetcher scheduledArrival() { - return environment -> getSource(environment).getScheduledArrival(); + return environment -> missingValueToNull(getSource(environment).getScheduledArrival()); } @Override public DataFetcher realtimeArrival() { - return environment -> getSource(environment).getRealtimeArrival(); + return environment -> missingValueToNull(getSource(environment).getRealtimeArrival()); } @Override public DataFetcher arrivalDelay() { - return environment -> getSource(environment).getArrivalDelay(); + return environment -> missingValueToNull(getSource(environment).getArrivalDelay()); } @Override public DataFetcher scheduledDeparture() { - return environment -> getSource(environment).getScheduledDeparture(); + return environment -> missingValueToNull(getSource(environment).getScheduledDeparture()); } @Override public DataFetcher realtimeDeparture() { - return environment -> getSource(environment).getRealtimeDeparture(); + return environment -> missingValueToNull(getSource(environment).getRealtimeDeparture()); } @Override @@ -108,4 +109,17 @@ private RoutingService getRoutingService(DataFetchingEnvironment environment) { private TripTimeOnDate getSource(DataFetchingEnvironment environment) { return environment.getSource(); } + + /** + * Generally the missing values are removed during the graph build. However, for flex + * trips they are not and have to be converted to null here. + */ + private Integer missingValueToNull(int value) { + if(value == StopTime.MISSING_VALUE) { + return null; + } + else { + return value; + } + } } diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLTripImpl.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLTripImpl.java index 014381ce8c0..e2d073f393f 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLTripImpl.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/datafetchers/LegacyGraphQLTripImpl.java @@ -169,7 +169,6 @@ public DataFetcher departureStoptime() { getSource(environment).getRoute().getAgency().getId() ); - Stop stop = timetable.getPattern().getStop(0); return new TripTimeOnDate(triptimes, 0, tripPattern, serviceDate ); } catch (ParseException e) { @@ -200,7 +199,6 @@ public DataFetcher arrivalStoptime() { getSource(environment).getRoute().getAgency().getId() ); - Stop stop = timetable.getPattern().getStop(triptimes.getNumStops() - 1); return new TripTimeOnDate(triptimes, triptimes.getNumStops() - 1, tripPattern, serviceDate ); } catch (ParseException e) { diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/LegacyGraphQLDataFetchers.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/LegacyGraphQLDataFetchers.java index a7fee03f1e4..4186f14691c 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/LegacyGraphQLDataFetchers.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/LegacyGraphQLDataFetchers.java @@ -694,6 +694,8 @@ public interface LegacyGraphQLStop { public DataFetcher direction(); + public DataFetcher geometries(); + public DataFetcher gtfsId(); public DataFetcher id(); @@ -739,6 +741,13 @@ public interface LegacyGraphQLStop { public DataFetcher zoneId(); } + public interface LegacyGraphQLStopGeometries { + + public DataFetcher geoJson(); + + public DataFetcher> googleEncoded(); + } + /** * Stop that should (but not guaranteed) to exist on a route. */ diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/graphql-codegen.yml b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/graphql-codegen.yml index 0ef2928e854..1e91dfd57f9 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/graphql-codegen.yml +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/generated/graphql-codegen.yml @@ -23,6 +23,7 @@ config: ID: graphql.relay.Relay.ResolvedGlobalId Long: Long Polyline: String + GeoJson: org.locationtech.jts.geom.Geometry mappers: Agency: org.opentripplanner.model.Agency#Agency Alert: org.opentripplanner.routing.alertpatch.TransitAlert#TransitAlert diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnRoute.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnRoute.java index 7230ec5357c..4a937c6e1d5 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnRoute.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnRoute.java @@ -2,6 +2,7 @@ import org.opentripplanner.model.Route; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; /** * Class that contains a {@link Stop} on a {@link Route}. @@ -12,7 +13,7 @@ public class LegacyGraphQLStopOnRoute { * Stop that should be on the route but technically it's possible that it isn't or that it's * null. */ - private final Stop stop; + private final StopLocation stop; /** * Route that should contain the stop but technically it's possible that the stop isn't on the @@ -20,12 +21,12 @@ public class LegacyGraphQLStopOnRoute { */ private final Route route; - public LegacyGraphQLStopOnRoute(Stop stop, Route route) { + public LegacyGraphQLStopOnRoute(StopLocation stop, Route route) { this.stop = stop; this.route = route; } - public Stop getStop() { + public StopLocation getStop() { return stop; } diff --git a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnTrip.java b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnTrip.java index d2afc9ef2e7..29a5ff1a275 100644 --- a/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnTrip.java +++ b/src/ext/java/org/opentripplanner/ext/legacygraphqlapi/model/LegacyGraphQLStopOnTrip.java @@ -1,5 +1,6 @@ package org.opentripplanner.ext.legacygraphqlapi.model; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.Trip; import org.opentripplanner.model.Stop; @@ -12,7 +13,7 @@ public class LegacyGraphQLStopOnTrip { * Stop that should be on the trip but technically it's possible that it isn't or that it's * null. */ - private final Stop stop; + private final StopLocation stop; /** * Trip that should contain the stop but technically it's possible that the stop isn't on the @@ -20,12 +21,12 @@ public class LegacyGraphQLStopOnTrip { */ private final Trip trip; - public LegacyGraphQLStopOnTrip(Stop stop, Trip trip) { + public LegacyGraphQLStopOnTrip(StopLocation stop, Trip trip) { this.stop = stop; this.trip = trip; } - public Stop getStop() { + public StopLocation getStop() { return stop; } diff --git a/src/ext/java/org/opentripplanner/ext/reportapi/model/TransfersReport.java b/src/ext/java/org/opentripplanner/ext/reportapi/model/TransfersReport.java index 6a6652dad56..9dabe644984 100644 --- a/src/ext/java/org/opentripplanner/ext/reportapi/model/TransfersReport.java +++ b/src/ext/java/org/opentripplanner/ext/reportapi/model/TransfersReport.java @@ -103,7 +103,7 @@ private TxPoint pointInfo( if (ptn.getStops().size() > p.getStopPosition()) { int pos = p.getStopPosition(); - Stop stop = ptn.getStops().get(pos); + var stop = ptn.getStops().get(pos); var tt = ptn.getScheduledTimetable().getTripTimes(trip); r.loc += stop.getName() + " [" + pos + "]" + " " + stop.getCoordinate(); r.time = arrival ? tt.getScheduledArrivalTime(pos) : tt.getScheduledDepartureTime(pos); diff --git a/src/ext/java/org/opentripplanner/ext/siri/SiriFuzzyTripMatcher.java b/src/ext/java/org/opentripplanner/ext/siri/SiriFuzzyTripMatcher.java index 89254b77df3..bd7e7d400c5 100644 --- a/src/ext/java/org/opentripplanner/ext/siri/SiriFuzzyTripMatcher.java +++ b/src/ext/java/org/opentripplanner/ext/siri/SiriFuzzyTripMatcher.java @@ -174,11 +174,11 @@ private Set getMatchingTripsOnStopOrSiblings(String lastStopPoint, ZonedDa if (trips == null || trips.isEmpty()) { //SIRI-data may report other platform, but still on the same Parent-stop String feedId = routingService.getFeedIds().iterator().next(); - Stop stop = routingService.getStopForId(new FeedScopedId(feedId, lastStopPoint)); + var stop = routingService.getStopForId(new FeedScopedId(feedId, lastStopPoint)); if (stop != null && stop.isPartOfStation()) { // TODO OTP2 resolve stop-station split - Collection allQuays = stop.getParentStation().getChildStops(); - for (Stop quay : allQuays) { + var allQuays = stop.getParentStation().getChildStops(); + for (var quay : allQuays) { Set tripSet = start_stop_tripCache.get(createStartStopKey(quay.getId().getId(), secondsSinceMidnight)); if (tripSet != null) { if (trips == null) { @@ -292,7 +292,7 @@ private static String getUnpaddedTripId(String id) { } public Set getRoutesForStop(FeedScopedId siriStopId) { - Stop stop = routingService.getStopForId(siriStopId); + var stop = routingService.getStopForId(siriStopId); return routingService.getRoutesForStop(stop); } @@ -306,7 +306,7 @@ public FeedScopedId getStop(String siriStopId) { //First, assume same agency - Stop firstStop = routingService.getAllStops().stream().findFirst().get(); + var firstStop = routingService.getAllStops().stream().findFirst().get(); FeedScopedId id = new FeedScopedId(firstStop.getId().getFeedId(), siriStopId); if (routingService.getStopForId(id) != null) { return id; @@ -316,8 +316,8 @@ else if (routingService.getStationById(id) != null) { } //Not same agency - loop through all stops/Stations - Collection stops = routingService.getAllStops(); - for (Stop stop : stops) { + var stops = routingService.getAllStops(); + for (var stop : stops) { if (stop.getId().getId().equals(siriStopId)) { return stop.getId(); } diff --git a/src/ext/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSource.java b/src/ext/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSource.java index 3da2b6b2ac8..a2656bbc390 100644 --- a/src/ext/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSource.java +++ b/src/ext/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSource.java @@ -6,6 +6,7 @@ import org.opentripplanner.model.Operator; import org.opentripplanner.model.Route; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopPattern; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Timetable; @@ -529,7 +530,7 @@ private boolean handleAddedTrip(Graph graph, String feedId, EstimatedVehicleJou trip.setTripShortName(null); // trip.setKeyValues(null); - List addedStops = new ArrayList<>(); + List addedStops = new ArrayList<>(); List aimedStopTimes = new ArrayList<>(); // TODO - SIRI: Handle RecordedCalls. Finding departureTime++ from first stop will fail when @@ -541,7 +542,7 @@ private boolean handleAddedTrip(Graph graph, String feedId, EstimatedVehicleJou for (int i = 0; i < estimatedCalls.size(); i++) { EstimatedCall estimatedCall = estimatedCalls.get(i); - Stop stop = getStopForStopId(feedId,estimatedCall.getStopPointRef().getValue()); + var stop = getStopForStopId(feedId,estimatedCall.getStopPointRef().getValue()); StopTime stopTime = new StopTime(); stopTime.setStop(stop); @@ -792,7 +793,7 @@ private boolean handleModifiedTrip(Graph graph, String feedId, EstimatedVehicleJ // Calculate modified stop-pattern Timetable currentTimetable = getCurrentTimetable(pattern, serviceDate); - List modifiedStops = createModifiedStops(currentTimetable, estimatedVehicleJourney, + var modifiedStops = createModifiedStops(currentTimetable, estimatedVehicleJourney, routingService ); List modifiedStopTimes = createModifiedStopTimes(currentTimetable, tripTimes, estimatedVehicleJourney, trip, @@ -851,7 +852,7 @@ private int calculateSecondsSinceMidnight(ZonedDateTime startOfService, ZonedDat * @return true if successful */ private boolean addTripToGraphAndBuffer(final String feedId, final Graph graph, final Trip trip, - final List stopTimes, final List stops, TripTimes updatedTripTimes, + final List stopTimes, final List stops, TripTimes updatedTripTimes, final ServiceDate serviceDate) { // Preconditions @@ -1007,8 +1008,8 @@ private Set getPatternsForTrip(Set matches, VehicleActivitySt continue; } - Stop firstStop = tripPattern.getStop(0); - Stop lastStop = tripPattern.getStop(tripPattern.getStops().size() - 1); + var firstStop = tripPattern.getStop(0); + var lastStop = tripPattern.getStop(tripPattern.getStops().size() - 1); String siriOriginRef = monitoredVehicleJourney.getOriginRef().getValue(); @@ -1019,14 +1020,14 @@ private Set getPatternsForTrip(Set matches, VehicleActivitySt boolean lastStopIsMatch = lastStop.getId().getId().equals(siriDestinationRef); if (!firstStopIsMatch && firstStop.isPartOfStation()) { - Stop otherFirstStop = routingService.getStopForId(new FeedScopedId(firstStop + var otherFirstStop = routingService.getStopForId(new FeedScopedId(firstStop .getId() .getFeedId(), siriOriginRef)); firstStopIsMatch = firstStop.isPartOfSameStationAs(otherFirstStop); } if (!lastStopIsMatch && lastStop.isPartOfStation()) { - Stop otherLastStop = routingService.getStopForId(new FeedScopedId(lastStop + var otherLastStop = routingService.getStopForId(new FeedScopedId(lastStop .getId() .getFeedId(), siriDestinationRef)); lastStopIsMatch = lastStop.isPartOfSameStationAs(otherLastStop); @@ -1123,15 +1124,15 @@ private TripPattern getPatternForTrip(Trip trip, EstimatedVehicleJourney journey } - Stop firstStop = tripPattern.getStop(0); - Stop lastStop = tripPattern.getStop(tripPattern.getStops().size() - 1); + var firstStop = tripPattern.getStop(0); + var lastStop = tripPattern.getStop(tripPattern.getStops().size() - 1); if (serviceDates.contains(journeyDate)) { boolean firstStopIsMatch = firstStop.getId().getId().equals(journeyFirstStopId); boolean lastStopIsMatch = lastStop.getId().getId().equals(journeyLastStopId); if (!firstStopIsMatch && firstStop.isPartOfStation()) { - Stop otherFirstStop = routingService + var otherFirstStop = routingService .getStopForId( new FeedScopedId(firstStop.getId().getFeedId(), journeyFirstStopId) ); @@ -1139,7 +1140,7 @@ private TripPattern getPatternForTrip(Trip trip, EstimatedVehicleJourney journey } if (!lastStopIsMatch && lastStop.isPartOfStation()) { - Stop otherLastStop = routingService + var otherLastStop = routingService .getStopForId( new FeedScopedId(lastStop.getId().getFeedId(), journeyLastStopId) ); @@ -1251,14 +1252,14 @@ private Set getTripForJourney(Set trips, EstimatedVehicleJourney jou if (stopNumber < pattern.getStopPattern().getStops().length) { boolean firstReportedStopIsFound = false; - Stop stop = pattern.getStopPattern().getStops()[stopNumber - 1]; + var stop = pattern.getStopPattern().getStops()[stopNumber - 1]; if (firstStopId.equals(stop.getId().getId())) { firstReportedStopIsFound = true; } else { String agencyId = stop.getId().getFeedId(); if (stop.isPartOfStation()) { - Stop alternativeStop = routingService.getStopForId( + var alternativeStop = routingService.getStopForId( new FeedScopedId(agencyId, firstStopId) ); if (alternativeStop != null && stop.isPartOfSameStationAs(alternativeStop)) { @@ -1320,7 +1321,7 @@ private Trip getTripForTripId(String feedId, String tripId) { * @param stopId trip id without the agency * @return stop or null if stop doesn't exist */ - private Stop getStopForStopId(String feedId, String stopId) { + private StopLocation getStopForStopId(String feedId, String stopId) { return routingService.getStopForId(new FeedScopedId(feedId, stopId)); } } diff --git a/src/ext/java/org/opentripplanner/ext/siri/SiriTripPatternCache.java b/src/ext/java/org/opentripplanner/ext/siri/SiriTripPatternCache.java index 86eb9992bbc..3fab23b0578 100644 --- a/src/ext/java/org/opentripplanner/ext/siri/SiriTripPatternCache.java +++ b/src/ext/java/org/opentripplanner/ext/siri/SiriTripPatternCache.java @@ -4,6 +4,7 @@ import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimaps; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopPattern; import org.opentripplanner.model.Trip; import org.opentripplanner.model.TripPattern; @@ -27,7 +28,7 @@ public class SiriTripPatternCache { private final Map cache = new HashMap<>(); - private final ListMultimap patternsForStop = Multimaps.synchronizedListMultimap(ArrayListMultimap.create()); + private final ListMultimap patternsForStop = Multimaps.synchronizedListMultimap(ArrayListMultimap.create()); private final Map updatedTripPatternsForTripCache = new HashMap<>(); @@ -145,7 +146,7 @@ public synchronized TripPattern getOrCreateTripPattern( } // To make these trip patterns visible for departureRow searches. - for (Stop stop: tripPattern.getStops()) { + for (var stop: tripPattern.getStops()) { if (!patternsForStop.containsEntry(stop, tripPattern)) { patternsForStop.put(stop, tripPattern); } diff --git a/src/ext/java/org/opentripplanner/ext/siri/TimetableHelper.java b/src/ext/java/org/opentripplanner/ext/siri/TimetableHelper.java index 904925768de..ab72dd0be9a 100644 --- a/src/ext/java/org/opentripplanner/ext/siri/TimetableHelper.java +++ b/src/ext/java/org/opentripplanner/ext/siri/TimetableHelper.java @@ -2,6 +2,7 @@ import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Timetable; import org.opentripplanner.model.TimetableSnapshot; @@ -94,7 +95,7 @@ public static TripTimes createUpdatedTripTimes(final Graph graph, Timetable time boolean stopPatternChanged = false; - Stop[] modifiedStops = timetable.getPattern().getStopPattern().getStops(); + var modifiedStops = timetable.getPattern().getStopPattern().getStops(); Trip trip = getTrip(tripId, timetable); @@ -118,7 +119,7 @@ public static TripTimes createUpdatedTripTimes(final Graph graph, Timetable time int departureFromPreviousStop = 0; int lastArrivalDelay = 0; int lastDepartureDelay = 0; - for (Stop stop : modifiedStops) { + for (var stop : modifiedStops) { boolean foundMatch = false; for (RecordedCall recordedCall : recordedCalls) { @@ -129,7 +130,7 @@ public static TripTimes createUpdatedTripTimes(final Graph graph, Timetable time foundMatch = stop.getId().getId().equals(recordedCall.getStopPointRef().getValue()); if (!foundMatch && stop.isPartOfStation()) { - Stop alternativeStop = graph.index.getStopForId( + var alternativeStop = graph.index.getStopForId( new FeedScopedId(stop.getId().getFeedId(), recordedCall.getStopPointRef().getValue()) ); if (alternativeStop != null && stop.isPartOfSameStationAs(alternativeStop)) { @@ -206,7 +207,7 @@ public static TripTimes createUpdatedTripTimes(final Graph graph, Timetable time foundMatch = stop.getId().getId().equals(estimatedCall.getStopPointRef().getValue()); if (!foundMatch && stop.isPartOfStation()) { - Stop alternativeStop = graph.index + var alternativeStop = graph.index .getStopForId( new FeedScopedId(stop.getId().getFeedId(), estimatedCall.getStopPointRef().getValue()) ); @@ -348,7 +349,7 @@ public static TripTimes createUpdatedTripTimes(final Graph graph, Timetable time * with the id specified in the trip descriptor of the TripUpdate; null if something * went wrong */ - public static List createModifiedStops(Timetable timetable, EstimatedVehicleJourney journey, RoutingService routingService) { + public static List createModifiedStops(Timetable timetable, EstimatedVehicleJourney journey, RoutingService routingService) { if (journey == null) { return null; } @@ -371,15 +372,15 @@ public static List createModifiedStops(Timetable timetable, EstimatedVehic } //Get all scheduled stops - Stop[] stops = timetable.getPattern().getStopPattern().getStops(); + var stops = timetable.getPattern().getStopPattern().getStops(); // Keeping track of visited stop-objects to allow multiple visits to a stop. List alreadyVisited = new ArrayList<>(); - List modifiedStops = new ArrayList<>(); + List modifiedStops = new ArrayList<>(); for (int i = 0; i < stops.length; i++) { - Stop stop = stops[i]; + StopLocation stop = stops[i]; boolean foundMatch = false; if (i < recordedCalls.size()) { @@ -392,7 +393,7 @@ public static List createModifiedStops(Timetable timetable, EstimatedVehic boolean stopsMatchById = stop.getId().getId().equals(recordedCall.getStopPointRef().getValue()); if (!stopsMatchById && stop.isPartOfStation()) { - Stop alternativeStop = routingService + var alternativeStop = routingService .getStopForId(new FeedScopedId(stop.getId().getFeedId(), recordedCall.getStopPointRef().getValue())); if (alternativeStop != null && stop.isPartOfSameStationAs(alternativeStop)) { stopsMatchById = true; @@ -417,7 +418,7 @@ public static List createModifiedStops(Timetable timetable, EstimatedVehic boolean stopsMatchById = stop.getId().getId().equals(estimatedCall.getStopPointRef().getValue()); if (!stopsMatchById && stop.isPartOfStation()) { - Stop alternativeStop = routingService + var alternativeStop = routingService .getStopForId(new FeedScopedId(stop.getId().getFeedId(), estimatedCall.getStopPointRef().getValue())); if (alternativeStop != null && stop.isPartOfSameStationAs(alternativeStop)) { stopsMatchById = true; @@ -465,7 +466,7 @@ public static List createModifiedStopTimes(Timetable timetable, TripTi estimatedCalls = EMPTY_LIST; } - List stops = createModifiedStops(timetable, journey, routingService); + var stops = createModifiedStops(timetable, journey, routingService); List modifiedStops = new ArrayList<>(); @@ -474,7 +475,7 @@ public static List createModifiedStopTimes(Timetable timetable, TripTi Set alreadyVisited = new HashSet<>(); // modify updated stop-times for (int i = 0; i < stops.size(); i++) { - Stop stop = stops.get(i); + StopLocation stop = stops.get(i); final StopTime stopTime = new StopTime(); stopTime.setStop(stop); @@ -503,7 +504,7 @@ public static List createModifiedStopTimes(Timetable timetable, TripTi boolean stopsMatchById = stop.getId().getId().equals(estimatedCall.getStopPointRef().getValue()); if (!stopsMatchById && stop.isPartOfStation()) { - Stop alternativeStop = routingService + var alternativeStop = routingService .getStopForId(new FeedScopedId(stop.getId().getFeedId(), estimatedCall.getStopPointRef().getValue())); if (alternativeStop != null && stop.isPartOfSameStationAs(alternativeStop)) { stopsMatchById = true; @@ -596,7 +597,7 @@ public static TripTimes createUpdatedTripTimes(Timetable timetable, Graph graph, if (update == null) { return null; } - final List stops = timetable.getPattern().getStops(); + final List stops = timetable.getPattern().getStops(); VehicleActivityStructure.MonitoredVehicleJourney monitoredVehicleJourney = activity.getMonitoredVehicleJourney(); @@ -618,13 +619,13 @@ public static TripTimes createUpdatedTripTimes(Timetable timetable, Graph graph, for (int index = 0; index < newTimes.getNumStops(); ++index) { if (!matchFound) { // Delay is set on a single stop at a time. When match is found - propagate delay on all following stops - final Stop stop = stops.get(index); + final var stop = stops.get(index); matchFound = stop.getId().getId().equals(monitoredCall.getStopPointRef().getValue()); if (!matchFound && stop.isPartOfStation()) { FeedScopedId alternativeId = new FeedScopedId(stop.getId().getFeedId(), monitoredCall.getStopPointRef().getValue()); - Stop alternativeStop = graph.index.getStopForId(alternativeId); + var alternativeStop = graph.index.getStopForId(alternativeId); if (alternativeStop != null && alternativeStop.isPartOfStation()) { matchFound = stop.isPartOfSameStationAs(alternativeStop); } diff --git a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/TripTimeShortHelper.java b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/TripTimeShortHelper.java index dffbbd97be0..0eb12f5f453 100644 --- a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/TripTimeShortHelper.java +++ b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/TripTimeShortHelper.java @@ -135,9 +135,9 @@ private static boolean matchesQuayOrSiblingQuay(StopLocation stop, FeedScopedId if (stop == null) return false; boolean foundMatch = stop.getId().equals(candidate); if (!foundMatch && stop instanceof Stop) { - if (((Stop) stop).isPartOfStation()) { - Station parentStation = ((Stop) stop).getParentStation(); - for (Stop childStop : parentStation.getChildStops()) { + if (stop.isPartOfStation()) { + Station parentStation = stop.getParentStation(); + for (var childStop : parentStation.getChildStops()) { if (childStop.getId().equals(candidate)) { return true; } diff --git a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/network/LineType.java b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/network/LineType.java index 48121254beb..4d08c129433 100644 --- a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/network/LineType.java +++ b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/network/LineType.java @@ -8,6 +8,7 @@ import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLOutputType; import graphql.schema.GraphQLTypeReference; +import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.ext.transmodelapi.mapping.TransitIdMapper; import org.opentripplanner.ext.transmodelapi.model.EnumTypes; import org.opentripplanner.ext.transmodelapi.model.TransmodelTransportSubmode; @@ -136,6 +137,7 @@ public static GraphQLObjectType create( result.addAll(GqlUtil.getRoutingService(environment).getFlexIndex().tripById .values() .stream() + .map(FlexTrip::getTrip) .filter(t -> t.getRoute().equals((Route) environment.getSource())) .collect(Collectors.toList())); } diff --git a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/siri/et/EstimatedCallType.java b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/siri/et/EstimatedCallType.java index 0da56b0f793..05376942356 100644 --- a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/siri/et/EstimatedCallType.java +++ b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/siri/et/EstimatedCallType.java @@ -254,7 +254,7 @@ private static Collection getAllRelevantAlerts( FeedScopedId stopId = tripTimeOnDate.getStopId(); - Stop stop = routingService.getStopForId(stopId); + var stop = routingService.getStopForId(stopId); FeedScopedId parentStopId = stop.getParentStation().getId(); Collection allAlerts = new HashSet<>(); diff --git a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/MonoOrMultiModalStation.java b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/MonoOrMultiModalStation.java index ecbfe4c078c..2fae7cb9fc0 100644 --- a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/MonoOrMultiModalStation.java +++ b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/MonoOrMultiModalStation.java @@ -30,7 +30,7 @@ public class MonoOrMultiModalStation extends TransitEntity { private final TimeZone timezone; - private final Collection childStops; + private final Collection childStops; private final MonoOrMultiModalStation parentStation; @@ -92,7 +92,7 @@ public TimeZone getTimezone() { return timezone; } - public Collection getChildStops() { + public Collection getChildStops() { return childStops; } diff --git a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/QuayType.java b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/QuayType.java index c5c85a94562..71b63e399f3 100644 --- a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/QuayType.java +++ b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/QuayType.java @@ -18,6 +18,7 @@ import org.opentripplanner.ext.transmodelapi.support.GqlUtil; import org.opentripplanner.model.Station; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.TransitMode; import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.routing.stoptimes.ArrivalDeparture; @@ -49,17 +50,17 @@ public static GraphQLObjectType create( .field(GraphQLFieldDefinition.newFieldDefinition() .name("latitude") .type(Scalars.GraphQLFloat) - .dataFetcher(environment -> (((Stop) environment.getSource()).getLat())) + .dataFetcher(environment -> (((StopLocation) environment.getSource()).getLat())) .build()) .field(GraphQLFieldDefinition.newFieldDefinition() .name("longitude") .type(Scalars.GraphQLFloat) - .dataFetcher(environment -> (((Stop) environment.getSource()).getLon())) + .dataFetcher(environment -> (((StopLocation) environment.getSource()).getLon())) .build()) .field(GraphQLFieldDefinition.newFieldDefinition() .name("description") .type(Scalars.GraphQLString) - .dataFetcher(environment -> (((Stop) environment.getSource()).getDescription())) + .dataFetcher(environment -> (((StopLocation) environment.getSource()).getDescription())) .build()) .field(GraphQLFieldDefinition.newFieldDefinition() .name("stopPlace") @@ -67,7 +68,7 @@ public static GraphQLObjectType create( .type(stopPlaceType) .dataFetcher(environment -> { - Station station = ((Stop) environment.getSource()).getParentStation(); + Station station = ((StopLocation) environment.getSource()).getParentStation(); if (station != null) { return new MonoOrMultiModalStation( station, @@ -84,13 +85,13 @@ public static GraphQLObjectType create( .name("wheelchairAccessible") .type(EnumTypes.WHEELCHAIR_BOARDING) .description("Whether this quay is suitable for wheelchair boarding.") - .dataFetcher(environment -> (((Stop) environment.getSource()).getWheelchairBoarding())) + .dataFetcher(environment -> (((StopLocation) environment.getSource()).getWheelchairBoarding())) .build()) .field(GraphQLFieldDefinition.newFieldDefinition() .name("publicCode") .type(Scalars.GraphQLString) .description("Public code used to identify this quay within the stop place. For instance a platform code.") - .dataFetcher(environment -> (((Stop) environment.getSource()).getCode())) + .dataFetcher(environment -> (((StopLocation) environment.getSource()).getCode())) .build()) .field(GraphQLFieldDefinition.newFieldDefinition() .name("lines") @@ -218,18 +219,18 @@ public static GraphQLObjectType create( .type(new GraphQLNonNull(new GraphQLList(ptSituationElementType))) .dataFetcher(env -> { return GqlUtil.getRoutingService(env).getTransitAlertService() - .getStopAlerts(((Stop)env.getSource()).getId()); + .getStopAlerts(((StopLocation)env.getSource()).getId()); }) .build()) // .field(GraphQLFieldDefinition.newFieldDefinition() // .name("stopType") // .type(stopTypeEnum) -// .dataFetcher(environment -> (((Stop) environment.getSource()).getStopType())) +// .dataFetcher(environment -> (((StopLocation) environment.getSource()).getStopType())) // .build()) .field(GraphQLFieldDefinition.newFieldDefinition() .name("tariffZones") .type(new GraphQLNonNull(new GraphQLList(tariffZoneType))) - .dataFetcher(environment -> ((Stop) environment.getSource()).getFareZones()) + .dataFetcher(environment -> ((StopLocation) environment.getSource()).getFareZones()) .build()) .build(); } diff --git a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/StopPlaceType.java b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/StopPlaceType.java index 81528367e87..913f5cd6555 100644 --- a/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/StopPlaceType.java +++ b/src/ext/java/org/opentripplanner/ext/transmodelapi/model/stop/StopPlaceType.java @@ -19,6 +19,7 @@ import org.opentripplanner.model.Station; import org.opentripplanner.model.Stop; import org.opentripplanner.model.StopCollection; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTimesInPattern; import org.opentripplanner.model.TransitMode; import org.opentripplanner.model.Trip; @@ -91,7 +92,7 @@ public static GraphQLObjectType create( .type(new GraphQLList(TRANSPORT_MODE)) .dataFetcher(environment -> ((MonoOrMultiModalStation) environment.getSource()).getChildStops() - .stream().map(Stop::getVehicleType).collect(Collectors.toSet()) + .stream().map(StopLocation::getVehicleType).collect(Collectors.toSet()) ) .build()) .field(GraphQLFieldDefinition.newFieldDefinition() @@ -121,7 +122,7 @@ public static GraphQLObjectType create( .defaultValue(Boolean.FALSE) .build()) .dataFetcher(environment -> { - Collection quays = ((MonoOrMultiModalStation) environment.getSource()).getChildStops(); + var quays = ((MonoOrMultiModalStation) environment.getSource()).getChildStops(); if (TRUE.equals(environment.getArgument("filterByInUse"))) { quays=quays.stream().filter(stop -> { return !GqlUtil.getRoutingService(environment) @@ -242,7 +243,7 @@ public static GraphQLObjectType create( } public static Stream getTripTimesForStop( - Stop stop, + StopLocation stop, Long startTimeSeconds, int timeRage, ArrivalDeparture arrivalDeparture, @@ -340,7 +341,7 @@ public static Collection fetchStopPlaces( Stream stations = routingService .getStopsByBoundingBox(minLat, minLon, maxLat, maxLon) .stream() - .map(Stop::getParentStation) + .map(StopLocation::getParentStation) .filter(Objects::nonNull) .distinct(); @@ -393,7 +394,7 @@ else if("parent".equals(multiModalMode)){ } public static boolean isStopPlaceInUse(StopCollection station, RoutingService routingService) { - for (Stop quay : station.getChildStops()) { + for (var quay : station.getChildStops()) { if (!routingService.getPatternsForStop(quay, true).isEmpty()) { return true; } 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 4972ca7fbdd..8988f204776 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 @@ -7,6 +7,7 @@ import org.opentripplanner.model.Station; import org.opentripplanner.model.StationElement; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.routing.graph.Graph; import java.util.Collection; @@ -25,7 +26,7 @@ public static DigitransitStationPropertyMapper create(Graph graph) { @Override public Collection> map(Station station) { - Collection childStops = station.getChildStops(); + var childStops = station.getChildStops(); return List.of( new T2<>("gtfsId", station.getId().toString()), @@ -38,7 +39,7 @@ public Collection> map(Station station) { .collect(Collectors.joining(","))), new T2<>("stops", JSONArray.toJSONString(childStops .stream() - .map(StationElement::getId) + .map(StopLocation::getId) .map(FeedScopedId::toString) .collect(Collectors.toUnmodifiableList()))), new T2<>("routes", JSONArray.toJSONString(childStops diff --git a/src/ext/resources/legacygraphqlapi/schema.graphqls b/src/ext/resources/legacygraphqlapi/schema.graphqls index a79fe5667e6..79edec69d15 100644 --- a/src/ext/resources/legacygraphqlapi/schema.graphqls +++ b/src/ext/resources/legacygraphqlapi/schema.graphqls @@ -837,6 +837,22 @@ type Geometry { points: Polyline } +scalar GeoJson + +type StopGeometries { + """Representation of the stop geometries as GeoJSON (https://geojson.org/)""" + geoJson: GeoJson, + + """ + Representation of a stop as a series of polylines. + + Polygons of flex stops are represented as linear rings (lines where the first and last point are the same). + + Proper stops are represented as single point "lines". + """ + googleEncoded: [Geometry] +} + input InputBanned { """A comma-separated list of banned route ids""" routes: String @@ -2476,6 +2492,21 @@ type Stop implements Node & PlaceInterface { """Longitude of the stop (WGS 84)""" lon: Float + """ + Representations of this stop's geometry. This is mainly interesting for flex stops which can be + a polygon or a group of stops either consisting of either points or polygons. + + Regular fixed-schedule stops return a single point. + + Stations (parent stations with child stops) contain a geometry collection with a point for the + central coordinate plus a convex hull polygon (https://en.wikipedia.org/wiki/Convex_hull) of all + coordinates of the child stops. + + If there are only two child stops then the convex hull is a straight line between the them. If + there is a single child stop then it's a single point. + """ + geometries: StopGeometries + """Stop code which is visible at the stop""" code: String diff --git a/src/main/java/org/opentripplanner/api/mapping/StopMapper.java b/src/main/java/org/opentripplanner/api/mapping/StopMapper.java index 20fd4ffd769..47989b9653c 100644 --- a/src/main/java/org/opentripplanner/api/mapping/StopMapper.java +++ b/src/main/java/org/opentripplanner/api/mapping/StopMapper.java @@ -1,26 +1,25 @@ package org.opentripplanner.api.mapping; -import org.opentripplanner.api.model.ApiStop; -import org.opentripplanner.api.model.ApiStopShort; -import org.opentripplanner.model.StationElement; -import org.opentripplanner.model.Stop; - 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.model.Stop; +import org.opentripplanner.model.StopLocation; public class StopMapper { - public static List mapToApi(Collection domain) { + public static List mapToApi(Collection domain) { if(domain == null) { return null; } return domain.stream().map(StopMapper::mapToApi).collect(Collectors.toList()); } - public static ApiStop mapToApi(Stop domain) { + public static ApiStop mapToApi(StopLocation domain) { return mapToApi(domain, true); } - public static ApiStop mapToApi(Stop domain, boolean extended) { + public static ApiStop mapToApi(StopLocation domain, boolean extended) { if(domain == null) { return null; } ApiStop api = new ApiStop(); @@ -45,7 +44,7 @@ public static ApiStop mapToApi(Stop domain, boolean extended) { return api; } - public static ApiStopShort mapToApiShort(Stop domain) { + public static ApiStopShort mapToApiShort(StopLocation domain) { if(domain == null) { return null; } ApiStopShort api = new ApiStopShort(); @@ -73,7 +72,7 @@ public static ApiStopShort mapToApiShort(Stop domain, int distance) { return api; } - public static List mapToApiShort(Collection domain) { + public static List mapToApiShort(Collection domain) { if(domain == null) { return null; } return domain.stream().map(StopMapper::mapToApiShort).collect(Collectors.toList()); } @@ -82,7 +81,7 @@ public static List mapToApiShort(Collection domain) { * Get the parent station id (without feed-scope) for the given station element, * this method should only be used to fetch old ids for beeing backward compatible. */ - private static String mapToParentStationOldId(StationElement stop) { + private static String mapToParentStationOldId(StopLocation stop) { return stop.isPartOfStation() ? stop.getParentStation().getId().getId() : null; } } diff --git a/src/main/java/org/opentripplanner/common/geometry/GeometryUtils.java b/src/main/java/org/opentripplanner/common/geometry/GeometryUtils.java index bfbabf5aeb5..9a10da84b8b 100644 --- a/src/main/java/org/opentripplanner/common/geometry/GeometryUtils.java +++ b/src/main/java/org/opentripplanner/common/geometry/GeometryUtils.java @@ -1,5 +1,7 @@ package org.opentripplanner.common.geometry; +import java.util.Arrays; +import java.util.List; import org.geojson.GeoJsonObject; import org.geojson.LngLatAlt; import org.geotools.referencing.CRS; @@ -7,21 +9,21 @@ import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.CoordinateSequenceFactory; import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.LinearRing; +import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.linearref.LengthLocationMap; import org.locationtech.jts.linearref.LinearLocation; import org.locationtech.jts.linearref.LocationIndexedLine; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opentripplanner.common.model.P2; +import org.opentripplanner.model.WgsCoordinate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; -import java.util.List; - public class GeometryUtils { private static final Logger LOG = LoggerFactory.getLogger(GeometryUtils.class); @@ -223,4 +225,5 @@ private static Coordinate[] convertPath(List path) { } return coords; } + } diff --git a/src/main/java/org/opentripplanner/graph_builder/issues/EntranceUnlinked.java b/src/main/java/org/opentripplanner/graph_builder/issues/EntranceUnlinked.java deleted file mode 100644 index c2a582e5fa1..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/issues/EntranceUnlinked.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.opentripplanner.graph_builder.issues; - -import org.opentripplanner.graph_builder.DataImportIssue; -import org.opentripplanner.routing.graph.Vertex; -import org.opentripplanner.routing.vertextype.TransitEntranceVertex; - -public class EntranceUnlinked implements DataImportIssue { - - public static final String FMT = "Entrance %s not near any streets; it will not be usable."; - public static final String HTMLFMT = "Entrance \"%s\" (%s) not near any streets; it will not be usable."; - - final TransitEntranceVertex entrance; - - public EntranceUnlinked(TransitEntranceVertex entrance) { - this.entrance = entrance; - } - - @Override - public String getMessage() { - return String.format(FMT, entrance); - } - - @Override - public String getHTMLMessage() { - return String.format( - HTMLFMT, - entrance.getEntrance().getLat(), - entrance.getEntrance().getLon(), - entrance.getName(), - entrance.getEntrance().getId() - ); - } - - @Override - public Vertex getReferencedVertex() { - return this.entrance; - } - -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/AddTransitModelEntitiesToGraph.java b/src/main/java/org/opentripplanner/graph_builder/module/AddTransitModelEntitiesToGraph.java index 82b2ca2abbe..12d02a6a3fd 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/AddTransitModelEntitiesToGraph.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/AddTransitModelEntitiesToGraph.java @@ -20,6 +20,7 @@ import org.opentripplanner.model.Station; import org.opentripplanner.model.StationElement; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.TransitMode; import org.opentripplanner.model.TripPattern; import org.opentripplanner.routing.edgetype.ElevatorAlightEdge; @@ -105,12 +106,12 @@ private void applyToGraph(Graph graph) { private void addStopsToGraphAndGenerateStopVertexes(Graph graph) { // Compute the set of modes for each stop based on all the TripPatterns it is part of - Map> stopModeMap = new HashMap<>(); + Map> stopModeMap = new HashMap<>(); for (TripPattern pattern : transitService.getTripPatterns()) { TransitMode mode = pattern.getMode(); graph.addTransitMode(mode); - for (Stop stop : pattern.getStops()) { + for (var stop : pattern.getStops()) { Set set = stopModeMap.computeIfAbsent(stop, s -> new HashSet<>()); set.add(mode); } diff --git a/src/main/java/org/opentripplanner/graph_builder/module/GtfsModule.java b/src/main/java/org/opentripplanner/graph_builder/module/GtfsModule.java index 98168692e5b..2b79ae3c5d0 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/GtfsModule.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/GtfsModule.java @@ -123,7 +123,9 @@ public void buildGraph( calendarServiceData.add(builder.buildCalendarServiceData()); if (OTPFeature.FlexRouting.isOn()) { - builder.getFlexTripsById().addAll(FlexTripsMapper.createFlexTrips(builder)); + builder.getFlexTripsById().addAll( + FlexTripsMapper.createFlexTrips(builder, issueStore) + ); } repairStopTimesForEachTrip(builder.getStopTimesSortedByTrip()); diff --git a/src/main/java/org/opentripplanner/graph_builder/module/StopsAlerts.java b/src/main/java/org/opentripplanner/graph_builder/module/StopsAlerts.java deleted file mode 100644 index ea465fa59c5..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/StopsAlerts.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.opentripplanner.graph_builder.module; - -import com.google.common.collect.Iterables; -import org.opentripplanner.graph_builder.DataImportIssueStore; -import org.opentripplanner.graph_builder.module.stopsAlerts.IStopTester; -import org.opentripplanner.graph_builder.services.GraphBuilderModule; -import org.opentripplanner.routing.graph.Graph; -import org.opentripplanner.routing.vertextype.TransitStopVertex; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * It prints the stops that satisfy certain criteria. - * The output is a list of stops, some of the stops attributes (coordinates and etc.) and the criteria it satisfies. - */ - -public class StopsAlerts implements GraphBuilderModule { - - private static org.slf4j.Logger LOG = LoggerFactory.getLogger(StopsAlerts.class); - - List stopTesters = new ArrayList(); - - String logFile = ""; - - @Override - public void buildGraph( - Graph graph, - HashMap, Object> extra, - DataImportIssueStore issueStore - ) { - try { - PrintWriter pw = new PrintWriter(new File(logFile)); - pw.printf("%s,%s,%s,%s\n","stopId","lon","lat","types"); - for (TransitStopVertex ts : graph.getVerticesOfType(TransitStopVertex.class)) { - StringBuilder types = new StringBuilder(); - for(IStopTester stopTester:stopTesters){ - if(stopTester.fulfillDemands(ts,graph)){ - if(types.length() > 0) types.append(";"); - types.append(stopTester.getType()); - } - } - if(types.length() > 0) { - pw.printf("%s,%f,%f,%s\n",ts.getStop().getId(), ts.getCoordinate().x, - ts.getCoordinate().y, types.toString()); - } - } - pw.close(); - } catch (FileNotFoundException e) { - LOG.error("Failed to write StopsAlerts log file", e); - } - } - - @Override - public void checkInputs() { - if(logFile.isEmpty()) - throw new RuntimeException("missing log file name"); - } -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/extra_elevation_data/ExtraElevationData.java b/src/main/java/org/opentripplanner/graph_builder/module/extra_elevation_data/ExtraElevationData.java deleted file mode 100644 index c1f84983d70..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/extra_elevation_data/ExtraElevationData.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.opentripplanner.graph_builder.module.extra_elevation_data; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.opentripplanner.routing.edgetype.StreetEdge; - -public class ExtraElevationData { - public Map> data = new HashMap>(); -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/geometry/GeometryAndBlockProcessor.java b/src/main/java/org/opentripplanner/graph_builder/module/geometry/GeometryAndBlockProcessor.java index 8577a9ddf41..b26b8c2d0ff 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/geometry/GeometryAndBlockProcessor.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/geometry/GeometryAndBlockProcessor.java @@ -18,6 +18,7 @@ import org.opentripplanner.common.geometry.PackedCoordinateSequence; import org.opentripplanner.common.geometry.SphericalDistanceLibrary; import org.opentripplanner.common.model.P2; +import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.graph_builder.DataImportIssueStore; import org.opentripplanner.graph_builder.issues.BogusShapeDistanceTraveled; import org.opentripplanner.graph_builder.issues.BogusShapeGeometry; @@ -26,7 +27,6 @@ import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.OtpTransitService; import org.opentripplanner.model.ShapePoint; -import org.opentripplanner.model.Stop; import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Timetable; @@ -225,8 +225,8 @@ private void interline(Collection tripPatterns, Graph graph) { } TripPattern prevPattern = patternForTripTimes.get(prev); TripPattern currPattern = patternForTripTimes.get(curr); - Stop fromStop = prevPattern.getStop(prevPattern.getStops().size() - 1); - Stop toStop = currPattern.getStop(0); + var fromStop = prevPattern.getStop(prevPattern.getStops().size() - 1); + var toStop = currPattern.getStop(0); double teleportationDistance = SphericalDistanceLibrary.fastDistance( fromStop.getLat(), fromStop.getLon(), @@ -352,6 +352,7 @@ private LineString[] getGeometriesByShape( } private List getLinearLocations(List stopTimes, LineString shape) { + var isFlexTrip = FlexTrip.containsFlexStops(stopTimes); // This trip does not have shape_dist in stop_times, but does have an associated shape. ArrayList segments = new ArrayList<>(); for (int i = 0 ; i < shape.getNumPoints() - 1; ++i) { @@ -375,7 +376,7 @@ private List getLinearLocations(List stopTimes, LineSt continue; } double distance = segment.distance(coord); - if (distance < maxStopToShapeSnapDistance) { + if (distance < maxStopToShapeSnapDistance || isFlexTrip) { stopSegments.add(segment); maxSegmentIndex = index; if (minSegmentIndexForThisStop == -1) diff --git a/src/main/java/org/opentripplanner/graph_builder/module/geometry/TripOvertakingException.java b/src/main/java/org/opentripplanner/graph_builder/module/geometry/TripOvertakingException.java deleted file mode 100644 index c36c29b6535..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/geometry/TripOvertakingException.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.opentripplanner.graph_builder.module.geometry; - -import org.opentripplanner.model.Trip; - -public class TripOvertakingException extends RuntimeException { - - /** - * Thrown when a trip overtakes another trip on the same pattern. - */ - private static final long serialVersionUID = 1L; - public Trip overtaker, overtaken; - public int stopIndex; - - public TripOvertakingException(Trip overtaker, Trip overtaken, int stopIndex) { - this.overtaker = overtaker; - this.overtaken = overtaken; - this.stopIndex = stopIndex; - } - - @Override - public String getMessage() { - return "Possible GTFS feed error: Trip " + overtaker + " overtakes trip " + overtaken - + " (which has the same stops) at stop index " - + stopIndex + " This will be handled correctly but inefficiently."; - } - -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/AbstractStopTester.java b/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/AbstractStopTester.java deleted file mode 100644 index d7febaf3bc3..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/AbstractStopTester.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.opentripplanner.graph_builder.module.stopsAlerts; - -import org.opentripplanner.routing.graph.Graph; -import org.opentripplanner.routing.vertextype.TransitStopVertex; - -public abstract class AbstractStopTester implements IStopTester{ - - String type; - - public String getType(){ - return this.type; - } - - @Override - abstract public boolean fulfillDemands(TransitStopVertex ts, Graph graph); - -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/IStopTester.java b/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/IStopTester.java deleted file mode 100644 index 4b40bafed8c..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/IStopTester.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.opentripplanner.graph_builder.module.stopsAlerts; - -import org.opentripplanner.routing.graph.Graph; -import org.opentripplanner.routing.vertextype.TransitStopVertex; - -public interface IStopTester { - boolean fulfillDemands(TransitStopVertex ts, Graph graph); - String getType(); -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/TransitType.java b/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/TransitType.java deleted file mode 100644 index f5eb7e369da..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/TransitType.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.opentripplanner.graph_builder.module.stopsAlerts; - -import org.opentripplanner.routing.core.TraverseMode; -import org.opentripplanner.routing.graph.Graph; -import org.opentripplanner.routing.vertextype.TransitStopVertex; - -public class TransitType extends AbstractStopTester { - - TraverseMode transitType; - - - /** - * @return true if a transit type of type transitType is pass through that stop - */ - @Override - public boolean fulfillDemands(TransitStopVertex ts, Graph graph) { - if (ts.getModes().contains(transitType)) { - return true; - } - return false; - } -} diff --git a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/UnconnectedStop.java b/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/UnconnectedStop.java deleted file mode 100644 index 2a8ee7232d6..00000000000 --- a/src/main/java/org/opentripplanner/graph_builder/module/stopsAlerts/UnconnectedStop.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.opentripplanner.graph_builder.module.stopsAlerts; - -import org.opentripplanner.routing.edgetype.PathwayEdge; -import org.opentripplanner.routing.edgetype.StreetTransitStopLink; -import org.opentripplanner.routing.graph.Edge; -import org.opentripplanner.routing.graph.Graph; -import org.opentripplanner.routing.vertextype.TransitStopVertex; - -import java.util.List; - -public class UnconnectedStop extends AbstractStopTester { - - - /** - * @return true if the stop is not connected to any street - */ - @Override - public boolean fulfillDemands(TransitStopVertex ts, Graph graph) { - List outgoingStreets = ts.getOutgoingStreetEdges(); - boolean hasStreetLink = false; - for(Edge e:ts.getIncoming()){ - if(e instanceof StreetTransitStopLink || e instanceof PathwayEdge){ - hasStreetLink = true; - break; - } - } - if(!hasStreetLink){ - //TODO: see what if there is incoming and not outgoing - for(Edge e:ts.getOutgoing()){ - if(e instanceof StreetTransitStopLink){ - hasStreetLink = true; - break; - } - } - } - return !(hasStreetLink || (outgoingStreets.size() > 0)); - } -} diff --git a/src/main/java/org/opentripplanner/gtfs/RepairStopTimesForEachTripOperation.java b/src/main/java/org/opentripplanner/gtfs/RepairStopTimesForEachTripOperation.java index b02203e284f..9803e051d36 100644 --- a/src/main/java/org/opentripplanner/gtfs/RepairStopTimesForEachTripOperation.java +++ b/src/main/java/org/opentripplanner/gtfs/RepairStopTimesForEachTripOperation.java @@ -2,7 +2,11 @@ import gnu.trove.list.TIntList; import gnu.trove.list.array.TIntArrayList; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import org.opentripplanner.common.geometry.SphericalDistanceLibrary; +import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.graph_builder.DataImportIssue; import org.opentripplanner.graph_builder.DataImportIssueStore; import org.opentripplanner.graph_builder.issues.HopSpeedFast; @@ -15,16 +19,13 @@ import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Trip; import org.opentripplanner.model.TripStopTimes; +import org.opentripplanner.util.OTPFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - /** * This class is responsible for cleaning stop times, removing duplicates, correcting bad data - * and so on. This do only apply to GTFS imports. + * and so on. This only applies to GTFS imports. */ public class RepairStopTimesForEachTripOperation { private static final Logger LOG = LoggerFactory.getLogger(RepairStopTimesForEachTripOperation.class); @@ -52,8 +53,11 @@ public void run() { /* Fetch the stop times for this trip. Copy the list since it's immutable. */ List stopTimes = new ArrayList<>(stopTimesByTrip.get(trip)); - /* Remove stoptimes without stops */ - stopTimes.removeIf(st -> !(st.getStop() instanceof Stop)); + // if we don't have flex routing enabled then remove all the flex locations and location + // groups + if(OTPFeature.FlexRouting.isOff()) { + stopTimes.removeIf(st -> !(st.getStop() instanceof Stop)); + } /* Stop times frequently contain duplicate, missing, or incorrect entries. Repair them. */ TIntList removedStopSequences = removeRepeatedStops(stopTimes); @@ -61,6 +65,7 @@ public void run() { issueStore.add(new RepeatedStops(trip, removedStopSequences)); } filterStopTimes(stopTimes); + interpolateStopTimes(stopTimes); stopTimesByTrip.replace(trip, stopTimes); @@ -258,7 +263,7 @@ private void interpolateStopTimes(List stopTimes) { /* Interpolate, if necessary, the times of non-timepoint stops */ /* genuine interpolation needed */ - if (!(st0.isDepartureTimeSet() && st0.isArrivalTimeSet())) { + if (!(st0.isDepartureTimeSet() && st0.isArrivalTimeSet()) && !FlexTrip.isFlexStop(st0.getStop())) { // figure out how many such stops there are in a row. int j; StopTime st = null; diff --git a/src/main/java/org/opentripplanner/gtfs/mapping/LocationMapper.java b/src/main/java/org/opentripplanner/gtfs/mapping/LocationMapper.java index 5b481357d25..060cbb887f5 100644 --- a/src/main/java/org/opentripplanner/gtfs/mapping/LocationMapper.java +++ b/src/main/java/org/opentripplanner/gtfs/mapping/LocationMapper.java @@ -32,6 +32,8 @@ private FlexStopLocation doMap(org.onebusaway.gtfs.model.Location gtfsLocation) FlexStopLocation otpLocation = new FlexStopLocation(mapAgencyAndId(gtfsLocation.getId())); otpLocation.setName(gtfsLocation.getName()); + otpLocation.setUrl(gtfsLocation.getUrl()); + otpLocation.setDescription(gtfsLocation.getDescription()); otpLocation.setZoneId(gtfsLocation.getZoneId()); try { otpLocation.setGeometry(GeometryUtils.convertGeoJsonToJtsGeometry(gtfsLocation.getGeometry())); diff --git a/src/main/java/org/opentripplanner/gtfs/mapping/TransferMapper.java b/src/main/java/org/opentripplanner/gtfs/mapping/TransferMapper.java index 850c0c8229b..2b6582fa3a7 100644 --- a/src/main/java/org/opentripplanner/gtfs/mapping/TransferMapper.java +++ b/src/main/java/org/opentripplanner/gtfs/mapping/TransferMapper.java @@ -11,6 +11,7 @@ import org.onebusaway.gtfs.model.Transfer; import org.opentripplanner.model.Route; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Trip; import org.opentripplanner.model.TripStopTimes; @@ -140,8 +141,8 @@ private Collection doMap(org.onebusaway.gtfs.model.Transfer // applies to all stops in that station." we thus expand transfers that use parent stations // to all the member stops. - Collection fromStops = getStopOrChildStops(rhs.getFromStop()); - Collection toStops = getStopOrChildStops(rhs.getToStop()); + var fromStops = getStopOrChildStops(rhs.getFromStop()); + var toStops = getStopOrChildStops(rhs.getToStop()); Collection fromPoints = mapTransferPoints(fromStops, fromTrip, fromRoute); Collection toPoints = mapTransferPoints(toStops, toTrip, toRoute); @@ -173,7 +174,7 @@ private TransferConstraint mapConstraint(Transfer rhs, Trip fromTrip, Trip toTri } private Collection mapTransferPoints( - Collection stops, + Collection stops, Trip trip, Route route ) { @@ -197,7 +198,7 @@ else if (route != null) { */ } else { - for (Stop stop : stops) { + for (var stop : stops) { result.add(new StopTransferPoint(stop)); } @@ -206,7 +207,7 @@ else if (route != null) { } private Collection createTransferPointForTrip( - Collection stops, + Collection stops, Trip trip, BiFunction createPoint ) { @@ -223,7 +224,7 @@ private Collection createTransferPointForTrip( return result; } - private Collection getStopOrChildStops(org.onebusaway.gtfs.model.Stop gtfsStop) { + private Collection getStopOrChildStops(org.onebusaway.gtfs.model.Stop gtfsStop) { if (gtfsStop.getLocationType() == 0) { return Collections.singletonList(stopMapper.map(gtfsStop)); } diff --git a/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java b/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java index fe25a98235c..5709e758fb5 100644 --- a/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java +++ b/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java @@ -31,10 +31,6 @@ Trip map(org.onebusaway.gtfs.model.Trip orginal) { return orginal == null ? null : mappedTrips.computeIfAbsent(orginal, this::doMap); } - Collection mappedTrips() { - return mappedTrips.values(); - } - private Trip doMap(org.onebusaway.gtfs.model.Trip rhs) { Trip lhs = new Trip(AgencyAndIdMapper.mapAgencyAndId(rhs.getId())); diff --git a/src/main/java/org/opentripplanner/index/IndexAPI.java b/src/main/java/org/opentripplanner/index/IndexAPI.java index 9a3ea3cfec7..eb0a8334db9 100644 --- a/src/main/java/org/opentripplanner/index/IndexAPI.java +++ b/src/main/java/org/opentripplanner/index/IndexAPI.java @@ -27,6 +27,7 @@ import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.Route; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTimesInPattern; import org.opentripplanner.model.Timetable; import org.opentripplanner.model.Trip; @@ -164,7 +165,7 @@ public Collection getAlertsForTrip( @GET @Path("/stops/{stopId}") public ApiStop getStop(@PathParam("stopId") String stopIdString) { - Stop stop = getStop(createRoutingService(), stopIdString); + var stop = getStop(createRoutingService(), stopIdString); return StopMapper.mapToApi(stop); } @@ -212,10 +213,9 @@ public List getStopsInRadius( .lessThan("minLat", minLat, "maxLat", maxLat) .lessThan("minLon", minLon, "maxLon", maxLon) .validate(); - Collection stops = createRoutingService() + var stops = createRoutingService() .getStopsByBoundingBox(minLat, minLon, maxLat, maxLon); - return StopMapper.mapToApiShort(stops - ); + return StopMapper.mapToApiShort(stops); } } @@ -223,7 +223,7 @@ public List getStopsInRadius( @Path("/stops/{stopId}/routes") public List getRoutesForStop(@PathParam("stopId") String stopId) { RoutingService routingService = createRoutingService(); - Stop stop = getStop(routingService, stopId); + var stop = getStop(routingService, stopId); return routingService .getPatternsForStop(stop) .stream() @@ -237,7 +237,7 @@ public List getRoutesForStop(@PathParam("stopId") String stopId) @Path("/stops/{stopId}/patterns") public List getPatternsForStop(@PathParam("stopId") String stopId) { RoutingService routingService = createRoutingService(); - Stop stop = getStop(routingService, stopId); + var stop = getStop(routingService, stopId); return routingService .getPatternsForStop(stop) .stream() @@ -263,7 +263,7 @@ public Collection getStopTimesForStop( @QueryParam("omitNonPickups") boolean omitNonPickups ) { RoutingService routingService = createRoutingService(); - Stop stop = getStop(routingService, stopIdString); + var stop = getStop(routingService, stopIdString); return routingService.stopTimesForStop( stop, @@ -290,7 +290,7 @@ public List getStoptimesForStopAndDate( @QueryParam("omitNonPickups") boolean omitNonPickups ) { RoutingService routingService = createRoutingService(); - Stop stop = getStop(routingService, stopId); + var stop = getStop(routingService, stopId); ServiceDate serviceDate = parseServiceDate("date", date); List stopTimes = routingService.getStopTimesForStop( stop, @@ -307,7 +307,7 @@ public List getStoptimesForStopAndDate( @Path("/stops/{stopId}/transfers") public Collection getTransfers(@PathParam("stopId") String stopId) { RoutingService routingService = createRoutingService(); - Stop stop = getStop(routingService, stopId); + var stop = getStop(routingService, stopId); // get the transfers for the stop return routingService.getTransfersByStop(stop) @@ -340,7 +340,7 @@ public List getRoutes(@QueryParam("hasStop") List stopIds // Protective copy, we are going to calculate the intersection destructively routes = new ArrayList<>(routes); for (String stopId : stopIds) { - Stop stop = getStop(routingService, stopId); + var stop = getStop(routingService, stopId); Set routesHere = new HashSet<>(); for (TripPattern pattern : routingService.getPatternsForStop(stop)) { routesHere.add(pattern.getRoute()); @@ -377,7 +377,7 @@ public List getStopsForRoute(@PathParam("routeId") String routeId) RoutingService routingService = createRoutingService(); Route route = getRoute(routingService, routeId); - Set stops = new HashSet<>(); + Set stops = new HashSet<>(); Collection patterns = routingService.getPatternsForRoute().get(route); for (TripPattern pattern : patterns) { stops.addAll(pattern.getStops()); @@ -425,7 +425,7 @@ public ApiTrip getTrip(@PathParam("tripId") String tripId) { @GET @Path("/trips/{tripId}/stops") public List getStopsForTrip(@PathParam("tripId") String tripId) { - Collection stops = getTripPatternForTripId(createRoutingService(), tripId).getStops(); + Collection stops = getTripPatternForTripId(createRoutingService(), tripId).getStops(); return StopMapper.mapToApiShort(stops); } @@ -493,7 +493,7 @@ public List getTripsForPattern(@PathParam("patternId") String patt @GET @Path("/patterns/{patternId}/stops") public List getStopsForPattern(@PathParam("patternId") String patternId) { - List stops = getTripPattern(createRoutingService(), patternId).getStops(); + var stops = getTripPattern(createRoutingService(), patternId).getStops(); return StopMapper.mapToApiShort(stops); } @@ -600,8 +600,8 @@ private static Agency getAgency(RoutingService routingService, String feedId, St return agency; } - private static Stop getStop(RoutingService routingService, String stopId) { - Stop stop = routingService.getStopForId(createId("stopId", stopId)); + private static StopLocation getStop(RoutingService routingService, String stopId) { + var stop = routingService.getStopForId(createId("stopId", stopId)); return validateExist("Stop", stop, "stopId", stop); } diff --git a/src/main/java/org/opentripplanner/model/FlexLocationGroup.java b/src/main/java/org/opentripplanner/model/FlexLocationGroup.java index df81a066d46..e825bbbf9eb 100644 --- a/src/main/java/org/opentripplanner/model/FlexLocationGroup.java +++ b/src/main/java/org/opentripplanner/model/FlexLocationGroup.java @@ -1,16 +1,13 @@ package org.opentripplanner.model; -import java.util.Collection; -import java.util.List; +import java.util.HashSet; +import java.util.Set; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.Point; import org.opentripplanner.common.geometry.GeometryUtils; -import java.util.HashSet; -import java.util.Set; - /** * A group of stopLocations, which can share a common Stoptime */ @@ -24,6 +21,8 @@ public class FlexLocationGroup extends TransitEntity implements StopLocation { private GeometryCollection geometry = new GeometryCollection(null, GeometryUtils.getGeometryFactory()); + private Point centroid; + public FlexLocationGroup(FeedScopedId id) { super(id); } @@ -37,12 +36,21 @@ public String getName() { return name; } + @Override + public String getDescription() { + return null; + } + + @Override + public String getUrl() { + return null; + } + /** * Returns the centroid of all stops and areas belonging to this location group. */ @Override public WgsCoordinate getCoordinate() { - Point centroid = geometry.getCentroid(); return new WgsCoordinate(centroid.getY(), centroid.getX()); } @@ -51,6 +59,21 @@ public String getFirstZoneAsString() { return null; } + @Override + public Geometry getGeometry() { + return geometry; + } + + @Override + public boolean isPartOfStation() { + return false; + } + + @Override + public boolean isPartOfSameStationAs(StopLocation alternativeStop) { + return false; + } + /** * Adds a new location to the location group. * This should ONLY be used during the graph build process. @@ -70,11 +93,12 @@ public void addLocation(StopLocation location) { envelope.expandBy(100 / xscale, 100); newGeometries[numGeometries] = GeometryUtils.getGeometryFactory().toGeometry(envelope); } else if (location instanceof FlexStopLocation) { - newGeometries[numGeometries] = ((FlexStopLocation) location).getGeometry(); + newGeometries[numGeometries] = location.getGeometry(); } else { throw new RuntimeException("Unknown location type"); } geometry = new GeometryCollection(newGeometries, GeometryUtils.getGeometryFactory()); + centroid = geometry.getCentroid(); } /** diff --git a/src/main/java/org/opentripplanner/model/FlexStopLocation.java b/src/main/java/org/opentripplanner/model/FlexStopLocation.java index 7684ba355b5..0a5274d0211 100644 --- a/src/main/java/org/opentripplanner/model/FlexStopLocation.java +++ b/src/main/java/org/opentripplanner/model/FlexStopLocation.java @@ -1,5 +1,6 @@ package org.opentripplanner.model; +import java.util.Optional; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; @@ -13,10 +14,16 @@ public class FlexStopLocation extends TransitEntity implements StopLocation { private String name; + private String description; + private Geometry geometry; private String zoneId; + private String url; + + private Point centroid; + public FlexStopLocation(FeedScopedId id) { super(id); } @@ -27,7 +34,23 @@ public FlexStopLocation(FeedScopedId id) { */ @Override public String getName() { - return name; + // according to the spec stop location names are optional for flex zones so, we return the id + // when it's null. *shrug* + return Optional.ofNullable(name).orElse(getId().toString()); + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; } public void setName(String name) { @@ -37,12 +60,14 @@ public void setName(String name) { /** * Returns the geometry of this location, can be any type of geometry. */ + @Override public Geometry getGeometry() { return geometry; } public void setGeometry(Geometry geometry) { this.geometry = geometry; + this.centroid = geometry.getCentroid(); } /** @@ -50,7 +75,6 @@ public void setGeometry(Geometry geometry) { */ @Override public WgsCoordinate getCoordinate() { - Point centroid = geometry.getCentroid(); return new WgsCoordinate(centroid.getY(), centroid.getX()); } @@ -62,4 +86,18 @@ public String getFirstZoneAsString() { public void setZoneId(String zoneId) { this.zoneId = zoneId; } + + @Override + public boolean isPartOfStation() { + return false; + } + + @Override + public boolean isPartOfSameStationAs(StopLocation alternativeStop) { + return false; + } + + public void setDescription(String description) { + this.description = description; + } } diff --git a/src/main/java/org/opentripplanner/model/GroupOfStations.java b/src/main/java/org/opentripplanner/model/GroupOfStations.java index becbe14a095..32a092426cc 100644 --- a/src/main/java/org/opentripplanner/model/GroupOfStations.java +++ b/src/main/java/org/opentripplanner/model/GroupOfStations.java @@ -48,7 +48,7 @@ public void setCoordinate(WgsCoordinate coordinate) { this.coordinate = coordinate; } - public Collection getChildStops() { + public Collection getChildStops() { return this.childStations.stream() .flatMap(s -> s.getChildStops().stream()) .collect(Collectors.toUnmodifiableList()); diff --git a/src/main/java/org/opentripplanner/model/MultiModalStation.java b/src/main/java/org/opentripplanner/model/MultiModalStation.java index 49838e165c9..254ed0cfcaa 100644 --- a/src/main/java/org/opentripplanner/model/MultiModalStation.java +++ b/src/main/java/org/opentripplanner/model/MultiModalStation.java @@ -88,7 +88,7 @@ public void setUrl(String url) { this.url = url; } - public Collection getChildStops() { + public Collection getChildStops() { return this.childStations.stream() .flatMap(s -> s.getChildStops().stream()) .collect(Collectors.toUnmodifiableList()); diff --git a/src/main/java/org/opentripplanner/model/Station.java b/src/main/java/org/opentripplanner/model/Station.java index 912c3089d87..29dfa02c2ed 100644 --- a/src/main/java/org/opentripplanner/model/Station.java +++ b/src/main/java/org/opentripplanner/model/Station.java @@ -1,11 +1,16 @@ package org.opentripplanner.model; -import com.fasterxml.jackson.annotation.JsonBackReference; +import static org.opentripplanner.common.geometry.GeometryUtils.getGeometryFactory; +import com.fasterxml.jackson.annotation.JsonBackReference; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.TimeZone; +import java.util.stream.Collectors; +import org.locationtech.jts.algorithm.ConvexHull; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; /** * A grouping of stops in GTFS or the lowest level grouping in NeTEx. It can be a train station, a @@ -27,6 +32,8 @@ public class Station extends TransitEntity implements StopCollection { private final StopTransferPriority priority; + private GeometryCollection geometry; + /** * URL to a web page containing information about this particular station */ @@ -36,7 +43,7 @@ public class Station extends TransitEntity implements StopCollection { // We serialize this class to json only for snapshot tests, and this creates cyclical structures @JsonBackReference - private final Set childStops = new HashSet<>(); + private final Set childStops = new HashSet<>(); public Station( FeedScopedId id, @@ -56,10 +63,12 @@ public Station( this.url = url; this.timezone = timezone; this.priority = priority == null ? DEFAULT_PRIORITY : priority; + this.geometry = computeGeometry(coordinate, childStops); } public void addChildStop(Stop stop) { this.childStops.add(stop); + this.geometry = computeGeometry(coordinate, childStops); } @Override @@ -106,7 +115,7 @@ public TimeZone getTimezone() { return timezone; } - public Collection getChildStops() { + public Collection getChildStops() { return childStops; } @@ -117,4 +126,23 @@ public double getLat() { public double getLon() { return coordinate.longitude(); } + + /** + * A geometry collection that contains the center point and the convex hull of all the + * child stops. + */ + public GeometryCollection getGeometry() { + return geometry; + } + + private static GeometryCollection computeGeometry(WgsCoordinate coordinate, Set childStops) { + var stationPoint = getGeometryFactory().createPoint(coordinate.asJtsCoordinate()); + var childGeometries = childStops.stream().map(StopLocation::getGeometry).collect(Collectors.toList()); + childGeometries.add(stationPoint); + + var geometryCollection = getGeometryFactory().createGeometryCollection(childGeometries.toArray(new Geometry[]{})); + var convexHull = new ConvexHull(geometryCollection).getConvexHull(); + + return getGeometryFactory().createGeometryCollection(new Geometry[]{ stationPoint, convexHull }); + } } diff --git a/src/main/java/org/opentripplanner/model/StationElement.java b/src/main/java/org/opentripplanner/model/StationElement.java index 5de09312dfe..6fd846d27b0 100644 --- a/src/main/java/org/opentripplanner/model/StationElement.java +++ b/src/main/java/org/opentripplanner/model/StationElement.java @@ -2,7 +2,7 @@ /** * Acts as the supertype for all entities, except stations, created from the GTFS stops table. Most - * of the fileds are shared between the types, and eg. in pathways the namespace any of them can be + * of the fields are shared between the types, and eg. in pathways the namespace any of them can be * used as from and to. */ public abstract class StationElement extends TransitEntity { @@ -60,14 +60,6 @@ public String getDescription() { return description; } - public double getLat() { - return getCoordinate().latitude(); - } - - public double getLon() { - return getCoordinate().longitude(); - } - /** * Center point/location for the station element. Returns the coordinate of the parent station, if * the coordinate is not defined for this station element. @@ -123,8 +115,8 @@ public boolean isPartOfStation() { * Return {@code true} if this stop (element) has the same parent station as the other stop * (element). */ - public boolean isPartOfSameStationAs(StationElement other) { - return isPartOfStation() && parentStation.equals(other.parentStation); + public boolean isPartOfSameStationAs(StopLocation other) { + return isPartOfStation() && parentStation.equals(other.getParentStation()); } public void setParentStation(Station parentStation) { diff --git a/src/main/java/org/opentripplanner/model/Stop.java b/src/main/java/org/opentripplanner/model/Stop.java index 0bf945137cf..62f1101aa3e 100644 --- a/src/main/java/org/opentripplanner/model/Stop.java +++ b/src/main/java/org/opentripplanner/model/Stop.java @@ -6,6 +6,10 @@ import java.util.HashSet; import java.util.TimeZone; import javax.validation.constraints.NotNull; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; +import org.locationtech.jts.geom.Point; +import org.opentripplanner.common.geometry.GeometryUtils; /** * A place where actual boarding/departing happens. It can be a bus stop on one side of a road or a @@ -126,4 +130,9 @@ public StopTransferPriority getPriority() { public Collection getFareZones() { return Collections.unmodifiableCollection(fareZones); } + + @Override + public Geometry getGeometry() { + return GeometryUtils.getGeometryFactory().createPoint(getCoordinate().asJtsCoordinate()); + } } diff --git a/src/main/java/org/opentripplanner/model/StopCollection.java b/src/main/java/org/opentripplanner/model/StopCollection.java index 7e6e4ac724d..e59b1124d9a 100644 --- a/src/main/java/org/opentripplanner/model/StopCollection.java +++ b/src/main/java/org/opentripplanner/model/StopCollection.java @@ -14,7 +14,7 @@ public interface StopCollection { * Implementations should go down the hierarchy and return all the underlying stops * recursively. */ - Collection getChildStops(); + Collection getChildStops(); double getLat(); diff --git a/src/main/java/org/opentripplanner/model/StopLocation.java b/src/main/java/org/opentripplanner/model/StopLocation.java index 5283852be7e..755c6ade0b3 100644 --- a/src/main/java/org/opentripplanner/model/StopLocation.java +++ b/src/main/java/org/opentripplanner/model/StopLocation.java @@ -2,6 +2,9 @@ import java.util.Collection; import java.util.List; +import java.util.TimeZone; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; /** * A StopLocation describes a place where a vehicle can be boarded or alighted, which is not @@ -16,6 +19,10 @@ public interface StopLocation { /** Name of the StopLocation, if provided */ String getName(); + String getDescription(); + + String getUrl(); + /** * Short text or a number that identifies the location for riders. These codes are often used in * phone-based reservation systems to make it easier for riders to specify a particular location. @@ -30,10 +37,24 @@ default String getPlatformCode() { return null; } + default TransitMode getVehicleType() { return null; } + + default double getLat() { + return getCoordinate().latitude(); + } + + default double getLon() { + return getCoordinate().longitude(); + } + + default Station getParentStation() { return null; } + default Collection getFareZones() { return List.of(); } + default WheelChairBoarding getWheelchairBoarding() { return null; }; + /** * This is to ensure backwards compatibility with the REST API, which expects the GTFS zone_id * which only permits one zone per stop. @@ -48,4 +69,23 @@ default String getFirstZoneAsString() { */ WgsCoordinate getCoordinate(); + /** + * The geometry of the stop. + * + * For fixed-schedule stops this will return the same data as + * getCoordinate(). + * + * For flex stops this will return the geometries of the stop or group of stops. + */ + Geometry getGeometry(); + + default TimeZone getTimeZone() { return null; } + + boolean isPartOfStation(); + + default StopTransferPriority getPriority() { + return StopTransferPriority.ALLOWED; + } + + boolean isPartOfSameStationAs(StopLocation alternativeStop); } diff --git a/src/main/java/org/opentripplanner/model/StopPattern.java b/src/main/java/org/opentripplanner/model/StopPattern.java index 72c65880de1..24c2fc8bba1 100644 --- a/src/main/java/org/opentripplanner/model/StopPattern.java +++ b/src/main/java/org/opentripplanner/model/StopPattern.java @@ -3,7 +3,6 @@ import com.google.common.hash.HashCode; import com.google.common.hash.HashFunction; import com.google.common.hash.Hasher; - import java.io.Serializable; import java.util.Arrays; import java.util.Collection; @@ -37,12 +36,12 @@ public class StopPattern implements Serializable { private static final long serialVersionUID = 20140101L; - private final Stop[] stops; + private final StopLocation[] stops; private final PickDrop[] pickups; private final PickDrop[] dropoffs; private StopPattern (int size) { - stops = new Stop[size]; + stops = new StopLocation[size]; pickups = new PickDrop[size]; dropoffs = new PickDrop[size]; } @@ -56,11 +55,11 @@ public StopPattern (Collection stopTimes) { for (int i = 0; i < size; ++i) { StopTime stopTime = stopTimeIterator.next(); - stops[i] = (Stop) stopTime.getStop(); + stops[i] = stopTime.getStop(); // should these just be booleans? anything but 1 means pick/drop is allowed. // pick/drop messages could be stored in individual trips - pickups[i] = stopTime.getPickupType(); - dropoffs[i] = stopTime.getDropOffType(); + pickups[i] = computePickDrop(stopTime.getStop(), stopTime.getPickupType()); + dropoffs[i] = computePickDrop(stopTime.getStop(), stopTime.getDropOffType()); } /* * TriMet GTFS has many trips that differ only in the pick/drop status of their initial and @@ -74,12 +73,25 @@ public StopPattern (Collection stopTimes) { pickups[size - 1] = PickDrop.SCHEDULED; } + /** + * Raptor should not be allowed to board or alight flex stops because they have fake + * coordinates (centroids) and might not have times. + */ + private static PickDrop computePickDrop(StopLocation stop, PickDrop pickDrop) { + if(stop instanceof FlexStopLocation) { + return PickDrop.NONE; + } + else { + return pickDrop; + } + } + /** * @param stopId in agency_id format */ public boolean containsStop (String stopId) { if (stopId == null) { return false; } - for (Stop stop : stops) if (stopId.equals(stop.getId().toString())) { return true; } + for (StopLocation stop : stops) if (stopId.equals(stop.getId().toString())) { return true; } return false; } @@ -128,7 +140,7 @@ public HashCode semanticHash(HashFunction hashFunction) { Hasher hasher = hashFunction.newHasher(); int size = stops.length; for (int s = 0; s < size; s++) { - Stop stop = stops[s]; + StopLocation stop = stops[s]; // Truncate the lat and lon to 6 decimal places in case they move slightly between // feed versions hasher.putLong((long) (stop.getLat() * 1000000)); @@ -143,11 +155,11 @@ public HashCode semanticHash(HashFunction hashFunction) { return hasher.hash(); } - public Stop[] getStops() { + public StopLocation[] getStops() { return stops; } - public Stop getStop(int i) { + public StopLocation getStop(int i) { return stops[i]; } diff --git a/src/main/java/org/opentripplanner/model/TimetableSnapshot.java b/src/main/java/org/opentripplanner/model/TimetableSnapshot.java index 5ec88ef8043..c23308361e9 100644 --- a/src/main/java/org/opentripplanner/model/TimetableSnapshot.java +++ b/src/main/java/org/opentripplanner/model/TimetableSnapshot.java @@ -122,7 +122,7 @@ public boolean equals(Object obj) { * * TODO Find a generic way to keep all realtime indexes. */ - private SetMultimap patternsForStop = HashMultimap.create(); + private SetMultimap patternsForStop = HashMultimap.create(); /** * Boolean value indicating that timetable snapshot is read only if true. Once it is true, it shouldn't @@ -376,31 +376,22 @@ public String toString() { return String.format("Timetable snapshot: %d timetables (%s)", timetables.size(), d); } - /** - * @return all TripPatterns for which we have any updated timetables created by realtime messages, including both - * patterns that were in the scheduled (static) transit data and those that were added to this snapshot by - * rerouted or added trips. - */ - public Collection getAllRealtimeTripPatterns () { - return timetables.keySet(); - } - /** * Add the patterns to the stop index, only if they come from a modified pattern */ private void addPatternToIndex(TripPattern tripPattern) { if (tripPattern.isCreatedByRealtimeUpdater()) { - for (Stop stop: tripPattern.getStops()) { + for (var stop: tripPattern.getStops()) { patternsForStop.put(stop, tripPattern); } } } - public Collection getPatternsForStop(Stop stop) { + public Collection getPatternsForStop(StopLocation stop) { return patternsForStop.get(stop); } - public void setPatternsForStop(SetMultimap patternsForStop) { + public void setPatternsForStop(SetMultimap patternsForStop) { this.patternsForStop = patternsForStop; } } diff --git a/src/main/java/org/opentripplanner/model/TripPattern.java b/src/main/java/org/opentripplanner/model/TripPattern.java index ec5a9d5b016..354d522166c 100644 --- a/src/main/java/org/opentripplanner/model/TripPattern.java +++ b/src/main/java/org/opentripplanner/model/TripPattern.java @@ -90,7 +90,7 @@ public void setName(String name) { } /** - * Convinience method to get the route traverse mode, the mode for all trips in this pattern. + * Convenience method to get the route traverse mode, the mode for all trips in this pattern. */ public final TransitMode getMode() { return route.getMode(); @@ -182,7 +182,7 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE scheduledTimetable.finish(); } - public Stop getStop(int stopIndex) { + public StopLocation getStop(int stopIndex) { return stopPattern.getStops()[stopIndex]; } @@ -191,7 +191,7 @@ public int getStopIndex(Stop stop) { return Arrays.asList(stopPattern.getStops()).indexOf(stop); } - public List getStops() { + public List getStops() { return Arrays.asList(stopPattern.getStops()); } @@ -218,11 +218,6 @@ public boolean wheelchairAccessible(int stopIndex) { return stopPattern.getStop(stopIndex).getWheelchairBoarding() == WheelChairBoarding.POSSIBLE; } - /** Returns the zone of a given stop */ - public String getZone(int stopIndex) { - return getStop(stopIndex).getFirstZoneAsString(); - } - public PickDrop getAlightType(int stopIndex) { return stopPattern.getDropoff(stopIndex); } @@ -347,7 +342,7 @@ public void setCreatedByRealtimeUpdater() { createdByRealtimeUpdater = true; } - private static String stopNameAndId (Stop stop) { + private static String stopNameAndId (StopLocation stop) { return stop.getName() + " (" + stop.getId().toString() + ")"; } @@ -429,24 +424,24 @@ public static void generateUniqueNames ( /* Do the patterns within this Route have a unique start, end, or via Stop? */ Multimap signs = ArrayListMultimap.create(); // prefer headsigns - Multimap starts = ArrayListMultimap.create(); - Multimap ends = ArrayListMultimap.create(); - Multimap vias = ArrayListMultimap.create(); + Multimap starts = ArrayListMultimap.create(); + Multimap ends = ArrayListMultimap.create(); + Multimap vias = ArrayListMultimap.create(); for (TripPattern pattern : routeTripPatterns) { - List stops = pattern.getStops(); - Stop start = stops.get(0); - Stop end = stops.get(stops.size() - 1); + List stops = pattern.getStops(); + StopLocation start = stops.get(0); + StopLocation end = stops.get(stops.size() - 1); starts.put(start, pattern); ends.put(end, pattern); - for (Stop stop : stops) vias.put(stop, pattern); + for (StopLocation stop : stops) vias.put(stop, pattern); } PATTERN : for (TripPattern pattern : routeTripPatterns) { - List stops = pattern.getStops(); + List stops = pattern.getStops(); StringBuilder sb = new StringBuilder(routeName); /* First try to name with destination. */ - Stop end = stops.get(stops.size() - 1); + var end = stops.get(stops.size() - 1); sb.append(" to " + stopNameAndId(end)); if (ends.get(end).size() == 1) { pattern.setName(sb.toString()); @@ -454,7 +449,7 @@ public static void generateUniqueNames ( } /* Then try to name with origin. */ - Stop start = stops.get(0); + var start = stops.get(0); sb.append(" from " + stopNameAndId(start)); if (starts.get(start).size() == 1) { pattern.setName((sb.toString())); @@ -471,7 +466,7 @@ public static void generateUniqueNames ( } /* Still not unique; try (end, start, via) for each via. */ - for (Stop via : stops) { + for (var via : stops) { if (via.equals(start) || via.equals(end)) continue; Set intersection = new HashSet<>(); intersection.addAll(remainingPatterns); @@ -607,7 +602,7 @@ public String getFeedId() { return route.getId().getFeedId(); } - private static Coordinate coordinate(Stop s) { + private static Coordinate coordinate(StopLocation s) { return new Coordinate(s.getLon(), s.getLat()); } } diff --git a/src/main/java/org/opentripplanner/model/transfer/StopTransferPoint.java b/src/main/java/org/opentripplanner/model/transfer/StopTransferPoint.java index 776f5e8358c..8c21d77db58 100644 --- a/src/main/java/org/opentripplanner/model/transfer/StopTransferPoint.java +++ b/src/main/java/org/opentripplanner/model/transfer/StopTransferPoint.java @@ -3,19 +3,20 @@ import java.io.Serializable; import java.util.Objects; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; public class StopTransferPoint implements TransferPoint, Serializable { private static final long serialVersionUID = 1L; - private final Stop stop; + private final StopLocation stop; - public StopTransferPoint(Stop stop) { + public StopTransferPoint(StopLocation stop) { this.stop = stop; } @Override - public Stop getStop() { + public StopLocation getStop() { return stop; } diff --git a/src/main/java/org/opentripplanner/model/transfer/TransferPoint.java b/src/main/java/org/opentripplanner/model/transfer/TransferPoint.java index 9badf442b36..f476572a77b 100644 --- a/src/main/java/org/opentripplanner/model/transfer/TransferPoint.java +++ b/src/main/java/org/opentripplanner/model/transfer/TransferPoint.java @@ -1,6 +1,6 @@ package org.opentripplanner.model.transfer; -import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.Trip; @@ -46,7 +46,7 @@ public interface TransferPoint { int NOT_AVAILABLE = -1; - default Stop getStop() { + default StopLocation getStop() { return null; } diff --git a/src/main/java/org/opentripplanner/model/transfer/TransferService.java b/src/main/java/org/opentripplanner/model/transfer/TransferService.java index 221daee6ff2..8e6d574c36a 100644 --- a/src/main/java/org/opentripplanner/model/transfer/TransferService.java +++ b/src/main/java/org/opentripplanner/model/transfer/TransferService.java @@ -12,6 +12,7 @@ import org.opentripplanner.common.model.P2; import org.opentripplanner.common.model.T2; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.Trip; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,17 +39,17 @@ public class TransferService implements Serializable { /** * Table which contains transfers between a trip/route and a stops */ - private final Map, ConstrainedTransfer> trip2StopTransfers; + private final Map, ConstrainedTransfer> trip2StopTransfers; /** * Table which contains transfers between a stop and a trip/route */ - private final Map, ConstrainedTransfer> stop2TripTransfers; + private final Map, ConstrainedTransfer> stop2TripTransfers; /** * Table which contains transfers between two stops */ - private final Map, ConstrainedTransfer> stop2StopTransfers; + private final Map, ConstrainedTransfer> stop2StopTransfers; public TransferService() { this.constrainedTransferByToPoint = ArrayListMultimap.create(); @@ -79,8 +80,8 @@ public Collection listConstrainedTransfersTo(Trip toTrip, i @Nullable public ConstrainedTransfer findTransfer( - Stop fromStop, - Stop toStop, + StopLocation fromStop, + StopLocation toStop, Trip fromTrip, Trip toTrip, int fromStopPosition, diff --git a/src/main/java/org/opentripplanner/netex/NetexModule.java b/src/main/java/org/opentripplanner/netex/NetexModule.java index 1b1587f6b25..b91f2f9bd1a 100644 --- a/src/main/java/org/opentripplanner/netex/NetexModule.java +++ b/src/main/java/org/opentripplanner/netex/NetexModule.java @@ -81,7 +81,9 @@ public void buildGraph( calendarServiceData.add(transitBuilder.buildCalendarServiceData()); if (OTPFeature.FlexRouting.isOn()) { - transitBuilder.getFlexTripsById().addAll(FlexTripsMapper.createFlexTrips(transitBuilder)); + transitBuilder.getFlexTripsById().addAll( + FlexTripsMapper.createFlexTrips(transitBuilder, issueStore) + ); } OtpTransitService otpService = transitBuilder.build(); diff --git a/src/main/java/org/opentripplanner/routing/RoutingService.java b/src/main/java/org/opentripplanner/routing/RoutingService.java index f732ac10f24..5ed6832b20a 100644 --- a/src/main/java/org/opentripplanner/routing/RoutingService.java +++ b/src/main/java/org/opentripplanner/routing/RoutingService.java @@ -5,6 +5,7 @@ import java.util.List; import lombok.experimental.Delegate; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTimesInPattern; import org.opentripplanner.model.Timetable; import org.opentripplanner.model.TimetableSnapshot; @@ -72,7 +73,7 @@ public RoutingResponse route(RoutingRequest request, Router router) { * @param includeCancelledTrips If true, cancelled trips will also be included in result. */ public List stopTimesForStop( - Stop stop, long startTime, int timeRange, int numberOfDepartures, ArrivalDeparture arrivalDeparture, boolean includeCancelledTrips + StopLocation stop, long startTime, int timeRange, int numberOfDepartures, ArrivalDeparture arrivalDeparture, boolean includeCancelledTrips ) { return StopTimesHelper.stopTimesForStop( this, @@ -94,7 +95,7 @@ public List stopTimesForStop( * @param serviceDate Return all departures for the specified date */ public List getStopTimesForStop( - Stop stop, ServiceDate serviceDate, ArrivalDeparture arrivalDeparture + StopLocation stop, ServiceDate serviceDate, ArrivalDeparture arrivalDeparture ) { return StopTimesHelper.stopTimesForStop(this, stop, serviceDate, arrivalDeparture); } @@ -116,7 +117,7 @@ public List getStopTimesForStop( * @param arrivalDeparture Filter by arrivals, departures, or both */ public List stopTimesForPatternAtStop( - Stop stop, TripPattern pattern, long startTime, int timeRange, int numberOfDepartures, ArrivalDeparture arrivalDeparture + StopLocation stop, TripPattern pattern, long startTime, int timeRange, int numberOfDepartures, ArrivalDeparture arrivalDeparture ) { return StopTimesHelper.stopTimesForPatternAtStop( this, @@ -134,7 +135,7 @@ public List stopTimesForPatternAtStop( * Returns all the patterns for a specific stop. If includeRealtimeUpdates is set, new patterns * added by realtime updates are added to the collection. */ - public Collection getPatternsForStop(Stop stop, boolean includeRealtimeUpdates) { + public Collection getPatternsForStop(StopLocation stop, boolean includeRealtimeUpdates) { return graph.index.getPatternsForStop(stop, includeRealtimeUpdates ? lazyGetTimeTableSnapShot() : null ); diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/AlertToLegMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/AlertToLegMapper.java index 78204769791..549ab954ec9 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/AlertToLegMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/AlertToLegMapper.java @@ -115,7 +115,7 @@ private static Collection getAlertsForStopAndRoute(Graph graph, St } // ...and siblings - platform may have been changed - for (Stop siblingStop : stop.getParentStation().getChildStops()) { + for (var siblingStop : stop.getParentStation().getChildStops()) { if (!stop.getId().equals(siblingStop.getId())) { Collection siblingAlerts = graph.getTransitAlertService().getStopAndRouteAlerts(stop.getParentStation().getId(), routeId); if (siblingAlerts != null) { @@ -181,7 +181,7 @@ private static Collection getAlertsForStopAndTrip(Graph graph, Sto } // ...and siblings - platform may have been changed - for (Stop siblingStop : stop.getParentStation().getChildStops()) { + for (var siblingStop : stop.getParentStation().getChildStops()) { if (!stop.getId().equals(siblingStop.getId())) { Collection siblingAlerts = graph.getTransitAlertService().getStopAndTripAlerts(stop.getParentStation().getId(), tripId, serviceDate); if (siblingAlerts != null) { @@ -227,7 +227,7 @@ private static Collection getAlertsForStop(Graph graph, Stop stop, } // ...and siblings - platform may have been changed - for (Stop siblingStop : stop.getParentStation().getChildStops()) { + for (var siblingStop : stop.getParentStation().getChildStops()) { if (!stop.getId().equals(siblingStop.getId())) { Collection siblingAlerts = graph.getTransitAlertService().getStopAlerts(stop.getParentStation().getId()); if (siblingAlerts != null) { diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java index 217b5dbd6a5..9eaaa6c008a 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java @@ -11,7 +11,7 @@ import java.util.TimeZone; import org.locationtech.jts.geom.Coordinate; import org.opentripplanner.common.geometry.SphericalDistanceLibrary; -import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.TripPattern; import org.opentripplanner.model.calendar.ServiceDate; import org.opentripplanner.model.plan.Itinerary; @@ -157,8 +157,8 @@ private Leg mapTransitLeg( boolean firstLeg ) { - Stop boardStop = transitLayer.getStopByIndex(pathLeg.fromStop()); - Stop alightStop = transitLayer.getStopByIndex(pathLeg.toStop()); + var boardStop = transitLayer.getStopByIndex(pathLeg.fromStop()); + var alightStop = transitLayer.getStopByIndex(pathLeg.toStop()); TripSchedule tripSchedule = pathLeg.trip(); TripTimes tripTimes = tripSchedule.getOriginalTripTimes(); @@ -228,8 +228,8 @@ private Leg mapTransitLeg( } private List mapTransferLeg(TransferPathLeg pathLeg, TraverseMode transferMode) { - Stop transferFromStop = transitLayer.getStopByIndex(pathLeg.fromStop()); - Stop transferToStop = transitLayer.getStopByIndex(pathLeg.toStop()); + var transferFromStop = transitLayer.getStopByIndex(pathLeg.fromStop()); + var transferToStop = transitLayer.getStopByIndex(pathLeg.toStop()); Transfer transfer = ((TransferWithDuration) pathLeg.transfer()).transfer(); Place from = Place.forStop(transferFromStop, null, null); @@ -330,7 +330,7 @@ public static void propagateStopPlaceNamesToWalkingLegs(List legs) { /** * Maps stops for transit legs. */ - private Place mapStopToPlace(Stop stop, Integer stopIndex, TripTimes tripTimes) { + private Place mapStopToPlace(StopLocation stop, Integer stopIndex, TripTimes tripTimes) { return Place.forStop(stop, stopIndex, tripTimes.getOriginalGtfsStopSequence(stopIndex)); } @@ -347,7 +347,7 @@ private List extractIntermediateStops(TransitPathLeg TripSchedule tripSchedule = pathLeg.trip(); for (int i = boardStopIndexInPattern + 1; i < alightStopIndexInPattern; i++) { - Stop stop = tripPattern.getStopPattern().getStops()[i]; + var stop = tripPattern.getStopPattern().getStops()[i]; Place place = mapStopToPlace(stop, i, tripSchedule.getOriginalTripTimes()); StopArrival visit = new StopArrival( diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/StopIndexForRaptor.java b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/StopIndexForRaptor.java index b7c4c25fcae..39bbacaca6c 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/StopIndexForRaptor.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/StopIndexForRaptor.java @@ -5,7 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTransferPriority; import org.opentripplanner.routing.algorithm.raptor.transit.cost.RaptorCostConverter; @@ -16,7 +16,7 @@ *

* Raptor uses an integer index to reference stops. This is not the stop id, but just a * sequence number - an index. Hence we donĀ“t care about the order - as long as the order does - * not change. Raptor reference stops as integers for performance reasons, it never access + * not change. Raptor reference stops as integers for performance reasons, it never accesses * stops, it does not need to. The returned itineraries from Raptor contain stop indexes, not * references to stops, so OTP must maintain the stop index. *

@@ -27,11 +27,11 @@ * stored in the {@link TransitLayer}. */ public class StopIndexForRaptor { - public final List stopsByIndex; - public final Map indexByStop = new HashMap<>(); + public final List stopsByIndex; + public final Map indexByStop = new HashMap<>(); public final int[] stopBoardAlightCosts; - public StopIndexForRaptor(Collection stops, TransitTuningParameters tuningParameters) { + public StopIndexForRaptor(Collection stops, TransitTuningParameters tuningParameters) { this.stopsByIndex = new ArrayList<>(stops); initializeIndexByStop(); this.stopBoardAlightCosts = createStopBoardAlightCosts(stopsByIndex, tuningParameters); @@ -49,7 +49,7 @@ void initializeIndexByStop() { /** * Create a list of stop indexes for a given list of stops. */ - public int[] listStopIndexesForStops(Stop[] stops) { + public int[] listStopIndexesForStops(StopLocation[] stops) { int[] stopIndex = new int[stops.length]; for (int i = 0; i < stops.length; i++) { @@ -62,7 +62,7 @@ public int[] listStopIndexesForStops(Stop[] stops) { * Create static board/alight cost for Raptor to include for each stop. */ private static int[] createStopBoardAlightCosts( - List stops, + List stops, TransitTuningParameters tuningParams ) { if(!tuningParams.enableStopTransferPriority()) { diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/TransitLayer.java b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/TransitLayer.java index 69e3f4436cf..59574f974db 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/TransitLayer.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/TransitLayer.java @@ -10,6 +10,7 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.transfer.TransferService; import org.opentripplanner.routing.algorithm.raptor.transit.request.RaptorRequestTransferCache; import org.opentripplanner.routing.api.request.RoutingRequest; @@ -79,7 +80,7 @@ public int getIndexByStop(Stop stop) { } @Nullable - public Stop getStopByIndex(int stop) { + public StopLocation getStopByIndex(int stop) { return stop != -1 ? this.stopIndex.stopsByIndex.get(stop) : null; } diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransfersMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransfersMapper.java index 47ec4e5a97f..0be15e583fc 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransfersMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransfersMapper.java @@ -22,7 +22,7 @@ static List> mapTransfers( List> transferByStopIndex = new ArrayList<>(); for (int i = 0; i < stopIndex.stopsByIndex.size(); ++i) { - Stop stop = stopIndex.stopsByIndex.get(i); + var stop = stopIndex.stopsByIndex.get(i); ArrayList list = new ArrayList<>(); transferByStopIndex.add(list); diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransitLayerMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransitLayerMapper.java index 7eb269f352f..504074741cc 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransitLayerMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/TransitLayerMapper.java @@ -63,7 +63,7 @@ private TransitLayer map(TransitTuningParameters tuningParameters) { LOG.info("Mapping transitLayer from Graph..."); - stopIndex = new StopIndexForRaptor(graph.index.getAllStops(), tuningParameters); + stopIndex = new StopIndexForRaptor(graph.index.getAllStops(), tuningParameters); Collection allTripPatterns = graph.tripPatternForId.values(); newTripPatternForOld = mapOldTripPatternToRaptorTripPattern( diff --git a/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/configure/TransferOptimizationServiceConfigurator.java b/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/configure/TransferOptimizationServiceConfigurator.java index b7f06dae3d3..bfc764075bc 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/configure/TransferOptimizationServiceConfigurator.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/configure/TransferOptimizationServiceConfigurator.java @@ -1,7 +1,7 @@ package org.opentripplanner.routing.algorithm.transferoptimization.configure; import java.util.function.IntFunction; -import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.transfer.TransferService; import org.opentripplanner.routing.algorithm.transferoptimization.OptimizeTransferService; import org.opentripplanner.routing.algorithm.transferoptimization.api.TransferOptimizationParameters; @@ -23,7 +23,7 @@ * Responsible for assembly of the prioritized-transfer services. */ public class TransferOptimizationServiceConfigurator { - private final IntFunction stopLookup; + private final IntFunction stopLookup; private final RaptorStopNameResolver stopNameResolver; private final TransferService transferService; private final RaptorTransitDataProvider transitDataProvider; @@ -33,7 +33,7 @@ public class TransferOptimizationServiceConfigurator stopLookup, + IntFunction stopLookup, RaptorStopNameResolver stopNameResolver, TransferService transferService, RaptorTransitDataProvider transitDataProvider, @@ -54,7 +54,7 @@ private TransferOptimizationServiceConfigurator( * Scope: Request */ public static OptimizeTransferService createOptimizeTransferService( - IntFunction stopLookup, + IntFunction stopLookup, RaptorStopNameResolver stopNameResolver, TransferService transferService, RaptorTransitDataProvider transitDataProvider, diff --git a/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/model/OptimizedPathTail.java b/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/model/OptimizedPathTail.java index c9710ccc567..941c56528c1 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/model/OptimizedPathTail.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/model/OptimizedPathTail.java @@ -86,7 +86,7 @@ public OptimizedPathTail mutate() { /** Start by adding the last transit leg with the egress leg attached. */ public OptimizedPathTail addTransitTail(TransitPathLeg leg) { var next = leg.nextLeg(); - // this could also be a transfer to a flex leg + // this can also be a transfer leg to a flex trip if(next.isTransferLeg()) { next = next.nextLeg(); } diff --git a/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/services/TransferServiceAdaptor.java b/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/services/TransferServiceAdaptor.java index 20ec84b9bde..d597dee0d1e 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/services/TransferServiceAdaptor.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/transferoptimization/services/TransferServiceAdaptor.java @@ -2,6 +2,7 @@ import java.util.function.IntFunction; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.Trip; import org.opentripplanner.model.transfer.ConstrainedTransfer; import org.opentripplanner.model.transfer.TransferService; @@ -20,12 +21,12 @@ * @param The TripSchedule type defined by the user of the raptor API. */ public class TransferServiceAdaptor { - private final IntFunction stopLookup; + private final IntFunction stopLookup; private final TransferService transferService; protected TransferServiceAdaptor( - IntFunction stopLookup, + IntFunction stopLookup, TransferService transferService ) { this.stopLookup = stopLookup; @@ -33,7 +34,7 @@ protected TransferServiceAdaptor( } public static TransferServiceAdaptor create( - IntFunction stopLookup, + IntFunction stopLookup, TransferService transferService ) { return new TransferServiceAdaptor<>(stopLookup, transferService); @@ -61,7 +62,7 @@ protected ConstrainedTransfer findTransfer(TripStopTime from, T toTrip, int t ); } - private Stop stop(int index) { + private StopLocation stop(int index) { return stopLookup.apply(index); } diff --git a/src/main/java/org/opentripplanner/routing/graph/Graph.java b/src/main/java/org/opentripplanner/routing/graph/Graph.java index 6dc23086f18..4973d914fd8 100644 --- a/src/main/java/org/opentripplanner/routing/graph/Graph.java +++ b/src/main/java/org/opentripplanner/routing/graph/Graph.java @@ -911,7 +911,7 @@ public TransitAlertService getTransitAlertService() { return transitAlertService; } - private Collection getStopsForId(FeedScopedId id) { + private Collection getStopsForId(FeedScopedId id) { // GroupOfStations GroupOfStations groupOfStations = groupOfStationsById.get(id); @@ -931,7 +931,7 @@ private Collection getStopsForId(FeedScopedId id) { return station.getChildStops(); } // Single stop - Stop stop = index.getStopForId(id); + var stop = index.getStopForId(id); if (stop != null) { return Collections.singleton(stop); } @@ -945,7 +945,7 @@ private Collection getStopsForId(FeedScopedId id) { * @return The associated TransitStopVertex or all underlying TransitStopVertices */ public Set getStopVerticesById(FeedScopedId id) { - Collection stops = getStopsForId(id); + var stops = getStopsForId(id); if (stops == null) { return null; @@ -991,7 +991,7 @@ public Collection getNotices() { } /** Get all stops within a given bounding box. */ - public Collection getStopsByBoundingBox(double minLat, double minLon, double maxLat, double maxLon) { + public Collection getStopsByBoundingBox(double minLat, double minLon, double maxLat, double maxLon) { Envelope envelope = new Envelope( new Coordinate(minLon, minLat), new Coordinate(maxLon, maxLat) diff --git a/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java b/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java index ad4796c4111..b7ae5c91a74 100644 --- a/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java +++ b/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java @@ -11,6 +11,7 @@ import org.opentripplanner.common.geometry.CompactElevationProfile; import org.opentripplanner.common.geometry.HashGridSpatialIndex; import org.opentripplanner.ext.flex.FlexIndex; +import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.model.Agency; import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.MultiModalStation; @@ -42,7 +43,7 @@ public class GraphIndex { // TODO: consistently key on model object or id string private final Map agencyForId = Maps.newHashMap(); private final Map operatorForId = Maps.newHashMap(); - private final Map stopForId = Maps.newHashMap(); + private final Map stopForId = Maps.newHashMap(); private final Map tripForId = Maps.newHashMap(); private final Map routeForId = Maps.newHashMap(); private final Map stopVertexForStop = Maps.newHashMap(); @@ -88,7 +89,7 @@ public GraphIndex(Graph graph) { patternForTrip.put(trip, pattern); tripForId.put(trip.getId(), trip); } - for (Stop stop : pattern.getStops()) { + for (StopLocation stop : pattern.getStops()) { patternsForStopId.put(stop, pattern); } } @@ -108,9 +109,11 @@ public GraphIndex(Graph graph) { for (Route route : flexIndex.routeById.values()) { routeForId.put(route.getId(), route); } - for (Trip trip : flexIndex.tripById.values()) { - tripForId.put(trip.getId(), trip); + for (FlexTrip flexTrip : flexIndex.tripById.values()) { + tripForId.put(flexTrip.getId(), flexTrip.getTrip()); + flexTrip.getStops().stream().forEach(stop -> stopForId.put(stop.getId(), stop)); } + } LOG.info("GraphIndex init complete."); @@ -155,7 +158,7 @@ public Agency getAgencyForId(FeedScopedId id) { return agencyForId.get(id); } - public Stop getStopForId(FeedScopedId id) { + public StopLocation getStopForId(FeedScopedId id) { return stopForId.get(id); } @@ -172,7 +175,7 @@ public void addRoutes(Route route) { } /** Dynamically generate the set of Routes passing though a Stop on demand. */ - public Set getRoutesForStop(Stop stop) { + public Set getRoutesForStop(StopLocation stop) { Set routes = Sets.newHashSet(); for (TripPattern p : getPatternsForStop(stop)) { routes.add(p.getRoute()); @@ -191,7 +194,7 @@ public Collection getPatternsForStop(StopLocation stop) { * TimetableSnapshot. */ public Collection getPatternsForStop( - Stop stop, + StopLocation stop, TimetableSnapshot timetableSnapshot ) { Set tripPatterns = new HashSet<>(getPatternsForStop(stop)); @@ -214,7 +217,7 @@ public Map getOperatorForId() { return operatorForId; } - public Collection getAllStops() { + public Collection getAllStops() { return stopForId.values(); } diff --git a/src/main/java/org/opentripplanner/routing/graphfinder/PatternAtStop.java b/src/main/java/org/opentripplanner/routing/graphfinder/PatternAtStop.java index 8fdd9ea5764..195ef5fad87 100644 --- a/src/main/java/org/opentripplanner/routing/graphfinder/PatternAtStop.java +++ b/src/main/java/org/opentripplanner/routing/graphfinder/PatternAtStop.java @@ -6,6 +6,7 @@ import java.util.Objects; import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.TripPattern; import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.model.base.ToStringBuilder; @@ -20,10 +21,10 @@ public class PatternAtStop { public String id; - public Stop stop; + public StopLocation stop; public TripPattern pattern; - public PatternAtStop(Stop stop, TripPattern pattern) { + public PatternAtStop(StopLocation stop, TripPattern pattern) { this.id = toId(stop, pattern); this.stop = stop; this.pattern = pattern; @@ -33,7 +34,7 @@ public PatternAtStop(Stop stop, TripPattern pattern) { * Converts the ids of the pattern and stop to an opaque id, which can be supplied to the users * to be used for refetching the combination. */ - private static String toId(Stop stop, TripPattern pattern) { + private static String toId(StopLocation stop, TripPattern pattern) { Base64.Encoder encoder = Base64.getEncoder(); return encoder.encodeToString(stop.getId().toString().getBytes(StandardCharsets.UTF_8)) + ";" + encoder.encodeToString(pattern.getId().toString().getBytes(StandardCharsets.UTF_8)); @@ -43,7 +44,7 @@ private static String toId(Stop stop, TripPattern pattern) { * Convert an id generated by the toId method to an instance of PatternAtStop. Uses the supplied * routingService to fetch the TripPattern and Stop instances. * - * @see PatternAtStop#toId(Stop, TripPattern) + * @see PatternAtStop#toId(StopLocation, TripPattern) */ public static PatternAtStop fromId(RoutingService routingService, String id) { String[] parts = id.split(";", 2); diff --git a/src/main/java/org/opentripplanner/routing/impl/TransitAlertServiceImpl.java b/src/main/java/org/opentripplanner/routing/impl/TransitAlertServiceImpl.java index f0525201ded..6994d8d5a6d 100644 --- a/src/main/java/org/opentripplanner/routing/impl/TransitAlertServiceImpl.java +++ b/src/main/java/org/opentripplanner/routing/impl/TransitAlertServiceImpl.java @@ -51,7 +51,7 @@ public Collection getStopAlerts(FeedScopedId stopId) { if (result.isEmpty()) { // Search for alerts on parent-stop if (graph != null && graph.index != null) { - Stop quay = graph.index.getStopForId(stopId); + var quay = graph.index.getStopForId(stopId); if (quay != null) { // TODO - SIRI: Add alerts from parent- and multimodal-stops diff --git a/src/main/java/org/opentripplanner/routing/stoptimes/StopTimesHelper.java b/src/main/java/org/opentripplanner/routing/stoptimes/StopTimesHelper.java index 83c072266da..a5665f32a08 100644 --- a/src/main/java/org/opentripplanner/routing/stoptimes/StopTimesHelper.java +++ b/src/main/java/org/opentripplanner/routing/stoptimes/StopTimesHelper.java @@ -3,6 +3,7 @@ import com.google.common.collect.MinMaxPriorityQueue; import org.opentripplanner.model.PickDrop; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTimesInPattern; import org.opentripplanner.model.Timetable; import org.opentripplanner.model.TimetableSnapshot; @@ -44,7 +45,7 @@ public class StopTimesHelper { public static List stopTimesForStop( RoutingService routingService, TimetableSnapshot timetableSnapshot, - Stop stop, + StopLocation stop, long startTime, int timeRange, int numberOfDepartures, @@ -143,7 +144,7 @@ private static List getStopTimesInPattern( */ public static List stopTimesForStop( RoutingService routingService, - Stop stop, + StopLocation stop, ServiceDate serviceDate, ArrivalDeparture arrivalDeparture ) { @@ -163,7 +164,7 @@ public static List stopTimesForStop( .getRoute() .getAgency().getId()); int sidx = 0; - for (Stop currStop : pattern.getStopPattern().getStops()) { + for (var currStop : pattern.getStopPattern().getStops()) { if (currStop == stop) { if(skipByPickUpDropOff(pattern, arrivalDeparture, sidx)) continue; for (TripTimes t : tt.getTripTimes()) { @@ -195,7 +196,7 @@ public static List stopTimesForStop( public static List stopTimesForPatternAtStop( RoutingService routingService, TimetableSnapshot timetableSnapshot, - Stop stop, + StopLocation stop, TripPattern pattern, long startTime, int timeRange, @@ -226,7 +227,7 @@ public static List stopTimesForPatternAtStop( private static Queue listTripTimeShortsForPatternAtStop( RoutingService routingService, TimetableSnapshot timetableSnapshot, - Stop stop, + StopLocation stop, TripPattern pattern, long startTime, int timeRange, @@ -266,7 +267,7 @@ private static Queue listTripTimeShortsForPatternAtStop( int secondsSinceMidnight = sd.secondsSinceMidnight(startTime); int stopIndex = 0; - for (Stop currStop : pattern.getStopPattern().getStops()) { + for (var currStop : pattern.getStopPattern().getStops()) { if (currStop == stop) { if (skipByPickUpDropOff(pattern, arrivalDeparture, stopIndex)) { continue; } diff --git a/src/main/java/org/opentripplanner/routing/vertextype/TransitBoardingAreaVertex.java b/src/main/java/org/opentripplanner/routing/vertextype/TransitBoardingAreaVertex.java index 98df959f71a..617f84c08ef 100644 --- a/src/main/java/org/opentripplanner/routing/vertextype/TransitBoardingAreaVertex.java +++ b/src/main/java/org/opentripplanner/routing/vertextype/TransitBoardingAreaVertex.java @@ -20,13 +20,13 @@ public TransitBoardingAreaVertex(Graph graph, BoardingArea boardingArea) { super( graph, boardingArea.getId().toString(), - boardingArea.getLon(), - boardingArea.getLat() + boardingArea.getCoordinate().longitude(), + boardingArea.getCoordinate().latitude() ); this.boardingArea = boardingArea; this.wheelchairAccessible = boardingArea.getWheelchairBoarding() != WheelChairBoarding.NOT_POSSIBLE; //Adds this vertex into graph envelope so that we don't need to loop over all vertices - graph.expandToInclude(boardingArea.getLon(), boardingArea.getLat()); + graph.expandToInclude(boardingArea.getCoordinate().longitude(), boardingArea.getCoordinate().latitude()); } @Override diff --git a/src/main/java/org/opentripplanner/routing/vertextype/TransitEntranceVertex.java b/src/main/java/org/opentripplanner/routing/vertextype/TransitEntranceVertex.java index a8b40ebf906..e57d9eaad94 100644 --- a/src/main/java/org/opentripplanner/routing/vertextype/TransitEntranceVertex.java +++ b/src/main/java/org/opentripplanner/routing/vertextype/TransitEntranceVertex.java @@ -25,13 +25,13 @@ public TransitEntranceVertex(Graph graph, Entrance entrance) { super( graph, entrance.getId().toString(), - entrance.getLon(), - entrance.getLat() + entrance.getCoordinate().longitude(), + entrance.getCoordinate().latitude() ); this.entrance = entrance; this.wheelchairEntrance = entrance.getWheelchairBoarding() != WheelChairBoarding.NOT_POSSIBLE; //Adds this vertex into graph envelope so that we don't need to loop over all vertices - graph.expandToInclude(entrance.getLon(), entrance.getLat()); + graph.expandToInclude(entrance.getCoordinate().longitude(), entrance.getCoordinate().latitude()); } @Override diff --git a/src/main/java/org/opentripplanner/routing/vertextype/TransitPathwayNodeVertex.java b/src/main/java/org/opentripplanner/routing/vertextype/TransitPathwayNodeVertex.java index 152837b8eb6..2092299c2a4 100644 --- a/src/main/java/org/opentripplanner/routing/vertextype/TransitPathwayNodeVertex.java +++ b/src/main/java/org/opentripplanner/routing/vertextype/TransitPathwayNodeVertex.java @@ -25,13 +25,13 @@ public TransitPathwayNodeVertex(Graph graph, PathwayNode node) { super( graph, node.getId().toString(), - node.getLon(), - node.getLat() + node.getCoordinate().longitude(), + node.getCoordinate().latitude() ); this.node = node; this.wheelchairEntrance = node.getWheelchairBoarding() != WheelChairBoarding.NOT_POSSIBLE; //Adds this vertex into graph envelope so that we don't need to loop over all vertices - graph.expandToInclude(node.getLon(), node.getLat()); + graph.expandToInclude(node.getCoordinate().longitude(), node.getCoordinate().latitude()); } @Override diff --git a/src/main/java/org/opentripplanner/updater/GraphUpdaterManager.java b/src/main/java/org/opentripplanner/updater/GraphUpdaterManager.java index aa8a8e1a0f8..e692064c8d5 100644 --- a/src/main/java/org/opentripplanner/updater/GraphUpdaterManager.java +++ b/src/main/java/org/opentripplanner/updater/GraphUpdaterManager.java @@ -202,7 +202,7 @@ private void reportReadinessForUpdaters() { while (true) { try { if (updaterList.stream().allMatch(GraphUpdater::isPrimed)) { - LOG.info("OTP UPDATERS INITIALIZED - OTP is read for routing!"); + LOG.info("OTP UPDATERS INITIALIZED - OTP is ready for routing!"); return; } //noinspection BusyWait diff --git a/src/main/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSource.java b/src/main/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSource.java index e6b4540bb8a..f91d89802d2 100644 --- a/src/main/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSource.java +++ b/src/main/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSource.java @@ -8,6 +8,7 @@ import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.Route; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopPattern; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Timetable; @@ -396,7 +397,7 @@ private boolean validateAndHandleAddedTrip(final Graph graph, final TripUpdate t } // Check whether all stop times are available and all stops exist - final List stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate); + final var stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate); if (stops == null) { return false; } @@ -417,11 +418,11 @@ private boolean validateAndHandleAddedTrip(final Graph graph, final TripUpdate t * @param tripUpdate trip update * @return stops when stop time updates are correct; null if there are errors */ - private List checkNewStopTimeUpdatesAndFindStops(final String feedId, final TripUpdate tripUpdate) { + private List checkNewStopTimeUpdatesAndFindStops(final String feedId, final TripUpdate tripUpdate) { Integer previousStopSequence = null; Long previousTime = null; final List stopTimeUpdates = tripUpdate.getStopTimeUpdateList(); - final List stops = new ArrayList<>(stopTimeUpdates.size()); + final List stops = new ArrayList<>(stopTimeUpdates.size()); for (int index = 0; index < stopTimeUpdates.size(); ++index) { final StopTimeUpdate stopTimeUpdate = stopTimeUpdates.get(index); @@ -451,7 +452,7 @@ private List checkNewStopTimeUpdatesAndFindStops(final String feedId, fina // Find stops if (stopTimeUpdate.hasStopId()) { // Find stop - final Stop stop = getStopForStopId(feedId, stopTimeUpdate.getStopId()); + final var stop = getStopForStopId(feedId, stopTimeUpdate.getStopId()); if (stop != null) { // Remember stop stops.add(stop); @@ -542,7 +543,7 @@ private boolean isStopSkipped(final StopTimeUpdate stopTimeUpdate) { * @param serviceDate service date for added trip * @return true iff successful */ - private boolean handleAddedTrip(final Graph graph, final TripUpdate tripUpdate, final List stops, + private boolean handleAddedTrip(final Graph graph, final TripUpdate tripUpdate, final List stops, final String feedId, final ServiceDate serviceDate) { // Preconditions Preconditions.checkNotNull(stops); @@ -604,7 +605,7 @@ private boolean handleAddedTrip(final Graph graph, final TripUpdate tripUpdate, trip.setServiceId(serviceIds.iterator().next()); } - final boolean success = addTripToGraphAndBuffer(feedId, graph, trip, tripUpdate, stops, serviceDate, RealTimeState.ADDED); + final boolean success = addTripToGraphAndBuffer(graph, trip, tripUpdate, stops, serviceDate, RealTimeState.ADDED); return success; } @@ -619,8 +620,8 @@ private boolean handleAddedTrip(final Graph graph, final TripUpdate tripUpdate, * @param realTimeState real-time state of new trip * @return true iff successful */ - private boolean addTripToGraphAndBuffer(final String feedId, final Graph graph, final Trip trip, - final TripUpdate tripUpdate, final List stops, final ServiceDate serviceDate, + private boolean addTripToGraphAndBuffer(final Graph graph, final Trip trip, + final TripUpdate tripUpdate, final List stops, final ServiceDate serviceDate, final RealTimeState realTimeState) { // Preconditions @@ -636,7 +637,7 @@ private boolean addTripToGraphAndBuffer(final String feedId, final Graph graph, final List stopTimes = new ArrayList<>(tripUpdate.getStopTimeUpdateCount()); for (int index = 0; index < tripUpdate.getStopTimeUpdateCount(); ++index) { final StopTimeUpdate stopTimeUpdate = tripUpdate.getStopTimeUpdate(index); - final Stop stop = stops.get(index); + final var stop = stops.get(index); // Determine whether stop is skipped final boolean skippedStop = isStopSkipped(stopTimeUpdate); @@ -852,7 +853,7 @@ private boolean validateAndHandleModifiedTrip(final Graph graph, final TripUpdat } // Check whether all stop times are available and all stops exist - List stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate); + var stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate); if (stops == null) { return false; } @@ -877,7 +878,7 @@ private boolean validateAndHandleModifiedTrip(final Graph graph, final TripUpdat * @param serviceDate service date for modified trip * @return true iff successful */ - private boolean handleModifiedTrip(final Graph graph, final Trip trip, final TripUpdate tripUpdate, final List stops, + private boolean handleModifiedTrip(final Graph graph, final Trip trip, final TripUpdate tripUpdate, final List stops, final String feedId, final ServiceDate serviceDate) { // Preconditions Preconditions.checkNotNull(stops); @@ -895,7 +896,7 @@ private boolean handleModifiedTrip(final Graph graph, final Trip trip, final Tri // Add new trip final boolean success = - addTripToGraphAndBuffer(feedId, graph, trip, tripUpdate, stops, serviceDate, RealTimeState.MODIFIED); + addTripToGraphAndBuffer(graph, trip, tripUpdate, stops, serviceDate, RealTimeState.MODIFIED); return success; } @@ -980,7 +981,7 @@ private Trip getTripForTripId(String feedId, String tripId) { * @param stopId trip id without the agency * @return stop or null if stop doesn't exist */ - private Stop getStopForStopId(String feedId, String stopId) { + private StopLocation getStopForStopId(String feedId, String stopId) { return routingService.getStopForId(new FeedScopedId(feedId, stopId)); } } diff --git a/src/main/java/org/opentripplanner/util/PolylineEncoder.java b/src/main/java/org/opentripplanner/util/PolylineEncoder.java index b1f2d58cf96..97f378660de 100644 --- a/src/main/java/org/opentripplanner/util/PolylineEncoder.java +++ b/src/main/java/org/opentripplanner/util/PolylineEncoder.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.Polygon; import org.opentripplanner.util.model.EncodedPolylineBean; import org.locationtech.jts.geom.Coordinate; @@ -32,13 +34,18 @@ public static EncodedPolylineBean createEncodings(Iterable points) { public static EncodedPolylineBean createEncodings(Geometry geometry) { if (geometry instanceof LineString) { - LineString string = (LineString) geometry; Coordinate[] coordinates = string.getCoordinates(); return createEncodings(new CoordinateList(coordinates)); } else if (geometry instanceof MultiLineString) { MultiLineString mls = (MultiLineString) geometry; return createEncodings(new CoordinateList(mls.getCoordinates())); + } else if (geometry instanceof Polygon) { + Polygon polygon = (Polygon) geometry; + return createEncodings(new CoordinateList(polygon.getCoordinates())); + } else if (geometry instanceof Point) { + Point point = (Point) geometry; + return createEncodings(new CoordinateList(point.getCoordinates())); } else { throw new IllegalArgumentException(geometry.toString()); } diff --git a/src/test/java/org/opentripplanner/gtfs/GtfsContextBuilder.java b/src/test/java/org/opentripplanner/gtfs/GtfsContextBuilder.java index 76aa1a7f89d..a318656be7c 100644 --- a/src/test/java/org/opentripplanner/gtfs/GtfsContextBuilder.java +++ b/src/test/java/org/opentripplanner/gtfs/GtfsContextBuilder.java @@ -93,18 +93,6 @@ public GtfsContextBuilder withDeduplicator(Deduplicator deduplicator) { return this; } - /** - * The {@link org.opentripplanner.graph_builder.module.GtfsModule} is responsible for repairing - * StopTimes for all trips and trip patterns generation, so turn this feature off - * when using GtfsModule to load data. - * - * This feature is turned on by default. - */ - public GtfsContextBuilder turnOffRepairStopTimesAndTripPatternsGeneration() { - this.repairStopTimesAndGenerateTripPatterns = false; - return this; - } - /** * This method will: *

    diff --git a/src/test/java/org/opentripplanner/gtfs/mapping/BoardingAreaMapperTest.java b/src/test/java/org/opentripplanner/gtfs/mapping/BoardingAreaMapperTest.java index 476f6560c31..c8aca8d93d9 100644 --- a/src/test/java/org/opentripplanner/gtfs/mapping/BoardingAreaMapperTest.java +++ b/src/test/java/org/opentripplanner/gtfs/mapping/BoardingAreaMapperTest.java @@ -73,8 +73,8 @@ public void testMap() { assertEquals("A:B1", result.getId().toString()); assertEquals(CODE, result.getCode()); assertEquals(DESC, result.getDescription()); - assertEquals(LAT, result.getLat(), 0.0001d); - assertEquals(LON, result.getLon(), 0.0001d); + assertEquals(LAT, result.getCoordinate().latitude(), 0.0001d); + assertEquals(LON, result.getCoordinate().longitude(), 0.0001d); assertEquals(NAME, result.getName()); assertEquals(WHEELCHAIR_BOARDING, result.getWheelchairBoarding()); } @@ -104,7 +104,7 @@ public void testThrowsNPEWhenCoordinateUnset() { org.opentripplanner.model.BoardingArea result = subject.map(input); - result.getLat(); + result.getCoordinate().latitude(); } /** Mapping the same object twice, should return the the same instance. */ diff --git a/src/test/java/org/opentripplanner/gtfs/mapping/EntranceMapperTest.java b/src/test/java/org/opentripplanner/gtfs/mapping/EntranceMapperTest.java index 46ff6017fdd..adfa7803fea 100644 --- a/src/test/java/org/opentripplanner/gtfs/mapping/EntranceMapperTest.java +++ b/src/test/java/org/opentripplanner/gtfs/mapping/EntranceMapperTest.java @@ -74,8 +74,8 @@ public void testMap() throws Exception { assertEquals("A:E1", result.getId().toString()); assertEquals(CODE, result.getCode()); assertEquals(DESC, result.getDescription()); - assertEquals(LAT, result.getLat(), 0.0001d); - assertEquals(LON, result.getLon(), 0.0001d); + assertEquals(LAT, result.getCoordinate().latitude(), 0.0001d); + assertEquals(LON, result.getCoordinate().longitude(), 0.0001d); assertEquals(NAME, result.getName()); assertEquals(WheelChairBoarding.POSSIBLE, result.getWheelchairBoarding()); } @@ -106,7 +106,7 @@ public void verifyMissingCoordinateThrowsException() { org.opentripplanner.model.Entrance result = subject.map(input); // Exception expected because the entrence and the parent do not have a coordinate - result.getLat(); + result.getCoordinate().latitude(); } /** Mapping the same object twice, should return the the same instance. */ diff --git a/src/test/java/org/opentripplanner/gtfs/mapping/PathwayNodeMapperTest.java b/src/test/java/org/opentripplanner/gtfs/mapping/PathwayNodeMapperTest.java index e751d10e693..f110514ffaf 100644 --- a/src/test/java/org/opentripplanner/gtfs/mapping/PathwayNodeMapperTest.java +++ b/src/test/java/org/opentripplanner/gtfs/mapping/PathwayNodeMapperTest.java @@ -74,8 +74,8 @@ public void testMap() throws Exception { assertEquals("A:N1", result.getId().toString()); assertEquals(CODE, result.getCode()); assertEquals(DESC, result.getDescription()); - assertEquals(LAT, result.getLat(), 0.0001d); - assertEquals(LON, result.getLon(), 0.0001d); + assertEquals(LAT, result.getCoordinate().latitude(), 0.0001d); + assertEquals(LON, result.getCoordinate().longitude(), 0.0001d); assertEquals(NAME, result.getName()); assertEquals(WheelChairBoarding.POSSIBLE, result.getWheelchairBoarding()); } @@ -105,7 +105,7 @@ public void verifyMissingCoordinateThrowsException() { org.opentripplanner.model.PathwayNode result = subject.map(input); - result.getLat(); + result.getCoordinate().latitude(); } /** Mapping the same object twice, should return the the same instance. */ diff --git a/src/test/java/org/opentripplanner/model/impl/OtpTransitServiceImplTest.java b/src/test/java/org/opentripplanner/model/impl/OtpTransitServiceImplTest.java index 63e015d6ea9..7d6255fc072 100644 --- a/src/test/java/org/opentripplanner/model/impl/OtpTransitServiceImplTest.java +++ b/src/test/java/org/opentripplanner/model/impl/OtpTransitServiceImplTest.java @@ -24,6 +24,7 @@ import org.opentripplanner.model.ShapePoint; import org.opentripplanner.model.Station; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTime; import org.opentripplanner.model.Trip; @@ -163,7 +164,7 @@ public void testGetStopForId() { @Test public void testGetStopsForStation() { - List stops = new ArrayList<>(subject.getStationForId(STATION_ID).getChildStops()); + List stops = new ArrayList<>(subject.getStationForId(STATION_ID).getChildStops()); assertEquals("[]", stops.toString()); } diff --git a/src/test/java/org/opentripplanner/netex/mapping/TripPatternMapperTest.java b/src/test/java/org/opentripplanner/netex/mapping/TripPatternMapperTest.java index a1d001d8069..fca09a102b4 100644 --- a/src/test/java/org/opentripplanner/netex/mapping/TripPatternMapperTest.java +++ b/src/test/java/org/opentripplanner/netex/mapping/TripPatternMapperTest.java @@ -57,7 +57,7 @@ public void testMapTripPattern() { assertEquals(4, tripPattern.getStops().size()); assertEquals(1, tripPattern.getTrips().size()); - List stops = tripPattern.getStops(); + var stops = tripPattern.getStops(); Trip trip = tripPattern.getTrips().get(0); assertEquals("RUT:ServiceJourney:1", trip.getId().getId()); diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/groupids/GroupByAllSameStationsTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/groupids/GroupByAllSameStationsTest.java index c1ee972acc7..4241c46b7da 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/groupids/GroupByAllSameStationsTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/groupids/GroupByAllSameStationsTest.java @@ -9,6 +9,7 @@ import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.Station; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.WgsCoordinate; import org.opentripplanner.model.plan.PlanTestConstants; class GroupByAllSameStationsTest implements PlanTestConstants { @@ -74,7 +75,7 @@ public void testMatchingItineraries() { Station createStation(String name) { - return new Station(new FeedScopedId(FEED_ID, name), name, null, null, null, null, null, null); + return new Station(new FeedScopedId(FEED_ID, name), name, new WgsCoordinate(0, 0), null, null, null, null, null); } } \ No newline at end of file diff --git a/src/test/java/org/opentripplanner/routing/algorithm/mapping/TransitSnapshotTest.java b/src/test/java/org/opentripplanner/routing/algorithm/mapping/TransitSnapshotTest.java index f65fd6b194f..9505d816ad1 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/mapping/TransitSnapshotTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/mapping/TransitSnapshotTest.java @@ -20,13 +20,9 @@ public class TransitSnapshotTest extends SnapshotTestBase { - static GenericLocation ptc = new GenericLocation("Rose Quarter Transit Center", - new FeedScopedId("prt", "79-tc"), null, null - ); + static GenericLocation ptc = GenericLocation.fromStopId("Rose Quarter Transit Center", "prt", "79-tc"); - static GenericLocation ps = new GenericLocation("NE 12th & Couch", - new FeedScopedId("prt", "6577"), null, null - ); + static GenericLocation ps = GenericLocation.fromStopId("NE 12th & Couch", "prt", "6577"); static GenericLocation p0 = new GenericLocation("SE Stark St. & SE 17th Ave. (P0)", null, 45.519320, -122.648567 diff --git a/src/test/java/org/opentripplanner/routing/algorithm/mapping/__snapshots__/TransitSnapshotTest.snap b/src/test/java/org/opentripplanner/routing/algorithm/mapping/__snapshots__/TransitSnapshotTest.snap index f279aa4d223..96228082f8c 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/mapping/__snapshots__/TransitSnapshotTest.snap +++ b/src/test/java/org/opentripplanner/routing/algorithm/mapping/__snapshots__/TransitSnapshotTest.snap @@ -10434,6 +10434,116 @@ org.opentripplanner.routing.algorithm.mapping.TransitSnapshotTest.test_trip_plan "latitude": 45.530205, "longitude": -122.666118 }, + "geometry": { + "SRID": 0, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "geometries": [ + { + "SRID": 0, + "coordinates": { + "coords": [ + -122.666118, + 45.530205 + ], + "dimension": 2 + }, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "rectangle": false, + "simple": true, + "valid": true + }, + { + "SRID": 0, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "holes": [ ], + "rectangle": false, + "shell": { + "SRID": 0, + "closed": true, + "empty": false, + "envelope": { + "maxx": -122.665648, + "maxy": 45.530703, + "minx": -122.667794, + "miny": 45.529724, + "null": false + }, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "points": { + "coords": [ + -122.666322, + 45.529724, + -122.667591, + 45.529829, + -122.667794, + 45.530244, + -122.66599, + 45.530703, + -122.665648, + 45.53069, + -122.665697, + 45.529888, + -122.666322, + 45.529724 + ], + "dimension": 2 + }, + "rectangle": false, + "ring": true, + "simple": true, + "valid": true + }, + "simple": true, + "valid": true + } + ], + "rectangle": false, + "simple": true, + "valid": true + }, "id": { "feedId": "prt", "id": "79-tc" @@ -12878,6 +12988,109 @@ org.opentripplanner.routing.algorithm.mapping.TransitSnapshotTest.test_trip_plan "latitude": 45.530205, "longitude": -122.666118 }, + "geometry": { + "SRID": 0, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "geometries": [ + { + "SRID": 0, + "coordinates": { + "coords": [ + -122.666118, + 45.530205 + ], + "dimension": 2 + }, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "rectangle": false, + "simple": true, + "valid": true + }, + { + "SRID": 0, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "holes": [ ], + "rectangle": false, + "shell": { + "SRID": 0, + "closed": true, + "empty": false, + "factory": { + "SRID": 0, + "coordinateSequenceFactory": { }, + "precisionModel": { + "floating": true, + "modelType": { + "name": "FLOATING" + }, + "scale": 0.0 + } + }, + "points": { + "coords": [ + -122.666322, + 45.529724, + -122.667591, + 45.529829, + -122.667794, + 45.530244, + -122.66599, + 45.530703, + -122.665648, + 45.53069, + -122.665697, + 45.529888, + -122.666322, + 45.529724 + ], + "dimension": 2 + }, + "rectangle": false, + "ring": true, + "simple": true, + "valid": true + }, + "simple": true, + "valid": true + } + ], + "rectangle": false, + "simple": true, + "valid": true + }, "id": { "feedId": "prt", "id": "79-tc" diff --git a/src/test/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/StopIndexForRaptorTest.java b/src/test/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/StopIndexForRaptorTest.java index c7aa83c41ce..7bd18b24bba 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/StopIndexForRaptorTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/raptor/transit/mappers/StopIndexForRaptorTest.java @@ -8,7 +8,9 @@ import org.opentripplanner.model.FeedScopedId; import org.opentripplanner.model.Station; import org.opentripplanner.model.Stop; +import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.StopTransferPriority; +import org.opentripplanner.model.WgsCoordinate; import org.opentripplanner.routing.algorithm.raptor.transit.StopIndexForRaptor; import org.opentripplanner.routing.algorithm.raptor.transit.TransitTuningParameters; @@ -20,7 +22,7 @@ public class StopIndexForRaptorTest { private final Stop STOP_3 = Stop.stopForTest("ID-" + 4, 0.0, 0.0); private final Stop STOP_4 = Stop.stopForTest("ID-" + 5, 0.0, 0.0); - private final List STOPS = Arrays.asList( + private final List STOPS = Arrays.asList( STOP_0, STOP_1, STOP_2, @@ -38,7 +40,7 @@ public class StopIndexForRaptorTest { @Test public void listStopIndexesForTripPattern() { - Stop[] input = new Stop[] { + StopLocation[] input = new Stop[] { STOP_0, STOP_2, STOP_4 @@ -66,6 +68,6 @@ public class StopIndexForRaptorTest { } Station createStation(String name, StopTransferPriority pri) { - return new Station(new FeedScopedId("F", name), name, null, null, null, null, null, pri); + return new Station(new FeedScopedId("F", name), name, new WgsCoordinate(0, 0), null, null, null, null, pri); } } diff --git a/src/test/java/org/opentripplanner/routing/graph/RoutingServiceTest.java b/src/test/java/org/opentripplanner/routing/graph/RoutingServiceTest.java index 8a04d25bf5c..765e8b4aacd 100644 --- a/src/test/java/org/opentripplanner/routing/graph/RoutingServiceTest.java +++ b/src/test/java/org/opentripplanner/routing/graph/RoutingServiceTest.java @@ -68,7 +68,7 @@ public void testPatternsCoherent() { assertEquals(pattern.getRoute(), route); } } - for (Stop stop : graph.index.getAllStops()) { + for (var stop : graph.index.getAllStops()) { for (TripPattern pattern : graph.index.getPatternsForStop(stop)) { assertTrue(pattern.getStopPattern().containsStop(stop.getId().toString())); } @@ -77,9 +77,9 @@ public void testPatternsCoherent() { public void testSpatialIndex() { String feedId = graph.getFeedIds().iterator().next(); - Stop stopJ = graph.index.getStopForId(new FeedScopedId(feedId, "J")); - Stop stopL = graph.index.getStopForId(new FeedScopedId(feedId, "L")); - Stop stopM = graph.index.getStopForId(new FeedScopedId(feedId, "M")); + var stopJ = graph.index.getStopForId(new FeedScopedId(feedId, "J")); + var stopL = graph.index.getStopForId(new FeedScopedId(feedId, "L")); + var stopM = graph.index.getStopForId(new FeedScopedId(feedId, "M")); TransitStopVertex stopvJ = graph.index.getStopVertexForStop().get(stopJ); TransitStopVertex stopvL = graph.index.getStopVertexForStop().get(stopL); TransitStopVertex stopvM = graph.index.getStopVertexForStop().get(stopM); diff --git a/src/test/java/org/opentripplanner/transit/raptor/_data/stoparrival/BasicPathTestCase.java b/src/test/java/org/opentripplanner/transit/raptor/_data/stoparrival/BasicPathTestCase.java index 0af48193de1..f7ef5dee1e0 100644 --- a/src/test/java/org/opentripplanner/transit/raptor/_data/stoparrival/BasicPathTestCase.java +++ b/src/test/java/org/opentripplanner/transit/raptor/_data/stoparrival/BasicPathTestCase.java @@ -10,12 +10,6 @@ import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.Test; -import org.opentripplanner.ext.flex.FlexAccessEgress; -import org.opentripplanner.model.Stop; -import org.opentripplanner.routing.algorithm.GraphRoutingTest; -import org.opentripplanner.routing.algorithm.raptor.transit.FlexAccessEgressAdapter; -import org.opentripplanner.routing.algorithm.raptor.transit.StopIndexForRaptor; -import org.opentripplanner.routing.algorithm.raptor.transit.TransitTuningParameters; import org.opentripplanner.routing.algorithm.raptor.transit.cost.DefaultCostCalculator; import org.opentripplanner.transit.raptor._data.RaptorTestConstants; import org.opentripplanner.transit.raptor._data.transit.TestTransfer; diff --git a/src/test/java/org/opentripplanner/transit/raptor/speed_test/model/Place.java b/src/test/java/org/opentripplanner/transit/raptor/speed_test/model/Place.java index c664c3d41c7..f9b24826e3e 100644 --- a/src/test/java/org/opentripplanner/transit/raptor/speed_test/model/Place.java +++ b/src/test/java/org/opentripplanner/transit/raptor/speed_test/model/Place.java @@ -19,7 +19,7 @@ public class Place { /** This is the stop index in the RaptorTransitData */ public final int rrStopIndex; - public Place(org.opentripplanner.model.Stop stop, int rrStopIndex) { + public Place(org.opentripplanner.model.StopLocation stop, int rrStopIndex) { this(stop.getName(), stop.getId(), stop.getCoordinate(), rrStopIndex); } diff --git a/src/test/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSourceTest.java b/src/test/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSourceTest.java index b9ce9afe348..c4589eb23c7 100644 --- a/src/test/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSourceTest.java +++ b/src/test/java/org/opentripplanner/updater/stoptime/TimetableSnapshotSourceTest.java @@ -269,7 +269,7 @@ public void testHandleAddedTrip() throws ParseException { // THEN // Find new pattern in graph starting from stop A - Stop stopA = graph.index.getStopForId(new FeedScopedId(feedId, "A")); + var stopA = graph.index.getStopForId(new FeedScopedId(feedId, "A")); // Get trip pattern of last (most recently added) outgoing edge // FIXME create a new test to see that add-trip realtime updates work TripPattern tripPattern = null; diff --git a/src/test/java/org/opentripplanner/util/PolylineEncoderTest.java b/src/test/java/org/opentripplanner/util/PolylineEncoderTest.java new file mode 100644 index 00000000000..cdf1580fe7c --- /dev/null +++ b/src/test/java/org/opentripplanner/util/PolylineEncoderTest.java @@ -0,0 +1,49 @@ +package org.opentripplanner.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.locationtech.jts.geom.Coordinate; +import org.opentripplanner.common.geometry.GeometryUtils; +import org.opentripplanner.util.model.EncodedPolylineBean; + +public class PolylineEncoderTest { + + @Test + public void testCreateEncodingsIterableOfCoordinate() { + // test taken from example usage + List points = new ArrayList(); + points.add(new Coordinate(-73.85062, 40.903125, Double.NaN)); + points.add(new Coordinate(-73.85136, 40.902261, Double.NaN)); + points.add(new Coordinate(-73.85151, 40.902066, Double.NaN)); + EncodedPolylineBean eplb = PolylineEncoder.createEncodings(points); + assertEquals("o{sxFl}vaMjDpCf@\\", eplb.getPoints()); + assertEquals(3, eplb.getLength()); + assertNull(eplb.getLevels()); + } + + @Test + public void testPolygon() { + var polygon = GeometryUtils.getGeometryFactory() + .createPolygon(new Coordinate[]{ + new Coordinate(0, 0), + new Coordinate(1, 1), + new Coordinate(2, 2), + new Coordinate(0, 0) + }); + var polyline = PolylineEncoder.createEncodings(polygon); + + assertEquals("??_ibE_ibE_ibE_ibE~reK~reK", polyline.getPoints()); + } + + @Test + public void testPoint() { + var point = GeometryUtils.getGeometryFactory().createPoint(new Coordinate(100, 100)); + var polyline = PolylineEncoder.createEncodings(point); + + assertEquals("_gjaR_gjaR", polyline.getPoints()); + } +} diff --git a/src/test/java/org/opentripplanner/util/TestPolylineEncoder.java b/src/test/java/org/opentripplanner/util/TestPolylineEncoder.java deleted file mode 100644 index 992e6b293cc..00000000000 --- a/src/test/java/org/opentripplanner/util/TestPolylineEncoder.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.opentripplanner.util; - -import java.util.ArrayList; -import java.util.List; - -import org.opentripplanner.util.model.EncodedPolylineBean; - -import org.locationtech.jts.geom.Coordinate; - -import junit.framework.TestCase; - -public class TestPolylineEncoder extends TestCase { - - public void testCreateEncodingsIterableOfCoordinate() { - // test taken from example usage - List points = new ArrayList(); - points.add(new Coordinate(-73.85062, 40.903125, Double.NaN)); - points.add(new Coordinate(-73.85136, 40.902261, Double.NaN)); - points.add(new Coordinate(-73.85151, 40.902066, Double.NaN)); - EncodedPolylineBean eplb = PolylineEncoder.createEncodings(points); - assertEquals("o{sxFl}vaMjDpCf@\\", eplb.getPoints()); - assertEquals(3, eplb.getLength()); - assertNull(eplb.getLevels()); - } -}