Skip to content
Open
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
# java-calculator-precourse
# java-calculator-precourse

## 기능 구현 목록

1. 덧셈할 문자열 입력 및 검증
- 예외 사항
- 잘못된 형식인 경우
- 잘못된 형식입니다.
- 커스텀 구분자의 기준
- 기본 구분자, 빈문자열, 숫자, “/“, “\”, “n”을 제외한 모든 문자 허용
- 1개만 허용
2. 문자열 파싱
1. 커스텀 구분자가 정의되었다면 저장
3. 숫자 계산
4. 출력
7 changes: 6 additions & 1 deletion src/main/java/calculator/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package calculator;

import calculator.controller.CalculatorController;
import calculator.service.CalculatorService;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
CalculatorService calculatorService = new CalculatorService();
CalculatorController calculatorController = new CalculatorController(calculatorService);
calculatorController.run();
}
}
18 changes: 18 additions & 0 deletions src/main/java/calculator/constant/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package calculator.constant;

public enum ErrorMessage {

FORMAT_ERROR("잘못된 형식입니다."),
;

private static final String ERROR_MESSAGE_PREFIX = "[ERROR] ";
private final String errorMessage;

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

public String getErrorMessage(Object... args) {
return ERROR_MESSAGE_PREFIX + String.format(errorMessage, args);
}
}
24 changes: 24 additions & 0 deletions src/main/java/calculator/controller/CalculatorController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package calculator.controller;

import calculator.service.CalculatorService;
import calculator.util.InputParser;
import calculator.view.InputView;
import calculator.view.OutputView;

public class CalculatorController {

private final CalculatorService calculatorService;

public CalculatorController(CalculatorService calculatorService) {
this.calculatorService = calculatorService;
}

public void run() {
String rawInput = InputView.readInput();
String input = InputParser.parseInput(rawInput);

int sum = calculatorService.calculate(input);

OutputView.printSum(sum);
}
}
29 changes: 29 additions & 0 deletions src/main/java/calculator/domain/Delimiter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package calculator.domain;

import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class Delimiter {

private static final String INIT_DELIMITER = "[,:]";

private String delimiter;

private Delimiter() {
delimiter = INIT_DELIMITER;
}

public static Delimiter newInstance() {
return new Delimiter();
}

public void addDelimiter(String customDelimiter) {
delimiter += "|" + Pattern.quote(customDelimiter);
}

public List<String> split(String target) {
return Stream.of(target.split(delimiter))
.toList();
}
}
28 changes: 28 additions & 0 deletions src/main/java/calculator/domain/Number.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package calculator.domain;

import calculator.constant.ErrorMessage;
import calculator.util.NumberConvertor;

public class Number {

private final int number;

private Number(int number) {
this.number = number;
}

public static Number from(String s) {
validateNumber(s);
return new Number(NumberConvertor.convertToNumber(s));
}

private static void validateNumber(String s) {
if (!s.matches("\\d+")) {
throw new IllegalArgumentException(ErrorMessage.FORMAT_ERROR.getErrorMessage());
}
}

public int addNumber(int addNumber) {
return addNumber + number;
}
}
27 changes: 27 additions & 0 deletions src/main/java/calculator/domain/Numbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package calculator.domain;

import java.util.List;

public class Numbers {

private final List<Number> numbers;

private Numbers(List<Number> numbers) {
this.numbers = numbers;
}

public static Numbers from(List<String> strings) {
List<Number> numbers = strings.stream()
.map(Number::from)
.toList();
return new Numbers(numbers);
}

public int calculateSum() {
int sum = 0;
for (Number number : numbers) {
sum = number.addNumber(sum);
}
return sum;
}
}
46 changes: 46 additions & 0 deletions src/main/java/calculator/domain/Parser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package calculator.domain;

import java.util.List;

public class Parser {

private final Delimiter delimiter;
private final String input;

private Parser(Delimiter delimiter, String input) {
this.delimiter = delimiter;
this.input = input;
}

public static Parser from(String input) {
Delimiter delimiter = Delimiter.newInstance();
return new Parser(delimiter, input);
}

public List<String> parseTarget() {
String target = input;

if (isCustom()) {
String customDelimiter = extractCustomDelimiter(input);
delimiter.addDelimiter(customDelimiter);
target = parseInput(input);
}

return delimiter.split(target);
}

private boolean isCustom() {
return input.startsWith("/");
}

private String extractCustomDelimiter(String input) {
int beginIndex = input.lastIndexOf("/") + 1;
int endIndex = input.indexOf("\\");
return input.substring(beginIndex, endIndex);
}

private String parseInput(String input) {
int beginIndex = input.indexOf("n") + 1;
return input.substring(beginIndex);
}
}
18 changes: 18 additions & 0 deletions src/main/java/calculator/service/CalculatorService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package calculator.service;

import calculator.domain.Numbers;
import calculator.domain.Parser;
import java.util.List;

public class CalculatorService {

public int calculate(String input) {
if (input.isBlank()) {
return 0;
}
Parser parser = Parser.from(input);
List<String> strings = parser.parseTarget();
Numbers numbers = Numbers.from(strings);
return numbers.calculateSum();
}
}
15 changes: 15 additions & 0 deletions src/main/java/calculator/util/InputParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package calculator.util;

public final class InputParser {

private InputParser() {
}

public static String parseInput(String rawInput) {
rawInput = rawInput.strip();

Validator.validateInputFormat(rawInput);

return rawInput;
}
}
14 changes: 14 additions & 0 deletions src/main/java/calculator/util/NumberConvertor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package calculator.util;

import calculator.constant.ErrorMessage;

public final class NumberConvertor {

public static Integer convertToNumber(String input) {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(ErrorMessage.FORMAT_ERROR.getErrorMessage());
}
}
}
16 changes: 16 additions & 0 deletions src/main/java/calculator/util/Validator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package calculator.util;

import calculator.constant.ErrorMessage;

public final class Validator {

private static final String FORMAT = "(//[^\\d,:/n\\\\]\\\\n)?[^/n\\\\]*";

private Validator() {}

public static void validateInputFormat(String input) {
if (!input.matches(FORMAT)) {
throw new IllegalArgumentException(ErrorMessage.FORMAT_ERROR.getErrorMessage());
}
}
}
11 changes: 11 additions & 0 deletions src/main/java/calculator/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package calculator.view;

import camp.nextstep.edu.missionutils.Console;

public class InputView {

public static String readInput() {
System.out.println("덧셈할 문자열을 입력해주세요.");
return Console.readLine();
}
}
11 changes: 11 additions & 0 deletions src/main/java/calculator/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package calculator.view;

public class OutputView {

private OutputView() {
}

public static void printSum(int sum) {
System.out.printf("결과 : %d\n", sum);
}
}
57 changes: 52 additions & 5 deletions src/test/java/calculator/ApplicationTest.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package calculator;

import camp.nextstep.edu.missionutils.test.NsTest;
import org.junit.jupiter.api.Test;

import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import calculator.constant.ErrorMessage;
import camp.nextstep.edu.missionutils.test.NsTest;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class ApplicationTest extends NsTest {
@Test
void 커스텀_구분자_사용() {
Expand All @@ -19,8 +24,49 @@ class ApplicationTest extends NsTest {
@Test
void 예외_테스트() {
assertSimpleTest(() ->
assertThatThrownBy(() -> runException("-1,2,3"))
.isInstanceOf(IllegalArgumentException.class)
assertThatThrownBy(() -> runException("-1,2,3"))
.isInstanceOf(IllegalArgumentException.class)
);
}

@ParameterizedTest
@MethodSource("successInputProvider")
void 성공_케이스(String input, int expectedResult) {
assertSimpleTest(() -> {
run(input);
assertThat(output()).contains("결과 : " + expectedResult);
});
}

static Stream<Arguments> successInputProvider() {
return Stream.of(
Arguments.of("//;\\n1,2:3;4", 10),
Arguments.of("//;\\n1234", 1234),
Arguments.of("1,2,3", 6),
Arguments.of("1,2:3", 6),
Arguments.of("123", 123)
);
}

@ParameterizedTest
@MethodSource("failureInputProvider")
void 실패_케이스(String input) {
assertSimpleTest(() ->
assertThatThrownBy(() -> runException(input))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining(ErrorMessage.FORMAT_ERROR.getErrorMessage())
);
}

static Stream<Arguments> failureInputProvider() {
return Stream.of(
Arguments.of("//;\\na,b:c;d"),
Arguments.of("//;\\nabcd"),
Arguments.of("a,b,c"),
Arguments.of("//;-\\n1-2:3;4"),
Arguments.of("//;\\\\n1,2:3;4"),
Arguments.of("//;\\n//-\\n1,2-3;4"),
Arguments.of("//;\\n1,2\\3;4")
);
}

Expand All @@ -29,3 +75,4 @@ public void runMain() {
Application.main(new String[]{});
}
}

Loading