-
Notifications
You must be signed in to change notification settings - Fork 257
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor(sections): Optional 리팩토링 * refactor(fixture): fixture 리팩토링 * docs(readme): step2 요구사항 작성 * refactor(test): 인수테스트 분리 * test(path): 최단경로 조회 인수 테스트 작성 * feat(controller): PathController 기능 및 테스트 추가 * feat(service): PathService 기능 및 테스트 추가 * feat(pathFinder): PathFinder 기능 및 테스트 추가 * refactor: 주 생성자 및 부 생성자 리팩토링 * test(pathfinder): 출발역과 도착역이 같은 경우 인수 테스트 작성 * feat(pathfinder): 출발역과 도착역이 같은 경우 예외처리 추가 * feat(pathfinder): 출발역과 도착역이 연결이 되어 있지 않은 경우 예외처리 추가 * feat(pathfinder): 존재하지 않은 출발역이나 도착역을 조회 할 경우 예외처리 추가
- Loading branch information
Showing
24 changed files
with
967 additions
and
323 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
src/main/java/nextstep/subway/path/application/PathService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package nextstep.subway.path.application; | ||
|
||
import nextstep.subway.line.domain.LineRepository; | ||
import nextstep.subway.path.domain.PathFinder; | ||
import nextstep.subway.path.ui.PathResponse; | ||
import nextstep.subway.station.domain.Station; | ||
import nextstep.subway.station.domain.StationRepository; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
public class PathService { | ||
|
||
private final LineRepository lineRepository; | ||
private final StationRepository stationRepository; | ||
|
||
public PathService(final LineRepository lineRepository, final StationRepository stationRepository) { | ||
this.lineRepository = lineRepository; | ||
this.stationRepository = stationRepository; | ||
} | ||
|
||
public PathResponse findShortestPath(final Long sourceId, final Long targetId) { | ||
Station sourceStation = findStationById(sourceId); | ||
Station targetStation = findStationById(targetId); | ||
PathFinder pathFinder = PathFinder.from(lineRepository.findAll()); | ||
return pathFinder.getShortestPath(sourceStation, targetStation); | ||
} | ||
|
||
private Station findStationById(final Long id) { | ||
return stationRepository.findById(id) | ||
.orElseThrow(() -> new IllegalArgumentException(id + "에 해당하는 Station을 찾을 수 없습니다.")); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package nextstep.subway.path.domain; | ||
|
||
import nextstep.subway.line.domain.Line; | ||
import nextstep.subway.path.ui.PathResponse; | ||
import nextstep.subway.station.domain.Station; | ||
import nextstep.subway.station.dto.StationResponse; | ||
import org.jgrapht.GraphPath; | ||
import org.jgrapht.alg.shortestpath.DijkstraShortestPath; | ||
import org.jgrapht.graph.DefaultWeightedEdge; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
|
||
public class PathFinder { | ||
private final SubwayGraph graph; | ||
|
||
private PathFinder(List<Line> lines) { | ||
this.graph = new SubwayGraph(DefaultWeightedEdge.class, lines); | ||
} | ||
|
||
public static PathFinder from(final List<Line> lines) { | ||
return new PathFinder(lines); | ||
} | ||
|
||
public PathResponse getShortestPath(final Station sourceStation, final Station targetStation) { | ||
validate(sourceStation, targetStation); | ||
GraphPath<Station, DefaultWeightedEdge> shortestPath = | ||
new DijkstraShortestPath<>(graph).getPath(sourceStation, targetStation); | ||
validate(shortestPath); | ||
List<StationResponse> responses = shortestPath.getVertexList() | ||
.stream() | ||
.map(StationResponse::of) | ||
.collect(Collectors.toList()); | ||
|
||
return new PathResponse(responses, (int) shortestPath.getWeight()); | ||
} | ||
|
||
private void validate(final GraphPath<Station, DefaultWeightedEdge> shortestPath) { | ||
if (Objects.isNull(shortestPath)) { | ||
throw new IllegalArgumentException("출발역과 도착역이 연결이 되어 있지 않습니다."); | ||
} | ||
} | ||
|
||
private void validate(final Station sourceStation, final Station targetStation) { | ||
if (Objects.equals(sourceStation, targetStation)) { | ||
throw new IllegalArgumentException("출발역과 도착역이 " + sourceStation.getName() + "으로 동일합니다."); | ||
} | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
src/main/java/nextstep/subway/path/domain/SubwayGraph.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package nextstep.subway.path.domain; | ||
|
||
import nextstep.subway.line.domain.Line; | ||
import nextstep.subway.line.domain.Section; | ||
import nextstep.subway.station.domain.Station; | ||
import org.jgrapht.graph.DefaultWeightedEdge; | ||
import org.jgrapht.graph.WeightedMultigraph; | ||
|
||
import java.util.List; | ||
|
||
public class SubwayGraph extends WeightedMultigraph<Station, DefaultWeightedEdge> { | ||
private final List<Line> lines; | ||
|
||
public SubwayGraph(final Class<? extends DefaultWeightedEdge> edgeClass, final List<Line> lines) { | ||
super(edgeClass); | ||
this.lines = lines; | ||
initializeVertex(); | ||
initializeEdge(); | ||
} | ||
|
||
private void initializeVertex() { | ||
lines.stream() | ||
.flatMap(sections -> sections.getStations().stream()) | ||
.forEach(this::addVertex); | ||
} | ||
|
||
private void initializeEdge() { | ||
lines.stream() | ||
.flatMap(sections -> sections.getSections().stream()) | ||
.forEach(this::setEdgeWeight); | ||
} | ||
|
||
private DefaultWeightedEdge addEdge(Section section) { | ||
return addEdge(section.upStation(), section.downStation()); | ||
} | ||
|
||
private void setEdgeWeight(final Section section) { | ||
setEdgeWeight(addEdge(section), section.getDistance()); | ||
} | ||
} |
Oops, something went wrong.