From 08774261e1c425aa425034bbe6f53a87ebe3d641 Mon Sep 17 00:00:00 2001 From: omegafrog Date: Thu, 19 Dec 2024 17:27:56 +0900 Subject: [PATCH 1/6] initial commit --- .gitignore | 46 ++++ build.gradle | 20 ++ gradlew | 234 ++++++++++++++++++ gradlew.bat | 89 +++++++ settings.gradle | 2 + src/main/java/org/example/App.java | 52 ++++ src/main/java/org/example/Main.java | 18 ++ src/main/java/org/example/Page.java | 50 ++++ src/main/java/org/example/WiseSaying.java | 46 ++++ .../org/example/WiseSayingController.java | 121 +++++++++ .../org/example/WiseSayingRepository.java | 225 +++++++++++++++++ .../java/org/example/WiseSayingService.java | 40 +++ src/test/java/org/example/AppTest.java | 145 +++++++++++ src/test/java/org/example/TestUtil.java | 32 +++ 14 files changed, 1120 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/main/java/org/example/App.java create mode 100644 src/main/java/org/example/Main.java create mode 100644 src/main/java/org/example/Page.java create mode 100644 src/main/java/org/example/WiseSaying.java create mode 100644 src/main/java/org/example/WiseSayingController.java create mode 100644 src/main/java/org/example/WiseSayingRepository.java create mode 100644 src/main/java/org/example/WiseSayingService.java create mode 100644 src/test/java/org/example/AppTest.java create mode 100644 src/test/java/org/example/TestUtil.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a89d63b --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store +.idea/ +gradle/ +build +db/WiseSaying \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..1e83663 --- /dev/null +++ b/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'java' +} + +group = 'org.example' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation("org.assertj:assertj-core:3.26.3") +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..1b6c787 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..4262c21 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'refactoredDevCorse' + diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java new file mode 100644 index 0000000..c9bcce8 --- /dev/null +++ b/src/main/java/org/example/App.java @@ -0,0 +1,52 @@ +package org.example; + +import java.util.Scanner; + +import static java.lang.System.exit; + +public class App { + private final WiseSayingController controller; + private final Scanner scanner; + + public App(WiseSayingController controller, Scanner scanner) { + this.controller = controller; + this.scanner = scanner; + } + + public void run(){ + System.out.println("== 명언 앱 == "); + while(true){ + System.out.print("명령) "); + // 임시방편 처리. 스캐너의 입력이 비어있는 채로 nextLine을 만나면 오류를 뱉어서 + // 입력 버퍼가 비었으면 출력 버퍼를 다 비우고 종료시킴 + if(!scanner.hasNextLine()){ + System.out.flush(); + return; + } + String input = scanner.nextLine(); + + + String[] split = input.split("\\?"); + String operator = split[0]; + String parameter = ""; + if(split.length == 2) + parameter = split[1]; + + switch (operator) { + case "종료" -> controller.exit(); + case "등록" -> controller.create(); + case "목록" -> { + if( parameter.length() > 0){ + controller.findBy(parameter); + break; + } + controller.readAll(1); + } + case "삭제" -> controller.delete(parameter); + case "수정" -> controller.update(parameter); + case "빌드" -> controller.build(); + default -> throw new IllegalArgumentException("Unknown operator: " + input); + } + } + } +} diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java new file mode 100644 index 0000000..39a2a72 --- /dev/null +++ b/src/main/java/org/example/Main.java @@ -0,0 +1,18 @@ +package org.example; + +import java.util.Scanner; + +public class Main { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + App app = new App(controller, scanner); + try { + app.run(); + }catch (RuntimeException e){ + System.out.println(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/example/Page.java b/src/main/java/org/example/Page.java new file mode 100644 index 0000000..c0855de --- /dev/null +++ b/src/main/java/org/example/Page.java @@ -0,0 +1,50 @@ +package org.example; + +import java.util.ArrayList; +import java.util.List; + +public class Page { + + private final List contents; + private final int pageSize; + private final int totalElementCount; + private int pageNum; + private final int totalPage; + + + public Page(List contents, int totalElementCount, int pageSize, int pageNum) { + this.totalElementCount = totalElementCount; + this.pageSize = pageSize; + this.contents = contents; + if(totalElementCount > pageSize){ + if(totalElementCount % pageSize >0){ + this.totalPage = totalElementCount / pageSize + 1; + } + else{ + this.totalPage = totalElementCount / pageSize; + } + }else{ + this.totalPage = 1; + } + this.pageNum = pageNum; + } + + public List getContents() { + return contents; + } + + + public String toString(){ + StringBuffer sb = new StringBuffer(); + sb.append("페이지 : "); + for(int i = 1; i <= totalPage; i+=1){ + if(i==pageNum) + sb.append("["+i+"]"); + else + sb.append(i); + if(i all = service.findAll(); + + printResult(all, pageNum ); + } + + private static void printResult(List all, int pageNum) { + System.out.println("번호 / 작가 / 명언"); + System.out.println("----------------------"); +// for (WiseSaying quote : all) { +// System.out.println(quote.getId()+" / "+quote.getAuthor()+" / "+quote.getContent()); +// } + List sorted = all.stream().sorted(Comparator.comparing(WiseSaying::getId).reversed()).toList(); + + + int fromIdx = (pageNum-1)*5; + int toIdx = Math.min((pageNum) * 5, sorted.size()); + Page paged = new Page(sorted.subList(fromIdx, toIdx), sorted.size(), 5, pageNum); + for (WiseSaying ws : paged.getContents()) { + System.out.println(ws.getId()+" / "+ws.getAuthor()+" / "+ws.getContent()); + } + System.out.println(paged); + + } + + + public void delete(String parameter) { + String[] parsedSplit = parameter.split("\\="); + int id = Integer.parseInt(parsedSplit[1]); + service.remove(id); + System.out.println(id+"번 명언이 삭제되었습니다."); + } + + public void update(String parameter) { + // parse parameter + String[] split = parameter.split("="); + if (split.length == 1) throw new IllegalArgumentException("Wrong parameter:" + parameter); + int id = Integer.parseInt(split[1]); + + //get quote + WiseSaying wiseSaying = service.find(id); + System.out.println("명언(기존) : "+wiseSaying.getContent() ); + System.out.print("명언 : "); + String changedContent = scanner.nextLine(); + + System.out.println("작가(기존) : "+wiseSaying.getAuthor() ); + System.out.print("작가 : "); + String changedAuthor = scanner.nextLine(); + + wiseSaying.update(changedContent, changedAuthor); + service.update(id, wiseSaying); + } + + public void build() { + service.build(); + System.out.println("data.json 파일의 내용이 갱신되었습니다."); + } + + public void findBy(String parameter) { + String[] parsedParams = parameter.split("&"); + String type = ""; + String word = ""; + int page = 1; + for(String param : parsedParams){ + String operator = param.split("=")[0].trim(); + String operand = param.split("=")[1].trim(); + if(operator.equals("keywordType")) + type = operand; + if(operator.equals("keyword")) + word = operand; + if(operator.equals("page")) + page = Integer.parseInt(operand); + } + + if(type.isEmpty() && word.isEmpty()){ + List all = service.findAll(); + printResult(all, page); + }else{ + System.out.println("----------------"); + System.out.println("검색타입 : " + type); + System.out.println("검색어 : " + word); + System.out.println("----------------"); + List founded = service.findBy(type, word); + printResult(founded, page); + } + + } +} diff --git a/src/main/java/org/example/WiseSayingRepository.java b/src/main/java/org/example/WiseSayingRepository.java new file mode 100644 index 0000000..239fc70 --- /dev/null +++ b/src/main/java/org/example/WiseSayingRepository.java @@ -0,0 +1,225 @@ +package org.example; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Stream; + +public class WiseSayingRepository { + + private static final String BASE_PATH = "db/wiseSaying/"; + + public WiseSaying insert(WiseSaying element) { + if(!element.validate()) + throw new IllegalArgumentException("특수문자가 포함되면 안됩니다."); + int id = getLastId()+1; + element.setId(id); + + serialize(element, id); + return element; + } + + public List findAll() { + List quotes = new ArrayList<>(); + + try(Stream paths = Files.list(Paths.get(BASE_PATH))){ + List list = paths.toList(); + for(Path path : list){ + if(path.toString().endsWith(".json") && !path.toString().endsWith("build.json")){ + quotes.add(deserialize(path.toString())); + } + } + }catch (IOException e){} + return quotes; + } + + public List findAll(int pageNum) { + List quotes = new ArrayList<>(); + + try(Stream paths = Files.list(Paths.get(BASE_PATH))){ + List list = paths.toList(); + for(Path path : list){ + if(path.toString().endsWith(".json") && !path.toString().endsWith("build.json")){ + quotes.add(deserialize(path.toString())); + } + } + }catch (IOException e){} + quotes.sort(new Comparator() { + @Override + public int compare(WiseSaying o1, WiseSaying o2) { + return Integer.compare(o1.getId(), o2.getId()); + } + }); + int fromIdx = pageNum*5; + int toIdx = (pageNum+1)*5 paths = Files.list(Paths.get(BASE_PATH))){ + List list = paths.filter( + path -> path.toString().endsWith(".json") && !path.toString().endsWith("build.json") + ).toList(); + // 파일명이 .json으로 끝나고 build.json이 아닌 파일들의 내용을 모두 빌드 파일 객체 writer에 씀 + for(int i = 0; i < list.size(); i++){ + Path path = list.get(i); + File entityFile = new File(path.toString()); + StringBuffer buffer = new StringBuffer(); + + try(BufferedReader entityReaderBuffer = new BufferedReader(new FileReader(entityFile))){ + entityReaderBuffer.lines().forEach(line -> { + buffer.append("\t").append(line); + if(!line.equals("}")) + buffer.append("\n"); + }); + } + if(i findBy(String type, String word) { + return findAll().stream().filter( + ws -> { + if (type.equals("content")) { + return ws.getContent().contains(word); + } else if (type.equals("author")) { + return ws.getAuthor().contains(word); + } + return false; + } + ).toList(); + } + + private static int getLastId(File file) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(file)); + String s = br.readLine(); + int id = Integer.parseInt(s); + br.close(); + return id; + } + private static void createLastIdFile(File file, int id) throws IOException { + file.createNewFile(); + FileWriter bw = new FileWriter(file); + bw.write(String.valueOf(id)); + bw.close(); + } + private void serialize(WiseSaying element, int id) { + String filePath = BASE_PATH + id + ".json"; + try{ + File file = new File(filePath); + file.createNewFile(); + + FileWriter writer = new FileWriter(file); + writer.write(toJson(element)); + writer.close(); + }catch (IOException e){ + e.printStackTrace(); + } + + String idPath = BASE_PATH+"lastId.txt"; + File file = new File(idPath); + try(FileWriter fw = new FileWriter(file)){ + fw.write(String.valueOf(id)); + }catch (IOException e){ + e.printStackTrace(); + } + } + private String toJson(WiseSaying e){ + return "{\n" + + "\t\"id\": "+e.getId()+",\n"+ + "\t\"content\": "+"\""+e.getContent()+"\""+",\n"+ + "\t\"author\": "+"\""+e.getAuthor()+"\"\n"+ + "}"; + } + private WiseSaying deserialize(String path) { + try{ + File file = new File(path); + try(BufferedReader br = new BufferedReader(new FileReader(file))) { + StringBuffer buffer = new StringBuffer(); + br.lines().forEach( + line -> buffer.append(line).append("\n") + ); + String s = buffer.toString(); + br.close(); + return parseJson(s); + } + }catch (IOException e){ + e.printStackTrace(); + return null; + } + } + private WiseSaying parseJson(String json){ + String s = json.replaceAll("\t", "") + .replaceAll("\n", ""); + String[] split = s.substring(1, s.length() - 1).split(","); + int id = Integer.parseInt(String.valueOf(split[0]).split(":")[1].strip()); + String content = String.valueOf(split[1]).split(":")[1].strip(); + String author = String.valueOf(split[2]).split(":")[1].strip(); + return new WiseSaying(id, content, author); + } + + +} + + diff --git a/src/main/java/org/example/WiseSayingService.java b/src/main/java/org/example/WiseSayingService.java new file mode 100644 index 0000000..c840dae --- /dev/null +++ b/src/main/java/org/example/WiseSayingService.java @@ -0,0 +1,40 @@ +package org.example; + +import java.util.List; + +public class WiseSayingService { + private final WiseSayingRepository repository; + + public WiseSayingService(WiseSayingRepository repository) { + this.repository = repository; + } + + public WiseSaying create(String content, String author) { + WiseSaying lifeQuote = new WiseSaying(content, author); + return repository.insert(lifeQuote); + } + + public List findAll() { + return repository.findAll(); + } + + public void remove(int id) { + repository.remove(id); + } + + public WiseSaying find(int id) { + return repository.find(id); + } + + public void update(int id, WiseSaying wiseSaying) { + repository.update(id, wiseSaying); + } + + public void build() { + repository.build(); + } + + public List findBy(String type, String word) { + return repository.findBy(type, word); + } +} diff --git a/src/test/java/org/example/AppTest.java b/src/test/java/org/example/AppTest.java new file mode 100644 index 0000000..6988471 --- /dev/null +++ b/src/test/java/org/example/AppTest.java @@ -0,0 +1,145 @@ +package org.example; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Scanner; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class AppTest { + private ByteArrayOutputStream outputStream; + @BeforeEach + void setUp() throws IOException { + Stream list = Files.list(Path.of("db/WiseSaying")); + list.forEach(file -> file.toFile().delete()); + outputStream = TestUtil.setOutToByteArray(); + } + @AfterEach + void tearDown() { + TestUtil.clearSetOutToByteArray(outputStream); + } + + @Test + void addTest(){ + Scanner scanner = TestUtil.genScanner(""" + 등록 + 너 자신을 알라 + 플라톤 + """); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + App app = new App(controller, scanner); + app.run(); + assertThat(outputStream.toString()) + .contains("명언 :") + .contains("작가 :") + .contains("1번 명언이 등록되었습니다."); + } + + @Test + void readAllTest(){ + String no1 = "1"; + String content1 = "\"너 자신을 알라\""; + String author1 = "\"플라톤\""; + Scanner scanner = TestUtil.genScanner(""" + 등록 + 너 자신을 알라 + 플라톤 + 목록 + """); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + + App app = new App(controller, scanner); + app.run(); + + assertThat(outputStream.toString()) + .contains("명령) 명언 : 작가 : 1번 명언이 등록되었습니다.") + .contains("번호 / 작가 / 명언") + .contains("----------------------") + .contains(no1 + " / " + author1 + " / " + content1); + } + + @Test + void deleteTest(){ + Scanner scanner = TestUtil.genScanner(""" + 등록 + 너 자신을 알라 + 플라톤 + 삭제?id=1 + """); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + + App app = new App(controller, scanner); + app.run(); + assertThat(outputStream.toString()) + .contains("1번 명언이 삭제되었습니다."); + } + + @Test + void updateTest(){ + Scanner scanner = TestUtil.genScanner(""" + 등록 + 너 자신을 알라 + 플라톤 + 수정?id=1 + 너 자신을 몰라도 된다 + 플라리스 + 목록 + """); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + + App app = new App(controller, scanner); + app.run(); + assertThat(outputStream.toString()) + .contains("번호 / 작가 / 명언") + .contains("----------------------") + .contains(1 + " / " + "\"플라리스\"" + " / " + "\"너 자신을 몰라도 된다\""); + } + + @Test + void buildTest() throws IOException { + Scanner scanner = TestUtil.genScanner(""" + 등록 + 너 자신을 알라 + 플라톤 + 등록 + 너 자신을 알라2 + 플라톤2 + 빌드 + """); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + + App app = new App(controller, scanner); + app.run(); + assertThat(outputStream.toString()) + .contains("data.json 파일의 내용이 갱신되었습니다."); + File file = new File("db/WiseSaying/build.json"); + assertThat(file.exists()).isTrue(); + BufferedReader reader = new BufferedReader(new FileReader(file)); + String s = reader.lines().collect(Collectors.joining("\n")); + assertThat(s).contains("\"id\": 1") + .contains("\"content\": \"너 자신을 알라\"") + .contains("\"author\": \"플라톤\"") + .contains("\"id\": 2") + .contains("\"content\": \"너 자신을 알라2\"") + .contains("\"author\": \"플라톤2\""); + } +} \ No newline at end of file diff --git a/src/test/java/org/example/TestUtil.java b/src/test/java/org/example/TestUtil.java new file mode 100644 index 0000000..e742780 --- /dev/null +++ b/src/test/java/org/example/TestUtil.java @@ -0,0 +1,32 @@ +package org.example; + +import java.io.*; +import java.util.Scanner; + +public class TestUtil { + // gen == generate 생성하다. + // 테스트용 스캐너 생성 + public static Scanner genScanner(final String input) { + final InputStream in = new ByteArrayInputStream(input.getBytes()); + + return new Scanner(in); + } + + // System.out의 출력을 스트림으로 받기 + public static ByteArrayOutputStream setOutToByteArray() { + final ByteArrayOutputStream output = new ByteArrayOutputStream(); + System.setOut(new PrintStream(output)); + + return output; + } + + // setOutToByteArray 함수의 사용을 완료한 후 정리하는 함수, 출력을 다시 정상화 하는 함수 + public static void clearSetOutToByteArray(final ByteArrayOutputStream output) { + System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); + try { + output.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file From b41b6446e63e40ed31224f7f13e348c1ffb6d7a9 Mon Sep 17 00:00:00 2001 From: omegafrog Date: Fri, 20 Dec 2024 10:00:21 +0900 Subject: [PATCH 2/6] =?UTF-8?q?refact=20:=20app=20routing=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화드코딩된 명령어를 enum 사용해 ide도움 받을 수 있도록 수정함. parameter parsing을 app에서 전체적으로 수행해 controller에는 실제로 사용할 타입의 값만 넘어갈 수 있도록 수정 parameter parsing중에 하드코딩된 분리자 (?, &)와 파라미터 key값을 enum으로 변경 --- src/main/java/org/example/App.java | 115 +++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index c9bcce8..b08278e 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -1,18 +1,68 @@ package org.example; +import java.util.HashMap; +import java.util.Map; import java.util.Scanner; -import static java.lang.System.exit; - public class App { private final WiseSayingController controller; private final Scanner scanner; + private enum COMMAND{ + EXIT("종료"), + CREATE("등록"), + LIST("목록"), + DELETE("삭제"), + UPDATE("수정"), + BUILD("빌드") + ; + String name; + COMMAND(String name) { + this.name = name; + } + + static COMMAND of(String name){ + switch (name){ + case "등록" -> { + return COMMAND.CREATE; + } + case "종료" -> { + return COMMAND.EXIT; + } + case "목록" -> { + return COMMAND.LIST; + } + case "수정" -> { + return COMMAND.UPDATE; + } + case "빌드" -> { + return COMMAND.BUILD; + } + case "삭제" -> { + return COMMAND.DELETE; + } + default -> throw new IllegalArgumentException("Unknown command: " + name); + } + } + } + + public enum PARAMETERS{ + KEYWORD_TYPE("keywordType"),KEYWORD("keyword"),PAGE_NUM("page"), + ID("id"), OPERATOR_SPLITTER("\\?"),PARAMETER_SPLITTER("&"), PARAMETER_VALUE_SPLITTER("="),; + String value; + PARAMETERS(String value) { + this.value = value; + } + } + public App(WiseSayingController controller, Scanner scanner) { this.controller = controller; this.scanner = scanner; } + /** + * 사용자로부터 명령 입력을 받아 세부 로직으로 라우팅함. + */ public void run(){ System.out.println("== 명언 앱 == "); while(true){ @@ -25,28 +75,51 @@ public void run(){ } String input = scanner.nextLine(); + Map parsedParameterMap = getParsedParameterMap(input); + COMMAND operator = COMMAND.of(parsedParameterMap.get("operator")); - String[] split = input.split("\\?"); - String operator = split[0]; - String parameter = ""; - if(split.length == 2) - parameter = split[1]; + route(operator, parsedParameterMap, input); + } + } - switch (operator) { - case "종료" -> controller.exit(); - case "등록" -> controller.create(); - case "목록" -> { - if( parameter.length() > 0){ - controller.findBy(parameter); - break; - } - controller.readAll(1); - } - case "삭제" -> controller.delete(parameter); - case "수정" -> controller.update(parameter); - case "빌드" -> controller.build(); - default -> throw new IllegalArgumentException("Unknown operator: " + input); + private void route(COMMAND operator, Map parsedParameterMap, String input) { + switch (operator) { + case EXIT -> controller.exit(); + case CREATE -> controller.create(); + case LIST -> { + if(parsedParameterMap.containsKey("keywordType") && parsedParameterMap.containsKey("keyword")) + controller.search(parsedParameterMap.get("keywordType"), + parsedParameterMap.get("keyword"), + Integer.parseInt(parsedParameterMap.get("page"))); + else + controller.readAll(Integer.parseInt(parsedParameterMap.get("page"))); } + case DELETE -> controller.delete(Integer.parseInt(parsedParameterMap.get(PARAMETERS.ID.value))); + case UPDATE -> controller.update(Integer.parseInt(parsedParameterMap.get(PARAMETERS.ID.value))); + case BUILD -> controller.build(); } } + + private static Map getParsedParameterMap(String input){ + Map parameterMap = new HashMap<>(); + parameterMap.put(PARAMETERS.PAGE_NUM.value, "1"); + + + String[] split = input.split(PARAMETERS.OPERATOR_SPLITTER.value); + String operator = split[0]; + parameterMap.put("operator",operator); + + String parameter = split.length == 2?split[1]:""; + + if(parameter.isEmpty()) + return parameterMap; + String[] parsedParams = parameter.split(PARAMETERS.PARAMETER_SPLITTER.value); + + for(String param : parsedParams) + parameterMap.put(param.split( + PARAMETERS.PARAMETER_VALUE_SPLITTER.value)[0], + param.split(PARAMETERS.PARAMETER_VALUE_SPLITTER.value)[1]); + + return parameterMap; + } } From 06952cb765015546d9b8d4dcbcd297ecf2c1d544 Mon Sep 17 00:00:00 2001 From: omegafrog Date: Fri, 20 Dec 2024 10:38:27 +0900 Subject: [PATCH 3/6] =?UTF-8?q?refact=20:=20page=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=EB=A5=BC=20=EB=A6=AC=ED=84=B4=ED=95=98=EB=8F=84=EB=A1=9D=20rep?= =?UTF-8?q?ository=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit page 클래스를 생성하고 service가 page 객체를 리턴하고 이 page 객체를 controller에서 출력하도록 변경함. --- src/main/java/org/example/Page.java | 9 +-- .../org/example/WiseSayingController.java | 75 ++++--------------- .../java/org/example/WiseSayingService.java | 12 +++ src/test/java/org/example/AppTest.java | 17 ++--- 4 files changed, 37 insertions(+), 76 deletions(-) diff --git a/src/main/java/org/example/Page.java b/src/main/java/org/example/Page.java index c0855de..485b5ea 100644 --- a/src/main/java/org/example/Page.java +++ b/src/main/java/org/example/Page.java @@ -1,6 +1,5 @@ package org.example; -import java.util.ArrayList; import java.util.List; public class Page { @@ -8,10 +7,9 @@ public class Page { private final List contents; private final int pageSize; private final int totalElementCount; - private int pageNum; + private final int pageNum; private final int totalPage; - public Page(List contents, int totalElementCount, int pageSize, int pageNum) { this.totalElementCount = totalElementCount; this.pageSize = pageSize; @@ -27,6 +25,7 @@ public Page(List contents, int totalElementCount, int pageSize, int this.totalPage = 1; } this.pageNum = pageNum; + } public List getContents() { @@ -35,11 +34,11 @@ public List getContents() { public String toString(){ - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("페이지 : "); for(int i = 1; i <= totalPage; i+=1){ if(i==pageNum) - sb.append("["+i+"]"); + sb.append("[").append(i).append("]"); else sb.append(i); if(i all = service.findAll(); - - printResult(all, pageNum ); + Page all = service.findAllByPage(pageNum); + printResult(all); } - private static void printResult(List all, int pageNum) { - System.out.println("번호 / 작가 / 명언"); - System.out.println("----------------------"); -// for (WiseSaying quote : all) { -// System.out.println(quote.getId()+" / "+quote.getAuthor()+" / "+quote.getContent()); -// } - List sorted = all.stream().sorted(Comparator.comparing(WiseSaying::getId).reversed()).toList(); - - - int fromIdx = (pageNum-1)*5; - int toIdx = Math.min((pageNum) * 5, sorted.size()); - Page paged = new Page(sorted.subList(fromIdx, toIdx), sorted.size(), 5, pageNum); - for (WiseSaying ws : paged.getContents()) { - System.out.println(ws.getId()+" / "+ws.getAuthor()+" / "+ws.getContent()); - } - System.out.println(paged); - - } - - - public void delete(String parameter) { - String[] parsedSplit = parameter.split("\\="); - int id = Integer.parseInt(parsedSplit[1]); + public void delete(int id) { service.remove(id); System.out.println(id+"번 명언이 삭제되었습니다."); } - public void update(String parameter) { - // parse parameter - String[] split = parameter.split("="); - if (split.length == 1) throw new IllegalArgumentException("Wrong parameter:" + parameter); - int id = Integer.parseInt(split[1]); - + public void update(int id) { //get quote WiseSaying wiseSaying = service.find(id); System.out.println("명언(기존) : "+wiseSaying.getContent() ); @@ -89,33 +57,20 @@ public void build() { System.out.println("data.json 파일의 내용이 갱신되었습니다."); } - public void findBy(String parameter) { - String[] parsedParams = parameter.split("&"); - String type = ""; - String word = ""; - int page = 1; - for(String param : parsedParams){ - String operator = param.split("=")[0].trim(); - String operand = param.split("=")[1].trim(); - if(operator.equals("keywordType")) - type = operand; - if(operator.equals("keyword")) - word = operand; - if(operator.equals("page")) - page = Integer.parseInt(operand); - } - - if(type.isEmpty() && word.isEmpty()){ - List all = service.findAll(); - printResult(all, page); - }else{ + public void search(String keywordType, String keyword, int pageNum) { System.out.println("----------------"); - System.out.println("검색타입 : " + type); - System.out.println("검색어 : " + word); + System.out.println("검색타입 : " + keywordType); + System.out.println("검색어 : " + keyword); System.out.println("----------------"); - List founded = service.findBy(type, word); - printResult(founded, page); + Page founded = service.findByPage(keywordType, keyword, pageNum); + printResult(founded); } + private static void printResult(Page page) { + System.out.println("번호 / 작가 / 명언"); + System.out.println("----------------------"); + for (WiseSaying ws : page.getContents()) + System.out.println(ws.getId()+" / "+ws.getAuthor()+" / "+ws.getContent()); + System.out.println(page); } } diff --git a/src/main/java/org/example/WiseSayingService.java b/src/main/java/org/example/WiseSayingService.java index c840dae..f5d2dd4 100644 --- a/src/main/java/org/example/WiseSayingService.java +++ b/src/main/java/org/example/WiseSayingService.java @@ -17,6 +17,12 @@ public WiseSaying create(String content, String author) { public List findAll() { return repository.findAll(); } + public Page findAllByPage(int pageNum) { + List res = repository.findAll(); + int fromIdx = (pageNum-1)*5; + int toIdx = Math.min((pageNum) * 5,res.size()); + return new Page(res.subList(fromIdx, toIdx), res.size(), 5, pageNum); + } public void remove(int id) { repository.remove(id); @@ -37,4 +43,10 @@ public void build() { public List findBy(String type, String word) { return repository.findBy(type, word); } + public Page findByPage(String type, String word, int pageNum){ + List res = repository.findBy(type, word); + int fromIdx = (pageNum-1)*5; + int toIdx = Math.min((pageNum) * 5,res.size()); + return new Page(res.subList(fromIdx, toIdx), res.size(), 5, pageNum); + } } diff --git a/src/test/java/org/example/AppTest.java b/src/test/java/org/example/AppTest.java index 6988471..6efe05c 100644 --- a/src/test/java/org/example/AppTest.java +++ b/src/test/java/org/example/AppTest.java @@ -1,7 +1,6 @@ package org.example; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,15 +12,15 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; class AppTest { private ByteArrayOutputStream outputStream; @BeforeEach void setUp() throws IOException { - Stream list = Files.list(Path.of("db/WiseSaying")); - list.forEach(file -> file.toFile().delete()); - outputStream = TestUtil.setOutToByteArray(); + try(Stream list = Files.list(Path.of("db/WiseSaying"))){ + list.forEach(file -> file.toFile().delete()); + outputStream = TestUtil.setOutToByteArray(); + } } @AfterEach void tearDown() { @@ -51,12 +50,8 @@ void readAllTest(){ String no1 = "1"; String content1 = "\"너 자신을 알라\""; String author1 = "\"플라톤\""; - Scanner scanner = TestUtil.genScanner(""" - 등록 - 너 자신을 알라 - 플라톤 - 목록 - """); + Scanner scanner = TestUtil.genScanner("등록\n너 자신을 알라\n플라톤\n목록\n"); + WiseSayingRepository repository = new WiseSayingRepository(); WiseSayingService service = new WiseSayingService(repository); WiseSayingController controller = new WiseSayingController(scanner, service); From fcc987ef0aad5c62c16b66028d46f053cc24f200 Mon Sep 17 00:00:00 2001 From: omegafrog Date: Fri, 20 Dec 2024 12:12:08 +0900 Subject: [PATCH 4/6] =?UTF-8?q?refact=20:=20=EC=A4=91=EB=B3=B5=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/example/WiseSayingRepository.java | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/example/WiseSayingRepository.java b/src/main/java/org/example/WiseSayingRepository.java index 239fc70..991d5e7 100644 --- a/src/main/java/org/example/WiseSayingRepository.java +++ b/src/main/java/org/example/WiseSayingRepository.java @@ -27,26 +27,18 @@ public List findAll() { List quotes = new ArrayList<>(); try(Stream paths = Files.list(Paths.get(BASE_PATH))){ - List list = paths.toList(); - for(Path path : list){ - if(path.toString().endsWith(".json") && !path.toString().endsWith("build.json")){ - quotes.add(deserialize(path.toString())); - } - } + getEntityFilePathList(paths).forEach(path -> quotes.add(deserialize(path.toString()))); }catch (IOException e){} return quotes; } + @Deprecated public List findAll(int pageNum) { List quotes = new ArrayList<>(); try(Stream paths = Files.list(Paths.get(BASE_PATH))){ - List list = paths.toList(); - for(Path path : list){ - if(path.toString().endsWith(".json") && !path.toString().endsWith("build.json")){ - quotes.add(deserialize(path.toString())); - } - } + getEntityFilePathList(paths) + .forEach(path -> quotes.add(deserialize(path.toString()))); }catch (IOException e){} quotes.sort(new Comparator() { @Override @@ -59,6 +51,13 @@ public int compare(WiseSaying o1, WiseSaying o2) { return quotes.subList(fromIdx, toIdx); } + private List getEntityFilePathList(Stream paths) { + List list = paths.toList(); + return list.stream() + .filter(path -> path.toString().endsWith(".json") && !path.toString().endsWith("build.json")) + .toList(); + } + private static int getLastId() { int id = 0; String idPath = BASE_PATH+"lastId.txt"; @@ -105,39 +104,31 @@ public void build() { // 빌드 파일 객체 생성 File file = new File(BASE_PATH + "build.json"); // 빌드 파일 객체 writer 생성 - try(FileWriter buildFileWriter = new FileWriter(file)){ - buildFileWriter.write("[\n"); + try(FileWriter resultFileWriter = new FileWriter(file)){ + resultFileWriter.write("[\n"); // 디렉토리 내부 파일명 모두 파싱 try(Stream paths = Files.list(Paths.get(BASE_PATH))){ - List list = paths.filter( - path -> path.toString().endsWith(".json") && !path.toString().endsWith("build.json") - ).toList(); // 파일명이 .json으로 끝나고 build.json이 아닌 파일들의 내용을 모두 빌드 파일 객체 writer에 씀 - for(int i = 0; i < list.size(); i++){ - Path path = list.get(i); - File entityFile = new File(path.toString()); - StringBuffer buffer = new StringBuffer(); - - try(BufferedReader entityReaderBuffer = new BufferedReader(new FileReader(entityFile))){ + StringBuilder builder = new StringBuilder(); + for(Path validPath : getEntityFilePathList(paths)){ + try(BufferedReader entityReaderBuffer = new BufferedReader(new FileReader(validPath.toFile()))){ entityReaderBuffer.lines().forEach(line -> { - buffer.append("\t").append(line); - if(!line.equals("}")) - buffer.append("\n"); + builder.append("\t").append(line); + builder.append("\n"); }); + builder.deleteCharAt(builder.length()-1); } - if(i findBy(String type, String word) { return findAll().stream().filter( ws -> { From 032f909c1e6243ab54ee68421019e270cf479b3b Mon Sep 17 00:00:00 2001 From: omegafrog Date: Fri, 20 Dec 2024 12:12:41 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat=20:=20exception=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exception을 모두 app까지 던지고 app에서 공통 처리. --- src/main/java/org/example/App.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index b08278e..2903428 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -78,7 +78,11 @@ public void run(){ Map parsedParameterMap = getParsedParameterMap(input); COMMAND operator = COMMAND.of(parsedParameterMap.get("operator")); - route(operator, parsedParameterMap, input); + try{ + route(operator, parsedParameterMap, input); + }catch (RuntimeException e){ + System.out.println(e.getMessage()); + } } } From 29cf9ae44711b8679cc5ed42ec7b6c0bd1ae8612 Mon Sep 17 00:00:00 2001 From: omegafrog Date: Fri, 20 Dec 2024 12:13:14 +0900 Subject: [PATCH 6/6] =?UTF-8?q?test=20:=20=EC=8B=A4=ED=8C=A8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B0=8F=20=EA=B2=80=EC=83=89=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8,=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/org/example/AppTest.java | 147 +++++++++++++++++++------ 1 file changed, 116 insertions(+), 31 deletions(-) diff --git a/src/test/java/org/example/AppTest.java b/src/test/java/org/example/AppTest.java index 6efe05c..81bb6d6 100644 --- a/src/test/java/org/example/AppTest.java +++ b/src/test/java/org/example/AppTest.java @@ -29,35 +29,36 @@ void tearDown() { @Test void addTest(){ - Scanner scanner = TestUtil.genScanner(""" + prepare(""" 등록 너 자신을 알라 플라톤 """); - WiseSayingRepository repository = new WiseSayingRepository(); - WiseSayingService service = new WiseSayingService(repository); - WiseSayingController controller = new WiseSayingController(scanner, service); - App app = new App(controller, scanner); - app.run(); + assertThat(outputStream.toString()) .contains("명언 :") .contains("작가 :") .contains("1번 명언이 등록되었습니다."); } + @Test + void validationTest(){ + prepare(""" + 등록 + 너 자신을 알라? + 플라톤 + """); + assertThat(outputStream.toString()) + .contains("특수문자가 포함되면 안됩니다."); + } + @Test void readAllTest(){ String no1 = "1"; String content1 = "\"너 자신을 알라\""; String author1 = "\"플라톤\""; - Scanner scanner = TestUtil.genScanner("등록\n너 자신을 알라\n플라톤\n목록\n"); + prepare("등록\n너 자신을 알라\n플라톤\n목록\n"); - WiseSayingRepository repository = new WiseSayingRepository(); - WiseSayingService service = new WiseSayingService(repository); - WiseSayingController controller = new WiseSayingController(scanner, service); - - App app = new App(controller, scanner); - app.run(); assertThat(outputStream.toString()) .contains("명령) 명언 : 작가 : 1번 명언이 등록되었습니다.") @@ -68,25 +69,33 @@ void readAllTest(){ @Test void deleteTest(){ - Scanner scanner = TestUtil.genScanner(""" + prepare(""" 등록 너 자신을 알라 플라톤 삭제?id=1 """); - WiseSayingRepository repository = new WiseSayingRepository(); - WiseSayingService service = new WiseSayingService(repository); - WiseSayingController controller = new WiseSayingController(scanner, service); - App app = new App(controller, scanner); - app.run(); assertThat(outputStream.toString()) .contains("1번 명언이 삭제되었습니다."); } + @Test + void deleteFailTest(){ + prepare(""" + 등록 + 너 자신을 알라 + 플라톤 + 삭제?id=2 + """); + assertThat(outputStream.toString()) + .contains("2번 명언은 존재하지 않습니다."); + } + + @Test void updateTest(){ - Scanner scanner = TestUtil.genScanner(""" + prepare(""" 등록 너 자신을 알라 플라톤 @@ -95,21 +104,28 @@ void updateTest(){ 플라리스 목록 """); - WiseSayingRepository repository = new WiseSayingRepository(); - WiseSayingService service = new WiseSayingService(repository); - WiseSayingController controller = new WiseSayingController(scanner, service); - App app = new App(controller, scanner); - app.run(); assertThat(outputStream.toString()) .contains("번호 / 작가 / 명언") .contains("----------------------") .contains(1 + " / " + "\"플라리스\"" + " / " + "\"너 자신을 몰라도 된다\""); } + @Test + void updateFailTest(){ + prepare(""" + 등록 + 너 자신을 알라 + 플라톤 + 수정?id=2 + """); + assertThat(outputStream.toString()) + .contains("2번 명언은 존재하지 않습니다."); + } + @Test void buildTest() throws IOException { - Scanner scanner = TestUtil.genScanner(""" + prepare(""" 등록 너 자신을 알라 플라톤 @@ -118,12 +134,7 @@ void buildTest() throws IOException { 플라톤2 빌드 """); - WiseSayingRepository repository = new WiseSayingRepository(); - WiseSayingService service = new WiseSayingService(repository); - WiseSayingController controller = new WiseSayingController(scanner, service); - App app = new App(controller, scanner); - app.run(); assertThat(outputStream.toString()) .contains("data.json 파일의 내용이 갱신되었습니다."); File file = new File("db/WiseSaying/build.json"); @@ -137,4 +148,78 @@ void buildTest() throws IOException { .contains("\"content\": \"너 자신을 알라2\"") .contains("\"author\": \"플라톤2\""); } + + @Test + void paginationTest(){ + prepare(""" + 등록 + 명언1 + 저자1 + 등록 + 명언2 + 저자2 + 등록 + 명언3 + 저자3 + 등록 + 명언4 + 저자4 + 등록 + 명언5 + 저자5 + 등록 + 명언6 + 저자6 + 등록 + 명언7 + 저자7 + 등록 + 명언8 + 저자8 + 등록 + 명언9 + 저자9 + 등록 + 명언10 + 저자10 + 목록?page=2 + """); + + assertThat(outputStream.toString()) + .contains("5 / \"저자5\" / \"명언5\""); + } + + @Test + void searchTest(){ + prepare(""" + 등록 + 명언검색어1 + 저자검색어1 + 등록 + 명언검색어2 + 저자검색어1 + 등록 + 명언검색어1 + 저자검색어2 + 등록 + 명언검색어2 + 저자검색어2 + 목록?keywordType=content&keyword=명언검색어1 + 목록?keywordType=author&keyword=저자검색어2 + """); + + assertThat(outputStream.toString()) + .contains("3 / \"저자검색어2\" / \"명언검색어1\"") + .contains("1 / \"저자검색어1\" / \"명언검색어1\""); + } + + private static void prepare(String input) { + Scanner scanner = TestUtil.genScanner(input); + WiseSayingRepository repository = new WiseSayingRepository(); + WiseSayingService service = new WiseSayingService(repository); + WiseSayingController controller = new WiseSayingController(scanner, service); + + App app = new App(controller, scanner); + app.run(); + } } \ No newline at end of file