diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..169393442
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,55 @@
+# 지하철 노선도 미션
+- 지하철 역과 노선을 관리하는 지하철 노선도 기능을 구현한다.
+
+## 구현할 기능 목록
+
+### 초기 설정
+- 프로그램 시작 시 역, 노선 등 필요한 정보를 미리 세팅하기
+> 아래의 사전 등록 정보로 초기 설정하기
+```
+ 1. 지하철역으로 교대역, 강남역, 역삼역, 남부터미널역, 양재역, 양재시민의숲역, 매봉역이 등록되어 있다.
+ 2. 지하철 노선으로 2호선, 3호선, 신분당선이 등록되어 있다.
+ 3. 노선에 역이 아래와 같이 등록되어 있다.(왼쪽 끝이 상행 종점)
+ - 2호선: 교대역 - 강남역 - 역삼역
+ - 3호선: 교대역 - 남부터미널역 - 양재역 - 매봉역
+ - 신분당선: 강남역 - 양재역 - 양재시민의숲역
+ ```
+
+### 지하철 역 관련 기능
+- 지하철 역 등록
+ - 예외: 지하철 역 이름은 2글자 이상이어야 한다.
+ - 예외: 지하철 역 이름은 중복될 수 없다.
+- 지하철 역 삭제
+ - 예외: 노선에 등록되어 있는 역은 삭제할 수 없다.
+- 지하철 역 목록 조회
+
+###지하철 노선 관련 기능
+- 지하철 노선 등록
+ - 예외: 지하철 노선 이름은 중복될 수 없다.
+ - 예외: 지하철 노선 이름은 2글자 이상이어야 한다.
+
+ 노선 등록 시 상행 종점역과 하행 종점역을 입력받아야 한다.
+ - 예외: 등록되어 있지 않은 역이 상,하행 종점역 입력으로 들어왔을 때
+
+- 지하철 노선 삭제
+ - 예외: 존재하지 않는 노선을 삭제하려는 경우
+
+- 지하철 노선 목록 조회
+
+###지하철 구간 추가 기능
+- 노선에 새로운 역을 등록하는 기능
+ - 역과 역 사이: 구간
+ - 구간들의 모음: 노선
+ - 예외: 이미 노선에 등록되어있는 역이 입력으로 들어오는 경우
+
+###지하철 구간 삭제 기능
+- 노선에 등록된 역을 제거하는 기능
+ - 상행 종점 제거 시 다음 역이 상행 종점
+ - 하행 종점 제거 시 이전 역이 하행 종점
+ - 예외: 노선에 포함된 역이 두 개 이하인 노선의 역을 제거하려는 경우
+
+###지하철 노선에 등록된 역 조회 기능
+- 노선의 상행 종점부터 하행 종점까지 연결된 순서대로 역 목록을 조회한다.
+
+###지하철 노선도 출력 기능
+
diff --git a/src/main/java/subway/Application.java b/src/main/java/subway/Application.java
index 0bcf786cc..f2fe66546 100644
--- a/src/main/java/subway/Application.java
+++ b/src/main/java/subway/Application.java
@@ -1,10 +1,14 @@
package subway;
+import subway.controller.SubwayMapEditor;
+
import java.util.Scanner;
public class Application {
public static void main(String[] args) {
final Scanner scanner = new Scanner(System.in);
// TODO: 프로그램 구현
+ SubwayMapEditor subwayMapEditor = new SubwayMapEditor(scanner);
+ subwayMapEditor.run();
}
}
diff --git a/src/main/java/subway/controller/SubwayMapEditor.java b/src/main/java/subway/controller/SubwayMapEditor.java
new file mode 100644
index 000000000..c5a89769c
--- /dev/null
+++ b/src/main/java/subway/controller/SubwayMapEditor.java
@@ -0,0 +1,24 @@
+package subway.controller;
+
+import subway.domain.SubwayMap;
+import subway.view.MainScreenInputView;
+import subway.view.MainScreenOutputView;
+
+import java.util.Scanner;
+
+public class SubwayMapEditor {
+ private final Scanner scanner;
+
+ public SubwayMapEditor(Scanner scanner) {
+ this.scanner = scanner;
+ }
+
+ public void run() {
+ SubwayMap subwayMap = new SubwayMap();
+ boolean isPersist = false;
+ do {
+ isPersist = MainScreenInputView.getMainScreenUserSelection(scanner);
+ } while (isPersist);
+
+ }
+}
diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java
index f4d738d5a..f1a9eac53 100644
--- a/src/main/java/subway/domain/Line.java
+++ b/src/main/java/subway/domain/Line.java
@@ -1,15 +1,59 @@
package subway.domain;
+import java.util.ArrayList;
+import java.util.List;
+
public class Line {
+ private static final String INFO = "[INFO] ";
+ private static final String STATION_NUMBER_MESSAGE = "[ERROR] 노선의 역 개수가 2개 이하이므로 삭제할 수 없습니다.";
+
private String name;
+ private List stationsOnLine = new ArrayList<>();
public Line(String name) {
this.name = name;
}
+ public void registerStation(Station station) {
+ stationsOnLine.add(station);
+ }
+
+ public boolean isStationRegistered(String stationName) {
+ for (Station station : stationsOnLine) {
+ if (station.getName().equals(stationName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void printStations() {
+ for (Station station : stationsOnLine) {
+ System.out.println(INFO + station.getName());
+ }
+ System.out.println();
+ }
+
public String getName() {
return name;
}
- // 추가 기능 구현
+ public boolean isSameName(String lineName) {
+ return this.name.equals(lineName);
+ }
+
+ public int getSize() {
+ return stationsOnLine.size();
+ }
+
+ public void insert(Station station, int order) {
+ stationsOnLine.add(order-1, station);
+ }
+
+ public void remove(String stationName) {
+ if (stationsOnLine.size() <= 2) {
+ throw new IllegalArgumentException(STATION_NUMBER_MESSAGE);
+ }
+ stationsOnLine.remove(new Station(stationName));
+ }
}
diff --git a/src/main/java/subway/domain/LineRepository.java b/src/main/java/subway/domain/LineRepository.java
index 49132ddb6..3d4062767 100644
--- a/src/main/java/subway/domain/LineRepository.java
+++ b/src/main/java/subway/domain/LineRepository.java
@@ -6,6 +6,12 @@
import java.util.Objects;
public class LineRepository {
+ private static final String INFO = "[INFO] ";
+ private static final String INFO_WITH_BORDER = "[INFO] ---";
+ private static final String LINE_LIST = "## 노선 목록";
+ private static final String SUBWAY_MAP = "## 지하철 노선도";
+ private static final String LINE_NOT_EXIST = "[ERROR] 존재하지 않는 노선입니다.";
+
private static final List lines = new ArrayList<>();
public static List lines() {
@@ -19,4 +25,33 @@ public static void addLine(Line line) {
public static boolean deleteLineByName(String name) {
return lines.removeIf(line -> Objects.equals(line.getName(), name));
}
+
+ public static void isLineExist(String lineName) {
+ boolean flag = false;
+ for (Line line : lines) {
+ flag = line.getName().equals(lineName);
+ if(flag) break;
+ }
+ if (!flag) {
+ throw new IllegalArgumentException(LINE_NOT_EXIST);
+ }
+ }
+
+ public static void printLines() {
+ System.out.println(LINE_LIST);
+ for (Line line : lines) {
+ System.out.println(INFO + line.getName());
+ }
+ System.out.println();
+ }
+
+ public static void printMap() {
+ System.out.println();
+ System.out.println(SUBWAY_MAP);
+ for (Line line : lines) {
+ System.out.println(INFO + line.getName());
+ System.out.println(INFO_WITH_BORDER);
+ line.printStations();
+ }
+ }
}
diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/Station.java
index bdb142590..010c9533b 100644
--- a/src/main/java/subway/domain/Station.java
+++ b/src/main/java/subway/domain/Station.java
@@ -1,9 +1,12 @@
package subway.domain;
+import java.util.Objects;
+
public class Station {
private String name;
public Station(String name) {
+ // TODO 이름 2글자 이상인지 확인할 것
this.name = name;
}
@@ -11,5 +14,20 @@ public String getName() {
return name;
}
- // 추가 기능 구현
+ public boolean isSameName(String stationName) {
+ return this.name.equals(stationName);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Station station = (Station) o;
+ return Objects.equals(name, station.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
}
diff --git a/src/main/java/subway/domain/StationRepository.java b/src/main/java/subway/domain/StationRepository.java
index b7245c0f3..16169f5a9 100644
--- a/src/main/java/subway/domain/StationRepository.java
+++ b/src/main/java/subway/domain/StationRepository.java
@@ -6,6 +6,9 @@
import java.util.Objects;
public class StationRepository {
+ private static final String INFO = "[INFO] ";
+ private static final String STATION_LIST = "## 역 목록";
+
private static final List stations = new ArrayList<>();
public static List stations() {
@@ -19,4 +22,21 @@ public static void addStation(Station station) {
public static boolean deleteStation(String name) {
return stations.removeIf(station -> Objects.equals(station.getName(), name));
}
+
+ public static boolean isStationExist(String stationName) {
+ for (Station station : stations) {
+ if (station.isSameName(stationName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void printStations() {
+ System.out.println();
+ System.out.println(STATION_LIST);
+ for (Station station : stations) {
+ System.out.println(INFO + station.getName());
+ }
+ }
}
diff --git a/src/main/java/subway/domain/SubwayMap.java b/src/main/java/subway/domain/SubwayMap.java
new file mode 100644
index 000000000..56f84a456
--- /dev/null
+++ b/src/main/java/subway/domain/SubwayMap.java
@@ -0,0 +1,75 @@
+package subway.domain;
+
+public class SubwayMap {
+ private static final String LINE_NUMBER_TWO = "2호선";
+ private static final String LINE_NUMBER_THREE = "3호선";
+ private static final String LINE_NEW_BOONDANG = "신분당선";
+ private static final String GYODAE_STATION = "교대역";
+ private static final String GANGNAM_STATION = "강남역";
+ private static final String YEOKSAM_STATION = "역삼역";
+ private static final String NAMBU_TERMINAL_STATION = "남부터미널역";
+ private static final String YANGJAE_STATION = "양재역";
+ private static final String YANGJAE_CITIZEN_FOREST_STATION = "양재시민의숲역";
+ private static final String MAEBONG_STATION = "매봉역";
+
+ private Line lineNumberTwo;
+ private Line lineNumberThree;
+ private Line lineNewBoondang;
+ private Station gyodaeStation;
+ private Station gangnamStation;
+ private Station yeoksamStation;
+ private Station nambuTerminalStation;
+ private Station yangjaeStation;
+ private Station yangjaeCitizenForestStation;
+ private Station maebongStation;
+
+ public SubwayMap() {
+ initialize();
+ }
+
+ public void initialize() {
+ initializeLine();
+ initializeStation();
+ initializeMap();
+ }
+
+ private void initializeLine() {
+ lineNumberTwo = new Line(LINE_NUMBER_TWO);
+ lineNumberThree = new Line(LINE_NUMBER_THREE);
+ lineNewBoondang = new Line(LINE_NEW_BOONDANG);
+ LineRepository.addLine(lineNumberTwo);
+ LineRepository.addLine(lineNumberThree);
+ LineRepository.addLine(lineNewBoondang);
+ }
+
+ private void initializeStation() {
+ gyodaeStation = new Station(GYODAE_STATION);
+ gangnamStation = new Station(GANGNAM_STATION);
+ yeoksamStation = new Station(YEOKSAM_STATION);
+ nambuTerminalStation = new Station(NAMBU_TERMINAL_STATION);
+ yangjaeStation = new Station(YANGJAE_STATION);
+ yangjaeCitizenForestStation = new Station(YANGJAE_CITIZEN_FOREST_STATION);
+ maebongStation = new Station(MAEBONG_STATION);
+ StationRepository.addStation(gyodaeStation);
+ StationRepository.addStation(gangnamStation);
+ StationRepository.addStation(yeoksamStation);
+ StationRepository.addStation(nambuTerminalStation);
+ StationRepository.addStation(yangjaeStation);
+ StationRepository.addStation(yangjaeCitizenForestStation);
+ StationRepository.addStation(maebongStation);
+ }
+
+ private void initializeMap() {
+ lineNumberTwo.registerStation(gyodaeStation);
+ lineNumberTwo.registerStation(gangnamStation);
+ lineNumberTwo.registerStation(yeoksamStation);
+ lineNumberThree.registerStation(gyodaeStation);
+ lineNumberThree.registerStation(nambuTerminalStation);
+ lineNumberThree.registerStation(yangjaeStation);
+ lineNumberThree.registerStation(maebongStation);
+ lineNewBoondang.registerStation(gangnamStation);
+ lineNewBoondang.registerStation(yangjaeStation);
+ lineNewBoondang.registerStation(yangjaeCitizenForestStation);
+ }
+
+}
diff --git a/src/main/java/subway/type/LineScreenFunctionType.java b/src/main/java/subway/type/LineScreenFunctionType.java
new file mode 100644
index 000000000..e0cc9c1ac
--- /dev/null
+++ b/src/main/java/subway/type/LineScreenFunctionType.java
@@ -0,0 +1,37 @@
+package subway.type;
+
+import subway.domain.LineRepository;
+import subway.view.LineInputView;
+
+public enum LineScreenFunctionType {
+ REGISTER_STATION(1) {
+ @Override
+ public void execute() {
+ LineInputView.registerLine();
+ }
+ },
+ REMOVE_STATION(2) {
+ @Override
+ public void execute() {
+ LineInputView.removeLine();
+ }
+ },
+ PRINT_STATION(3) {
+ @Override
+ public void execute() {
+ LineRepository.printLines();
+ }
+ };
+
+ private final int functionCode;
+
+ LineScreenFunctionType(int functionCode) {
+ this.functionCode = functionCode;
+ }
+
+ public boolean isSameFunctionCode(int number) {
+ return this.functionCode == number;
+ }
+
+ public abstract void execute();
+}
diff --git a/src/main/java/subway/type/MainScreenFunctionType.java b/src/main/java/subway/type/MainScreenFunctionType.java
new file mode 100644
index 000000000..706bdea7b
--- /dev/null
+++ b/src/main/java/subway/type/MainScreenFunctionType.java
@@ -0,0 +1,46 @@
+package subway.type;
+
+import subway.domain.LineRepository;
+import subway.view.LineInputView;
+import subway.view.SectionInputView;
+import subway.view.SectionOutputView;
+import subway.view.StationInputView;
+
+public enum MainScreenFunctionType {
+ MANAGE_STATION(1) {
+ @Override
+ public void execute() {
+ StationInputView.getStationScreenUserSelection();
+ }
+ },
+ MANAGE_LINE(2) {
+ @Override
+ public void execute() {
+ LineInputView.getLineScreenUserSelection();
+ }
+ },
+ MANAGE_SECTION(3) {
+ @Override
+ public void execute() {
+ SectionInputView.getSectionScreenUserSelection();
+ }
+ },
+ PRINT_MAP(4) {
+ @Override // TODO 지하철 노선도 출력
+ public void execute() {
+ LineRepository.printMap();
+ }
+ };
+
+ private final int functionCode;
+
+ MainScreenFunctionType(int functionCode) {
+ this.functionCode = functionCode;
+ }
+
+ public boolean isSameFunctionCode(int number) {
+ return this.functionCode == number;
+ }
+
+ public abstract void execute();
+}
diff --git a/src/main/java/subway/type/SectionScreenFunctionType.java b/src/main/java/subway/type/SectionScreenFunctionType.java
new file mode 100644
index 000000000..d1690ebdf
--- /dev/null
+++ b/src/main/java/subway/type/SectionScreenFunctionType.java
@@ -0,0 +1,31 @@
+package subway.type;
+
+import subway.view.LineInputView;
+import subway.view.SectionInputView;
+
+public enum SectionScreenFunctionType {
+ REGISTER_SECTION(1) {
+ @Override
+ public void execute() {
+ SectionInputView.registerSection();
+ }
+ },
+ REMOVE_SECTION(2) {
+ @Override
+ public void execute() {
+ SectionInputView.removeSection();
+ }
+ };
+
+ private final int functionCode;
+
+ SectionScreenFunctionType(int functionCode) {
+ this.functionCode = functionCode;
+ }
+
+ public boolean isSameFunctionCode(int number) {
+ return this.functionCode == number;
+ }
+
+ public abstract void execute();
+}
diff --git a/src/main/java/subway/type/StationScreenFunctionType.java b/src/main/java/subway/type/StationScreenFunctionType.java
new file mode 100644
index 000000000..901d6033f
--- /dev/null
+++ b/src/main/java/subway/type/StationScreenFunctionType.java
@@ -0,0 +1,38 @@
+package subway.type;
+
+import subway.view.StationInputView;
+
+import static subway.domain.StationRepository.printStations;
+
+public enum StationScreenFunctionType {
+ REGISTER_STATION(1) {
+ @Override
+ public void execute() {
+ StationInputView.registerStation();
+ }
+ },
+ REMOVE_STATION(2) {
+ @Override
+ public void execute() {
+ StationInputView.removeStation();
+ }
+ },
+ PRINT_STATION(3) {
+ @Override
+ public void execute() {
+ printStations();
+ }
+ };
+
+ private final int functionCode;
+
+ StationScreenFunctionType(int functionCode) {
+ this.functionCode = functionCode;
+ }
+
+ public boolean isSameFunctionCode(int number) {
+ return this.functionCode == number;
+ }
+
+ public abstract void execute();
+}
diff --git a/src/main/java/subway/view/LineInputView.java b/src/main/java/subway/view/LineInputView.java
new file mode 100644
index 000000000..39bdef258
--- /dev/null
+++ b/src/main/java/subway/view/LineInputView.java
@@ -0,0 +1,213 @@
+package subway.view;
+
+import subway.domain.Line;
+import subway.domain.LineRepository;
+import subway.domain.Station;
+import subway.domain.StationRepository;
+import subway.type.LineScreenFunctionType;
+
+import java.util.Scanner;
+
+public class LineInputView {
+ private static final String SELECT_MESSAGE = "## 원하는 기능을 선택하세요.";
+ private static final String CANNOT_SELECT_MESSAGE = "[ERROR] 선택할 수 없는 기능입니다.";
+ private static final String REGISTER_LINE_MESSAGE = "## 등록할 노선 이름을 입력하세요.";
+ private static final String REGISTER_COMPLETE_MESSAGE = "[INFO] 지하철 노선이 등록되었습니다.";
+ private static final String REMOVE_LINE_MESSAGE = "## 삭제할 노선 이름을 입력하세요.";
+ private static final char LINE_NAME_ENDED_WITH = '선';
+ private static final String LINE_NAME_LENGTH_MESSAGE = "[ERROR] 노선 이름은 두 글자 이상이어야 합니다.";
+ private static final String LINE_NAME_INCLUDE_NOT_KOREAN_MESSAGE = "[ERROR] 노선 이름은 한글이어야 합니다.";
+ private static final String LINE_NAME_SHOULD_BE_ENDED_WITH_LINE_MESSAGE = "[ERROR] 노선 이름 맨 뒤에 '선'을 붙여주세요.";
+ private static final String LINE_NAME_INCLUDE_NUMBER_MESSAGE = "[ERROR] 노선 이름에 숫자를 포함하면 안 됩니다.";
+ private static final String LINE_NAME_INCLUDE_SPACE_MESSAGE = "[ERROR] 노선 이름에 공백을 포함하면 안 됩니다.";
+ private static final String LINE_NAME_HAS_DUPLICATION_MESSAGE = "[ERROR] 이미 등록되어 있는 노선입니다.";
+ private static final char ONE = '1';
+ private static final int INTEGER_ONE = 1;
+ private static final char MINIMUM_LINE_NAME_LENGTH = 2;
+ private static final char THREE = '3';
+ private static final char BACK = 'B';
+ private static final String SPACE = " ";
+ private static final int FIRST_CHARACTER = 0;
+ private static final String KOREAN_REGULAR_EXPRESSION = "^[가-힣]*$";
+ private static final String HAS_NUMBER_REGULAR_EXPRESSION = ".*[0-9].*";
+
+ private static final Scanner scanner = new Scanner(System.in);
+
+ private LineInputView() {
+
+ }
+
+ public static void getLineScreenUserSelection() {
+ LineOutputView.printManageLineScreen();
+ System.out.println(SELECT_MESSAGE);
+ String userInput = scanner.nextLine();
+ try {
+ validateUserInput(userInput);
+ if (isUserInputBack(userInput.charAt(FIRST_CHARACTER))) {
+ MainScreenInputView.getMainScreenUserSelection(scanner);
+ return;
+ }
+ executeFunction(userInput);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ getLineScreenUserSelection();
+ }
+ }
+
+ private static void executeFunction(String userInput) {
+ for (LineScreenFunctionType lineScreenFunctionType : LineScreenFunctionType.values()) {
+ if (lineScreenFunctionType.isSameFunctionCode(Integer.parseInt(userInput))) {
+ lineScreenFunctionType.execute();
+ }
+ }
+ }
+
+ private static void validateUserInput(String userInput) {
+ validateUserInputLength(userInput);
+ char characterizedUserInput = userInput.charAt(FIRST_CHARACTER);
+ if (!isUserInputBack(characterizedUserInput)) {
+ validateUserInputRange(characterizedUserInput);
+ }
+ }
+
+ private static void validateUserInputLength(String userInput) {
+ if (userInput.length() != INTEGER_ONE) {
+ System.out.println(userInput.length());
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ private static boolean isUserInputBack(char userInput) {
+ return Character.toUpperCase(userInput) == BACK;
+ }
+
+ private static void validateUserInputRange(char userInput) {
+ if ((userInput < ONE || userInput > THREE)) {
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ public static void registerLine() {
+ System.out.println(REGISTER_LINE_MESSAGE);
+ String lineName = scanner.nextLine();
+ try {
+ validateLineName(lineName);
+ makeNewLine(lineName);
+ System.out.println(REGISTER_COMPLETE_MESSAGE);
+ System.out.println();
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ registerLine();
+ }
+ }
+
+ private static void makeNewLine(String lineName) {
+ Line newLine = new Line(lineName);
+ Station upwardTerminalStation = getUpwardTerminalStation();
+ Station downwardTerminalStation = getDownwardTerminalStation();
+ validateAreStationSame(upwardTerminalStation, downwardTerminalStation);
+ newLine.registerStation(upwardTerminalStation);
+ newLine.registerStation(downwardTerminalStation);
+ LineRepository.addLine(newLine);
+ }
+
+ private static void validateAreStationSame(Station upwardTerminalStation, Station downwardTerminalStation) {
+ if (upwardTerminalStation.equals(downwardTerminalStation)) {
+ throw new IllegalArgumentException("상행 종점과 하행 종점끼리 같은 역일 수 없습니다.");
+ }
+ }
+
+ private static Station getUpwardTerminalStation() {
+ System.out.println("## 등록할 노선의 상행 종점역 이름을 입력하세요.");
+ String upwardTerminalStation = scanner.nextLine();
+ try {
+ validateStationExistence(upwardTerminalStation);
+
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ getUpwardTerminalStation();
+ }
+ return new Station(upwardTerminalStation);
+ }
+
+ private static Station getDownwardTerminalStation() {
+ System.out.println("## 등록할 노선의 하행 종점역 이름을 입력하세요.");
+ String downwardTerminalStation = scanner.nextLine();
+ try {
+ validateStationExistence(downwardTerminalStation);
+
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ getDownwardTerminalStation();
+ }
+ return new Station(downwardTerminalStation);
+ }
+
+ private static void validateStationExistence(String stationName) {
+ if (!StationRepository.isStationExist(stationName)) {
+ throw new IllegalArgumentException("존재하지 않는 역입니다.");
+ }
+ }
+
+ public static void removeLine() {
+ System.out.println(REMOVE_LINE_MESSAGE);
+ String lineName = scanner.nextLine();
+ try {
+ LineRepository.isLineExist(lineName);
+ LineRepository.deleteLineByName(lineName);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ getLineScreenUserSelection();
+ }
+ }
+
+ private static void validateLineName(String lineName) {
+ validateLineNameLength(lineName);
+ validateLineNameEndedWithLine(lineName);
+ validateLineNameHasNumber(lineName);
+ validateLineNameHasOnlyKorean(lineName);
+ validateLineNameHasSpace(lineName);
+ validateLineNameHasDuplication(lineName);
+ }
+
+ private static void validateLineNameLength(String lineName) {
+ if (lineName.length() < MINIMUM_LINE_NAME_LENGTH) {
+ throw new IllegalArgumentException(LINE_NAME_LENGTH_MESSAGE);
+ }
+ }
+
+ private static void validateLineNameEndedWithLine(String lineName) {
+ if (!(lineName.charAt(lineName.length() - INTEGER_ONE) == LINE_NAME_ENDED_WITH)) {
+ throw new IllegalArgumentException(LINE_NAME_SHOULD_BE_ENDED_WITH_LINE_MESSAGE);
+ }
+ }
+
+ private static void validateLineNameHasNumber(String lineName) {
+ if (lineName.matches(HAS_NUMBER_REGULAR_EXPRESSION)) {
+ throw new IllegalArgumentException(LINE_NAME_INCLUDE_NUMBER_MESSAGE);
+ }
+ }
+
+ private static void validateLineNameHasOnlyKorean(String lineName) {
+ if (!lineName.matches(KOREAN_REGULAR_EXPRESSION)) {
+ throw new IllegalArgumentException(LINE_NAME_INCLUDE_NOT_KOREAN_MESSAGE);
+ }
+ }
+
+ private static void validateLineNameHasSpace(String lineName) {
+ if (lineName.contains(SPACE)) {
+ throw new IllegalArgumentException(LINE_NAME_INCLUDE_SPACE_MESSAGE);
+ }
+ }
+
+ private static void validateLineNameHasDuplication(String lineName) {
+ for (Line line : LineRepository.lines()) {
+ if (line.isSameName(lineName)) {
+ throw new IllegalArgumentException(LINE_NAME_HAS_DUPLICATION_MESSAGE);
+ }
+ }
+ }
+}
diff --git a/src/main/java/subway/view/LineOutputView.java b/src/main/java/subway/view/LineOutputView.java
new file mode 100644
index 000000000..e075ad644
--- /dev/null
+++ b/src/main/java/subway/view/LineOutputView.java
@@ -0,0 +1,22 @@
+package subway.view;
+
+public class LineOutputView {
+ private static final String MANAGE_LINE_SCREEN = "## 노선 관리 화면";
+ private static final String REGISTER_LINE = "1. 노선 등록";
+ private static final String REMOVE_LINE = "2. 노선 삭제";
+ private static final String PRINT_LINE = "3. 노선 조회";
+ private static final String BACK = "B. 돌아가기";
+
+ private LineOutputView() {
+ }
+
+ public static void printManageLineScreen() {
+ System.out.println();
+ System.out.println(MANAGE_LINE_SCREEN);
+ System.out.println(REGISTER_LINE);
+ System.out.println(REMOVE_LINE);
+ System.out.println(PRINT_LINE);
+ System.out.println(BACK);
+ System.out.println();
+ }
+}
diff --git a/src/main/java/subway/view/MainScreenInputView.java b/src/main/java/subway/view/MainScreenInputView.java
new file mode 100644
index 000000000..3b5aa4f49
--- /dev/null
+++ b/src/main/java/subway/view/MainScreenInputView.java
@@ -0,0 +1,68 @@
+package subway.view;
+
+import subway.type.MainScreenFunctionType;
+
+import java.util.Scanner;
+
+public class MainScreenInputView {
+ private static final String SELECT_MESSAGE = "## 원하는 기능을 선택하세요.";
+ private static final String CANNOT_SELECT_MESSAGE = "[ERROR] 선택할 수 없는 기능입니다.";
+ private static final char ONE = '1';
+ private static final int INTEGER_ONE = 1;
+ private static final char FOUR = '4';
+ private static final char QUIT = 'Q';
+ private static final int FIRST_CHARACTER = 0;
+
+ private MainScreenInputView() {
+ }
+
+ public static boolean getMainScreenUserSelection(Scanner scanner) {
+ MainScreenOutputView.printMainScreen();
+ System.out.println(SELECT_MESSAGE);
+ String userInput = scanner.nextLine();
+ try {
+ validateUserInput(userInput);
+ if (isUserInputQuit(userInput.charAt(FIRST_CHARACTER))) {
+ return false;
+ }
+ executeFunction(userInput);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ getMainScreenUserSelection(scanner);
+ }
+ return true;
+ }
+
+ private static void executeFunction(String userInput) {
+ for (MainScreenFunctionType mainScreenFunctionType : MainScreenFunctionType.values()) {
+ if (mainScreenFunctionType.isSameFunctionCode(Integer.parseInt(userInput))) {
+ mainScreenFunctionType.execute();
+ }
+ }
+ }
+
+ private static void validateUserInput(String userInput) {
+ validateUserInputLength(userInput);
+ char characterizedUserInput = userInput.charAt(FIRST_CHARACTER);
+ if (!isUserInputQuit(characterizedUserInput)) {
+ validateUserInputRange(characterizedUserInput);
+ }
+ }
+
+ private static void validateUserInputLength(String userInput) {
+ if (userInput.length() != INTEGER_ONE) {
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ private static boolean isUserInputQuit(char userInput) {
+ return Character.toUpperCase(userInput) == QUIT;
+ }
+
+ private static void validateUserInputRange(char userInput) {
+ if ((userInput < ONE || userInput > FOUR)) {
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+}
diff --git a/src/main/java/subway/view/MainScreenOutputView.java b/src/main/java/subway/view/MainScreenOutputView.java
new file mode 100644
index 000000000..8477bb5c8
--- /dev/null
+++ b/src/main/java/subway/view/MainScreenOutputView.java
@@ -0,0 +1,23 @@
+package subway.view;
+
+public class MainScreenOutputView {
+ private static final String MAIN_SCREEN = "## 메인 화면";
+ private static final String MANAGE_STATION = "1. 역 관리";
+ private static final String MANAGE_LINE = "2. 노선 관리";
+ private static final String MANAGE_SECTION = "3. 구간 관리";
+ private static final String PRINT_MAP = "4. 지하철 노선도 출력";
+ private static final String QUIT = "Q. 종료";
+
+ private MainScreenOutputView() {
+ }
+
+ public static void printMainScreen() {
+ System.out.println(MAIN_SCREEN);
+ System.out.println(MANAGE_STATION);
+ System.out.println(MANAGE_LINE);
+ System.out.println(MANAGE_SECTION);
+ System.out.println(PRINT_MAP);
+ System.out.println(QUIT);
+ System.out.println();
+ }
+}
diff --git a/src/main/java/subway/view/SectionInputView.java b/src/main/java/subway/view/SectionInputView.java
new file mode 100644
index 000000000..55802e603
--- /dev/null
+++ b/src/main/java/subway/view/SectionInputView.java
@@ -0,0 +1,190 @@
+package subway.view;
+
+import subway.domain.Line;
+import subway.domain.LineRepository;
+import subway.domain.Station;
+import subway.domain.StationRepository;
+import subway.type.SectionScreenFunctionType;
+
+import java.util.Scanner;
+
+public class SectionInputView {
+ private static final String SELECT_MESSAGE = "## 원하는 기능을 선택하세요.";
+ private static final String CANNOT_SELECT_MESSAGE = "[ERROR] 선택할 수 없는 기능입니다.";
+ private static final String INPUT_LINE_MESSAGE = "## 노선을 입력하세요.";
+ private static final String DELETE_LINE_MESSAGE = "## 삭제할 구간의 노선을 입력하세요.";
+ private static final String DELETE_STATION_MESSAGE = "## 삭제할 구간의 역을 입력하세요.";
+ private static final String INPUT_STATION_MESSAGE = "## 역 이름을 입력하세요.";
+ private static final String INPUT_ORDER_MESSAGE = "## 순서를 입력하세요.";
+ private static final String SECTION_REMOVAL_MESSAGE = "[INFO] 구간이 삭제되었습니다.";
+ private static final String STATION_NOT_EXIST = "[ERROR] 노선에 역이 존재하지 않습니다.";
+ private static final String INVALID_ORDER_MESSAGE = "[ERROR] 순서는 양수이며 노선에 포함된 역의 개수 이하여야 합니다.";
+ private static final String INVALID_STATION_MESSAGE = "[ERROR] 노선에 이미 등록되어 있는 역이므로 등록이 불가능합니다.";
+ private static final int INTEGER_ONE = 1;
+ private static final char BACK = 'B';
+ private static final int FIRST_CHARACTER = 0;
+ private static final char ONE = '1';
+ private static final char TWO = '2';
+
+ private static final Scanner scanner = new Scanner(System.in);
+
+ private SectionInputView() {
+ }
+
+ public static void getSectionScreenUserSelection() {
+ SectionOutputView.printManageSectionScreen();
+ System.out.println(SELECT_MESSAGE);
+ String userInput = scanner.nextLine();
+ try {
+ validateUserInput(userInput);
+ if (isUserInputBack(userInput.charAt(FIRST_CHARACTER))) {
+ MainScreenInputView.getMainScreenUserSelection(scanner);
+ return;
+ }
+ executeFunction(userInput);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ getSectionScreenUserSelection();
+ }
+ }
+
+ private static void executeFunction(String userInput) {
+ for (SectionScreenFunctionType sectionScreenFunctionType : SectionScreenFunctionType.values()) {
+ if (sectionScreenFunctionType.isSameFunctionCode(Integer.parseInt(userInput))) {
+ sectionScreenFunctionType.execute();
+ }
+ }
+ }
+
+ private static boolean isUserInputBack(char userInput) {
+ return Character.toUpperCase(userInput) == BACK;
+ }
+
+ private static void validateUserInput(String userInput) {
+ validateUserInputLength(userInput);
+ char characterizedUserInput = userInput.charAt(FIRST_CHARACTER);
+ if (!isUserInputBack(characterizedUserInput)) {
+ validateUserInputRange(characterizedUserInput);
+ }
+ }
+
+ private static void validateUserInputLength(String userInput) {
+ if (userInput.length() != INTEGER_ONE) {
+ System.out.println(userInput.length());
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ private static void validateUserInputRange(char userInput) {
+ if ((userInput < ONE || userInput > TWO)) {
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ public static void registerSection() { // TODO 순서가 노선 size 넘어가면 안됨
+ try {
+ System.out.println(INPUT_LINE_MESSAGE);
+ String lineName = getLineName();
+ System.out.println(INPUT_STATION_MESSAGE);
+ String stationName = getStationName();
+ validateStationRegisteredNotOnLine(lineName, stationName);
+ int order = getOrder(lineName);
+ insertStation(lineName, stationName, order);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ getSectionScreenUserSelection();
+ }
+ }
+
+ private static void insertStation(String lineName, String stationName, int order) {
+ for (Line line : LineRepository.lines()) {
+ if (line.getName().equals(lineName)) {
+ line.insert(new Station(stationName), order);
+ }
+ }
+ }
+
+ private static int getOrder(String lineName) {
+ System.out.println(INPUT_ORDER_MESSAGE);
+ int order = scanner.nextInt();
+ if (INTEGER_ONE > order || getSizeOfLine(lineName) < order) {
+ throw new IllegalArgumentException(INVALID_ORDER_MESSAGE);
+ }
+ return order;
+ }
+
+ private static int getSizeOfLine(String lineName) {
+ for (Line line : LineRepository.lines()) {
+ if (line.getName().equals(lineName)) {
+ return line.getSize();
+ }
+ }
+ return -1;
+ }
+
+ private static String getLineName() {
+ String lineName = scanner.nextLine();
+ LineRepository.isLineExist(lineName);
+ return lineName;
+ }
+
+ private static String getStationName() {
+ String stationName = scanner.nextLine();
+ validateStationExistence(stationName);
+ return stationName;
+ }
+
+ private static void validateStationExistence(String stationName) {
+ if (!StationRepository.isStationExist(stationName)) {
+ throw new IllegalArgumentException(INVALID_ORDER_MESSAGE);
+ }
+ }
+
+ private static void validateStationRegisteredNotOnLine(String lineName, String stationName) {
+ for (Line line : LineRepository.lines()) {
+ if (line.getName().equals(lineName) && line.isStationRegistered(stationName)) {
+ throw new IllegalArgumentException(INVALID_STATION_MESSAGE);
+ }
+ }
+ }
+
+ public static void removeSection() {
+ System.out.println(DELETE_LINE_MESSAGE);
+ try {
+ String lineName = getLineName();
+ System.out.println(DELETE_STATION_MESSAGE);
+ String stationName = scanner.nextLine();
+ validateStationOnLine(lineName, stationName);
+ removeStation(lineName, stationName);
+ System.out.println(SECTION_REMOVAL_MESSAGE);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ getSectionScreenUserSelection();
+ }
+
+ }
+
+ private static void removeStation(String lineName, String stationName) {
+ for (Line line : LineRepository.lines()) {
+ if (line.getName().equals(lineName)) {
+ line.remove(stationName);
+ }
+ }
+ }
+
+ private static void validateStationOnLine(String lineName, String stationName) {
+ if (!isStationOnLine(lineName, stationName)) {
+ throw new IllegalArgumentException(STATION_NOT_EXIST);
+ }
+ }
+
+ private static boolean isStationOnLine(String lineName, String stationName) {
+ for (Line line : LineRepository.lines()) {
+ if (line.getName().equals(lineName) && line.isStationRegistered(stationName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/subway/view/SectionOutputView.java b/src/main/java/subway/view/SectionOutputView.java
new file mode 100644
index 000000000..d0135b3f3
--- /dev/null
+++ b/src/main/java/subway/view/SectionOutputView.java
@@ -0,0 +1,20 @@
+package subway.view;
+
+public class SectionOutputView {
+ private static final String MANAGE_SECTION_SCREEN = "## 구간 관리 화면";
+ private static final String REGISTER_SECTION = "1. 구간 등록";
+ private static final String REMOVE_SECTION = "2. 구간 삭제";
+ private static final String BACK = "B. 돌아가기";
+
+ private SectionOutputView() {
+ }
+
+ public static void printManageSectionScreen() {
+ System.out.println();
+ System.out.println(MANAGE_SECTION_SCREEN);
+ System.out.println(REGISTER_SECTION);
+ System.out.println(REMOVE_SECTION);
+ System.out.println(BACK);
+ System.out.println();
+ }
+}
diff --git a/src/main/java/subway/view/StationInputView.java b/src/main/java/subway/view/StationInputView.java
new file mode 100644
index 000000000..e3274b3c2
--- /dev/null
+++ b/src/main/java/subway/view/StationInputView.java
@@ -0,0 +1,169 @@
+package subway.view;
+
+import subway.domain.Line;
+import subway.domain.LineRepository;
+import subway.domain.Station;
+import subway.domain.StationRepository;
+import subway.type.StationScreenFunctionType;
+
+import java.util.Scanner;
+
+public class StationInputView {
+ private static final String SELECT_MESSAGE = "## 원하는 기능을 선택하세요.";
+ private static final String CANNOT_SELECT_MESSAGE = "[ERROR] 선택할 수 없는 기능입니다.";
+ private static final String REGISTER_STATION_MESSAGE = "## 등록할 역 이름을 입력하세요.";
+ private static final String REGISTER_COMPLETE_MESSAGE = "[INFO] 지하철 역이 등록되었습니다.";
+ private static final String REMOVE_STATION_MESSAGE = "## 삭제할 역 이름을 입력하세요.";
+ private static final char STATION_NAME_ENDED_WITH = '역';
+ private static final String STATION_NAME_LENGTH_MESSAGE = "[ERROR] 역 이름은 두 글자 이상이어야 합니다.";
+ private static final String STATION_NAME_INCLUDE_NOT_KOREAN_MESSAGE = "[ERROR] 역 이름은 한글이어야 합니다.";
+ private static final String STATION_NAME_SHOULD_BE_ENDED_WITH_STATION_MESSAGE = "[ERROR] 역 이름 맨 뒤에 '역'을 붙여주세요.";
+ private static final String STATION_NAME_INCLUDE_NUMBER_MESSAGE = "[ERROR] 역 이름에 숫자를 포함하면 안 됩니다.";
+ private static final String STATION_NAME_INCLUDE_SPACE_MESSAGE = "[ERROR] 역 이름에 공백을 포함하면 안 됩니다.";
+ private static final String STATION_NAME_HAS_DUPLICATION_MESSAGE = "[ERROR] 이미 등록되어 있는 역입니다.";
+ private static final char ONE = '1';
+ private static final char MINIMUM_STATION_NAME_LENGTH = 2;
+ private static final char THREE = '3';
+ private static final char BACK = 'B';
+ private static final String SPACE = " ";
+ private static final int FIRST_CHARACTER = 0;
+ private static final String KOREAN_REGULAR_EXPRESSION = "^[가-힣]*$";
+ private static final String HAS_NUMBER_REGULAR_EXPRESSION = ".*[0-9].*";
+
+ private static final Scanner scanner = new Scanner(System.in);
+
+ private StationInputView() {
+ }
+
+ public static void getStationScreenUserSelection() {
+ StationOutputView.printManageStationScreen();
+ System.out.println(SELECT_MESSAGE);
+ String userInput = scanner.nextLine();
+ try {
+ validateUserInput(userInput);
+ if (isUserInputBack(userInput.charAt(FIRST_CHARACTER))) {
+ MainScreenInputView.getMainScreenUserSelection(scanner);
+ return;
+ }
+ executeFunction(userInput);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ getStationScreenUserSelection();
+ }
+ }
+
+ private static void executeFunction(String userInput) {
+ for (StationScreenFunctionType stationScreenFunctionType : StationScreenFunctionType.values()) {
+ if (stationScreenFunctionType.isSameFunctionCode(Integer.parseInt(userInput))) {
+ stationScreenFunctionType.execute();
+ }
+ }
+ }
+
+ private static void validateUserInput(String userInput) {
+ validateUserInputLength(userInput);
+ char characterizedUserInput = userInput.charAt(FIRST_CHARACTER);
+ if (!isUserInputBack(characterizedUserInput)) {
+ validateUserInputRange(characterizedUserInput);
+ }
+ }
+
+ private static void validateUserInputLength(String userInput) {
+ if (userInput.length() != 1) {
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ private static boolean isUserInputBack(char userInput) {
+ return Character.toUpperCase(userInput) == BACK;
+ }
+
+ private static void validateUserInputRange(char userInput) {
+ if ((userInput < ONE || userInput > THREE)) {
+ throw new IllegalArgumentException(CANNOT_SELECT_MESSAGE);
+ }
+ }
+
+ public static void registerStation() {
+ System.out.println(REGISTER_STATION_MESSAGE);
+ String stationName = scanner.nextLine();
+ try {
+ validateStationName(stationName);
+ StationRepository.addStation(new Station(stationName));
+ System.out.println(REGISTER_COMPLETE_MESSAGE);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ registerStation();
+ }
+ }
+
+ public static void removeStation() {
+ System.out.println(REMOVE_STATION_MESSAGE);
+ String stationName = scanner.nextLine();
+ try { // TODO 노선에 포함된 역이 두 개 이하이면 역을 삭제할 수 없다.
+ validateStationRegisteredOnLine(stationName);
+ StationRepository.deleteStation(stationName);
+ } catch (Exception e) {
+ System.out.println();
+ System.out.println(e.getMessage());
+ getStationScreenUserSelection();
+ }
+ }
+
+ private static void validateStationRegisteredOnLine(String stationName) {
+ for (Line line : LineRepository.lines()) {
+ if (line.isStationRegistered(stationName)) {
+ throw new IllegalArgumentException("[ERROR] 노선에 등록되어 있는 역이므로 삭제가 불가능합니다.");
+ }
+ }
+ }
+
+ private static void validateStationName(String stationName) {
+ validateStationNameLength(stationName);
+ validateStationNameEndedWithStation(stationName);
+ validateStationNameHasNumber(stationName);
+ validateStationNameHasOnlyKorean(stationName);
+ validateStationNameHasSpace(stationName);
+ validateStationNameHasDuplication(stationName);
+ }
+
+ private static void validateStationNameLength(String stationName) {
+ if (stationName.length() < MINIMUM_STATION_NAME_LENGTH) {
+ throw new IllegalArgumentException(STATION_NAME_LENGTH_MESSAGE);
+ }
+ }
+
+ private static void validateStationNameEndedWithStation(String stationName) {
+ if (!(stationName.charAt(stationName.length() - 1) == STATION_NAME_ENDED_WITH)) {
+ throw new IllegalArgumentException(STATION_NAME_SHOULD_BE_ENDED_WITH_STATION_MESSAGE);
+ }
+ }
+
+ private static void validateStationNameHasNumber(String stationName) {
+ if (stationName.matches(HAS_NUMBER_REGULAR_EXPRESSION)) {
+ throw new IllegalArgumentException(STATION_NAME_INCLUDE_NUMBER_MESSAGE);
+ }
+ }
+
+ private static void validateStationNameHasOnlyKorean(String stationName) {
+ if (!stationName.matches(KOREAN_REGULAR_EXPRESSION)) {
+ throw new IllegalArgumentException(STATION_NAME_INCLUDE_NOT_KOREAN_MESSAGE);
+ }
+ }
+
+ private static void validateStationNameHasSpace(String stationName) {
+ if (stationName.contains(SPACE)) {
+ throw new IllegalArgumentException(STATION_NAME_INCLUDE_SPACE_MESSAGE);
+ }
+ }
+
+ private static void validateStationNameHasDuplication(String stationName) {
+ for (Station station : StationRepository.stations()) {
+ if (station.isSameName(stationName)) {
+ throw new IllegalArgumentException(STATION_NAME_HAS_DUPLICATION_MESSAGE);
+ }
+ }
+ }
+}
diff --git a/src/main/java/subway/view/StationOutputView.java b/src/main/java/subway/view/StationOutputView.java
new file mode 100644
index 000000000..315042b26
--- /dev/null
+++ b/src/main/java/subway/view/StationOutputView.java
@@ -0,0 +1,22 @@
+package subway.view;
+
+public class StationOutputView {
+ private static final String MANAGE_STATION_SCREEN = "## 역 관리 화면";
+ private static final String REGISTER_STATION = "1. 역 등록";
+ private static final String REMOVE_STATION = "2. 역 삭제";
+ private static final String PRINT_STATION = "3. 역 조회";
+ private static final String BACK = "B. 돌아가기";
+
+ private StationOutputView() {
+ }
+
+ public static void printManageStationScreen() {
+ System.out.println();
+ System.out.println(MANAGE_STATION_SCREEN);
+ System.out.println(REGISTER_STATION);
+ System.out.println(REMOVE_STATION);
+ System.out.println(PRINT_STATION);
+ System.out.println(BACK);
+ System.out.println();
+ }
+}