package graphs.shortestpaths; import graphs.BaseEdge; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; /** * {@link ShortestPathFinder} return an object implementing this interface. * The exact implementation returned will depend on the result of the shortest path computation. */ public interface ShortestPath> { /** Returns true iff a path was found from the start vertex to the end vertex. */ boolean exists(); /** * Returns the list of edges in the shortest path (in order from start to end). * @throws UnsupportedOperationException if no path exists from start to end */ List edges(); /** * Returns the list of vertices in the shortest path (in order from start to end). * @throws UnsupportedOperationException if no path exists from start to end */ List vertices(); /** * Returns the total weight of the edges in the shortest path. * @throws UnsupportedOperationException if no path exists from start to end */ default double totalWeight() { return edges().stream().mapToDouble(E::weight).sum(); } /** A result used when a shortest path is found from start to end. */ class Success> implements ShortestPath { private final List edges; /** * @param edges The list of edges in this shortest path (in order from start to end). * @throws IllegalArgumentException if edges is empty or null */ public Success(List edges) { if (edges == null || edges.isEmpty()) { throw new IllegalArgumentException("Input edges must not be null or empty."); } this.edges = edges; } @Override public boolean exists() { return true; } @Override public List edges() { return this.edges; } @Override public List vertices() { return Stream.concat( Stream.of(this.edges.get(0).from()), this.edges.stream().map(E::to) ).collect(Collectors.toList()); } } /** A result used when a shortest path consists of a single vertex (same start and end). */ class SingleVertex> implements ShortestPath { private final List vertex; /** * @param vertex the only vertex in the path */ public SingleVertex(V vertex) { this.vertex = List.of(vertex); } @Override public boolean exists() { return true; } @Override public List edges() { return List.of(); } @Override public List vertices() { return this.vertex; } } /** A result used when no path exists from start to end. */ class Failure> implements ShortestPath { public Failure() {} @Override public boolean exists() { return false; } @Override public List edges() { throw new UnsupportedOperationException("No path found."); } @Override public List vertices() { throw new UnsupportedOperationException("No path found."); } } }