diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..190b513c1 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,70 @@ +# 지하철 노선도 미션 + +## 🎯 구현할 기능 목록 + +### 초기 설정 +- [x] 아래의 사전 등록 정보로 초기 설정을 한다. + ``` + 1. 지하철역으로 교대역, 강남역, 역삼역, 남부터미널역, 양재역, 양재시민의숲역, 매봉역이 등록되어 있다. + 2. 지하철 노선으로 2호선, 3호선, 신분당선이 등록되어 있다. + 3. 노선에 역이 아래와 같이 등록되어 있다.(왼쪽 끝이 상행 종점) + - 2호선: 교대역 - 강남역 - 역삼역 + - 3호선: 교대역 - 남부터미널역 - 양재역 - 매봉역 + - 신분당선: 강남역 - 양재역 - 양재시민의숲역 + ``` + +### 메인 화면 관련 기능 +- [x] 메인 화면을 출력한다. +- [x] 원하는 기능을 선택한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [ ] 선택할 수 없는 기능을 선택한 경우 +- [ ] 역 관리 화면을 출력한다. +- [ ] 노선 관리 화면을 출력한다. +- [ ] 구간 관리 화면을 출력한다. +- [ ] 지하철 노선도를 출력한다. + - 노선의 상행 종점부터 하행 종점까지 연결된 순서대로 역 목록을 출력한다. +- [ ] 프로그램을 종료한다. + +### 역 관리 화면 관련 기능 +- [x] 원하는 기능을 선택한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [ ] 선택할 수 없는 기능을 선택한 경우 +- [x] 지하철 역을 등록한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [x] 중복된 지하철 역 이름을 등록하는 경우 + - [x] 지하철 역 이름이 2글자 미만인 경우 + - [x] 입력이 없는 경우 + - [x] 지하철 역 이름에 공백이 포함된 경우 +- [x] 지하철 역을 삭제한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [x] 노선에 등록된 역을 삭제하는 경우 + - [x] 등록되지 않은 역을 삭제하는 경우 +- [x] 지하철 역의 목록을 조회한다. + +### 노선 관리 화면 관련 기능 +- [x] 원하는 기능을 선택한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [ ] 선택할 수 없는 기능을 선택한 경우 +- [x] 지하철 노선을 등록한다. 노선 등록 시 상행 종점역과 하행 종점역을 입력받는다. + - **예외 상황 시 에러 문구를 출력한다.** + - [x] 중복된 지하철 노선 이름을 등록하는 경우 + - [x] 지하철 노선 이름이 2글자 미만인 경우 + - [x] 지하철 노선 이름이 없는 경우 + - [x] 지하철 노선 이름에 공백이 포함된 경우 +- [x] 지하철 노선을 삭제한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [x] 등록되지 않은 노선을 삭제하는 경우 +- [x] 지하철 노선의 목록을 조회한다. + +### 구간 관리 화면 관련 기능 +- [x] 원하는 기능을 선택한다. + - **예외 상황 시 에러 문구를 출력한다.** + - [ ] 선택할 수 없는 기능을 선택한 경우 +- [x] 지하철 구간을 등록한다. 구간 등록 시 노선과 역 이름, 순서를 입력받는다. + - **예외 상황 시 에러 문구를 출력한다.** + - [ ] 중복된 지하철 구간을 등록하는 경우 +- [ ] 지하철 구간을 삭제한다. + - 종점을 제거할 경우 다음 역이 종점이 된다. + - **예외 상황 시 에러 문구를 출력한다.** + - [ ] 노선에 등록되지 않은 역을 제거하는 경우 + - [ ] 노선에 포함된 역이 두개 이하일 때 역을 삭제하는 경우 diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java index 0bcf786cc..30f73ff29 100644 --- a/src/main/java/subway/Application.java +++ b/src/main/java/subway/Application.java @@ -1,10 +1,10 @@ package subway; -import java.util.Scanner; +import subway.controller.SubwayController; public class Application { public static void main(String[] args) { - final Scanner scanner = new Scanner(System.in); // TODO: 프로그램 구현 + SubwayController.run(); } } diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java new file mode 100644 index 000000000..9797f357c --- /dev/null +++ b/src/main/java/subway/controller/LineController.java @@ -0,0 +1,47 @@ +package subway.controller; + +import subway.controller.function.LineFunction; +import subway.controller.message.LineMessage; +import subway.controller.screen.SubwayScreen; +import subway.service.LineService; +import subway.controller.validation.LineValidator; +import subway.service.SectionService; +import subway.view.SubwayView; + +public class LineController { + public static void run() { + SubwayView.displayScreen(SubwayScreen.LINE_MANAGEMENT); + SubwayView.notice(LineMessage.SELECT_FUNCTION); + String functionCode = LineValidator.validateLineFunction(SubwayView.userInput()); + LineFunction.callBy(functionCode); + } + + public static void lines() { + SubwayView.notice(LineMessage.NOTICE_LINE_LIST); + LineService.lines().stream() + .forEach(line -> SubwayView.info(line.getName())); + SubwayView.newLine(); + } + + public static void addLine() { + SubwayView.notice(LineMessage.ENTER_LINE_NAME); + String lineName = LineValidator.validateLineName(SubwayView.userInput()); + SubwayView.notice(LineMessage.ENTER_UPWARD_STATION_NAME); + String upwardStationName = + LineValidator.validateUpwardStationName(SubwayView.userInput()); + SubwayView.notice(LineMessage.ENTER_DOWNWARD_STATION_NAME); + String downwardStationName = + LineValidator.validateDownwardStationName(upwardStationName, SubwayView.userInput()); + + LineService.addLine(lineName); + SectionService.createSection(lineName, upwardStationName, downwardStationName); + SubwayView.info(LineMessage.INFO_ADD_LINE); + } + + public static void deleteLineByName() { + SubwayView.notice(LineMessage.ENTER_LINE_NAME_TO_BE_DELETED); + String lineName = LineValidator.validateLineNameToBeDeleted(SubwayView.userInput()); + LineService.deleteLineByName(lineName); + SubwayView.info(LineMessage.INFO_DELETE_LINE); + } +} diff --git a/src/main/java/subway/controller/MainController.java b/src/main/java/subway/controller/MainController.java new file mode 100644 index 000000000..17149cea6 --- /dev/null +++ b/src/main/java/subway/controller/MainController.java @@ -0,0 +1,32 @@ +package subway.controller; + +import subway.controller.function.MainFunction; +import subway.controller.message.MainMessage; +import subway.controller.screen.SubwayScreen; +import subway.controller.validation.MainValidator; +import subway.view.SubwayView; + +import java.util.Objects; + +public class MainController { + private static boolean isQuit(String functionCode) { + return Objects.equals(MainFunction.QUIT.getCode(), functionCode); + } + + public static void run() { + while (true) { + SubwayView.displayScreen(SubwayScreen.MAIN); + SubwayView.notice(MainMessage.SELECT_FUNCTION); + String functionCode = MainValidator.validateMainFunction(SubwayView.userInput()); + + if (isQuit(functionCode)) { + return; + } + + MainFunction.callBy(functionCode); + } + } + + public static void redirect() { + } +} diff --git a/src/main/java/subway/controller/SectionController.java b/src/main/java/subway/controller/SectionController.java new file mode 100644 index 000000000..27e984c48 --- /dev/null +++ b/src/main/java/subway/controller/SectionController.java @@ -0,0 +1,44 @@ +package subway.controller; + +import subway.controller.function.SectionFunction; +import subway.controller.message.SectionMessage; +import subway.controller.screen.SubwayScreen; +import subway.controller.validation.SectionValidator; +import subway.service.SectionService; +import subway.view.SubwayView; + +public class SectionController { + public static void run() { + SubwayView.displayScreen(SubwayScreen.SECTION_MANAGEMENT); + SubwayView.notice(SectionMessage.SELECT_FUNCTION); + String functionCode = SectionValidator.validateSectionFunction(SubwayView.userInput()); + SectionFunction.callBy(functionCode); + } + + public static void sections() { + SubwayView.notice(SectionMessage.NOTICE_SECTION_LIST); + SectionService.sections().stream() + .forEach(section -> SubwayView.printSubwayMap(section)); + SubwayView.newLine(); + } + + public static void addSection() { + SubwayView.notice(SectionMessage.ENTER_LINE_NAME); + String lineName = SectionValidator.validateLineNameExist(SubwayView.userInput()); + SubwayView.notice(SectionMessage.ENTER_STATION_NAME); + String stationName = SectionValidator.validateStationNameExist(SubwayView.userInput()); + SubwayView.notice(SectionMessage.ENTER_ORDER); + int order = SectionValidator.validateOrder(SubwayView.userInput()); + SectionService.addSection(lineName, stationName, order); + SubwayView.info(SectionMessage.INFO_ADD_SECTION); + } + + public static void deleteSection() { + SubwayView.notice(SectionMessage.ENTER_LINE_NAME_TO_BE_DELETED); + String lineName = SectionValidator.validateLineNameExist(SubwayView.userInput()); + SubwayView.notice(SectionMessage.ENTER_STATION_NAME_TO_BE_DELETED); + String stationName = SectionValidator.validateLineNameToBeDeleted(SubwayView.userInput()); + SectionService.deleteSectionByName(lineName, stationName); + SubwayView.info(SectionMessage.INFO_DELETE_SECTION); + } +} diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/controller/StationController.java new file mode 100644 index 000000000..51b10e4be --- /dev/null +++ b/src/main/java/subway/controller/StationController.java @@ -0,0 +1,38 @@ +package subway.controller; + +import subway.controller.function.StationFunction; +import subway.controller.message.StationMessage; +import subway.controller.screen.SubwayScreen; +import subway.controller.validation.StationValidator; +import subway.service.StationService; +import subway.view.SubwayView; + +public class StationController { + public static void run() { + SubwayView.displayScreen(SubwayScreen.STATION_MANAGEMENT); + SubwayView.notice(StationMessage.SELECT_FUNCTION); + String functionCode = StationValidator.validateStationFunction(SubwayView.userInput()); + StationFunction.callBy(functionCode); + } + + public static void stations() { + SubwayView.notice(StationMessage.NOTICE_STATION_LIST); + StationService.stations().stream() + .forEach(station -> SubwayView.info(station.getName())); + SubwayView.newLine(); + } + + public static void addStation() { + SubwayView.notice(StationMessage.ENTER_STATION_NAME); + String stationName = StationValidator.validateStationName(SubwayView.userInput()); + StationService.addStation(stationName); + SubwayView.info(StationMessage.INFO_ADD_STATION); + } + + public static void deleteStation() { + SubwayView.notice(StationMessage.ENTER_STATION_NAME_TO_BE_DELETED); + String stationName = StationValidator.validateStationNameToBeDeleted(SubwayView.userInput()); + StationService.deleteStationByName(stationName); + SubwayView.info(StationMessage.INFO_DELETE_STATION); + } +} diff --git a/src/main/java/subway/controller/SubwayController.java b/src/main/java/subway/controller/SubwayController.java new file mode 100644 index 000000000..93244f298 --- /dev/null +++ b/src/main/java/subway/controller/SubwayController.java @@ -0,0 +1,44 @@ +package subway.controller; + +import subway.controller.initialization.InitialLine; +import subway.controller.initialization.InitialSection; +import subway.controller.initialization.InitialStation; +import subway.service.LineService; +import subway.service.SectionService; +import subway.service.StationService; + +import java.util.Arrays; +import java.util.List; + +public class SubwayController { + public static void initStation() { + Arrays.stream(InitialStation.values()) + .forEach(station -> StationService.addStation(station.getName())); + } + + public static void initLine() { + Arrays.stream(InitialLine.values()) + .forEach(line -> LineService.addLine(line.getName())); + Arrays.stream(InitialLine.values()) + .forEach(line -> SectionService.createSection(line.getName())); + } + + public static void initSection() { + Arrays.stream(InitialSection.values()) + .forEach(initialSection -> initSection(initialSection)); + } + + public static void initSection(InitialSection initialSection) { + String lineName = initialSection.getLineName(); + List stationNames = initialSection.getStationNames(); + stationNames.stream() + .forEach(stationName -> SectionService.addSection(lineName, stationName)); + } + + public static void run() { + initStation(); + initLine(); + initSection(); + MainController.run(); + } +} diff --git a/src/main/java/subway/controller/function/Function.java b/src/main/java/subway/controller/function/Function.java new file mode 100644 index 000000000..ef911d716 --- /dev/null +++ b/src/main/java/subway/controller/function/Function.java @@ -0,0 +1,9 @@ +package subway.controller.function; + +public interface Function { + String getCode(); + + String getTitle(); + + Runnable getFunction(); +} diff --git a/src/main/java/subway/controller/function/LineFunction.java b/src/main/java/subway/controller/function/LineFunction.java new file mode 100644 index 000000000..3b7126c21 --- /dev/null +++ b/src/main/java/subway/controller/function/LineFunction.java @@ -0,0 +1,48 @@ +package subway.controller.function; + +import subway.controller.LineController; +import subway.controller.MainController; + +import java.util.Arrays; +import java.util.Objects; + +public enum LineFunction implements Function { + REGISTER_LINE("1", "노선 등록", LineController::addLine), + DELETE_LINE("2", "노선 삭제", LineController::deleteLineByName), + SEARCH_LINE("3", "노선 조회", LineController::lines), + BACK("B", "돌아가기", MainController::redirect); + + private String code; + private String title; + private Runnable function; + + LineFunction(String code, String title, Runnable function) { + this.code = code; + this.title = title; + this.function = function; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public Runnable getFunction() { + return function; + } + + public static void callBy(String code) { + Arrays.stream(LineFunction.values()) + .filter(function -> Objects.equals(function.getCode(), code)) + .findAny() + .get() + .getFunction() + .run(); + } +} diff --git a/src/main/java/subway/controller/function/MainFunction.java b/src/main/java/subway/controller/function/MainFunction.java new file mode 100644 index 000000000..73ff27bdb --- /dev/null +++ b/src/main/java/subway/controller/function/MainFunction.java @@ -0,0 +1,52 @@ +package subway.controller.function; + +import subway.controller.LineController; +import subway.controller.MainController; +import subway.controller.SectionController; +import subway.controller.StationController; + +import java.util.Arrays; +import java.util.Objects; + +public enum MainFunction implements Function { + MANAGE_STATION("1", "역 관리", StationController::run), + MANAGE_LINE("2", "노선 관리", LineController::run), + MANAGE_SECTION("3", "구간 관리", SectionController::run), + PRINT_SUBWAY_MAP("4", "지하철 노선도 출력", SectionController::sections), + QUIT("Q", "종료", MainController::run); + + private String code; + private String title; + private Runnable function; + + MainFunction(String code, String title, Runnable function) { + this.code = code; + this.title = title; + this.function = function; + + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public Runnable getFunction() { + return function; + } + + public static void callBy(String code) { + Arrays.stream(MainFunction.values()) + .filter(function -> Objects.equals(function.getCode(), code)) + .findAny() + .get() + .getFunction() + .run(); + } +} diff --git a/src/main/java/subway/controller/function/SectionFunction.java b/src/main/java/subway/controller/function/SectionFunction.java new file mode 100644 index 000000000..d1dea9ace --- /dev/null +++ b/src/main/java/subway/controller/function/SectionFunction.java @@ -0,0 +1,47 @@ +package subway.controller.function; + +import subway.controller.MainController; +import subway.controller.SectionController; + +import java.util.Arrays; +import java.util.Objects; + +public enum SectionFunction implements Function { + REGISTER_SECTION("1", "구간 등록", SectionController::addSection), + DELETE_SECTION("2", "구간 삭제", SectionController::deleteSection), + BACK("B", "돌아가기", MainController::redirect); + + private String code; + private String title; + private Runnable function; + + SectionFunction(String code, String title, Runnable function) { + this.code = code; + this.title = title; + this.function = function; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public Runnable getFunction() { + return function; + } + + public static void callBy(String code) { + Arrays.stream(SectionFunction.values()) + .filter(function -> Objects.equals(function.getCode(), code)) + .findAny() + .get() + .getFunction() + .run(); + } +} diff --git a/src/main/java/subway/controller/function/StationFunction.java b/src/main/java/subway/controller/function/StationFunction.java new file mode 100644 index 000000000..62e7a7702 --- /dev/null +++ b/src/main/java/subway/controller/function/StationFunction.java @@ -0,0 +1,48 @@ +package subway.controller.function; + +import subway.controller.MainController; +import subway.controller.StationController; + +import java.util.Arrays; +import java.util.Objects; + +public enum StationFunction implements Function { + REGISTER_STATION("1", "역 등록", StationController::addStation), + DELETE_STATION("2", "역 삭제", StationController::deleteStation), + SEARCH_STATION("3", "역 조회", StationController::stations), + BACK("B", "돌아가기", MainController::redirect); + + private String code; + private String title; + private Runnable function; + + StationFunction(String code, String title, Runnable function) { + this.code = code; + this.title = title; + this.function = function; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public Runnable getFunction() { + return function; + } + + public static void callBy(String code) { + Arrays.stream(StationFunction.values()) + .filter(function -> Objects.equals(function.getCode(), code)) + .findAny() + .get() + .getFunction() + .run(); + } +} diff --git a/src/main/java/subway/controller/initialization/InitialLine.java b/src/main/java/subway/controller/initialization/InitialLine.java new file mode 100644 index 000000000..29b602257 --- /dev/null +++ b/src/main/java/subway/controller/initialization/InitialLine.java @@ -0,0 +1,17 @@ +package subway.controller.initialization; + +public enum InitialLine { + LINE_NUMBER_2("2호선"), + LINE_NUMBER_3("3호선"), + SHINBUNDANG_LINE("신분당선"); + + private String name; + + InitialLine(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/subway/controller/initialization/InitialSection.java b/src/main/java/subway/controller/initialization/InitialSection.java new file mode 100644 index 000000000..c09670dbe --- /dev/null +++ b/src/main/java/subway/controller/initialization/InitialSection.java @@ -0,0 +1,26 @@ +package subway.controller.initialization; + +import java.util.Arrays; +import java.util.List; + +public enum InitialSection { + LINE_NUMBER_2("2호선", Arrays.asList("교대역", "강남역", "역삼역")), + LINE_NUMBER_3("3호선", Arrays.asList("교대역", "남부터미널역", "양재역", "매봉역")), + SHINBUNDANG_LINE("신분당선", Arrays.asList("강남역", "양재역", "양재시민의숲역")); + + private String lineName; + private List stationNames; + + InitialSection(String lineName, List stationNames) { + this.lineName = lineName; + this.stationNames = stationNames; + } + + public String getLineName() { + return lineName; + } + + public List getStationNames() { + return stationNames; + } +} diff --git a/src/main/java/subway/controller/initialization/InitialStation.java b/src/main/java/subway/controller/initialization/InitialStation.java new file mode 100644 index 000000000..6dc1e60c5 --- /dev/null +++ b/src/main/java/subway/controller/initialization/InitialStation.java @@ -0,0 +1,21 @@ +package subway.controller.initialization; + +public enum InitialStation { + GYODAE_STATION("교대역"), + GANGNAM_STATION("강남역"), + YEOKSAM_STATION("역삼역"), + NAMBU_TERMINAL_STATION("남부터미널역"), + YANGJAE_STATION("양재역"), + YANGJAE_CITIZENS_FOREST_STATION("양재시민의숲역"), + MAEBONG_STATION("매봉역"); + + private String name; + + InitialStation(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/subway/controller/message/LineMessage.java b/src/main/java/subway/controller/message/LineMessage.java new file mode 100644 index 000000000..ae3c68d20 --- /dev/null +++ b/src/main/java/subway/controller/message/LineMessage.java @@ -0,0 +1,27 @@ +package subway.controller.message; + +public enum LineMessage implements Message { + SELECT_FUNCTION("원하는 기능을 선택하세요."), + ENTER_LINE_NAME("등록할 노선 이름을 입력하세요."), + ENTER_UPWARD_STATION_NAME("등록할 노선의 상행 종점역 이름을 입력하세요."), + ENTER_DOWNWARD_STATION_NAME("등록할 노선의 하행 종점역 이름을 입력하세요."), + ENTER_LINE_NAME_TO_BE_DELETED("삭제할 노선 이름을 입력하세요."), + INFO_ADD_LINE("지하철 노선이 등록되었습니다."), + INFO_DELETE_LINE("지하철 노선이 삭제되었습니다."), + NOTICE_LINE_LIST("노선 목록"), + ERROR_SELECT_FUNCTION("선택할 수 없는 기능입니다."), + ERROR_DUPLICATE_LINE_NAME("이미 등록된 노선 이름입니다."), + ERROR_INVALID_LINE_NAME_LENGTH("노선 이름은 2글자 이상이어야 합니다."), + ERROR_NOT_EXIST_LINE("존재하지 않는 노선 이름입니다."); + + private String content; + + LineMessage(String content) { + this.content = content; + } + + @Override + public String getContent() { + return content; + } +} diff --git a/src/main/java/subway/controller/message/MainMessage.java b/src/main/java/subway/controller/message/MainMessage.java new file mode 100644 index 000000000..12d49c75e --- /dev/null +++ b/src/main/java/subway/controller/message/MainMessage.java @@ -0,0 +1,17 @@ +package subway.controller.message; + +public enum MainMessage implements Message { + SELECT_FUNCTION("원하는 기능을 선택하세요."), + ERROR_SELECT_FUNCTION("선택할 수 없는 기능입니다."); + + private String content; + + MainMessage(String content) { + this.content = content; + } + + @Override + public String getContent() { + return content; + } +} diff --git a/src/main/java/subway/controller/message/Message.java b/src/main/java/subway/controller/message/Message.java new file mode 100644 index 000000000..ce56e1ebd --- /dev/null +++ b/src/main/java/subway/controller/message/Message.java @@ -0,0 +1,5 @@ +package subway.controller.message; + +public interface Message { + String getContent(); +} diff --git a/src/main/java/subway/controller/message/SectionMessage.java b/src/main/java/subway/controller/message/SectionMessage.java new file mode 100644 index 000000000..55d2d4dcf --- /dev/null +++ b/src/main/java/subway/controller/message/SectionMessage.java @@ -0,0 +1,26 @@ +package subway.controller.message; + +public enum SectionMessage implements Message { + SELECT_FUNCTION("원하는 기능을 선택하세요."), + ENTER_LINE_NAME("노선 이름을 입력하세요."), + ENTER_STATION_NAME("역 이름을 입력하세요."), + ENTER_ORDER("순서를 입력하세요."), + ENTER_LINE_NAME_TO_BE_DELETED("삭제할 구간의 노선을 입력하세요."), + ENTER_STATION_NAME_TO_BE_DELETED("삭제할 구간의 역을 입력하세요."), + NOTICE_SECTION_LIST("지하철 노선도"), + INFO_ADD_SECTION("구간이 등록되었습니다."), + INFO_DELETE_SECTION("구간이 삭제되었습니다."), + ERROR_SELECT_FUNCTION("선택할 수 없는 기능입니다."), + ERROR_INVALID_ORDER("잘못된 순서입니다."); + + private String content; + + SectionMessage(String content) { + this.content = content; + } + + @Override + public String getContent() { + return content; + } +} diff --git a/src/main/java/subway/controller/message/StationMessage.java b/src/main/java/subway/controller/message/StationMessage.java new file mode 100644 index 000000000..4334c90bb --- /dev/null +++ b/src/main/java/subway/controller/message/StationMessage.java @@ -0,0 +1,26 @@ +package subway.controller.message; + +public enum StationMessage implements Message { + SELECT_FUNCTION("원하는 기능을 선택하세요."), + ENTER_STATION_NAME("등록할 역 이름을 입력하세요."), + ENTER_STATION_NAME_TO_BE_DELETED("삭제할 역 이름을 입력하세요."), + INFO_ADD_STATION("지하철 역이 등록되었습니다."), + INFO_DELETE_STATION("지하철 역이 삭제되었습니다."), + NOTICE_STATION_LIST("역 목록"), + ERROR_SELECT_FUNCTION("선택할 수 없는 기능입니다."), + ERROR_DUPLICATE_STATION_NAME("이미 등록된 역 이름입니다."), + ERROR_INVALID_STATION_NAME_LENGTH("역 이름은 2글자 이상이어야 합니다."), + ERROR_NOT_EXIST_STATION("존재하지 않는 역 이름입니다."), + ERROR_STATION_ADDED_TO_LINE("노선에 등록된 역은 삭제할 수 없습니다."); + + private String content; + + StationMessage(String content) { + this.content = content; + } + + @Override + public String getContent() { + return content; + } +} diff --git a/src/main/java/subway/controller/screen/Screen.java b/src/main/java/subway/controller/screen/Screen.java new file mode 100644 index 000000000..7f747c347 --- /dev/null +++ b/src/main/java/subway/controller/screen/Screen.java @@ -0,0 +1,11 @@ +package subway.controller.screen; + +import subway.controller.function.Function; + +import java.util.List; + +public interface Screen { + String getTitle(); + + List getFunctions(); +} diff --git a/src/main/java/subway/controller/screen/SubwayScreen.java b/src/main/java/subway/controller/screen/SubwayScreen.java new file mode 100644 index 000000000..e1b5cc4e7 --- /dev/null +++ b/src/main/java/subway/controller/screen/SubwayScreen.java @@ -0,0 +1,35 @@ +package subway.controller.screen; + +import subway.controller.function.Function; +import subway.controller.function.LineFunction; +import subway.controller.function.MainFunction; +import subway.controller.function.SectionFunction; +import subway.controller.function.StationFunction; + +import java.util.Arrays; +import java.util.List; + +public enum SubwayScreen implements Screen { + MAIN("메인 화면", Arrays.asList(MainFunction.values())), + STATION_MANAGEMENT("역 관리 화면", Arrays.asList(StationFunction.values())), + LINE_MANAGEMENT("노선 관리 화면", Arrays.asList(LineFunction.values())), + SECTION_MANAGEMENT("구간 관리 화면", Arrays.asList(SectionFunction.values())); + + private String title; + private List functions; + + SubwayScreen(String title, List functions) { + this.title = title; + this.functions = functions; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public List getFunctions() { + return functions; + } +} diff --git a/src/main/java/subway/controller/validation/LineValidator.java b/src/main/java/subway/controller/validation/LineValidator.java new file mode 100644 index 000000000..6016afa7c --- /dev/null +++ b/src/main/java/subway/controller/validation/LineValidator.java @@ -0,0 +1,138 @@ +package subway.controller.validation; + +import subway.controller.message.LineMessage; +import subway.controller.message.StationMessage; +import subway.service.LineService; +import subway.view.SubwayView; + +import java.util.Objects; + +public class LineValidator { + private static final String LINE_FUNCTION_REGULAR_EXPRESSION = "^([1-3B])$"; + private static final int MINIMUM_LINE_NAME_LENGTH = 2; + + public static boolean isValidLineFunction(String functionCode) { + if (functionCode.matches(LINE_FUNCTION_REGULAR_EXPRESSION)) { + return true; + } + return false; + } + + public static boolean isValidLineNameLength(String lineName) { + if (lineName.length() >= MINIMUM_LINE_NAME_LENGTH) { + return true; + } + return false; + } + + public static Boolean hasLineName(String lineName) { + return LineService.lines().stream() + .anyMatch(line -> line.getName().equals(lineName)); + } + + public static String validateLineFunction(String functionCode) { + if (isValidLineFunction(functionCode)) { + return functionCode; + } + + SubwayView.error(LineMessage.ERROR_SELECT_FUNCTION); + SubwayView.notice(LineMessage.SELECT_FUNCTION); + functionCode = SubwayView.userInput(); + functionCode = validateLineFunction(functionCode); + return functionCode; + } + + public static String validateLineNameLength(String lineName) { + if (isValidLineNameLength(lineName)) { + return lineName; + } + + SubwayView.error(LineMessage.ERROR_INVALID_LINE_NAME_LENGTH); + SubwayView.notice(LineMessage.ENTER_LINE_NAME); + lineName = SubwayView.userInput(); + lineName = validateLineName(lineName); + return lineName; + } + + public static String validateDuplicateLineName(String lineName) { + if (!hasLineName(lineName)) { + return lineName; + } + + SubwayView.error(LineMessage.ERROR_DUPLICATE_LINE_NAME); + SubwayView.notice(LineMessage.ENTER_LINE_NAME); + lineName = SubwayView.userInput(); + lineName = validateLineName(lineName); + return lineName; + } + + public static String validateLineNameExist(String lineName) { + if (hasLineName(lineName)) { + return lineName; + } + + SubwayView.error(LineMessage.ERROR_NOT_EXIST_LINE); + SubwayView.notice(LineMessage.ENTER_LINE_NAME_TO_BE_DELETED); + lineName = SubwayView.userInput(); + lineName = validateLineNameToBeDeleted(lineName); + return lineName; + } + + public static String validateLineNameToBeDeleted(String lineName) { + lineName = validateLineNameExist(lineName); + return lineName; + } + + public static String validateLineName(String lineName) { + lineName = validateLineNameLength(lineName); + lineName = validateDuplicateLineName(lineName); + return lineName; + } + + public static String validateUpwardStationName(String upwardStationName) { + if (StationValidator.hasStationName(upwardStationName)) { + return upwardStationName; + } + + SubwayView.error(StationMessage.ERROR_NOT_EXIST_STATION); + SubwayView.notice(LineMessage.ENTER_UPWARD_STATION_NAME); + upwardStationName = SubwayView.userInput(); + upwardStationName = validateUpwardStationName(upwardStationName); + return upwardStationName; + } + + public static String validateDuplicateDownwardStationName(String upwardStationName, + String downwardStationName) { + if (!Objects.equals(upwardStationName, downwardStationName)) { + return downwardStationName; + } + + SubwayView.error(StationMessage.ERROR_DUPLICATE_STATION_NAME); + SubwayView.notice(LineMessage.ENTER_DOWNWARD_STATION_NAME); + downwardStationName = SubwayView.userInput(); + downwardStationName = validateDownwardStationName(upwardStationName, downwardStationName); + return downwardStationName; + } + + public static String validateDownwardStationNameExist(String upwardStationName, + String downwardStationName) { + if (StationValidator.hasStationName(downwardStationName)) { + return downwardStationName; + } + + SubwayView.error(StationMessage.ERROR_NOT_EXIST_STATION); + SubwayView.notice(LineMessage.ENTER_DOWNWARD_STATION_NAME); + downwardStationName = SubwayView.userInput(); + downwardStationName = validateDownwardStationName(upwardStationName, downwardStationName); + return downwardStationName; + } + + public static String validateDownwardStationName(String upwardStationName, + String downwardStationName) { + downwardStationName = + validateDuplicateDownwardStationName(upwardStationName, downwardStationName); + downwardStationName = + validateDownwardStationNameExist(upwardStationName, downwardStationName); + return downwardStationName; + } +} diff --git a/src/main/java/subway/controller/validation/MainValidator.java b/src/main/java/subway/controller/validation/MainValidator.java new file mode 100644 index 000000000..4f7b2472a --- /dev/null +++ b/src/main/java/subway/controller/validation/MainValidator.java @@ -0,0 +1,27 @@ +package subway.controller.validation; + +import subway.controller.message.MainMessage; +import subway.view.SubwayView; + +public class MainValidator { + private static final String MAIN_FUNCTION_REGULAR_EXPRESSION = "^([1-4Q])$"; + + public static boolean isValidMainFunction(String functionCode) { + if (functionCode.matches(MAIN_FUNCTION_REGULAR_EXPRESSION)) { + return true; + } + return false; + } + + public static String validateMainFunction(String functionCode) { + if (isValidMainFunction(functionCode)) { + return functionCode; + } + + SubwayView.error(MainMessage.ERROR_SELECT_FUNCTION); + SubwayView.notice(MainMessage.SELECT_FUNCTION); + functionCode = SubwayView.userInput(); + functionCode = validateMainFunction(functionCode); + return functionCode; + } +} diff --git a/src/main/java/subway/controller/validation/SectionValidator.java b/src/main/java/subway/controller/validation/SectionValidator.java new file mode 100644 index 000000000..9be704d4b --- /dev/null +++ b/src/main/java/subway/controller/validation/SectionValidator.java @@ -0,0 +1,98 @@ +package subway.controller.validation; + +import subway.controller.message.LineMessage; +import subway.controller.message.SectionMessage; +import subway.controller.message.StationMessage; +import subway.service.LineService; +import subway.service.SectionService; +import subway.view.SubwayView; + +public class SectionValidator { + private static final String SECTION_FUNCTION_REGULAR_EXPRESSION = "^([1-2B])$"; + private static final int MINIMUM_NUMBER_OF_STATIONS_ON_LINE = 0; + + public static boolean isValidSectionFunction(String functionCode) { + if (functionCode.matches(SECTION_FUNCTION_REGULAR_EXPRESSION)) { + return true; + } + return false; + } + + public static boolean isNumeric(String stringOrder) { + try { + int order = Integer.parseInt(stringOrder); + } catch (NumberFormatException numberFormatException) { + return false; + } + return true; + } + + public static boolean isValidOrder(String stringOrder) { + if (!isNumeric(stringOrder)) { + return false; + } + + int order = Integer.parseInt(stringOrder); + + if (order >= MINIMUM_NUMBER_OF_STATIONS_ON_LINE + && order <= SectionService.sections().size()) { + return true; + } + return false; + } + + public static String validateSectionFunction(String functionCode) { + if (isValidSectionFunction(functionCode)) { + return functionCode; + } + + SubwayView.error(SectionMessage.ERROR_SELECT_FUNCTION); + SubwayView.notice(SectionMessage.SELECT_FUNCTION); + functionCode = SubwayView.userInput(); + functionCode = validateSectionFunction(functionCode); + return functionCode; + } + + public static String validateLineNameExist(String lineName) { + if (LineValidator.hasLineName(lineName)) { + return lineName; + } + + SubwayView.error(LineMessage.ERROR_NOT_EXIST_LINE); + SubwayView.notice(SectionMessage.ENTER_LINE_NAME); + lineName = SubwayView.userInput(); + lineName = validateLineNameExist(lineName); + return lineName; + } + + public static String validateStationNameExist(String stationName) { + if (StationValidator.hasStationName(stationName)) { + return stationName; + } + + SubwayView.error(StationMessage.ERROR_NOT_EXIST_STATION); + SubwayView.notice(SectionMessage.ENTER_STATION_NAME); + stationName = SubwayView.userInput(); + stationName = validateStationNameExist(stationName); + return stationName; + } + + public static int validateOrder(String stringOrder) { + if (isValidOrder(stringOrder)) { + int order = Integer.parseInt(stringOrder); + return order; + } + + SubwayView.error(SectionMessage.ERROR_INVALID_ORDER); + SubwayView.notice(SectionMessage.ENTER_ORDER); + stringOrder = SubwayView.userInput(); + int order = validateOrder(stringOrder); + return order; + } + + public static String validateSectionToBeDeleted(String lineName, String stationName) { + + stationName = validateStationNameExist(stationName); + return stationName; + } +} diff --git a/src/main/java/subway/controller/validation/StationValidator.java b/src/main/java/subway/controller/validation/StationValidator.java new file mode 100644 index 000000000..14a8fb70b --- /dev/null +++ b/src/main/java/subway/controller/validation/StationValidator.java @@ -0,0 +1,115 @@ +package subway.controller.validation; + +import subway.controller.message.StationMessage; +import subway.domain.Section; +import subway.service.SectionService; +import subway.service.StationService; +import subway.view.SubwayView; + +import java.util.Objects; + +public class StationValidator { + private static final String STATION_FUNCTION_REGULAR_EXPRESSION = "^([1-3B])$"; + private static final int MINIMUM_STATION_NAME_LENGTH = 2; + + public static boolean isValidStationFunction(String functionCode) { + if (functionCode.matches(STATION_FUNCTION_REGULAR_EXPRESSION)) { + return true; + } + return false; + } + + public static boolean isValidStationNameLength(String stationName) { + if (stationName.length() >= MINIMUM_STATION_NAME_LENGTH) { + return true; + } + return false; + } + + public static Boolean hasStationName(String stationName) { + return StationService.stations().stream() + .anyMatch(station -> station.getName().equals(stationName)); + } + + public static String validateStationFunction(String functionCode) { + if (isValidStationFunction(functionCode)) { + return functionCode; + } + + SubwayView.error(StationMessage.ERROR_SELECT_FUNCTION); + SubwayView.notice(StationMessage.SELECT_FUNCTION); + functionCode = SubwayView.userInput(); + functionCode = validateStationFunction(functionCode); + return functionCode; + } + + public static String validateStationNameLength(String stationName) { + if (isValidStationNameLength(stationName)) { + return stationName; + } + + SubwayView.error(StationMessage.ERROR_INVALID_STATION_NAME_LENGTH); + SubwayView.notice(StationMessage.ENTER_STATION_NAME); + stationName = SubwayView.userInput(); + stationName = validateStationName(stationName); + return stationName; + } + + public static String validateDuplicateStationName(String stationName) { + if (!hasStationName(stationName)) { + return stationName; + } + + SubwayView.error(StationMessage.ERROR_DUPLICATE_STATION_NAME); + SubwayView.notice(StationMessage.ENTER_STATION_NAME); + stationName = SubwayView.userInput(); + stationName = validateStationName(stationName); + return stationName; + } + + public static String validateStationName(String stationName) { + stationName = validateStationNameLength(stationName); + stationName = validateDuplicateStationName(stationName); + return stationName; + } + + public static String validateStationNameExist(String stationName) { + if (hasStationName(stationName)) { + return stationName; + } + + SubwayView.error(StationMessage.ERROR_NOT_EXIST_STATION); + SubwayView.notice(StationMessage.ENTER_STATION_NAME_TO_BE_DELETED); + stationName = SubwayView.userInput(); + stationName = validateStationNameToBeDeleted(stationName); + return stationName; + } + + public static boolean findAddedToLine(String stationName, Section section) { + return section.getStations().stream() + .anyMatch(station -> Objects.equals(station.getName(), stationName)); + } + + public static boolean findAddedToLine(String stationName) { + return SectionService.sections().stream() + .anyMatch(section -> findAddedToLine(stationName, section)); + } + + public static String isAddedToLine(String stationName) { + if (!findAddedToLine(stationName)) { + return stationName; + } + + SubwayView.error(StationMessage.ERROR_STATION_ADDED_TO_LINE); + SubwayView.notice(StationMessage.ENTER_STATION_NAME_TO_BE_DELETED); + stationName = SubwayView.userInput(); + stationName = validateStationNameToBeDeleted(stationName); + return stationName; + } + + public static String validateStationNameToBeDeleted(String stationName) { + stationName = validateStationNameExist(stationName); + stationName = isAddedToLine(stationName); + return stationName; + } +} diff --git a/src/main/java/subway/domain/Section.java b/src/main/java/subway/domain/Section.java new file mode 100644 index 000000000..11d0b0cad --- /dev/null +++ b/src/main/java/subway/domain/Section.java @@ -0,0 +1,38 @@ +package subway.domain; + +import java.util.ArrayList; +import java.util.List; + +public class Section { + private Line line; + private List stations; + + public Section(Line line) { + this.line = line; + this.stations = new ArrayList<>(); + } + + public Section(Line line, Station upwardStation, Station downwardStation) { + this.line = line; + this.stations = new ArrayList<>(); + this.stations.add(upwardStation); + this.stations.add(downwardStation); + } + + public Line getLine() { + return line; + } + + public List getStations() { + return stations; + } + + // 추가 기능 구현 + public void addStation(Station station) { + stations.add(station); + } + + public void addStation(int index, Station station) { + stations.add(index, station); + } +} diff --git a/src/main/java/subway/domain/LineRepository.java b/src/main/java/subway/repository/LineRepository.java similarity index 90% rename from src/main/java/subway/domain/LineRepository.java rename to src/main/java/subway/repository/LineRepository.java index 49132ddb6..2cf84c862 100644 --- a/src/main/java/subway/domain/LineRepository.java +++ b/src/main/java/subway/repository/LineRepository.java @@ -1,4 +1,6 @@ -package subway.domain; +package subway.repository; + +import subway.domain.Line; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/subway/repository/SectionRepository.java b/src/main/java/subway/repository/SectionRepository.java new file mode 100644 index 000000000..6876d5402 --- /dev/null +++ b/src/main/java/subway/repository/SectionRepository.java @@ -0,0 +1,47 @@ +package subway.repository; + +import subway.domain.Section; +import subway.domain.Station; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class SectionRepository { + private static final List
sections = new ArrayList<>(); + + public static List
sections() { + return Collections.unmodifiableList(sections); + } + + public static void createSection(Section section) { + sections.add(section); + } + + public static void addSection(String lineName, String stationName) { + Section foundSection = sections.stream() + .filter(section -> section.getLine().getName().equals(lineName)) + .findAny() + .get(); + + Station station = new Station(stationName); + foundSection.addStation(station); + } + + public static void addSection(String lineName, String stationName, int order) { + Section foundSection = sections.stream() + .filter(section -> section.getLine().getName().equals(lineName)) + .findAny() + .get(); + + Station station = new Station(stationName); + foundSection.addStation(order, station); + } + + public static boolean deleteSectionByName(String lineName, String stationName) { +// sections.removeIf(section -> Objects.equals(section.getLine(), line.getName()) && +// Objects.equals(section.getStations()., line.getName())) + return false; + } +} diff --git a/src/main/java/subway/domain/StationRepository.java b/src/main/java/subway/repository/StationRepository.java similarity index 80% rename from src/main/java/subway/domain/StationRepository.java rename to src/main/java/subway/repository/StationRepository.java index b7245c0f3..78217e659 100644 --- a/src/main/java/subway/domain/StationRepository.java +++ b/src/main/java/subway/repository/StationRepository.java @@ -1,4 +1,6 @@ -package subway.domain; +package subway.repository; + +import subway.domain.Station; import java.util.ArrayList; import java.util.Collections; @@ -16,7 +18,7 @@ public static void addStation(Station station) { stations.add(station); } - public static boolean deleteStation(String name) { + public static boolean deleteStationByName(String name) { return stations.removeIf(station -> Objects.equals(station.getName(), name)); } } diff --git a/src/main/java/subway/service/LineService.java b/src/main/java/subway/service/LineService.java new file mode 100644 index 000000000..b768d99ae --- /dev/null +++ b/src/main/java/subway/service/LineService.java @@ -0,0 +1,21 @@ +package subway.service; + +import subway.domain.Line; +import subway.repository.LineRepository; + +import java.util.List; + +public class LineService { + public static List lines() { + return LineRepository.lines(); + } + + public static void addLine(String lineName) { + Line line = new Line(lineName); + LineRepository.addLine(line); + } + + public static void deleteLineByName(String lineName) { + LineRepository.deleteLineByName(lineName); + } +} diff --git a/src/main/java/subway/service/SectionService.java b/src/main/java/subway/service/SectionService.java new file mode 100644 index 000000000..697b680ed --- /dev/null +++ b/src/main/java/subway/service/SectionService.java @@ -0,0 +1,45 @@ +package subway.service; + +import subway.domain.Line; +import subway.domain.Section; +import subway.domain.Station; +import subway.repository.SectionRepository; + +import java.util.List; + +public class SectionService { + public static List
sections() { + return SectionRepository.sections(); + } + + public static void createSection(String lineName) { + Line line = new Line(lineName); + Section section = new Section(line); + SectionRepository.createSection(section); + } + + public static void createSection(String lineName, String upwardStationName, String downwardStationName) { + Line line = new Line(lineName); + Station upwardStation = new Station(upwardStationName); + Station downwardStation = new Station(downwardStationName); + Section section = new Section(line, upwardStation, downwardStation); + SectionRepository.createSection(section); + } + + public static void addSection(String lineName, String stationName) { + SectionRepository.addSection(lineName, stationName); + } + + public static void addSection(String lineName, String stationName, int order) { +// Section foundSection = SectionRepository.sections().stream() +// .filter(section -> section.getLine().getName().equals(lineName)) +// .findAny() +// .get(); +// foundSection. + SectionRepository.addSection(lineName, stationName, order); + } + + public static void deleteSectionByName(String lineName, String stationName) { + SectionRepository.deleteSectionByName(lineName, stationName); + } +} diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java new file mode 100644 index 000000000..4034ebafb --- /dev/null +++ b/src/main/java/subway/service/StationService.java @@ -0,0 +1,21 @@ +package subway.service; + +import subway.domain.Station; +import subway.repository.StationRepository; + +import java.util.List; + +public class StationService { + public static List stations() { + return StationRepository.stations(); + } + + public static void addStation(String stationName) { + Station station = new Station(stationName); + StationRepository.addStation(station); + } + + public static void deleteStationByName(String stationName) { + StationRepository.deleteStationByName(stationName); + } +} diff --git a/src/main/java/subway/view/SubwayView.java b/src/main/java/subway/view/SubwayView.java new file mode 100644 index 000000000..58d8fac0c --- /dev/null +++ b/src/main/java/subway/view/SubwayView.java @@ -0,0 +1,96 @@ +package subway.view; + +import subway.controller.function.Function; +import subway.controller.message.Message; +import subway.controller.screen.Screen; +import subway.domain.Section; + +import java.util.List; +import java.util.Scanner; + +public class SubwayView { + private static final Scanner scanner = new Scanner(System.in); + private static final String NOTICE_FORMAT = "## %s"; + private static final String INFO_FORMAT = "[INFO] %s"; + private static final String ERROR_FORMAT = "[ERROR] %s"; + private static final String FUNCTION_FORMAT = "%s. %s"; + private static final String HYPHEN_DIVIDER = "---"; + + public static String userInput() { + String userInput = scanner.nextLine(); + newLine(); + return userInput; + } + + public static void printSubwayMap(Section section) { + info(section.getLine().getName()); + printHyphenDivider(); + section.getStations().stream() + .forEach(station -> info(station.getName())); + newLine(); + } + + public static void printFunction(Function function) { + String formatted = String.format(FUNCTION_FORMAT, function.getCode(), function.getTitle()); + println(formatted); + } + + public static void printFunctionList(List functions) { + functions.stream() + .forEach(function -> printFunction(function)); + newLine(); + } + + public static void displayScreen(Screen screen) { + notice(screen.getTitle()); + printFunctionList(screen.getFunctions()); + } + + public static void notice(String message) { + String formatted = String.format(NOTICE_FORMAT, message); + println(formatted); + } + + public static void notice(Message message) { + String formatted = String.format(NOTICE_FORMAT, message.getContent()); + println(formatted); + } + + public static void info(String message) { + String formatted = String.format(INFO_FORMAT, message); + println(formatted); + } + + public static void info(Message message) { + String formatted = String.format(INFO_FORMAT, message.getContent()); + println(formatted); + newLine(); + } + + public static void error(String message) { + String formatted = String.format(ERROR_FORMAT, message); + println(formatted); + } + + public static void error(Message message) { + String formatted = String.format(ERROR_FORMAT, message.getContent()); + println(formatted); + newLine(); + } + + public static void printHyphenDivider() { + System.out.println(HYPHEN_DIVIDER); + } + + public static void print(String message) { + System.out.print(message); + } + + public static void println(String message) { + System.out.println(message); + } + + public static void newLine() { + System.out.println(); + } +}