/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.routing.impl; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.opentripplanner.routing.core.RoutingRequest; import org.opentripplanner.routing.core.State; import org.opentripplanner.routing.graph.Edge; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graph.Vertex; import org.opentripplanner.routing.pathparser.BasicPathParser; import org.opentripplanner.routing.pathparser.NoThruTrafficPathParser; import org.opentripplanner.routing.pathparser.PathParser; import org.opentripplanner.routing.pathparser.TransitStartPathParser; import org.opentripplanner.routing.services.GraphService; import org.opentripplanner.routing.services.PathService; import org.opentripplanner.routing.services.SPTService; import org.opentripplanner.routing.spt.GraphPath; import org.springframework.beans.factory.annotation.Autowired; /** * This path service allows paths to be generated with a specific first transit stop. The starting * time is treated as the time to start at that transit stop; a complete path is generated by * routing backwards from that transit stop to the requested origin. * * @author novalis * */ public class TransitStartPathService implements PathService { @Autowired public GraphService graphService; @Autowired public SPTService tspSptService; private PathService chainedPathService; @Override public List<GraphPath> getPaths(RoutingRequest options) { Graph graph = graphService.getGraph(options.routerId); options.setRoutingContext(graph); Vertex startingTransitStop = options.rctx.startingStop; if (startingTransitStop == null) { // no intermediate places specified, chain to main path service return chainedPathService.getPaths(options); } RoutingRequest subOptions = options.clone(); subOptions.setStartingTransitStopId(null); subOptions.setRoutingContext(graph, startingTransitStop, options.rctx.toVertex); List<GraphPath> pathsOnTransit = chainedPathService.getPaths(subOptions); if (pathsOnTransit == null || pathsOnTransit.size() == 0) return null; subOptions.setArriveBy(true); List<GraphPath> finishedPaths = new ArrayList<GraphPath>(pathsOnTransit.size()); for (GraphPath onTransit : pathsOnTransit) { // get path to origin subOptions.dateTime = onTransit.getStartTime(); subOptions.setRoutingContext(graph, options.rctx.fromVertex, startingTransitStop); subOptions.rctx.pathParsers = new PathParser[1]; subOptions.rctx.pathParsers[0] = new TransitStartPathParser(); List<GraphPath> pathsToTransit = chainedPathService.getPaths(subOptions); if (pathsToTransit == null || pathsToTransit.size() == 0) continue; GraphPath toTransit = pathsToTransit.get(0); subOptions.setArriveBy(false); subOptions.rctx.pathParsers = new PathParser[] { new BasicPathParser(), new NoThruTrafficPathParser() }; State firstState = toTransit.states.getFirst(); State state = new State(firstState.getVertex(), firstState.getTimeSeconds(), subOptions); LinkedList<Edge> edges = toTransit.edges; toTransit.edges = new LinkedList<Edge>(); toTransit.states = new LinkedList<State>(); for (Edge e : edges) { toTransit.states.add(state); toTransit.edges.add(e); state = e.traverse(state); } for (Edge e : onTransit.edges) { state = e.traverse(state); toTransit.edges.add(e); toTransit.states.add(state); } finishedPaths.add(toTransit); } return finishedPaths; } public PathService getChainedPathService() { return chainedPathService; } @Autowired public void setChainedPathService(PathService chainedPathService) { this.chainedPathService = chainedPathService; } }