From 7ba802b605a4ff786a868cb88bec06378ce2a0de Mon Sep 17 00:00:00 2001
From: Kim Uijin <127496156+sansan20535@users.noreply.github.com>
Date: Wed, 9 Oct 2024 21:11:11 +0900
Subject: [PATCH 1/5] =?UTF-8?q?[FEAT]=20:=201=EC=B0=A8=20=EC=84=B8?=
=?UTF-8?q?=EB=AF=B8=EB=82=98=20=EA=B3=BC=EC=A0=9C=20=ED=95=84=EC=88=98=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/git_toolbox_prj.xml | 15 ++
.idea/gradle.xml | 17 ++
.idea/misc.xml | 9 +
.idea/vcs.xml | 6 +
.idea/workspace.xml | 109 ++++++++---
src/main/java/org/sopt/week1/Diary.java | 21 +++
.../java/org/sopt/week1/DiaryController.java | 47 +++++
.../java/org/sopt/week1/DiaryRepository.java | 44 +++++
.../java/org/sopt/week1/DiaryService.java | 26 +++
src/main/java/org/sopt/week1/Main.java | 173 ++++++++++++++++++
10 files changed, 442 insertions(+), 25 deletions(-)
create mode 100644 .idea/git_toolbox_prj.xml
create mode 100644 .idea/gradle.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/vcs.xml
create mode 100644 src/main/java/org/sopt/week1/Diary.java
create mode 100644 src/main/java/org/sopt/week1/DiaryController.java
create mode 100644 src/main/java/org/sopt/week1/DiaryRepository.java
create mode 100644 src/main/java/org/sopt/week1/DiaryService.java
create mode 100644 src/main/java/org/sopt/week1/Main.java
diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
new file mode 100644
index 0000000..02b915b
--- /dev/null
+++ b/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..43cc8e4
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..340c0ad
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 9f14b44..b2364b2 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,15 +5,7 @@
-
-
-
-
-
-
-
-
-
+
@@ -25,32 +17,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "associatedIndex": 8
+}
+
- {
+ "keyToString": {
+ "Gradle.assignment [:Main.main()].executor": "Run",
+ "RunOnceActivity.OpenProjectViewOnStart": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "git-widget-placeholder": "seminar/#1",
+ "kotlin-language-version-configured": "true",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "onboarding.tips.debug.path": "/Users/a./Desktop/AND-SOPT/assignment/src/main/java/org/sopt/Main.java",
+ "project.structure.last.edited": "Project",
+ "project.structure.proportion": "0.0",
+ "project.structure.side.proportion": "0.0",
+ "settings.editor.selected.configurable": "org.jetbrains.plugins.github.ui.GithubSettingsConfigurable",
+ "vue.rearranger.settings.migration": "true"
}
-}]]>
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -67,6 +122,10 @@
1727684220630
+
+
+
+
@@ -84,7 +143,7 @@
-
+
diff --git a/src/main/java/org/sopt/week1/Diary.java b/src/main/java/org/sopt/week1/Diary.java
new file mode 100644
index 0000000..8525e80
--- /dev/null
+++ b/src/main/java/org/sopt/week1/Diary.java
@@ -0,0 +1,21 @@
+package org.sopt.week1;
+
+import java.time.LocalDateTime;
+
+public class Diary {
+ private final Long id;
+ private final String body;
+
+ public Diary(Long id, String body) {
+ this.id = id;
+ this.body = body;
+ }
+
+ public Long getId() {
+ return this.id;
+ }
+
+ public String getBody() {
+ return this.body;
+ }
+}
diff --git a/src/main/java/org/sopt/week1/DiaryController.java b/src/main/java/org/sopt/week1/DiaryController.java
new file mode 100644
index 0000000..d2f2463
--- /dev/null
+++ b/src/main/java/org/sopt/week1/DiaryController.java
@@ -0,0 +1,47 @@
+package org.sopt.week1;
+
+import java.util.List;
+
+public class DiaryController {
+ private Status status = Status.READY;
+ private final DiaryService diaryService = new DiaryService();
+
+ Status getStatus() {
+ return status;
+ }
+
+ void boot() {
+ this.status = Status.RUNNING;
+ }
+
+ void finish() {
+ this.status = Status.FINISHED;
+ }
+
+ // APIS
+ final List getList() {
+ return diaryService.getDiaryList();
+ }
+
+ final void post(final String body) {
+ if (body.length() > 30) {
+ throw new IllegalArgumentException();
+ }
+ diaryService.writeDiary(body);
+ }
+
+ final void delete(final String id) {
+ diaryService.deleteDiary(Long.parseLong(id));
+ }
+
+ final void patch(final String id, final String body) {
+ diaryService.updateDiary(Long.parseLong(id), body);
+ }
+
+ enum Status {
+ READY,
+ RUNNING,
+ FINISHED,
+ ERROR,
+ }
+}
diff --git a/src/main/java/org/sopt/week1/DiaryRepository.java b/src/main/java/org/sopt/week1/DiaryRepository.java
new file mode 100644
index 0000000..ae8699d
--- /dev/null
+++ b/src/main/java/org/sopt/week1/DiaryRepository.java
@@ -0,0 +1,44 @@
+package org.sopt.week1;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class DiaryRepository {
+ private final Map storage = new ConcurrentHashMap<>();
+ private final AtomicLong numbering = new AtomicLong();
+
+ void save(final Diary diary) {
+ // 채번 과정
+ final long id = numbering.addAndGet(1);
+ // 저장 과정
+ storage.put(id, diary.getBody());
+ }
+
+ List findAll() {
+ // (1) diary를 담을 자료구조
+ final List diaryList = new ArrayList<>();
+ // (2) 저장한 값을 불러오는 반복 구조
+ for (long index = 1; index <= numbering.intValue(); index++) {
+ final String body = storage.get(index);
+ // (2-1) 저장한 값을 불러오는 반복 구조
+ if (body != null) {
+ diaryList.add(new Diary(index, body));
+ }
+ }
+ // (3) 불러온 자료구조를 응답
+ return diaryList;
+ }
+
+ void deleteById(final Long id) {
+ storage.remove(id);
+ }
+
+ void updateById(final Long id, final String body) {
+ storage.replace(id, body);
+ }
+
+}
diff --git a/src/main/java/org/sopt/week1/DiaryService.java b/src/main/java/org/sopt/week1/DiaryService.java
new file mode 100644
index 0000000..96aa495
--- /dev/null
+++ b/src/main/java/org/sopt/week1/DiaryService.java
@@ -0,0 +1,26 @@
+package org.sopt.week1;
+
+import java.util.List;
+
+public class DiaryService {
+ private final DiaryRepository diaryRepository = new DiaryRepository();
+
+ void writeDiary(final String body) {
+ final Diary diary = new Diary(null, body);
+
+ diaryRepository.save(diary);
+ }
+
+ List getDiaryList() {
+ return diaryRepository.findAll();
+ }
+
+ void deleteDiary(final Long id) {
+ diaryRepository.deleteById(id);
+ }
+
+ void updateDiary(final Long id, final String body) {
+ diaryRepository.updateById(id, body);
+ }
+
+}
diff --git a/src/main/java/org/sopt/week1/Main.java b/src/main/java/org/sopt/week1/Main.java
new file mode 100644
index 0000000..1b4df8e
--- /dev/null
+++ b/src/main/java/org/sopt/week1/Main.java
@@ -0,0 +1,173 @@
+package org.sopt.week1;
+
+import java.io.*;
+
+public class Main {
+ public static void main(String[] args) {
+ final UI ui;
+ try {
+ ui = new DiaryUI(new DiaryController());
+ ui.runRepeatedly();
+ } catch (Throwable t) {
+
+ }
+ }
+
+ interface UI {
+ void runRepeatedly() throws IOException;
+
+ class UIException extends RuntimeException {
+ }
+
+ class InvalidInputException extends UIException {
+ }
+ }
+
+ static class DiaryUI implements UI {
+ private final DiaryController server;
+ private String selected;
+
+ public DiaryUI(DiaryController server) throws IOException {
+ this.server = server;
+ server.boot();
+ ConsoleIO.printLine(getStartMessage());
+ }
+
+ public void runRepeatedly() throws IOException {
+
+ do {
+ if (onMenu()) {
+ ConsoleIO.printLine("");
+ ConsoleIO.printLine(getMenu());
+ selected = ConsoleIO.readLine().trim().toUpperCase();
+ }
+
+ try {
+ run();
+ } catch (InvalidInputException e) {
+ ConsoleIO.printLine("잘못된 값을 입력하였습니다.");
+ }
+
+ if (isFinished()) {
+ ConsoleIO.printLine(getFinishMessage());
+ break;
+ }
+
+ selected = null;
+ } while (isRunning());
+ }
+
+ private void run() throws IOException {
+ switch (server.getStatus()) {
+ case READY, FINISHED, ERROR -> throw new UIException();
+
+ case RUNNING -> {
+ switch (selected) {
+ case "GET" -> {
+ server.getList().forEach(diary -> {
+ try {
+ ConsoleIO.printLine(diary.getId() + " : " + diary.getBody());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+ case "POST" -> {
+ ConsoleIO.printLine("한 줄 일기를 작성해주세요!");
+ final String input = ConsoleIO.readLine();
+ server.post(input);
+ }
+
+ case "DELETE" -> {
+ ConsoleIO.printLine("삭제할 id 를 입력하세요!");
+ final String input = ConsoleIO.readLine();
+ server.delete(input);
+ }
+ case "PATCH" -> {
+ ConsoleIO.printLine("수정할 id 를 입력하세요!");
+ final String inputId = ConsoleIO.readLine();
+
+ ConsoleIO.printLine("수정 body 를 입력하세요!");
+ final String inputBody = ConsoleIO.readLine();
+
+ server.patch(inputId, inputBody);
+ }
+ case "FINISH" -> {
+ server.finish();
+ }
+ default -> {
+ throw new InvalidInputException();
+ }
+ }
+ }
+
+ }
+ }
+
+ private boolean isRunning() {
+ return server.getStatus() == DiaryController.Status.RUNNING;
+ }
+
+ private boolean isFinished() {
+ return server.getStatus() == DiaryController.Status.FINISHED;
+ }
+
+ private boolean onMenu() {
+ return selected == null;
+ }
+
+ private String getMenu() {
+ return """
+ ============================
+ - GET : 일기 불러오기
+ - POST : 일기 작성하기
+ - DELETE : 일기 제거하기
+ - PATCH : 일기 수정하기
+ """;
+
+ }
+
+ private String getStartMessage() {
+ return "시작합니다 :)";
+ }
+
+ private String getFinishMessage() {
+ return "종료됩니다 :)";
+ }
+ }
+
+ // not thread safe
+ private static class ConsoleIO {
+ private final static BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
+ private final static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
+ private final static StringBuilder sb = new StringBuilder();
+
+ public static void printLine(final String toPrint) throws IOException {
+ if (toPrint == null) {
+ throw new IllegalArgumentException("console can not print null");
+ }
+
+ appendLine(toPrint);
+ print();
+ clearStringBuilder();
+ }
+
+ public static String readLine() throws IOException {
+ return bufferedReader.readLine();
+ }
+
+ private static void appendLine(final String toPrint) {
+ sb.append(toPrint);
+ sb.append("\n");
+ }
+
+ private static void print() throws IOException {
+ bufferedWriter.write(sb.toString());
+ bufferedWriter.flush();
+ }
+
+ private static void clearStringBuilder() {
+ sb.setLength(0);
+ }
+ }
+}
From 24a6973f009b98a93bf2e4be4038400507e4a39f Mon Sep 17 00:00:00 2001
From: Kim Uijin <127496156+sansan20535@users.noreply.github.com>
Date: Wed, 9 Oct 2024 21:28:00 +0900
Subject: [PATCH 2/5] =?UTF-8?q?[FEAT]=20:=201=EC=B0=A8=20=EC=84=B8?=
=?UTF-8?q?=EB=AF=B8=EB=82=98=20=EA=B3=BC=EC=A0=9C=20=EC=84=A0=ED=83=9D=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EC=82=AD=EC=A0=9C=EB=90=9C=20?=
=?UTF-8?q?=EC=9D=BC=EA=B8=B0=20=EB=B3=B5=EA=B5=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/workspace.xml | 47 +++++++++++--------
.../java/org/sopt/week1/DiaryController.java | 4 ++
.../java/org/sopt/week1/DiaryRepository.java | 8 ++++
.../java/org/sopt/week1/DiaryService.java | 3 ++
src/main/java/org/sopt/week1/Main.java | 6 +++
5 files changed, 49 insertions(+), 19 deletions(-)
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index b2364b2..d9b8eb0 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -6,6 +6,10 @@
+
+
+
+
@@ -35,6 +39,10 @@
+
+
+
+
@@ -66,26 +74,26 @@
- {
- "keyToString": {
- "Gradle.assignment [:Main.main()].executor": "Run",
- "RunOnceActivity.OpenProjectViewOnStart": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "git-widget-placeholder": "seminar/#1",
- "kotlin-language-version-configured": "true",
- "node.js.detected.package.eslint": "true",
- "node.js.detected.package.tslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "node.js.selected.package.tslint": "(autodetect)",
- "nodejs_package_manager_path": "npm",
- "onboarding.tips.debug.path": "/Users/a./Desktop/AND-SOPT/assignment/src/main/java/org/sopt/Main.java",
- "project.structure.last.edited": "Project",
- "project.structure.proportion": "0.0",
- "project.structure.side.proportion": "0.0",
- "settings.editor.selected.configurable": "org.jetbrains.plugins.github.ui.GithubSettingsConfigurable",
- "vue.rearranger.settings.migration": "true"
+
+}]]>
@@ -126,6 +134,7 @@
+
diff --git a/src/main/java/org/sopt/week1/DiaryController.java b/src/main/java/org/sopt/week1/DiaryController.java
index d2f2463..35c22c1 100644
--- a/src/main/java/org/sopt/week1/DiaryController.java
+++ b/src/main/java/org/sopt/week1/DiaryController.java
@@ -38,6 +38,10 @@ final void patch(final String id, final String body) {
diaryService.updateDiary(Long.parseLong(id), body);
}
+ final void restore() {
+ diaryService.restoreDiaryList();
+ }
+
enum Status {
READY,
RUNNING,
diff --git a/src/main/java/org/sopt/week1/DiaryRepository.java b/src/main/java/org/sopt/week1/DiaryRepository.java
index ae8699d..1ca4272 100644
--- a/src/main/java/org/sopt/week1/DiaryRepository.java
+++ b/src/main/java/org/sopt/week1/DiaryRepository.java
@@ -9,6 +9,7 @@
public class DiaryRepository {
private final Map storage = new ConcurrentHashMap<>();
+ private final Map trash = new HashMap<>();
private final AtomicLong numbering = new AtomicLong();
void save(final Diary diary) {
@@ -34,6 +35,7 @@ List findAll() {
}
void deleteById(final Long id) {
+ trash.put(id, storage.get(id));
storage.remove(id);
}
@@ -41,4 +43,10 @@ void updateById(final Long id, final String body) {
storage.replace(id, body);
}
+ void restoreAll() {
+ for (Long id : trash.keySet()) {
+ storage.put(id, trash.get(id));
+ }
+ trash.clear();
+ }
}
diff --git a/src/main/java/org/sopt/week1/DiaryService.java b/src/main/java/org/sopt/week1/DiaryService.java
index 96aa495..8d6b5b4 100644
--- a/src/main/java/org/sopt/week1/DiaryService.java
+++ b/src/main/java/org/sopt/week1/DiaryService.java
@@ -23,4 +23,7 @@ void updateDiary(final Long id, final String body) {
diaryRepository.updateById(id, body);
}
+ void restoreDiaryList() {
+ diaryRepository.restoreAll();
+ }
}
diff --git a/src/main/java/org/sopt/week1/Main.java b/src/main/java/org/sopt/week1/Main.java
index 1b4df8e..dabed1f 100644
--- a/src/main/java/org/sopt/week1/Main.java
+++ b/src/main/java/org/sopt/week1/Main.java
@@ -92,6 +92,11 @@ private void run() throws IOException {
server.patch(inputId, inputBody);
}
+ case "RESTORE" -> {
+ server.restore();
+
+ ConsoleIO.printLine("삭제된 일기를 복구했습니다.");
+ }
case "FINISH" -> {
server.finish();
}
@@ -123,6 +128,7 @@ private String getMenu() {
- POST : 일기 작성하기
- DELETE : 일기 제거하기
- PATCH : 일기 수정하기
+ - RESTORE : 일기 복구하기
""";
}
From 1e98bfc13d003809245d9253a1e6dcdfea1ffbf6 Mon Sep 17 00:00:00 2001
From: Kim Uijin <127496156+sansan20535@users.noreply.github.com>
Date: Wed, 9 Oct 2024 21:39:34 +0900
Subject: [PATCH 3/5] =?UTF-8?q?[REFACTOR]=20:=201=EC=B0=A8=20=EC=84=B8?=
=?UTF-8?q?=EB=AF=B8=EB=82=98=20=EA=B3=BC=EC=A0=9C=20=EC=84=A0=ED=83=9D=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EC=9E=85=EB=A0=A5=EA=B0=92=20?=
=?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/org/sopt/week1/DiaryController.java | 2 +-
src/main/java/org/sopt/week1/DiaryRepository.java | 8 ++++++++
src/main/java/org/sopt/week1/Main.java | 2 ++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/sopt/week1/DiaryController.java b/src/main/java/org/sopt/week1/DiaryController.java
index 35c22c1..df574e1 100644
--- a/src/main/java/org/sopt/week1/DiaryController.java
+++ b/src/main/java/org/sopt/week1/DiaryController.java
@@ -25,7 +25,7 @@ final List getList() {
final void post(final String body) {
if (body.length() > 30) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("30자 이하로 적어주세요");
}
diaryService.writeDiary(body);
}
diff --git a/src/main/java/org/sopt/week1/DiaryRepository.java b/src/main/java/org/sopt/week1/DiaryRepository.java
index 1ca4272..46057da 100644
--- a/src/main/java/org/sopt/week1/DiaryRepository.java
+++ b/src/main/java/org/sopt/week1/DiaryRepository.java
@@ -35,11 +35,13 @@ List findAll() {
}
void deleteById(final Long id) {
+ isValidateId(id);
trash.put(id, storage.get(id));
storage.remove(id);
}
void updateById(final Long id, final String body) {
+ isValidateId(id);
storage.replace(id, body);
}
@@ -49,4 +51,10 @@ void restoreAll() {
}
trash.clear();
}
+
+ void isValidateId(final Long id) {
+ if (storage.get(id) == null) {
+ throw new IllegalArgumentException("존재하지 않는 일기 id입니다.");
+ }
+ }
}
diff --git a/src/main/java/org/sopt/week1/Main.java b/src/main/java/org/sopt/week1/Main.java
index dabed1f..da2160a 100644
--- a/src/main/java/org/sopt/week1/Main.java
+++ b/src/main/java/org/sopt/week1/Main.java
@@ -46,6 +46,8 @@ public void runRepeatedly() throws IOException {
run();
} catch (InvalidInputException e) {
ConsoleIO.printLine("잘못된 값을 입력하였습니다.");
+ } catch (IllegalArgumentException e) {
+ ConsoleIO.printLine(e.getMessage());
}
if (isFinished()) {
From 2ece0f04e8cba65ce148ee43f957b9415be1084f Mon Sep 17 00:00:00 2001
From: Kim Uijin <127496156+sansan20535@users.noreply.github.com>
Date: Wed, 9 Oct 2024 22:28:18 +0900
Subject: [PATCH 4/5] =?UTF-8?q?[FEAT]=20:=201=EC=B0=A8=20=EC=84=B8?=
=?UTF-8?q?=EB=AF=B8=EB=82=98=20=EA=B3=BC=EC=A0=9C=20=EC=84=A0=ED=83=9D=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EC=9D=B4=EB=AA=A8=EC=A7=80=20?=
=?UTF-8?q?=ED=8F=AC=ED=95=A8=20=EA=B8=80=EC=9E=90=EC=88=98=20=EA=B3=84?=
=?UTF-8?q?=EC=82=B0=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/workspace.xml | 6 +----
.../java/org/sopt/week1/DiaryController.java | 2 +-
src/main/java/org/sopt/week1/TextUtils.java | 24 ++++++++++++++++++
src/test/java/TextUtilsTest.java | 25 +++++++++++++++++++
4 files changed, 51 insertions(+), 6 deletions(-)
create mode 100644 src/main/java/org/sopt/week1/TextUtils.java
create mode 100644 src/test/java/TextUtilsTest.java
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index d9b8eb0..a4a3077 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -6,10 +6,6 @@
-
-
-
-
@@ -134,7 +130,7 @@
-
+
diff --git a/src/main/java/org/sopt/week1/DiaryController.java b/src/main/java/org/sopt/week1/DiaryController.java
index df574e1..d738125 100644
--- a/src/main/java/org/sopt/week1/DiaryController.java
+++ b/src/main/java/org/sopt/week1/DiaryController.java
@@ -24,7 +24,7 @@ final List getList() {
}
final void post(final String body) {
- if (body.length() > 30) {
+ if (TextUtils.getLengthOfBody(body) > 30) {
throw new IllegalArgumentException("30자 이하로 적어주세요");
}
diaryService.writeDiary(body);
diff --git a/src/main/java/org/sopt/week1/TextUtils.java b/src/main/java/org/sopt/week1/TextUtils.java
new file mode 100644
index 0000000..750dc0e
--- /dev/null
+++ b/src/main/java/org/sopt/week1/TextUtils.java
@@ -0,0 +1,24 @@
+package org.sopt.week1;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class TextUtils {
+
+ private static final Pattern graphemePattern = Pattern.compile("\\X");
+ private static final Matcher graphemeMatcher = graphemePattern.matcher("");
+
+ public static int getLengthOfBody(final String body) {
+ if (body == null) {
+ return 0;
+ }
+
+ graphemeMatcher.reset(body);
+
+ int count = 0;
+ while (graphemeMatcher.find()) {
+ count++;
+ }
+ return count;
+ }
+}
diff --git a/src/test/java/TextUtilsTest.java b/src/test/java/TextUtilsTest.java
new file mode 100644
index 0000000..aa7d035
--- /dev/null
+++ b/src/test/java/TextUtilsTest.java
@@ -0,0 +1,25 @@
+import org.junit.jupiter.api.*;
+import org.sopt.week1.TextUtils;
+
+@DisplayName("일기 글자 수 세기 테스트")
+@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
+public class TextUtilsTest {
+
+ @Test
+ void 이모지는_한_개의_문자로_인식한다() {
+ //given
+ final String test1 = "😃행복한 하루였어요👍";
+ final String test2 = "🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻🤞🏻";
+ final int expected1 = 11;
+ final int expected2 = 31;
+
+ //when
+ final int actual1 = TextUtils.getLengthOfBody(test1);
+ final int actual2 = TextUtils.getLengthOfBody(test2);
+
+ //then
+ Assertions.assertEquals(actual1, expected1);
+ Assertions.assertEquals(actual2, expected2);
+
+ }
+}
From 7b13befd3c09f86870cfd81834ae1c19d8a34cc0 Mon Sep 17 00:00:00 2001
From: Kim Uijin <127496156+sansan20535@users.noreply.github.com>
Date: Thu, 10 Oct 2024 16:08:48 +0900
Subject: [PATCH 5/5] =?UTF-8?q?[FEAT]=20:=201=EC=B0=A8=20=EC=84=B8?=
=?UTF-8?q?=EB=AF=B8=EB=82=98=20=EA=B3=BC=EC=A0=9C=20=EC=84=A0=ED=83=9D=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EC=95=A0=ED=94=8C=EB=A6=AC=EC=BC=80?=
=?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=A2=85=EB=A3=8C=20=ED=9B=84=20=EC=A0=80?=
=?UTF-8?q?=EC=9E=A5=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/uiDesigner.xml | 124 +++++++++++
.idea/workspace.xml | 41 +++-
diary.txt | 4 +
id.txt | 1 +
.../java/org/sopt/week1/DiaryRepository.java | 206 +++++++++++++++---
src/main/java/org/sopt/week1/TextUtils.java | 7 +
trash.txt | 0
7 files changed, 354 insertions(+), 29 deletions(-)
create mode 100644 .idea/uiDesigner.xml
create mode 100644 diary.txt
create mode 100644 id.txt
create mode 100644 trash.txt
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index a4a3077..a1992c8 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,13 +5,20 @@
+
+
+
+
+
+
+
@@ -72,6 +79,7 @@
-
+
@@ -104,8 +112,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ true
+ false
+ true
+
+
+
@@ -131,6 +164,8 @@
+
+
@@ -148,7 +183,7 @@
-
+
diff --git a/diary.txt b/diary.txt
new file mode 100644
index 0000000..3397f58
--- /dev/null
+++ b/diary.txt
@@ -0,0 +1,4 @@
+1 test
+3 test3
+4 testest
+2 update
diff --git a/id.txt b/id.txt
new file mode 100644
index 0000000..bf0d87a
--- /dev/null
+++ b/id.txt
@@ -0,0 +1 @@
+4
\ No newline at end of file
diff --git a/src/main/java/org/sopt/week1/DiaryRepository.java b/src/main/java/org/sopt/week1/DiaryRepository.java
index 46057da..b96695f 100644
--- a/src/main/java/org/sopt/week1/DiaryRepository.java
+++ b/src/main/java/org/sopt/week1/DiaryRepository.java
@@ -1,60 +1,214 @@
package org.sopt.week1;
+import java.io.*;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
public class DiaryRepository {
- private final Map storage = new ConcurrentHashMap<>();
- private final Map trash = new HashMap<>();
- private final AtomicLong numbering = new AtomicLong();
+ File diaryFile = new File("diary.txt");
+ File idFile = new File("id.txt");
+ File trashFile = new File("trash.txt");
+ File tempFile = new File("tempDiary.txt");
void save(final Diary diary) {
- // 채번 과정
- final long id = numbering.addAndGet(1);
- // 저장 과정
- storage.put(id, diary.getBody());
+
+ long lastId = loadLastId();
+ final long id = lastId + 1;
+
+ try {
+ BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(diaryFile, true));
+
+ if (diaryFile.isFile() && diaryFile.canWrite()) {
+ bufferedWriter.write(id + " " + diary.getBody());
+ bufferedWriter.newLine();
+ bufferedWriter.close();
+ }
+
+ saveLastId(id);
+
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
}
List findAll() {
- // (1) diary를 담을 자료구조
final List diaryList = new ArrayList<>();
- // (2) 저장한 값을 불러오는 반복 구조
- for (long index = 1; index <= numbering.intValue(); index++) {
- final String body = storage.get(index);
- // (2-1) 저장한 값을 불러오는 반복 구조
- if (body != null) {
- diaryList.add(new Diary(index, body));
+
+ try {
+ FileReader fileReader = new FileReader(diaryFile);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+ String diaryFileInfo = "";
+
+ while ((diaryFileInfo = bufferedReader.readLine()) != null) {
+ List diaryInfo = TextUtils.splitDiaryInfo(diaryFileInfo);
+ diaryList.add(new Diary(Long.parseLong(diaryInfo.get(0)), diaryInfo.get(1)));
}
+
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
}
- // (3) 불러온 자료구조를 응답
return diaryList;
}
void deleteById(final Long id) {
isValidateId(id);
- trash.put(id, storage.get(id));
- storage.remove(id);
+ try {
+ // diaryFile에서 삭제할 ID를 제외하고 임시 파일에 저장
+ BufferedWriter tempWriter = new BufferedWriter(new FileWriter(tempFile));
+ BufferedReader diaryReader = new BufferedReader(new FileReader(diaryFile));
+ BufferedWriter trashWriter = new BufferedWriter(new FileWriter(trashFile, true));
+
+ String currentLine;
+ boolean isFound = false;
+
+ while ((currentLine = diaryReader.readLine()) != null) {
+ List diaryInfo = TextUtils.splitDiaryInfo(currentLine);
+ if (diaryInfo.get(0).equals(id.toString())) {
+ // 삭제할 Diary를 trash.txt에 저장
+ trashWriter.write(currentLine);
+ trashWriter.newLine();
+ isFound = true; // ID를 찾았음을 표시
+ } else {
+ tempWriter.write(currentLine);
+ tempWriter.newLine();
+ }
+ }
+
+ tempWriter.close();
+ diaryReader.close();
+ trashWriter.close();
+
+ // ID가 존재했으면 임시 파일을 원본 파일로 대체
+ if (isFound) {
+ diaryFile.delete();
+ tempFile.renameTo(diaryFile);
+ } else {
+ // ID가 존재하지 않을 경우 임시 파일을 삭제
+ tempFile.delete();
+ throw new IllegalArgumentException("해당 ID의 Diary가 존재하지 않습니다.");
+ }
+
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
}
void updateById(final Long id, final String body) {
isValidateId(id);
- storage.replace(id, body);
+ try {
+ BufferedWriter tempWriter = new BufferedWriter(new FileWriter(tempFile));
+ BufferedReader diaryReader = new BufferedReader(new FileReader(diaryFile));
+
+ String currentLine;
+ boolean isFound = false;
+
+ while ((currentLine = diaryReader.readLine()) != null) {
+ List diaryInfo = TextUtils.splitDiaryInfo(currentLine);
+ if (diaryInfo.get(0).equals(id.toString())) {
+ // 수정된 내용으로 기록
+ tempWriter.write(id + " " + body);
+ tempWriter.newLine();
+ isFound = true; // ID를 찾았음을 표시
+ } else {
+ tempWriter.write(currentLine);
+ tempWriter.newLine();
+ }
+ }
+
+ tempWriter.close();
+ diaryReader.close();
+
+ // ID가 존재했으면 임시 파일을 원본 파일로 대체
+ if (isFound) {
+ diaryFile.delete();
+ tempFile.renameTo(diaryFile);
+ } else {
+ // ID가 존재하지 않을 경우 임시 파일을 삭제
+ tempFile.delete();
+ throw new IllegalArgumentException("해당 ID의 Diary가 존재하지 않습니다.");
+ }
+
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
}
void restoreAll() {
- for (Long id : trash.keySet()) {
- storage.put(id, trash.get(id));
+ try {
+ BufferedReader trashReader = new BufferedReader(new FileReader(trashFile));
+ BufferedWriter diaryWriter = new BufferedWriter(new FileWriter(diaryFile, true)); // append mode로 diary.txt에 추가
+
+ String currentLine;
+ boolean isRestored = false;
+
+ while ((currentLine = trashReader.readLine()) != null) {
+ diaryWriter.write(currentLine);
+ diaryWriter.newLine();
+ isRestored = true; // 복원 작업이 있음을 표시
+ }
+
+ trashReader.close();
+ diaryWriter.close();
+
+ // 복원이 완료되었으면 trash.txt 파일 비우기
+ if (isRestored) {
+ BufferedWriter trashCleaner = new BufferedWriter(new FileWriter(trashFile)); // trash.txt 초기화
+ trashCleaner.write("");
+ trashCleaner.close();
+ }
+
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
}
- trash.clear();
}
+
void isValidateId(final Long id) {
- if (storage.get(id) == null) {
+ List diaryIds = new ArrayList();
+
+ try {
+ FileReader fileReader = new FileReader(diaryFile);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+ String diaryFileInfo = "";
+
+
+ while ((diaryFileInfo = bufferedReader.readLine()) != null) {
+ List diaryInfo = TextUtils.splitDiaryInfo(diaryFileInfo);
+ diaryIds.add(Long.parseLong(diaryInfo.get(0)));
+ }
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
+ if (!diaryIds.contains(id)) {
throw new IllegalArgumentException("존재하지 않는 일기 id입니다.");
}
}
+
+ private long loadLastId() {
+ long lastId = 0;
+ if (idFile.exists()) {
+ try {
+ BufferedReader bufferedReader = new BufferedReader(new FileReader(idFile));
+ String idStr = bufferedReader.readLine(); // ID 값을 한 줄로 저장
+ if (idStr != null) {
+ lastId = Long.parseLong(idStr);
+ }
+ bufferedReader.close();
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ return lastId;
+ }
+
+ private void saveLastId(long id) {
+ try {
+ BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(idFile));
+ bufferedWriter.write(Long.toString(id));
+ bufferedWriter.close();
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
}
diff --git a/src/main/java/org/sopt/week1/TextUtils.java b/src/main/java/org/sopt/week1/TextUtils.java
index 750dc0e..6abd078 100644
--- a/src/main/java/org/sopt/week1/TextUtils.java
+++ b/src/main/java/org/sopt/week1/TextUtils.java
@@ -1,5 +1,7 @@
package org.sopt.week1;
+import java.util.ArrayList;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -7,6 +9,7 @@ public class TextUtils {
private static final Pattern graphemePattern = Pattern.compile("\\X");
private static final Matcher graphemeMatcher = graphemePattern.matcher("");
+ private static final String SPLIT_CHARACTERS = " ";
public static int getLengthOfBody(final String body) {
if (body == null) {
@@ -21,4 +24,8 @@ public static int getLengthOfBody(final String body) {
}
return count;
}
+
+ public static List splitDiaryInfo(String diaryInfo) {
+ return new ArrayList(List.of(diaryInfo.split(SPLIT_CHARACTERS)));
+ }
}
diff --git a/trash.txt b/trash.txt
new file mode 100644
index 0000000..e69de29