Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[문자열 덧셈 계산기] 정재우 미션 제출합니다. #1

Open
wants to merge 116 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
74857b7
docs: 초기 기능 구현 목록 작성
holyPigeon Oct 15, 2024
def14f8
feat: InputView 클래스 생성
holyPigeon Oct 15, 2024
92563d8
feat: 사용자로부터 덧셈 문자열을 입력받는 기능 구현
holyPigeon Oct 15, 2024
433332e
docs: 기능 구현 목록 수정
holyPigeon Oct 15, 2024
e2cad86
feat: 입력값 검증을 담당하는 클래스 생성
holyPigeon Oct 15, 2024
c845e49
feat: 입력값에 숫자가 포함되지 않은 경우, 예외를 반환하는 기능 구현
holyPigeon Oct 15, 2024
d08f262
feat: 입력값에 기본 구분자가 포함되어 있지 않은 경우, 예외를 반환하는 기능 구현
holyPigeon Oct 15, 2024
28c579c
docs: 기능 구현 목록 수정
holyPigeon Oct 15, 2024
82aa671
feat: 입력값에 커스텀 구분자가 포함되어 있는지 확인하는 기능 구현
holyPigeon Oct 15, 2024
24676f9
feat: 커스텀 구분자를 입력값에서 잘라내어 구분자 목록에 포함시키는 기능 구현
holyPigeon Oct 15, 2024
e4cd131
docs: 기능 구현 목록 수정
holyPigeon Oct 17, 2024
bdc7364
feat: 커스텀 구분자를 뺸 문자열을 입력값을 최종 저장하는 기능 구현
holyPigeon Oct 17, 2024
d5c49b2
refactor: 입력값 파싱 전의 전처리 과정 리팩토링
holyPigeon Oct 17, 2024
84ad4a6
feat: 구분자를 기준으로 문자열을 분리하는 기능 구현
holyPigeon Oct 17, 2024
9cea28f
feat: 구분자를 통해 분리된 값이 숫자가 아닐 경우, 예외를 반환하는 기능 구현
holyPigeon Oct 17, 2024
ea427f9
Feat: 문자열로부터 숫자들을 추출하는 기능 구현
holyPigeon Oct 17, 2024
76e8e17
feat: Calculator 클래스 생성
holyPigeon Oct 17, 2024
6764b1a
feat: 구분자를 통해 분리된 값이 음수일 경우, 예외를 반환하는 기능 구현
holyPigeon Oct 17, 2024
ea3f44c
feat: 구분자를 통해 분리된 값이 빈 문자열일 경우, 결과로 0을 반환하는 기능 구현
holyPigeon Oct 17, 2024
6e2e254
feat: Calculator 클래스의 숫자 목록 필드 추가
holyPigeon Oct 17, 2024
ac8e140
feat: Calculator 클래스의 생성자 구현
holyPigeon Oct 17, 2024
2c2a8a7
feat: Calculator 클래스의 덧셈 기능 구현
holyPigeon Oct 17, 2024
83a6ebf
docs: 구현 완료되었지만 미처 체크되지 못한 기능들 체크
holyPigeon Oct 17, 2024
7fb4892
feat: OutputView 클래스 생성
holyPigeon Oct 17, 2024
9e3388e
feat: 덧셈 결과 출력 기능 구현
holyPigeon Oct 17, 2024
f881ad6
feat: CalculatorController 클래스 생성
holyPigeon Oct 17, 2024
db6ca6a
feat: 커스텀 구분자 제거 메서드를 private으로 접근 제한
holyPigeon Oct 17, 2024
16a3b77
feat: 입력값으로부터 숫자를 추출하는 메서드의 구분자 목록 관련 파라미터 제거
holyPigeon Oct 17, 2024
613606d
refactor: 기존 InputParser 클래스의 input 필드 제거 및 그에 따른 구조 변경
holyPigeon Oct 17, 2024
0bb7a9d
refactor: 여러 검증 메서드들을 묶어주는 통합 검증 메서드 추가 및 기존 메서드 private으로 접근 제한 처리
holyPigeon Oct 17, 2024
a91b735
refactor: InputValidator 클래스의 delimiters 필드 초기화 시점 수정
holyPigeon Oct 17, 2024
35dec0d
feat: CalculatorController 클래스 필드 변수 및 생성자 구현
holyPigeon Oct 18, 2024
1e2e160
feat: 입출력 및 핵심 로직을 CalculatorController 클래스에 종합
holyPigeon Oct 18, 2024
868d629
feat: 계산기 기능 1차 구현 완료
holyPigeon Oct 18, 2024
18d5c88
fix: 허용된 구분자가 들어갔음에도 예외를 반환하는 에러 수정
holyPigeon Oct 18, 2024
8b9ced4
fix: 필요없는 구분자 검증 관련 메서드 제거
holyPigeon Oct 18, 2024
f18b5a4
fix: 커스텀 구분자의 끝을 인식하지 못하는 에러 수정
holyPigeon Oct 18, 2024
6af00a7
fix: 불변 크기 리스트 사용으로 인해 add 연산이 제한되는 에러 수정
holyPigeon Oct 18, 2024
edde85f
fix: 커스텀 구분자 부분을 제대로 제거하지 못하는 에러 수정
holyPigeon Oct 18, 2024
3292709
refactor: 미허가 구분자 검증 시 사용되는 정규식을 보다 직관적으로 보이도록 분리
holyPigeon Oct 18, 2024
36b8e73
refactor: 미허가 구분자 검증 메서드명을 보다 직관적으로 변경
holyPigeon Oct 18, 2024
2b2b320
feat: 허용되지 않은 구분자를 에러 메시지에 추가하는 기능 구현
holyPigeon Oct 18, 2024
d6cde41
feat: 사용자 입력 종료를 위한 메서드 구현
holyPigeon Oct 18, 2024
ebdde3b
feat: 사용자 입력 종료 로직 적용
holyPigeon Oct 18, 2024
99a3daa
refactor: 검증 담당 클래스의 디렉토리 변경
holyPigeon Oct 18, 2024
b8fe0c7
feat: 입력값이 빈 문자열일 경우, Calculator 객체에 빈 숫자 리스트를 전달하는 기능 구현
holyPigeon Oct 19, 2024
099b536
refactor: 정수 검증 메서드명 및 내부에서 던지는 에러 메시지를 직관적으로 변경
holyPigeon Oct 19, 2024
3276f8e
refactor: 양수 검증 메서드에서 반환하는 에러 메시지를 직관적으로 변경
holyPigeon Oct 19, 2024
be4be31
docs: 리팩토링 목록 작성
holyPigeon Oct 19, 2024
32efd80
refactor: 필요없는 검증 메서드 제거
holyPigeon Oct 20, 2024
3686a82
refactor: 가독성을 위한 InputParser 클래스 내 메서드 위치 변경
holyPigeon Oct 20, 2024
dd96717
refactor: 기존에 InputParser 클래스에 혼재됐던 검증 로직을 InputValidator 클래스로 이동
holyPigeon Oct 20, 2024
b130196
refactor: InputParser 클래스에서 InputValidator를 참조하여 검증 로직을 사용하도록 수정
holyPigeon Oct 20, 2024
f8c5efa
feat: 구분자에 의해 분리된 값이 Blank일 경우 0으로 치환되지 않도록 변경
holyPigeon Oct 20, 2024
423b7f1
refactor: 필요 없는 통합 검증 메서드 제거
holyPigeon Oct 20, 2024
c7a9c64
refactor: InputValidator 클래스에서 구분자 목록을 직접 관리하지 않고 주입받도록 수정
holyPigeon Oct 20, 2024
8c9f357
feat: 커스텀 구분자에 이스케이프 문자("\")가 포함된 경우에 대한 예외 처리 추가
holyPigeon Oct 20, 2024
cd704ce
feat: 커스텀 구분자가 빈 문자열("")일 경우에 대한 예외 처리 추가
holyPigeon Oct 20, 2024
e1ef257
docs: 리팩토링 목록 수정
holyPigeon Oct 20, 2024
193dfdb
feat: 커스텀 구분자에 숫자가 포함되는 경우에 대한 예외 처리를 추가
holyPigeon Oct 20, 2024
fe9902f
feat: 에러 메시지 관리 Enum 구현
holyPigeon Oct 21, 2024
a4212d0
feat: 에러 메시지 리팩토링 사할 InputValidator 클래스에 적용
holyPigeon Oct 21, 2024
1146400
docs: 리팩토링 목록 수정
holyPigeon Oct 21, 2024
5c951a9
feat: 구분자 목록을 관리할 수 있는 Delimiters 클래스 구현
holyPigeon Oct 21, 2024
7f00236
feat: 기본 구분자 관련 Enum 구현
holyPigeon Oct 21, 2024
5ab4468
feat: 기본 구분자 초기화 로직 적용
holyPigeon Oct 21, 2024
c96593c
refactor: Delimiters 클래스명 Delimiter로 직관적 변경
holyPigeon Oct 21, 2024
439a5f0
refactor: DefaultDelimiters 클래스명 DefaultDelimiter로 직관적 변경
holyPigeon Oct 21, 2024
46fbd96
refactor: Delimiter 클래스에 불변 Set을 반환하는 getter 추가
holyPigeon Oct 21, 2024
ca9e340
refactor: Delimiter 클래스 적용 관련 변경사항 수정
holyPigeon Oct 21, 2024
ec8f471
refactor: InputValidator 클래스를 정적 클래스로 변경
holyPigeon Oct 21, 2024
52a7b30
refactor: 검증 관련 로직을 정적으로 처리하도록 변경
holyPigeon Oct 21, 2024
8ee1c49
refactor: InputParser 클래스를 정적 클래스로 변경
holyPigeon Oct 21, 2024
578f312
refactor: 파싱 로직을 정적으로 처리하도록 변경
holyPigeon Oct 21, 2024
1f5f76f
fix: 커스텀 구분자 추가 관련 로직 수정
holyPigeon Oct 21, 2024
e90fc39
feat: 커스텀 구분자 패턴 관련 Enum 구현
holyPigeon Oct 21, 2024
9ecad45
feat: 커스텀 구분자 패턴 Enum 로직 적용
holyPigeon Oct 21, 2024
ca68a6d
docs: 리팩토링 목록 수정
holyPigeon Oct 21, 2024
ce48b60
refactor: 기존 InputParser 클래스에 있던 커스텀 구분자 처리 로직 CustomDelimiterProcess…
holyPigeon Oct 21, 2024
4ea06f9
refactor: 에러 메시지를 가독성있게 분류
holyPigeon Oct 21, 2024
e96c725
feat: 커스텀 구분자 패턴 관련 에러 메시지 추가
holyPigeon Oct 21, 2024
b9ebb90
feat: 커스텀 구분자 패턴 관련 검증 로직 추가
holyPigeon Oct 21, 2024
2256d1c
refactor: 기존 CalculatorController 클래스의 커스텀 구분자 처리 로직 변경
holyPigeon Oct 21, 2024
ac11202
refactor: 사용자 입력값으로부터 커스텀 구분자 패턴을 제거하는 로직 이동
holyPigeon Oct 21, 2024
878c747
refactor: InputParser 클래스명을 InputFilter로 변경
holyPigeon Oct 21, 2024
cdf1ecc
refactor: 커스텀 구분자 제거 로직 직관적으로 변경
holyPigeon Oct 21, 2024
def0b17
refactor: 구분자 관련 클래스 디렉토리 변경
holyPigeon Oct 21, 2024
6ea48ec
refactor: Calculator 클래스를 stateless하게 변경
holyPigeon Oct 21, 2024
a3e4748
refactor: InputView와 OutputView의 역할을 명확하게 분리
holyPigeon Oct 21, 2024
a5e41b9
refactor: CalculatorController 클래스 내부 로직을 가독성있게 메서드로 분리
holyPigeon Oct 21, 2024
a1ca666
docs: 리팩토링 목록 수정
holyPigeon Oct 21, 2024
4d1b3dd
refactor: Delimiter 클래스명 Delimiters로 변경
holyPigeon Oct 21, 2024
386a14f
refactor: CalculatorController 클래스 내 로직을 직관적으로 변경
holyPigeon Oct 21, 2024
afca529
refactor: 구분자 추가 메서드명 변경
holyPigeon Oct 21, 2024
004c393
refactor: CalculatorController 클래스 내 덧셈 연산 관련 메서드명 직관적 변경
holyPigeon Oct 21, 2024
3c2cd62
refactor: InputFilter 클래스를 일반 클래스로 변경
holyPigeon Oct 21, 2024
b6fc622
refactor: InputValidator 클래스를 제외한 모든 클래스 인스턴스화
holyPigeon Oct 21, 2024
9c2e4bb
refactor: `ApplicationConfig` 클래스를 통해 여러 개의 인스턴스를 한 곳에서 관리하도록 구현
holyPigeon Oct 21, 2024
c0d9e9d
refactor: 메인 어플리케이션에 ApplicationConfig 클래스를 이용한 CalculatorController …
holyPigeon Oct 21, 2024
5bdf81a
refactor: CalculatorController 클래스 개행 수정
holyPigeon Oct 21, 2024
676ddc5
refactor: 숫자 및 구분자 리스트에 대한 불변 개념 적용
holyPigeon Oct 21, 2024
4c5fc55
refactor: 커스텀 구분자 위치 관련 에러 메시지를 상수 처리
holyPigeon Oct 21, 2024
ecd9f37
feat: 구분자를 이용한 정규식 생성 관련 메서드 구현
holyPigeon Oct 21, 2024
9641c28
refactor: 구분자를 이용한 정규식 생성 로직 적용
holyPigeon Oct 21, 2024
aaed52e
refactor: 계산기에 들어갈 숫자를 통합적으로 검증하는 메서드 구현
holyPigeon Oct 21, 2024
6eae554
refactor: 숫자 추출 로직 및 세부 메서드명을 보다 직관적으로 변경
holyPigeon Oct 21, 2024
01c03be
refactor: 코드 상의 주석 제거
holyPigeon Oct 21, 2024
b675b3f
docs: 미처 수정하지 못한 리팩토링 완료 사항 체크
holyPigeon Oct 21, 2024
73602e9
docs: 리팩토링 목록 수정
holyPigeon Oct 21, 2024
f0250d2
refactor: 구분자 설정 관련 Enum 디렉토리 변경
holyPigeon Oct 21, 2024
377f6bf
refactor: 출력 관련 메시지 상수 처리
holyPigeon Oct 21, 2024
1e49ae7
feat: 출력 메시지 관련 Enum 구현
holyPigeon Oct 21, 2024
9d857c0
refactor: 정수형 변환 메서드명 변경
holyPigeon Oct 21, 2024
638e35e
refactor: 정수형 변환 메서드명 재변경
holyPigeon Oct 21, 2024
f89a2a0
refactor: 사용자 입력값이 빈 칸일 경우 숫자 추출 시 명시적으로 0이 담긴 리스트를 반환하도록 수정
holyPigeon Oct 21, 2024
d727f40
refactor: 계산기에 들어가는 숫자를 List가 아닌 Set 타입으로 저장하도록 수정
holyPigeon Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 78 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,78 @@
# java-calculator-precourse
# java-calculator-precourse

## 🚀 구현할 기능 목록

### ⌨️ 입력

- [x] 덧셈할 문자열을 입력받는 기능을 구현한다.
- [x] 덧셈 문자열 입력 안내 메시지를 출력한다.
- [x] 사용자로부터 덧셈할 문자열을 입력받는다.
- [x] 입력된 문자열을 검증한다.
- [x] 숫자가 하나라도 포함되어있지 않은 경우, 예외를 반환한다.
- [x] 기본 구분자 중 하나라도 포함되어있지 않은 경우, 예외를 반환한다.
- [x] 입력된 문자열을 파싱 및 추가 검증한다.
- [x] 입력값에서 편리하게 숫자를 추출하기 위해 전처리를 진행한다.
- [x] 문자열에 커스텀 구분자가 포함되어 있는지 확인한다.
- [x] 문자열 앞 부분에 커스텀 구분자가 있는 경우, 이를 따로 저장한다.
- [x] 커스텀 구분자를 뺸 문자열을 입력값으로 최종 저장한다.
- [x] 문자열로부터 숫자들을 추출한다.
- [x] 주어진 문자열에 구분자가 포함되어 있는지 확인한다.
- [x] 만약 구분자가 포함되어 있는 경우, 구분자를 기준으로 문자열을 분리한다.
- [x] 구분자를 통해 분리된 값이 빈 문자열일 경우, 결과로 0을 반환한다.
- [x] 구분자를 통해 분리된 값이 숫자가 아닐 경우, 예외를 반환한다.
- [x] 구분자를 통해 분리된 값이 음수일 경우, 예외를 반환한다.
- [x] 최종적으로 분리된 숫자들을 리스트에 저장한다.

### 🖥 출력

- [x] 덧셈 결과를 출력한다.
- [x] "결과"라는 문자열와 덧셈 결과를 ":" 구분자를 통해 구분한다.

### ⚙️ 로직

- [x] 리스트에 저장된 숫자들을 더하는 기능을 구현한다.
- [x] 리스트에 저장된 숫자들을 모두 더한 결과를 반환한다.

---

## 🛠️ 리팩토링 목록

### 1️⃣ 모든 예외를 처리하지 못하는 있는 현 검증 로직 → 더 많은 예외에 대비하기 위해, 더 많은 검증 메서드 구현

- [x] 커스텀 구분자에 실제 이스케이프 문법("\")이 포함된 경우에 대한 예외 처리를 추가한다.
- [x] 커스텀 구분자에 숫자가 포함되는 경우에 대한 예외 처리를 추가한다.
- [x] 커스텀 구분자가 빈 문자열("")일 경우에 대한 예외 처리를 추가한다.
- [x] 구분자에 의해 분리된 값이 숫자가 아닌 경우에 대한 예외 처리를 추가한다.

### 2️⃣ 입력값 검증과 파싱 로직이 혼용되는 문제 발생 → 확실하게 책임을 분리

- [x] 입력값 검증과 관련된 메서드들은 모두 `InputValidator`에서 관리하도록 이동시킨다.
- [x] 입력값 파싱 과정에서 쓰이는 검증 메서드들은 `InputFilter` 내에서 `InputValidator`를 참조하여 사용하도록 수정한다.

### 3️⃣ 매직 넘버 및 리터럴 사용으로 인한 추후 유지보수에서의 어려움 예상 → 클래스 및 상수로서 관리

- [x] 에러 메시지를 Enum을 통해 상수로 관리하도록 수정한다.
- [x] 구분자 목록을 Enum을 통해 상수로 관리하도록 수정한다.

### 4️⃣ 숫자 값들이 각 객체와 메서드를 거치며 변경될 여지가 있음 → 불변 개념 적용

- [x] 숫자 값들을 변경할 수 없도록 `final` 키워드를 추가한다.
- [x] 숫자 리스트를 전달할 떄, 불변 리스트로 전달될 수 있도록 List.of 또는 unmodifiableList를 적용한다.

### 5️⃣ 인스턴스 관리가 여러 곳에 산재되어 있음 → 모든 인스턴스를 한 곳에서 관리

- [x] 정적 클래스와 일반 클래스의 구분을 분명히 하기 위해 `InputValidator` 클래스를 제외한 모든 클래스를 인스턴스화한다.
- [x] `ApplicationConfig` 클래스를 통해 여러 개의 인스턴스를 한 곳에서 관리한다.

### 6️⃣ 테스트 케이스가 단 2개밖에 없는 상황 → 더 많은 테스트 케이스를 작성하여 테스트 용이성 향상

- [ ] 각 예외 상황에 대한 테스트 케이스를 추가한다.
- [ ] 그 외에 각 메서드들이 정상적으로 동작하는지 확인할 수 있도록 테스트 케이스를 추가한다.

### 7️⃣ 구분자를 단순 필드 변수로 관리중 → 구분자 관리를 위한 별도 클래스 생성

- [x] `Delimiters` 클래스를 생성하여, 구분자 목록을 관리하도록 수정한다.

### 8️⃣ 커스텀 구분자에 대한 처리를 `InputFilter` 클래스에서 전담하고 있는 상황 → `CustomDelimiterProcessor` 클래스 생성을 통한 책임 분리

- [x] 기존 `InputFilter` 클래스에 있던 커스텀 구분자 처리 로직을 `CustomDelimiterProcessor` 클래스로 이동시킨다.
13 changes: 10 additions & 3 deletions src/main/java/calculator/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package calculator;

import calculator.config.ApplicationConfig;
import calculator.controller.CalculatorController;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
}

public static void main(String[] args) {
ApplicationConfig applicationConfig = new ApplicationConfig();
CalculatorController calculatorController = applicationConfig.initializeController();

calculatorController.run();
}
}
22 changes: 22 additions & 0 deletions src/main/java/calculator/config/ApplicationConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package calculator.config;

import calculator.controller.CalculatorController;
import calculator.model.Calculator;
import calculator.model.InputFilter;
import calculator.model.delimiter.CustomDelimiterProcessor;
import calculator.model.delimiter.Delimiters;
import calculator.view.InputView;
import calculator.view.OutputView;

public class ApplicationConfig {
public CalculatorController initializeController() {
return new CalculatorController(
new InputView(),
new OutputView(),
new Delimiters(),
new CustomDelimiterProcessor(),
new InputFilter(),
new Calculator()
);
}
}
20 changes: 20 additions & 0 deletions src/main/java/calculator/config/CustomDelimiterPattern.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package calculator.config;

public enum CustomDelimiterPattern {
START("//"),
END("\\n");

private final String pattern;

CustomDelimiterPattern(String pattern) {
this.pattern = pattern;
}

public String getPattern() {
return pattern;
}

public int getPatternLength() {
return pattern.length();
}
}
16 changes: 16 additions & 0 deletions src/main/java/calculator/config/DefaultDelimiter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package calculator.config;

public enum DefaultDelimiter {
COMMA(","),
COLON(":");

private final String delimiter;

DefaultDelimiter(String delimiter) {
this.delimiter = delimiter;
}

public String getDelimiter() {
return delimiter;
}
}
74 changes: 74 additions & 0 deletions src/main/java/calculator/controller/CalculatorController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package calculator.controller;

import java.util.List;
import java.util.Optional;
import java.util.Set;

import calculator.model.Calculator;
import calculator.model.delimiter.CustomDelimiterProcessor;
import calculator.model.delimiter.Delimiters;
import calculator.model.InputFilter;
import calculator.view.InputView;
import calculator.view.OutputView;

public class CalculatorController {
private final InputView inputView;
private final OutputView outputView;
private final Delimiters delimiters;
private final CustomDelimiterProcessor customDelimiterProcessor;
private final InputFilter inputFilter;
private final Calculator calculator;

public CalculatorController(
InputView inputView,
OutputView outputView,
Delimiters delimiters,
CustomDelimiterProcessor customDelimiterProcessor,
InputFilter inputFilter,
Calculator calculator
) {
this.inputView = inputView;
this.outputView = outputView;
this.delimiters = delimiters;
this.customDelimiterProcessor = customDelimiterProcessor;
this.inputFilter = inputFilter;
this.calculator = calculator;
}

public void run() {
String input = readInput();

String processedInput = processCustomDelimiter(input);
Set<Integer> numbers = extractNumbers(processedInput);
int result = sum(numbers);

printResult(result);
}

private String readInput() {
outputView.printReadCommand();
String input = inputView.readInput();
inputView.closeRead();

return input;
}

private String processCustomDelimiter(String input) {
Optional<String> customDelimiter = customDelimiterProcessor.extractCustomDelimiter(input);
customDelimiter.ifPresent(delimiters::addDelimiter);

return customDelimiterProcessor.removeCustomDelimiterPattern(input);
}

private Set<Integer> extractNumbers(String processedInput) {
return inputFilter.extractNumbers(processedInput, delimiters);
}

private int sum(Set<Integer> numbers) {
return calculator.sum(numbers);
}

private void printResult(int result) {
outputView.printResult(result);
}
}
30 changes: 30 additions & 0 deletions src/main/java/calculator/exception/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package calculator.exception;

public enum ErrorMessage {
// prefix
ERROR_PREFIX("[ERROR] "),

// delimiter
INVALID_DELIMITER("허용되지 않은 구분자가 포함되어 있습니다."),
INVALID_CUSTOM_DELIMITER("커스텀 구분자는 정수일 수 없습니다."),
EMPTY_CUSTOM_DELIMITER("커스텀 구분자는 빈 문자열일 수 없습니다."),

// calculator
NON_INTEGER_VALUE("계산기에 입력될 숫자는 정수이어야 합니다."),
NON_POSITIVE_NUMBER("계산기에 입력될 숫자는 양수이어야 합니다."),

// custom delimiter pattern
INVALID_START_PATTERN("커스텀 구분자의 시작 패턴이 올바르지 않습니다."),
INVALID_END_PATTERN("커스텀 구분자의 종료 패턴이 올바르지 않습니다."),
INVALID_PATTERN_POSITION("커스텀 구분자의 위치가 올바르지 않습니다.");

private final String message;

ErrorMessage(String message) {
this.message = message;
}

public String getMessage() {
return ERROR_PREFIX.message + message;
}
}
11 changes: 11 additions & 0 deletions src/main/java/calculator/model/Calculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package calculator.model;

import java.util.Set;

public class Calculator {
public int sum(Set<Integer> numbers) {
return numbers.stream()
.mapToInt(Integer::intValue)
.sum();
}
}
39 changes: 39 additions & 0 deletions src/main/java/calculator/model/InputFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package calculator.model;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

import calculator.model.delimiter.Delimiters;
import calculator.validation.InputValidator;

public class InputFilter {
public Set<Integer> extractNumbers(String processedInput, Delimiters delimiters) {
if (processedInput.isBlank()) {
return Set.of(0);
}
String[] splitParts = splitInput(processedInput, delimiters);
validateEachPart(splitParts);

return mapToIntegerSet(splitParts);
}

private String[] splitInput(String processedInput, Delimiters delimiters) {
InputValidator.validateInvalidDelimiter(processedInput, delimiters);
String regex = String.join("|", delimiters.getRegex());

return processedInput.split(regex);
}

private static void validateEachPart(String[] splitParts) {
Arrays.stream(splitParts)
.map(String::trim)
.forEach(InputValidator::validateCalculatorNumber);
}

private static Set<Integer> mapToIntegerSet(String[] splitParts) {
return Arrays.stream(splitParts)
.map(Integer::valueOf)
.collect(Collectors.toUnmodifiableSet());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package calculator.model.delimiter;

import static calculator.config.CustomDelimiterPattern.*;

import java.util.Optional;

import calculator.validation.InputValidator;

public class CustomDelimiterProcessor {
public String removeCustomDelimiterPattern(String input) {
if (hasCustomDelimiterPattern(input)) {
int endIndex = findEndIndex(input);

return input.substring(endIndex + END.getPatternLength());
}

return input;
}

public Optional<String> extractCustomDelimiter(String input) {
if (!hasCustomDelimiterPattern(input)) {
return Optional.empty();
}
int startIndex = findStartIndex(input);
int endIndex = findEndIndex(input);

return Optional.of(extractCustomDelimiter(input, startIndex, endIndex));
}

private boolean hasCustomDelimiterPattern(String input) {
return input.contains(START.getPattern()) && input.contains(END.getPattern());
}

private int findStartIndex(String input) {
int startIndex = input.indexOf(START.getPattern());
InputValidator.validateStartPattern(startIndex);

return startIndex + START.getPatternLength();
}

private int findEndIndex(String input) {
int endIndex = input.indexOf(END.getPattern());
InputValidator.validateEndPattern(endIndex);

return endIndex;
}

private String extractCustomDelimiter(String input, int start, int end) {
InputValidator.validatePatternPosition(start, end);

return input.substring(start, end);
}
}
Loading