diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..f9bd7d6f7 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,110 @@ +# πŸ’ͺ ν”„λ‘œμ νŠΈ κ°œμš” + +μ§€ν•˜μ²  μ—­, λ…Έμ„ , ꡬ간을 κ΄€λ¦¬ν•˜κ³  μ§€ν•˜μ²  노선도λ₯Ό 좜λ ₯ν•˜λŠ” ν”„λ‘œμ νŠΈλ₯Ό κ΅¬ν˜„ν•œλ‹€. + +# πŸ“ κ΅¬ν˜„ κΈ°λŠ₯ λͺ©λ‘ + +### 초기 섀정을 μ €μž₯ν•˜λŠ” κΈ°λŠ₯ + +- [x] `κ΅λŒ€μ—­, 강남역, μ—­μ‚Όμ—­, 남뢀터미널역, μ–‘μž¬μ—­, μ–‘μž¬μ‹œλ―Όμ˜μˆ²μ—­, 맀봉역`을 μ§€ν•˜μ²  μ—­μœΌλ‘œ λ“±λ‘ν•œλ‹€. +- [x] `2ν˜Έμ„ , 3ν˜Έμ„ , μ‹ λΆ„λ‹Ήμ„ `을 μ§€ν•˜μ²  λ…Έμ„ μœΌλ‘œ λ“±λ‘ν•œλ‹€. +- [x] λ…Έμ„ λ§ˆλ‹€ μ—­μ˜ 정보λ₯Ό μ•„λž˜μ™€ 같이 λ“±λ‘ν•œλ‹€. + - `2ν˜Έμ„ : κ΅λŒ€μ—­ - 강남역 - μ—­μ‚Όμ—­` + - `3ν˜Έμ„ : κ΅λŒ€μ—­ - 남뢀터미널역 - μ–‘μž¬μ—­ - 맀봉역` + - `μ‹ λΆ„λ‹Ήμ„ : 강남역 - μ–‘μž¬μ—­ - μ–‘μž¬μ‹œλ―Όμ˜μˆ²μ—­` + +### 메인 화면을 좜λ ₯ν•˜κ³  μ›ν•˜λŠ” κΈ°λŠ₯을 μž…λ ₯ν•˜λŠ” κΈ°λŠ₯ + +- [x] `## 메인 ν™”λ©΄`κ³Ό κΈ°λŠ₯의 λͺ©λ‘μ„ 좜λ ₯ν•œλ‹€. +- [x] `## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] μ›ν•˜λŠ” κΈ°λŠ₯을 숫자 ν˜Ήμ€ `Q`둜 μž…λ ₯λ°›λŠ”λ‹€. + - [x] μ£Όμ–΄μ§„ μž…λ ₯에 ν•΄λ‹Ήν•˜λŠ” μž…λ ₯μž„μ„ κ²€μ¦ν•œλ‹€. +- [x] μž…λ ₯에 따라 μ μ ˆν•œ κΈ°λŠ₯을 ν˜ΈμΆœν•œλ‹€. + +### 역을 κ΄€λ¦¬ν•˜λŠ” κΈ°λŠ₯ + +- [x] `## μ—­ 관리 ν™”λ©΄`κ³Ό 관리 λͺ©λ‘μ„ 좜λ ₯ν•œλ‹€. +- [x] `## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] μ›ν•˜λŠ” κΈ°λŠ₯을 숫자 ν˜Ήμ€ `B`둜 μž…λ ₯λ°›λŠ”λ‹€. + - [x] μ£Όμ–΄μ§„ μž…λ ₯에 ν•΄λ‹Ήν•˜λŠ” μž…λ ₯μž„μ„ κ²€μ¦ν•œλ‹€. +- [x] 역을 λ“±λ‘ν•œλ‹€. + - [x] `## 등둝할 μ—­ 이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] 등둝할 μ—­ 이름을 μž…λ ₯ λ°›λŠ”λ‹€. + - [x] 빈 λ¬Έμžμ—΄μ΄ μ•„λ‹˜μ„ κ²€μ¦ν•œλ‹€. + - [x] μ€‘λ³΅λ˜λŠ” μ—­ 이름이 μ•„λ‹˜μ„ κ²€μ¦ν•œλ‹€. + - [x] 2κΈ€μž μ΄μƒμž„μ„ κ²€μ¦ν•œλ‹€. + - [x] μ—­ 이름을 μ €μž₯ν•œλ‹€. + - [x] `[INFO] μ§€ν•˜μ²  역이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] 역을 μ‘°νšŒν•œλ‹€. + - [x] `## μ—­ λͺ©λ‘`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] μ €μž₯된 μ—­μ˜ 내역을 λΆˆλŸ¬μ™€ 좜λ ₯ν•œλ‹€. +- [x] 역을 μ‚­μ œν•œλ‹€. + - [x] `## μ‚­μ œν•  μ—­ 이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] μ—­ 이름을 μž…λ ₯λ°›λŠ”λ‹€. + - [x] 빈 λ¬Έμžμ—΄μ΄ μ•„λ‹˜μ„ κ²€μ¦ν•œλ‹€. + - [x] μ‘΄μž¬ν•˜λŠ” 이름이 μ•„λ‹Œ 경우 λ‹€μ‹œ μž…λ ₯λ°›λŠ”λ‹€. + - [x] μž…λ ₯된 역을 μ‚­μ œν•œλ‹€. + - [x] `[INFO] μ§€ν•˜μ²  역이 μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.`λ₯Ό 좜λ ₯ν•œλ‹€. + +### 노선을 κ΄€λ¦¬ν•˜λŠ” κΈ°λŠ₯ + +- [x] `## λ…Έμ„  관리 ν™”λ©΄`κ³Ό 관리 λͺ©λ‘μ„ 좜λ ₯ν•œλ‹€. +- [x] `## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] μ›ν•˜λŠ” κΈ°λŠ₯을 숫자 ν˜Ήμ€ `B`둜 μž…λ ₯λ°›λŠ”λ‹€. + - [x] μ£Όμ–΄μ§„ μž…λ ₯에 ν•΄λ‹Ήν•˜λŠ” μž…λ ₯μž„μ„ κ²€μ¦ν•œλ‹€. +- [x] 노선을 λ“±λ‘ν•œλ‹€. + - [x] `## 등둝할 λ…Έμ„  이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] 등둝할 λ…Έμ„  이름을 μž…λ ₯ λ°›λŠ”λ‹€. + - [x] 빈 λ¬Έμžμ—΄μ΄ μ•„λ‹˜μ„ κ²€μ¦ν•œλ‹€. + - [x] μ€‘λ³΅λ˜λŠ” μ—­ 이름이 μ•„λ‹˜μ„ κ²€μ¦ν•œλ‹€. + - [x] 2κΈ€μž μ΄μƒμž„μ„ κ²€μ¦ν•œλ‹€. + - [x] `## 등둝할 λ…Έμ„ μ˜ 상행 쒅점역 이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] 상행 쒅점역 이름을 μž…λ ₯ν•œλ‹€. + - [x] μ €μž₯된 역이 μ•„λ‹Œ 경우 λ‹€μ‹œ μž…λ ₯λ°›λŠ”λ‹€. + - [x] `## 등둝할 λ…Έμ„ μ˜ ν•˜ν–‰ 쒅점역 이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] ν•˜ν–‰ 쒅점역 이름을 μž…λ ₯ν•œλ‹€. + - [x] μ €μž₯된 역이 μ•„λ‹Œ 경우 λ‹€μ‹œ μž…λ ₯λ°›λŠ”λ‹€. + - [x] λ…Έμ„  이름을 μ €μž₯ν•œλ‹€. + - [x] `[INFO] μ§€ν•˜μ²  노선이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] 노선을 μ‘°νšŒν•œλ‹€. + - [x] `## λ…Έμ„  λͺ©λ‘`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] μ €μž₯된 λ…Έμ„ μ˜ 이름 내역을 λΆˆλŸ¬μ™€ 좜λ ₯ν•œλ‹€. +- [x] 노선을 μ‚­μ œν•œλ‹€. + - [x] `## μ‚­μ œν•  λ…Έμ„  이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] λ…Έμ„  이름을 μž…λ ₯λ°›λŠ”λ‹€. + - [x] 빈 λ¬Έμžμ—΄μ΄ μ•„λ‹˜μ„ κ²€μ¦ν•œλ‹€. + - [x] μ‘΄μž¬ν•˜λŠ” 이름이 μ•„λ‹Œ 경우 λ‹€μ‹œ μž…λ ₯λ°›λŠ”λ‹€. + - [x] μž…λ ₯된 노선을 μ‚­μ œν•œλ‹€. + - [x] `[INFO] μ§€ν•˜μ²  노선이 μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.`λ₯Ό 좜λ ₯ν•œλ‹€. + +### ꡬ간을 κ΄€λ¦¬ν•˜λŠ” κΈ°λŠ₯ + +- [x] `## ꡬ간 관리 ν™”λ©΄`κ³Ό 관리 λͺ©λ‘μ„ 좜λ ₯ν•œλ‹€. +- [x] `## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] μ›ν•˜λŠ” κΈ°λŠ₯을 숫자 ν˜Ήμ€ `B`둜 μž…λ ₯λ°›λŠ”λ‹€. + - [x] μ£Όμ–΄μ§„ μž…λ ₯에 ν•΄λ‹Ήν•˜λŠ” μž…λ ₯μž„μ„ κ²€μ¦ν•œλ‹€. +- [x] ꡬ간을 λ“±λ‘ν•œλ‹€. + - [x] `## 등둝할 λ…Έμ„  이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] ꡬ간을 μΆ”κ°€ν•  λ…Έμ„  이름을 μž…λ ₯ λ°›λŠ”λ‹€. + - [x] μ‘΄μž¬ν•˜λŠ” 노선이 μ•„λ‹Œ 경우, λ‹€μ‹œ μž…λ ₯ λ°›λŠ”λ‹€. + - [x] `## 등둝할 μ—­ 이름을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] ꡬ간에 μΆ”κ°€ν•  μ—­ 이름을 μž…λ ₯ λ°›λŠ”λ‹€. + - [x] μ‘΄μž¬ν•˜λŠ” 역이 μ•„λ‹Œ 경우, λ‹€μ‹œ μž…λ ₯ λ°›λŠ”λ‹€. + - [x] 역을 μΆ”κ°€ν•  μˆœμ„œλ₯Ό μž…λ ₯λ°›λŠ”λ‹€. + - [x] 숫자 μž…λ ₯이 μ•„λ‹Œ 경우 λ‹€μ‹œ μž…λ ₯λ°›λŠ”λ‹€. + - [x] μΆ”κ°€ν•  수 μžˆλŠ” ꡬ간 λ²”μœ„λ₯Ό λ„˜μ–΄κ°„ 경우, λ‹€μ‹œ μž…λ ₯λ°›λŠ”λ‹€. + - [x] `[INFO] ꡬ간이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] ꡬ간을 μ‚­μ œν•œλ‹€. + - [x] `## μ‚­μ œν•  κ΅¬κ°„μ˜ 노선을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] λ…Έμ„ μ˜ 이름을 μž…λ ₯ν•œλ‹€. + - [x] μ‘΄μž¬ν•˜λŠ” 노선이 μ•„λ‹Œ 경우, λ‹€μ‹œ μž…λ ₯ λ°›λŠ”λ‹€. + - [x] `## μ‚­μ œν•  κ΅¬κ°„μ˜ 역을 μž…λ ₯ν•˜μ„Έμš”.`λ₯Ό 좜λ ₯ν•œλ‹€. + - [x] μ—­μ˜ 이름을 μž…λ ₯ν•œλ‹€. + - [x] μ‘΄μž¬ν•˜λŠ” 역이 μ•„λ‹Œ 경우, λ‹€μ‹œ μž…λ ₯ λ°›λŠ”λ‹€. + - [x] ν•΄λ‹Ή 노선에 μ‘΄μž¬ν•˜λŠ” 역을 μ‚­μ œν•œλ‹€. + - [x] `[INFO] ꡬ간이 μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.`λ₯Ό 좜λ ₯ν•œλ‹€. + +### μ§€ν•˜μ²  노선도λ₯Ό 좜λ ₯ν•˜λŠ” κΈ°λŠ₯ + +- [x] `## μ§€ν•˜μ²  노선도`λ₯Ό 좜λ ₯ν•œλ‹€. +- [x] λ…Έμ„ κ³Ό ν•΄λ‹Ή 노선이 μ§€λ‚˜λŠ” μ—­μ˜ 정보λ₯Ό μ°¨λ‘€λ‘œ 좜λ ₯ν•œλ‹€. diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java new file mode 100644 index 000000000..62c00ed63 --- /dev/null +++ b/src/main/java/subway/controller/LineController.java @@ -0,0 +1,56 @@ +package subway.controller; + +import java.util.List; +import subway.domain.constants.LineCommand; +import subway.service.RouteService; +import subway.service.SubwayService; +import subway.view.LineView; + +public class LineController { + private final LineView lineView; + private final SubwayService subwayService; + private final RouteService routeService; + + public LineController(LineView lineView, SubwayService subwayService, RouteService routeService) { + this.lineView = lineView; + this.subwayService = subwayService; + this.routeService = routeService; + } + + public void run() { + lineView.printFunctions(); + LineCommand function = lineView.enterFunction(); + if (function.equals(LineCommand.ADD)) { + addLine(); + } + if (function.equals(LineCommand.DELETE)) { + deleteLine(); + } + if (function.equals(LineCommand.GET)) { + getLines(); + } + } + + public void addLines(List lines) { + subwayService.addAll(lines); + } + + private void addLine() { + String name = lineView.enterLineNameToAdd(); + String head = lineView.enterHeadStation(); + String tail = lineView.enterTailStation(); + routeService.addRoute(name, head, tail); + subwayService.add(name); + lineView.printAddResult(); + } + + private void deleteLine() { + String name = lineView.enterLineNameToDelete(); + subwayService.delete(name); + lineView.printDeleteResult(); + } + + private void getLines() { + lineView.printAllLines(subwayService.getAll()); + } +} diff --git a/src/main/java/subway/controller/RouteController.java b/src/main/java/subway/controller/RouteController.java new file mode 100644 index 000000000..c823fb109 --- /dev/null +++ b/src/main/java/subway/controller/RouteController.java @@ -0,0 +1,51 @@ +package subway.controller; + +import java.util.List; +import java.util.Map; +import subway.domain.constants.LineCommand; +import subway.domain.constants.RouteCommand; +import subway.service.RouteService; +import subway.view.RouteView; + +public class RouteController { + private final RouteService routeService; + private final RouteView routeView; + + public RouteController(RouteService routeService, RouteView routeView) { + this.routeService = routeService; + this.routeView = routeView; + } + + public void addRoutes(Map> route) { + routeService.addAll(route); + } + + public void run() { + routeView.printFunctions(); + RouteCommand function = routeView.enterFunction(); + if (function.equals(LineCommand.ADD)) { + addRoute(); + } + if (function.equals(LineCommand.DELETE)) { + deleteRoute(); + } + } + + private void addRoute() { + String line = routeView.enterLineNameToAdd(); + String station = routeView.enterStationNameToAdd(); + int index = routeView.enterIndexToAdd(); + routeService.addStation(line, station, index); + routeView.printAddResult(); + } + + /** + * ꡬ간을 μ‚­μ œν•˜λŠ” ν•¨μˆ˜ + */ + private void deleteRoute() { + String line = routeView.enterLineNameToDelete(); + String station = routeView.enterStationNameToDelete(); + routeService.deleteStation(line, station); + routeView.printDeleteResult(); + } +} diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/controller/StationController.java new file mode 100644 index 000000000..f76ff16a3 --- /dev/null +++ b/src/main/java/subway/controller/StationController.java @@ -0,0 +1,50 @@ +package subway.controller; + +import java.util.List; +import subway.domain.constants.StationCommand; +import subway.service.SubwayService; +import subway.view.StationView; + +public class StationController { + private final SubwayService subwayService; + private final StationView stationView; + + public StationController(SubwayService subwayService, StationView stationView) { + this.subwayService = subwayService; + this.stationView = stationView; + } + + public void run() { + stationView.printFunctions(); + StationCommand function = stationView.enterFunction(); + if (function.equals(StationCommand.ADD)) { + addStation(); + } + if (function.equals(StationCommand.DELETE)) { + deleteStation(); + } + if (function.equals(StationCommand.GET)) { + getStation(); + } + } + + public void addStations(List stations) { + subwayService.addAll(stations); + } + + private void addStation() { + String name = stationView.enterStationNameToAdd(); + subwayService.add(name); + stationView.printAddResult(); + } + + private void deleteStation() { + String name = stationView.enterStationNameToDelete(); + subwayService.delete(name); + stationView.printDeleteResult(); + } + + private void getStation() { + stationView.printAllStation(subwayService.getAll()); + } +} diff --git a/src/main/java/subway/controller/SubwayManager.java b/src/main/java/subway/controller/SubwayManager.java new file mode 100644 index 000000000..f68c4f448 --- /dev/null +++ b/src/main/java/subway/controller/SubwayManager.java @@ -0,0 +1,64 @@ +package subway.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import subway.domain.constants.FunctionCommand; +import subway.view.MainView; + +public class SubwayManager { + private final MainView mainView; + private final LineController lineController; + private final StationController stationController; + private final RouteController routeController; + + public SubwayManager(MainView mainView, + LineController lineController, + StationController stationController, + RouteController routeController + ) { + this.mainView = mainView; + this.lineController = lineController; + this.stationController = stationController; + this.routeController = routeController; + preprocess(); + } + + public void preprocess() { + List stations = List.of( + "κ΅λŒ€μ—­", "강남역", "μ—­μ‚Όμ—­", "남뢀터미널역", "μ–‘μž¬μ—­", "μ–‘μž¬μ‹œλ―Όμ˜μˆ²μ—­", "맀봉역" + ); + stationController.addStations(stations); + List lines = List.of( + "2ν˜Έμ„ ", "3ν˜Έμ„ ", "μ‹ λΆ„λ‹Ήμ„ " + ); + lineController.addLines(lines); + Map> route = new HashMap<>(); + route.put("2ν˜Έμ„ ", List.of("κ΅λŒ€μ—­", "강남역", "μ—­μ‚Όμ—­")); + route.put("3ν˜Έμ„ ", List.of("κ΅λŒ€μ—­", "남뢀터미널역", "μ–‘μž¬μ—­", "맀봉역")); + route.put("μ‹ λΆ„λ‹Ήμ„ ", List.of("강남역", "μ–‘μž¬μ—­", "μ–‘μž¬μ‹œλ―Όμ˜μˆ²μ—­")); + routeController.addRoutes(route); + } + + public void run() { + while (true) { + mainView.printMainScreen(); + FunctionCommand function = mainView.enterFunction(); + if (function.equals(FunctionCommand.STATION)) { + stationController.run(); + } + if (function.equals(FunctionCommand.LINE)) { + lineController.run(); + } + if (function.equals(FunctionCommand.ROUTE)) { + routeController.run(); + } + if (function.equals(FunctionCommand.PRINT)) { + routeController.print(); + } + if (function.equals(FunctionCommand.QUIT)) { + break; + } + } + } +} diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java index f4d738d5a..0855bd870 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -1,15 +1,17 @@ package subway.domain; +import subway.global.validator.Validator; + public class Line { + private static final int MIN_LENGTH = 2; private String name; public Line(String name) { + Validator.validateMinLength(name, MIN_LENGTH); this.name = name; } public String getName() { return name; } - - // μΆ”κ°€ κΈ°λŠ₯ κ΅¬ν˜„ } diff --git a/src/main/java/subway/domain/LineRepository.java b/src/main/java/subway/domain/LineRepository.java index 49132ddb6..42b59b01c 100644 --- a/src/main/java/subway/domain/LineRepository.java +++ b/src/main/java/subway/domain/LineRepository.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; public class LineRepository { private static final List lines = new ArrayList<>(); @@ -19,4 +20,10 @@ public static void addLine(Line line) { public static boolean deleteLineByName(String name) { return lines.removeIf(line -> Objects.equals(line.getName(), name)); } + + public Optional findByName(String line) { + return lines.stream() + .filter(name -> name.getName().equals(line)) + .findFirst(); + } } diff --git a/src/main/java/subway/domain/Route.java b/src/main/java/subway/domain/Route.java new file mode 100644 index 000000000..cb9168de5 --- /dev/null +++ b/src/main/java/subway/domain/Route.java @@ -0,0 +1,39 @@ +package subway.domain; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public class Route { + private Map> route; + + public Route() { + this.route = new HashMap<>(); + } + + public void add(Line line, List stations) { + route.put(line, stations); + } + + public void addStation(Line line, Station station, int index) { + if (route.get(line).isEmpty()) { + throw CustomException.from(ErrorMessage.LINE_NOT_FOUND_ERROR); + } + route.get(line).set(index, station); + } + + public void deleteStation(Line line, Station target) { + List stations = route.get(line); + Station station = findByName(stations, target.getName()); + stations.remove(station); + } + + private Station findByName(List stations, String target) { + return stations.stream() + .filter(station -> station.getName().equals(target)) + .findFirst() + .orElseThrow(() -> CustomException.from(ErrorMessage.STATION_NOT_FOUND_ERROR)); + } +} diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/Station.java index bdb142590..e72a033d9 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/Station.java @@ -1,15 +1,17 @@ package subway.domain; +import subway.global.validator.Validator; + public class Station { + private static final int MIN_LENGTH = 2; private String name; public Station(String name) { + Validator.validateMinLength(name, MIN_LENGTH); this.name = name; } public String getName() { return name; } - - // μΆ”κ°€ κΈ°λŠ₯ κ΅¬ν˜„ } diff --git a/src/main/java/subway/domain/StationRepository.java b/src/main/java/subway/domain/StationRepository.java index b7245c0f3..15cf2aa72 100644 --- a/src/main/java/subway/domain/StationRepository.java +++ b/src/main/java/subway/domain/StationRepository.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; public class StationRepository { private static final List stations = new ArrayList<>(); @@ -19,4 +20,10 @@ public static void addStation(Station station) { public static boolean deleteStation(String name) { return stations.removeIf(station -> Objects.equals(station.getName(), name)); } + + public static Optional findByName(String station) { + return stations.stream() + .filter(name -> name.getName().equals(station)) + .findFirst(); + } } diff --git a/src/main/java/subway/domain/constants/FunctionCommand.java b/src/main/java/subway/domain/constants/FunctionCommand.java new file mode 100644 index 000000000..f138ad9cb --- /dev/null +++ b/src/main/java/subway/domain/constants/FunctionCommand.java @@ -0,0 +1,27 @@ +package subway.domain.constants; + +import java.util.Arrays; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public enum FunctionCommand { + STATION("1"), + LINE("2"), + ROUTE("3"), + PRINT("4"), + QUIT("Q"); + + private final String command; + + FunctionCommand(String command) { + this.command = command; + } + + public static FunctionCommand from(String command) { + return Arrays.stream(FunctionCommand.values()) + .filter(element -> element.command.equals(command)) + .findFirst() + .orElseThrow(() -> CustomException.from(ErrorMessage.INVALID_FUNCTION_COMMAND)); + } + +} diff --git a/src/main/java/subway/domain/constants/LineCommand.java b/src/main/java/subway/domain/constants/LineCommand.java new file mode 100644 index 000000000..41631259e --- /dev/null +++ b/src/main/java/subway/domain/constants/LineCommand.java @@ -0,0 +1,26 @@ +package subway.domain.constants; + +import java.util.Arrays; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public enum LineCommand { + ADD("1"), + DELETE("2"), + GET("3"), + BACK("B"); + + private final String command; + + LineCommand(String command) { + this.command = command; + } + + public static LineCommand from(String command) { + return Arrays.stream(LineCommand.values()) + .filter(element -> element.command.equals(command)) + .findFirst() + .orElseThrow(() -> CustomException.from(ErrorMessage.INVALID_FUNCTION_COMMAND)); + + } +} diff --git a/src/main/java/subway/domain/constants/RouteCommand.java b/src/main/java/subway/domain/constants/RouteCommand.java new file mode 100644 index 000000000..11ac25753 --- /dev/null +++ b/src/main/java/subway/domain/constants/RouteCommand.java @@ -0,0 +1,25 @@ +package subway.domain.constants; + +import java.util.Arrays; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public enum RouteCommand { + ADD("1"), + DELETE("2"), + BACK("B"); + + private final String command; + + RouteCommand(String command) { + this.command = command; + } + + public static RouteCommand from(String command) { + return Arrays.stream(RouteCommand.values()) + .filter(element -> element.command.equals(command)) + .findFirst() + .orElseThrow(() -> CustomException.from(ErrorMessage.INVALID_FUNCTION_COMMAND)); + + } +} diff --git a/src/main/java/subway/domain/constants/StationCommand.java b/src/main/java/subway/domain/constants/StationCommand.java new file mode 100644 index 000000000..fb3e6e222 --- /dev/null +++ b/src/main/java/subway/domain/constants/StationCommand.java @@ -0,0 +1,26 @@ +package subway.domain.constants; + +import java.util.Arrays; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public enum StationCommand { + ADD("1"), + DELETE("2"), + GET("3"), + BACK("B"); + + private final String command; + + StationCommand(String command) { + this.command = command; + } + + public static StationCommand from(String command) { + return Arrays.stream(StationCommand.values()) + .filter(element -> element.command.equals(command)) + .findFirst() + .orElseThrow(() -> CustomException.from(ErrorMessage.INVALID_FUNCTION_COMMAND)); + + } +} diff --git a/src/main/java/subway/global/exception/CustomException.java b/src/main/java/subway/global/exception/CustomException.java new file mode 100644 index 000000000..240e93706 --- /dev/null +++ b/src/main/java/subway/global/exception/CustomException.java @@ -0,0 +1,13 @@ +package subway.global.exception; + +public class CustomException extends IllegalArgumentException { + private static final String PREFIX = "[ERROR] "; + + private CustomException(ErrorMessage errorMessage) { + super(PREFIX + errorMessage.getMessage()); + } + + public static CustomException from(ErrorMessage errorMessage) { + return new CustomException(errorMessage); + } +} diff --git a/src/main/java/subway/global/exception/ErrorMessage.java b/src/main/java/subway/global/exception/ErrorMessage.java new file mode 100644 index 000000000..d69ac1138 --- /dev/null +++ b/src/main/java/subway/global/exception/ErrorMessage.java @@ -0,0 +1,31 @@ +package subway.global.exception; + +public enum ErrorMessage { + // String + BLANK_INPUT_ERROR("빈 λ¬Έμžμ—΄μ΄ μž…λ ₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€."), + INVALID_LENGTH_ERROR("μ˜¬λ°”λ₯Έ 길이의 λ¬Έμžμ—΄μ„ μž…λ ₯ν•΄μ£Όμ„Έμš”."), + + // Global + INVALID_FUNCTION_COMMAND("선택할 수 μ—†λŠ” κΈ°λŠ₯μž…λ‹ˆλ‹€."), + + // Station + STATION_DUPLICATED_ERROR("μ€‘λ³΅λœ μ—­ 이름을 μž…λ ₯ν•˜μ˜€μŠ΅λ‹ˆλ‹€."), + STATION_NOT_FOUND_ERROR("μž…λ ₯ν•œ 역을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."), + + // Line + LINE_DUPLICATED_ERROR("μ€‘λ³΅λœ λ…Έμ„  이름을 μž…λ ₯ν•˜μ˜€μŠ΅λ‹ˆλ‹€."), + LINE_NOT_FOUND_ERROR("μž…λ ₯ν•œ 노선을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."), + + // Route + INVALID_INDEX_ERROR("μ˜¬λ°”λ₯Έ μˆœμ„œλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”."); + + private final String message; + + ErrorMessage(String message) { + this.message = message; + } + + public String getMessage() { + return this.message; + } +} diff --git a/src/main/java/subway/global/validator/Validator.java b/src/main/java/subway/global/validator/Validator.java new file mode 100644 index 000000000..3d3fcba02 --- /dev/null +++ b/src/main/java/subway/global/validator/Validator.java @@ -0,0 +1,23 @@ +package subway.global.validator; + +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public final class Validator { + public static void validateMinLength(String input, int min) { + if (input.length() < min) { + throw CustomException.from(ErrorMessage.INVALID_LENGTH_ERROR); + } + } + + public static int validateNumber(String message, ErrorMessage errorMessage) { + if (isNotNumber(message)) { + throw CustomException.from(errorMessage); + } + return Integer.parseInt(message); + } + + public static boolean isNotNumber(String str) { + return !str.matches("\\d+"); + } +} diff --git a/src/main/java/subway/service/LineService.java b/src/main/java/subway/service/LineService.java new file mode 100644 index 000000000..e8753e36b --- /dev/null +++ b/src/main/java/subway/service/LineService.java @@ -0,0 +1,43 @@ +package subway.service; + +import java.util.List; +import subway.domain.Line; +import subway.domain.LineRepository; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public class LineService implements SubwayService { + private final LineRepository lineRepository; + + public LineService(LineRepository lineRepository) { + this.lineRepository = lineRepository; + } + + @Override + public void addAll(List lines) { + for (String line : lines) { + lineRepository.addLine(new Line(line)); + } + } + + @Override + public void add(String line) { + if (lineRepository.findByName(line).isPresent()) { + throw CustomException.from(ErrorMessage.LINE_DUPLICATED_ERROR); + } + lineRepository.addLine(new Line(line)); + } + + @Override + public void delete(String line) { + if (lineRepository.findByName(line).isEmpty()) { + throw CustomException.from(ErrorMessage.LINE_NOT_FOUND_ERROR); + } + lineRepository.deleteLineByName(line); + } + + @Override + public List getAll() { + return null; + } +} diff --git a/src/main/java/subway/service/RouteService.java b/src/main/java/subway/service/RouteService.java new file mode 100644 index 000000000..2eded5034 --- /dev/null +++ b/src/main/java/subway/service/RouteService.java @@ -0,0 +1,68 @@ +package subway.service; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import subway.domain.Line; +import subway.domain.LineRepository; +import subway.domain.Route; +import subway.domain.Station; +import subway.domain.StationRepository; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public class RouteService { + private final Route route; + private final LineRepository lineRepository; + private final StationRepository stationRepository; + + public RouteService( + Route route, + LineRepository lineRepository, + StationRepository stationRepository + ) { + this.route = route; + this.lineRepository = lineRepository; + this.stationRepository = stationRepository; + } + + public void addAll(Map> elements) { + for (Map.Entry> entry : elements.entrySet()) { + String line = entry.getKey(); + List stations = entry.getValue(); + route.add(new Line(line), convertStations(stations)); + } + } + + private List convertStations(List stations) { + return stations.stream() + .map(Station::new) + .collect(Collectors.toList()); + } + + public void addRoute(String lineName, String headName, String tailName) { + Line line = lineRepository.findByName(lineName) + .orElseThrow(() -> CustomException.from(ErrorMessage.LINE_NOT_FOUND_ERROR)); + Station head = stationRepository.findByName(headName) + .orElseThrow(() -> CustomException.from(ErrorMessage.STATION_NOT_FOUND_ERROR)); + Station tail = stationRepository.findByName(tailName) + .orElseThrow(() -> CustomException.from(ErrorMessage.STATION_NOT_FOUND_ERROR)); + route.add(line, List.of(head, tail)); + } + + public void addStation(String lineName, String stationName, int index) { + Line line = lineRepository.findByName(lineName) + .orElseThrow(() -> CustomException.from(ErrorMessage.LINE_NOT_FOUND_ERROR)); + Station station = stationRepository.findByName(stationName) + .orElseThrow(() -> CustomException.from(ErrorMessage.STATION_NOT_FOUND_ERROR)); + route.addStation(line, station, index); + } + + public void deleteStation(String lineName, String stationName) { + Line line = lineRepository.findByName(lineName) + .orElseThrow(() -> CustomException.from(ErrorMessage.LINE_NOT_FOUND_ERROR)); + Station station = stationRepository.findByName(stationName) + .orElseThrow(() -> CustomException.from(ErrorMessage.STATION_NOT_FOUND_ERROR)); + route.deleteStation(line, station); + } +} diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java new file mode 100644 index 000000000..28fea2818 --- /dev/null +++ b/src/main/java/subway/service/StationService.java @@ -0,0 +1,47 @@ +package subway.service; + +import java.util.List; +import java.util.stream.Collectors; +import subway.domain.Station; +import subway.domain.StationRepository; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public class StationService implements SubwayService { + private final StationRepository stationRepository; + + public StationService(StationRepository stationRepository) { + this.stationRepository = stationRepository; + } + + @Override + public void addAll(List stations) { + for (String station : stations) { + stationRepository.addStation(new Station(station)); + } + } + + @Override + public void add(String station) { + if (stationRepository.findByName(station).isPresent()) { + throw CustomException.from(ErrorMessage.STATION_DUPLICATED_ERROR); + } + stationRepository.addStation(new Station(station)); + } + + @Override + public void delete(String station) { + if (stationRepository.findByName(station).isEmpty()) { + throw CustomException.from(ErrorMessage.STATION_NOT_FOUND_ERROR); + } + stationRepository.deleteStation(station); + } + + @Override + public List getAll() { + return stationRepository.stations() + .stream() + .map(Station::getName) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/subway/service/SubwayService.java b/src/main/java/subway/service/SubwayService.java new file mode 100644 index 000000000..5982d5ae5 --- /dev/null +++ b/src/main/java/subway/service/SubwayService.java @@ -0,0 +1,14 @@ +package subway.service; + +import java.util.List; + +public interface SubwayService { + + void addAll(List elements); + + void add(String element); + + void delete(String element); + + List getAll(); +} diff --git a/src/main/java/subway/view/LineView.java b/src/main/java/subway/view/LineView.java new file mode 100644 index 000000000..6c25d426a --- /dev/null +++ b/src/main/java/subway/view/LineView.java @@ -0,0 +1,63 @@ +package subway.view; + +import java.util.List; +import subway.domain.constants.LineCommand; +import subway.view.console.ConsoleReader; +import subway.view.console.ConsoleWriter; + +public class LineView { + private final ConsoleReader consoleReader; + + public LineView(ConsoleReader consoleReader) { + this.consoleReader = consoleReader; + } + + public LineCommand enterFunction() { + ConsoleWriter.printlnMessage("## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”."); + return LineCommand.from(consoleReader.enterMessage()); + } + + public String enterLineNameToAdd() { + ConsoleWriter.printlnMessage("## 등둝할 λ…Έμ„  이름을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public String enterLineNameToDelete() { + ConsoleWriter.printlnMessage("## μ‚­μ œν•  λ…Έμ„  이름을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public void printFunctions() { + ConsoleWriter.printlnMessage("## λ…Έμ„  관리 ν™”λ©΄"); + ConsoleWriter.printlnMessage("1. λ…Έμ„  등둝"); + ConsoleWriter.printlnMessage("2. λ…Έμ„  μ‚­μ œ"); + ConsoleWriter.printlnMessage("3. λ…Έμ„  쑰회"); + ConsoleWriter.printlnMessage("B. λŒμ•„κ°€κΈ°"); + } + + public void printAddResult() { + ConsoleWriter.printlnMessage("[INFO] μ§€ν•˜μ²  노선이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€."); + } + + public void printDeleteResult() { + ConsoleWriter.printlnMessage("[INFO] μ§€ν•˜μ²  노선이 μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€."); + } + + public void printAllLines(List lines) { + ConsoleWriter.printlnMessage("## λ…Έμ„  λͺ©λ‘"); + for (String line : lines) { + ConsoleWriter.printlnMessage("[INFO] " + line); + } + ConsoleWriter.println(); + } + + public String enterHeadStation() { + ConsoleWriter.printlnMessage("## 등둝할 λ…Έμ„ μ˜ 상행 쒅점역 이름을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public String enterTailStation() { + ConsoleWriter.printlnMessage("## 등둝할 λ…Έμ„ μ˜ ν•˜ν–‰ 쒅점역 이름을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } +} diff --git a/src/main/java/subway/view/MainView.java b/src/main/java/subway/view/MainView.java new file mode 100644 index 000000000..0d6489af4 --- /dev/null +++ b/src/main/java/subway/view/MainView.java @@ -0,0 +1,27 @@ +package subway.view; + +import subway.domain.constants.FunctionCommand; +import subway.view.console.ConsoleReader; +import subway.view.console.ConsoleWriter; + +public class MainView { + private final ConsoleReader consoleReader; + + public MainView(ConsoleReader consoleReader) { + this.consoleReader = consoleReader; + } + + public FunctionCommand enterFunction() { + return FunctionCommand.from(consoleReader.enterMessage()); + } + + public void printMainScreen() { + ConsoleWriter.printlnMessage("## 메인 ν™”λ©΄"); + ConsoleWriter.printlnMessage("1. μ—­ 관리"); + ConsoleWriter.printlnMessage("2. λ…Έμ„  관리"); + ConsoleWriter.printlnMessage("3. ꡬ간 관리"); + ConsoleWriter.printlnMessage("4. μ§€ν•˜μ²  노선도 좜λ ₯"); + ConsoleWriter.printlnMessage("Q. μ’…λ£Œ"); + ConsoleWriter.println(); + } +} diff --git a/src/main/java/subway/view/RouteView.java b/src/main/java/subway/view/RouteView.java new file mode 100644 index 000000000..b4d499a97 --- /dev/null +++ b/src/main/java/subway/view/RouteView.java @@ -0,0 +1,63 @@ +package subway.view; + +import subway.domain.constants.RouteCommand; +import subway.global.exception.ErrorMessage; +import subway.global.validator.Validator; +import subway.view.console.ConsoleReader; +import subway.view.console.ConsoleWriter; + +public class RouteView { + private final ConsoleReader consoleReader; + + public RouteView(ConsoleReader consoleReader) { + this.consoleReader = consoleReader; + } + + public void printFunctions() { + ConsoleWriter.printlnMessage("## ꡬ간 관리 ν™”λ©΄"); + ConsoleWriter.printlnMessage("1. ꡬ간 등둝"); + ConsoleWriter.printlnMessage("2. ꡬ간 μ‚­μ œ"); + ConsoleWriter.printlnMessage("B. λŒμ•„κ°€κΈ°"); + } + + public RouteCommand enterFunction() { + ConsoleWriter.printlnMessage("## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”."); + return RouteCommand.from(consoleReader.enterMessage()); + } + + public String enterLineNameToAdd() { + ConsoleWriter.printlnMessage("## 노선을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public String enterStationNameToAdd() { + ConsoleWriter.printlnMessage("## 역을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public int enterIndexToAdd() { + ConsoleWriter.printlnMessage("## μˆœμ„œλ₯Ό μž…λ ₯ν•˜μ„Έμš”."); + return Validator.validateNumber( + consoleReader.enterMessage(), + ErrorMessage.INVALID_INDEX_ERROR + ); + } + + public String enterLineNameToDelete() { + ConsoleWriter.printlnMessage("## μ‚­μ œν•  κ΅¬κ°„μ˜ 노선을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public String enterStationNameToDelete() { + ConsoleWriter.printlnMessage("## μ‚­μ œν•  κ΅¬κ°„μ˜ 역을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public void printAddResult() { + ConsoleWriter.printlnMessage("[INFO] ꡬ간이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€."); + } + + public void printDeleteResult() { + ConsoleWriter.printlnMessage("[INFO] ꡬ간이 μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€."); + } +} diff --git a/src/main/java/subway/view/StationView.java b/src/main/java/subway/view/StationView.java new file mode 100644 index 000000000..4c703f3ad --- /dev/null +++ b/src/main/java/subway/view/StationView.java @@ -0,0 +1,53 @@ +package subway.view; + +import java.util.List; +import subway.domain.constants.StationCommand; +import subway.view.console.ConsoleReader; +import subway.view.console.ConsoleWriter; + +public class StationView { + private final ConsoleReader consoleReader; + + public StationView(ConsoleReader consoleReader) { + this.consoleReader = consoleReader; + } + + public StationCommand enterFunction() { + ConsoleWriter.printlnMessage("## μ›ν•˜λŠ” κΈ°λŠ₯을 μ„ νƒν•˜μ„Έμš”."); + return StationCommand.from(consoleReader.enterMessage()); + } + + public String enterStationNameToAdd() { + ConsoleWriter.printlnMessage("## 등둝할 μ—­ 이름을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public String enterStationNameToDelete() { + ConsoleWriter.printlnMessage("## μ‚­μ œν•  μ—­ 이름을 μž…λ ₯ν•˜μ„Έμš”."); + return consoleReader.enterMessage(); + } + + public void printFunctions() { + ConsoleWriter.printlnMessage("## μ—­ 관리 ν™”λ©΄"); + ConsoleWriter.printlnMessage("1. μ—­ 등둝"); + ConsoleWriter.printlnMessage("2. μ—­ μ‚­μ œ"); + ConsoleWriter.printlnMessage("3. μ—­ 쑰회"); + ConsoleWriter.printlnMessage("B. λŒμ•„κ°€κΈ°"); + } + + public void printAddResult() { + ConsoleWriter.printlnMessage("[INFO] μ§€ν•˜μ²  역이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€."); + } + + public void printDeleteResult() { + ConsoleWriter.printlnMessage("[INFO] μ§€ν•˜μ²  역이 μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€."); + } + + public void printAllStation(List stations) { + ConsoleWriter.printlnMessage("## μ—­ λͺ©λ‘"); + for (String station : stations) { + ConsoleWriter.printlnMessage("[INFO] " + station); + } + ConsoleWriter.println(); + } +} diff --git a/src/main/java/subway/view/console/ConsoleReader.java b/src/main/java/subway/view/console/ConsoleReader.java new file mode 100644 index 000000000..47e757b10 --- /dev/null +++ b/src/main/java/subway/view/console/ConsoleReader.java @@ -0,0 +1,26 @@ +package subway.view.console; + +import java.util.Scanner; +import subway.global.exception.CustomException; +import subway.global.exception.ErrorMessage; + +public final class ConsoleReader { + Scanner scanner = new Scanner(System.in); + + public String enterMessage() { + return Validator.validate(scanner.nextLine()); + } + + private static class Validator { + public static String validate(String message) { + validateBlankInput(message); + return message; + } + + private static void validateBlankInput(String message) { + if (message.isBlank()) { + throw CustomException.from(ErrorMessage.BLANK_INPUT_ERROR); + } + } + } +} diff --git a/src/main/java/subway/view/console/ConsoleWriter.java b/src/main/java/subway/view/console/ConsoleWriter.java new file mode 100644 index 000000000..9d65dfe77 --- /dev/null +++ b/src/main/java/subway/view/console/ConsoleWriter.java @@ -0,0 +1,15 @@ +package subway.view.console; + +public final class ConsoleWriter { + public static void printlnMessage(String message) { + System.out.println(message); + } + + public static void printlnFormat(String message, Object... args) { + printlnMessage(String.format(message, args)); + } + + public static void println() { + System.out.println(); + } +}