/* 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;
}
}