diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..a8e8e2e --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,72 @@ +name: Docker Image CI/CD + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + name: Build Docker Image + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Authenticate with GCP + run: echo "${GOOGLE_APPLICATION_CREDENTIALS}" > key.json + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Convert gradlew to Unix format + run: sed -i 's/\r$//' gradlew + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + + - name: Verify gradlew exists + run: ls -al + + - name: Check gradlew file type + run: file gradlew + + - name: Build JAR file + run: ./gradlew build + + - name: Log in to Docker Hub + run: echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin + + - name: Build Docker Image + run: | + docker build -t ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest . + + - name: Push Docker Image to Docker Hub + run: | + docker push ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest + + deploy: + name: Deploy to Server + runs-on: ubuntu-latest + needs: build + + steps: + - name: Deploy via SSH + uses: appleboy/ssh-action@v1.2.0 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + echo ${{ secrets.SERVER_PASSWORD }} | sudo -S docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest + echo ${{ secrets.SERVER_PASSWORD }} | sudo -S docker stop app || true + echo ${{ secrets.SERVER_PASSWORD }} | sudo -S docker rm app || true + echo ${{ secrets.SERVER_PASSWORD }} | sudo -S docker run -d -e GOOGLE_APPLICATION_CREDENTIALS="/credential.json" -v /etc/credentials/gcloud-credential.json:/credential.json -v /home/ubuntu/images:/app/images --name app -p 8080:8080 ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest + echo ${{ secrets.SERVER_PASSWORD }} | sudo -S docker system prune -af diff --git a/.gradle/8.10/checksums/checksums.lock b/.gradle/8.10/checksums/checksums.lock new file mode 100644 index 0000000..5304baf Binary files /dev/null and b/.gradle/8.10/checksums/checksums.lock differ diff --git a/.gradle/8.10/checksums/md5-checksums.bin b/.gradle/8.10/checksums/md5-checksums.bin new file mode 100644 index 0000000..d0494c4 Binary files /dev/null and b/.gradle/8.10/checksums/md5-checksums.bin differ diff --git a/.gradle/8.10/checksums/sha1-checksums.bin b/.gradle/8.10/checksums/sha1-checksums.bin new file mode 100644 index 0000000..4fa465a Binary files /dev/null and b/.gradle/8.10/checksums/sha1-checksums.bin differ diff --git a/.gradle/8.10/dependencies-accessors/gc.properties b/.gradle/8.10/dependencies-accessors/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/8.10/executionHistory/executionHistory.bin b/.gradle/8.10/executionHistory/executionHistory.bin new file mode 100644 index 0000000..e73110c Binary files /dev/null and b/.gradle/8.10/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.10/executionHistory/executionHistory.lock b/.gradle/8.10/executionHistory/executionHistory.lock new file mode 100644 index 0000000..fcd2ff2 Binary files /dev/null and b/.gradle/8.10/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.10/fileChanges/last-build.bin b/.gradle/8.10/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/8.10/fileChanges/last-build.bin differ diff --git a/.gradle/8.10/fileHashes/fileHashes.bin b/.gradle/8.10/fileHashes/fileHashes.bin new file mode 100644 index 0000000..98117f6 Binary files /dev/null and b/.gradle/8.10/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.10/fileHashes/fileHashes.lock b/.gradle/8.10/fileHashes/fileHashes.lock new file mode 100644 index 0000000..faf4dcf Binary files /dev/null and b/.gradle/8.10/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.10/gc.properties b/.gradle/8.10/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/8.12.1/checksums/checksums.lock b/.gradle/8.12.1/checksums/checksums.lock new file mode 100644 index 0000000..651481d Binary files /dev/null and b/.gradle/8.12.1/checksums/checksums.lock differ diff --git a/.gradle/8.12.1/checksums/md5-checksums.bin b/.gradle/8.12.1/checksums/md5-checksums.bin new file mode 100644 index 0000000..80b2de3 Binary files /dev/null and b/.gradle/8.12.1/checksums/md5-checksums.bin differ diff --git a/.gradle/8.12.1/checksums/sha1-checksums.bin b/.gradle/8.12.1/checksums/sha1-checksums.bin new file mode 100644 index 0000000..0f075f6 Binary files /dev/null and b/.gradle/8.12.1/checksums/sha1-checksums.bin differ diff --git a/.gradle/8.12.1/executionHistory/executionHistory.bin b/.gradle/8.12.1/executionHistory/executionHistory.bin new file mode 100644 index 0000000..4a927e5 Binary files /dev/null and b/.gradle/8.12.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.12.1/executionHistory/executionHistory.lock b/.gradle/8.12.1/executionHistory/executionHistory.lock new file mode 100644 index 0000000..0335e16 Binary files /dev/null and b/.gradle/8.12.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.12.1/fileChanges/last-build.bin b/.gradle/8.12.1/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/8.12.1/fileChanges/last-build.bin differ diff --git a/.gradle/8.12.1/fileHashes/fileHashes.bin b/.gradle/8.12.1/fileHashes/fileHashes.bin new file mode 100644 index 0000000..8a83d10 Binary files /dev/null and b/.gradle/8.12.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.12.1/fileHashes/fileHashes.lock b/.gradle/8.12.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000..cb6247f Binary files /dev/null and b/.gradle/8.12.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.12.1/fileHashes/resourceHashesCache.bin b/.gradle/8.12.1/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..d098d72 Binary files /dev/null and b/.gradle/8.12.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/8.12.1/gc.properties b/.gradle/8.12.1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/8.5/checksums/checksums.lock b/.gradle/8.5/checksums/checksums.lock new file mode 100644 index 0000000..4f7c83f Binary files /dev/null and b/.gradle/8.5/checksums/checksums.lock differ diff --git a/.gradle/8.5/checksums/md5-checksums.bin b/.gradle/8.5/checksums/md5-checksums.bin new file mode 100644 index 0000000..9374d02 Binary files /dev/null and b/.gradle/8.5/checksums/md5-checksums.bin differ diff --git a/.gradle/8.5/checksums/sha1-checksums.bin b/.gradle/8.5/checksums/sha1-checksums.bin new file mode 100644 index 0000000..1785461 Binary files /dev/null and b/.gradle/8.5/checksums/sha1-checksums.bin differ diff --git a/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock b/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 0000000..7fb9c3f Binary files /dev/null and b/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock differ diff --git a/.gradle/8.5/dependencies-accessors/gc.properties b/.gradle/8.5/dependencies-accessors/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/8.5/executionHistory/executionHistory.bin b/.gradle/8.5/executionHistory/executionHistory.bin new file mode 100644 index 0000000..1fe24ab Binary files /dev/null and b/.gradle/8.5/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.5/executionHistory/executionHistory.lock b/.gradle/8.5/executionHistory/executionHistory.lock new file mode 100644 index 0000000..48bebb3 Binary files /dev/null and b/.gradle/8.5/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.5/fileChanges/last-build.bin b/.gradle/8.5/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/8.5/fileChanges/last-build.bin differ diff --git a/.gradle/8.5/fileHashes/fileHashes.bin b/.gradle/8.5/fileHashes/fileHashes.bin new file mode 100644 index 0000000..66f1cbc Binary files /dev/null and b/.gradle/8.5/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.5/fileHashes/fileHashes.lock b/.gradle/8.5/fileHashes/fileHashes.lock new file mode 100644 index 0000000..d59ca7b Binary files /dev/null and b/.gradle/8.5/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.5/fileHashes/resourceHashesCache.bin b/.gradle/8.5/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..c37dac0 Binary files /dev/null and b/.gradle/8.5/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/8.5/gc.properties b/.gradle/8.5/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..d76e0a1 Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..85e5236 --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sat Feb 15 20:00:07 KST 2025 +gradle.version=8.5 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..7b432d1 Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe new file mode 100644 index 0000000..4a45d40 Binary files /dev/null and b/.gradle/file-system.probe differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/workspace-id.txt b/.gradle/workspace-id.txt new file mode 100644 index 0000000..e33db28 Binary files /dev/null and b/.gradle/workspace-id.txt differ diff --git a/.gradle/workspace-id.txt.lock b/.gradle/workspace-id.txt.lock new file mode 100644 index 0000000..a96087b Binary files /dev/null and b/.gradle/workspace-id.txt.lock differ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..0d9a609 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +gdgback \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..2052ec6 --- /dev/null +++ b/.idea/compiler.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..84e0be8 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..fdc392f --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..581ee55 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file 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/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/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d7f6fff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM eclipse-temurin:21-jre-alpine + +# Google Cloud ADC를 위한 설치 및 인증 설정 +ENV GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json + +WORKDIR /GDG-Back +COPY /build/libs/gdgback-latest.jar /gdgback.jar +ENTRYPOINT ["java","-jar","/gdgback.jar"] \ No newline at end of file diff --git a/HELP.md b/HELP.md index 5e9734d..3aceb08 100644 --- a/HELP.md +++ b/HELP.md @@ -1,30 +1,30 @@ -# Getting Started - -### Reference Documentation -For further reference, please consider the following sections: - -* [Official Gradle documentation](https://docs.gradle.org) -* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/3.4.2/gradle-plugin) -* [Create an OCI image](https://docs.spring.io/spring-boot/3.4.2/gradle-plugin/packaging-oci-image.html) -* [Spring Web](https://docs.spring.io/spring-boot/3.4.2/reference/web/servlet.html) -* [Spring Data MongoDB](https://docs.spring.io/spring-boot/3.4.2/reference/data/nosql.html#data.nosql.mongodb) -* [Spring Security](https://docs.spring.io/spring-boot/3.4.2/reference/web/spring-security.html) -* [Spring Reactive Web](https://docs.spring.io/spring-boot/3.4.2/reference/web/reactive.html) - -### Guides -The following guides illustrate how to use some features concretely: - -* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) -* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) -* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/) -* [Accessing Data with MongoDB](https://spring.io/guides/gs/accessing-data-mongodb/) -* [Securing a Web Application](https://spring.io/guides/gs/securing-web/) -* [Spring Boot and OAuth2](https://spring.io/guides/tutorials/spring-boot-oauth2/) -* [Authenticating a User with LDAP](https://spring.io/guides/gs/authenticating-ldap/) -* [Building a Reactive RESTful Web Service](https://spring.io/guides/gs/reactive-rest-service/) - -### Additional Links -These additional references should also help you: - -* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) - +# Getting Started + +### Reference Documentation +For further reference, please consider the following sections: + +* [Official Gradle documentation](https://docs.gradle.org) +* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/3.4.2/gradle-plugin) +* [Create an OCI image](https://docs.spring.io/spring-boot/3.4.2/gradle-plugin/packaging-oci-image.html) +* [Spring Web](https://docs.spring.io/spring-boot/3.4.2/reference/web/servlet.html) +* [Spring Data MongoDB](https://docs.spring.io/spring-boot/3.4.2/reference/data/nosql.html#data.nosql.mongodb) +* [Spring Security](https://docs.spring.io/spring-boot/3.4.2/reference/web/spring-security.html) +* [Spring Reactive Web](https://docs.spring.io/spring-boot/3.4.2/reference/web/reactive.html) + +### Guides +The following guides illustrate how to use some features concretely: + +* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) +* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) +* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/) +* [Accessing Data with MongoDB](https://spring.io/guides/gs/accessing-data-mongodb/) +* [Securing a Web Application](https://spring.io/guides/gs/securing-web/) +* [Spring Boot and OAuth2](https://spring.io/guides/tutorials/spring-boot-oauth2/) +* [Authenticating a User with LDAP](https://spring.io/guides/gs/authenticating-ldap/) +* [Building a Reactive RESTful Web Service](https://spring.io/guides/gs/reactive-rest-service/) + +### Additional Links +These additional references should also help you: + +* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) + diff --git a/README.md b/README.md index e9c6f26..a4897fe 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,86 @@ -# 공황 및 불안 장애 대처 서비스 제공 애플리케이션 - -## 목표 -- 공황에 대처할 수 있는 AI 에이전트 학습 -- 에이전트와 사용자를 연결할 수 있는 네트워크 구성 -- 사용자 데이터를 저장할 수 있는 DB 구성 -- 사용자 데이터를 분석할 수 있는 환경 구성 - -## AI Agent -공황을 겪는 사용자 전문 음성 상담 AI 에이전트 - -요구사항: -- 맥락 분석 - - 공황 원인 - - 사용자 감정 상태 - - 상황 심각성 -- 의사소통: - - 실시간 음성 인식 - - 음성 출력 -- 데이터 학습: - - 사용자와의 대화를 기록 - - 기록한 데이터에 사용자 정보 마스킹 적용 - - 마스킹 된 대화 데이터를 학습 데이터로 활용 - -## Database -사용자 데이터 CRUD를 위한 데이터베이스 -요구사항: -- 사용자 데이터 -- 대화 로그 -DBMS: -- MongoDB - -## Networking -서비스 간의 네트워크 연결 -요구사항: -- 백엔드 서버와 DB 서버 연결 -- 백엔드 서버와 Gemini API 서버 요청망 구성 -- 프론트 서버와 백엔드 서버 연결 - -## TODO -1. 파인튜닝을 위한 학습/검증/테스트 데이터셋 구성 => 패스 -2. 사용자 정보 및 대화 로그 저장, 조회를 위한 데이터베이스 구성 -3. Gemini API 모델과 원활히 통신할 수 있는 백엔드 환경 구성 -4. +# 공황 및 불안 장애 대처 서비스 제공 애플리케이션 + +## 목표 +- 공황에 대처할 수 있는 AI 에이전트 학습 +- 에이전트와 사용자를 연결할 수 있는 네트워크 구성 +- 사용자 데이터를 저장할 수 있는 DB 구성 +- 사용자 데이터를 분석할 수 있는 환경 구성 + +## AI Agent +요구사항: +- 맥락 분석 + - 공황 원인 + - 사용자 감정 상태 + - 상황 심각성 +- 의사소통: + - 실시간 음성 인식 + - 음성 출력 +- 데이터 학습: + - 사용자와의 대화를 기록 + - 기록한 데이터에 사용자 정보 마스킹 적용 + - 마스킹 된 대화 데이터를 학습 데이터로 활용 + +## Database +요구사항: +- 사용자 + - ID + - 이름 +- 공황 + - ID + - 사용자 ID + - 날짜 + - 기록 + - 사진 + - 공포 수치 + - 전화 시간 + - 장소 + - 상황 + - 내용 +- 대화 로그 + - ID + - 사용자 ID + - 날짜 + - 내용 + - 대화 내용 (텍스트) + - 발화 주체 +DBMS: +- MongoDB +Cloud Service: +- MongoDB Atlas +### Document + + +## Networking +서비스 간의 네트워크 연결 +요구사항: +- 백엔드 서버와 DB 서버 연결 +- 백엔드 서버와 Gemini API 서버 요청망 구성 +- 프론트 서버와 백엔드 서버 연결 + +## TODO +### WAS +- ~~WAS 선정~~ Spring boot +- ~~CI/CD 구성~~ GitHub Actions +- 사용자 CRUD +- 대화 로그 CRUD +- ~~서버 호스팅 및 서비스 활성화~~ +### DATABASE +- ~~데이터베이스 선정~~ 빠른 응답을 위해 MongoDB 선정/ 촉박한 개발 시간으로 인해 Atlas 클라우드 서비스를 이용 +- ~~데이터베이스 연결~~ WAS 서버를 통해 접근 가능 +- 데이터베이스 구성 +### AGENT +- ~~프롬프트 전달 받고 응답 하기~~ +- ~~Text To Speech~~ +- Speech To Text +- 전달 받은 프롬프트 요약 +- 파인튜닝을 위한 학습/검증/테스트 데이터셋 구성 + +# 백엔드 서비스 구현에 사용되는 프레임워크/ 클라우드 서비스 +- REST API - Spring Boot +- Gemini Cloud - Google Cloud +- Database Cloud - MongoDB Atlas +- Deployment - Docker +- CI/CD - GitHub Actions + +![image](https://github.com/user-attachments/assets/f066a76a-89b7-49b8-afdb-0289200f16c8) +![image](https://github.com/user-attachments/assets/25173ef2-dcd5-4c7d-87fc-c5b229822cea) diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md new file mode 100644 index 0000000..d41e464 --- /dev/null +++ b/REQUIREMENTS.md @@ -0,0 +1,28 @@ +# 요구사항 정리 문서 +## 기능 요구사항 +### 상담 +- 채팅 상담 + 1. 텍스트 프롬프트를 에이전트에게 전송한다. + 2. 프롬프트 내용을 대화 내역에 저장한다. + 3. 에이전트 응답 내용을 대화 내역에 저장한다. +- 음성 상담 + 1. 음성 프롬프트를 텍스트 프롬프트로 변환한다. + 2. Function { 채팅상담(텍스트 프롬프트) } + 3. 수신한 응답 내용을 음성 응답으로 변환한다. +- 상담 기록 조회 + 1. 기록에 어떤 방식으로 접근할 것인가? + 2. +- 상담 내용 요약 +### 공황 일지 +- 일지 작성 +- 일지 조회 + 1. 일지에 어떤 방식으로 접근할 것인가? +### 공황 분석 +1. 상담 당시에 자주 언급된 키워드를 파악한다. +### 사용자 +- 회원가입 + +- 사용자 조회 + 1. 사용자 아이디로 사용자를 조회한다. +## 비기능 요구사항 +## 제약사항 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 04fc543..a56b03f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,33 +1,45 @@ -plugins { - id 'java' - id 'org.springframework.boot' version '3.4.2' - id 'io.spring.dependency-management' version '1.1.7' -} - -group = 'com.gdg' -version = '0.0.1-SNAPSHOT' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(23) - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-webflux' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'io.projectreactor:reactor-test' - testImplementation 'org.springframework.security:spring-security-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' -} - -tasks.named('test') { - useJUnitPlatform() -} +plugins { + id 'java' + id 'org.springframework.boot' version '3.4.2' + id 'io.spring.dependency-management' version '1.1.7' +} +jar { + archiveFileName = 'gdg' + enabled = false +} +group = 'com.gdg' +version = 'latest' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(platform("com.google.cloud:libraries-bom:26.47.0")) + implementation('com.google.cloud:google-cloud-vertexai') + implementation('com.google.cloud:google-cloud-texttospeech') + implementation('com.google.cloud:google-cloud-speech') + // implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.projectlombok:lombok' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'io.projectreactor:reactor-test' + testImplementation 'org.springframework.security:spring-security-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + annotationProcessor 'org.projectlombok:lombok' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/AgentController.class b/build/classes/java/main/com/gdg/gdgback/Agent/AgentController.class new file mode 100644 index 0000000..254bb0c Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/AgentController.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Context/Context$ContextBuilder.class b/build/classes/java/main/com/gdg/gdgback/Agent/Context/Context$ContextBuilder.class new file mode 100644 index 0000000..7476716 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Context/Context$ContextBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Context/Context.class b/build/classes/java/main/com/gdg/gdgback/Agent/Context/Context.class new file mode 100644 index 0000000..4bb5c2a Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Context/Context.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Context/ContextService.class b/build/classes/java/main/com/gdg/gdgback/Agent/Context/ContextService.class new file mode 100644 index 0000000..c90f155 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Context/ContextService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Context/DialogueEntry$DialogueEntryBuilder.class b/build/classes/java/main/com/gdg/gdgback/Agent/Context/DialogueEntry$DialogueEntryBuilder.class new file mode 100644 index 0000000..dbce010 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Context/DialogueEntry$DialogueEntryBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Context/DialogueEntry.class b/build/classes/java/main/com/gdg/gdgback/Agent/Context/DialogueEntry.class new file mode 100644 index 0000000..635679a Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Context/DialogueEntry.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Context/SessionContextService.class b/build/classes/java/main/com/gdg/gdgback/Agent/Context/SessionContextService.class new file mode 100644 index 0000000..31b90cc Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Context/SessionContextService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Core/GenerativeModelApi.class b/build/classes/java/main/com/gdg/gdgback/Agent/Core/GenerativeModelApi.class new file mode 100644 index 0000000..04506c7 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Core/GenerativeModelApi.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto$AgentAudioRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto$AgentAudioRequestDtoBuilder.class new file mode 100644 index 0000000..23324a2 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto$AgentAudioRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto.class new file mode 100644 index 0000000..890dc8f Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto$AgentTextRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto$AgentTextRequestDtoBuilder.class new file mode 100644 index 0000000..ee6753f Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto$AgentTextRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto.class new file mode 100644 index 0000000..6deac17 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateSTTError.class b/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateSTTError.class new file mode 100644 index 0000000..578c793 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateSTTError.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateTTSError.class b/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateTTSError.class new file mode 100644 index 0000000..4a62827 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateTTSError.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToRespondException.class b/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToRespondException.class new file mode 100644 index 0000000..cb8bc5d Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Exception/AgentFailedToRespondException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Service/AgentService.class b/build/classes/java/main/com/gdg/gdgback/Agent/Service/AgentService.class new file mode 100644 index 0000000..8aa1b3b Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Service/AgentService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Service/GoogleAgentService.class b/build/classes/java/main/com/gdg/gdgback/Agent/Service/GoogleAgentService.class new file mode 100644 index 0000000..3e67966 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Service/GoogleAgentService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Speech/GoogleSpeechService.class b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/GoogleSpeechService.class new file mode 100644 index 0000000..6d67e4f Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/GoogleSpeechService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Speech/SpeechService.class b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/SpeechService.class new file mode 100644 index 0000000..d5ffa9e Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/SpeechService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Speech/SpeechToTextApi.class b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/SpeechToTextApi.class new file mode 100644 index 0000000..d43a535 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/SpeechToTextApi.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Agent/Speech/TextToSpeechApi.class b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/TextToSpeechApi.class new file mode 100644 index 0000000..aad10f8 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Agent/Speech/TextToSpeechApi.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselController.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselController.class new file mode 100644 index 0000000..3db38a6 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselController.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselDocument$CounselDocumentBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselDocument$CounselDocumentBuilder.class new file mode 100644 index 0000000..b5f7dae Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselDocument$CounselDocumentBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselDocument.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselDocument.class new file mode 100644 index 0000000..7565fcf Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselDocument.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselMapper.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselMapper.class new file mode 100644 index 0000000..06cbaea Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselMapper.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselNotExistsException.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselNotExistsException.class new file mode 100644 index 0000000..ba7804f Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselNotExistsException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselRepository.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselRepository.class new file mode 100644 index 0000000..cdccbae Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselRepository.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselService.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselService.class new file mode 100644 index 0000000..16f4bd8 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/CounselServiceImpl.class b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselServiceImpl.class new file mode 100644 index 0000000..1d6ae16 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/CounselServiceImpl.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto$CounselCreateRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto$CounselCreateRequestDtoBuilder.class new file mode 100644 index 0000000..dbcd2f9 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto$CounselCreateRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto.class new file mode 100644 index 0000000..78a5d59 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto$CounselDeleteRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto$CounselDeleteRequestDtoBuilder.class new file mode 100644 index 0000000..e227b26 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto$CounselDeleteRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto.class new file mode 100644 index 0000000..bf20c5e Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto$CounselEndRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto$CounselEndRequestDtoBuilder.class new file mode 100644 index 0000000..f7bf7a7 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto$CounselEndRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto.class new file mode 100644 index 0000000..5ece816 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto$CounselCreateResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto$CounselCreateResponseDtoBuilder.class new file mode 100644 index 0000000..dd98e10 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto$CounselCreateResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto.class new file mode 100644 index 0000000..298d572 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto$CounselReadListResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto$CounselReadListResponseDtoBuilder.class new file mode 100644 index 0000000..c47c960 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto$CounselReadListResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto.class new file mode 100644 index 0000000..7ea4cfe Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto$CounselReadResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto$CounselReadResponseDtoBuilder.class new file mode 100644 index 0000000..cb8cd4b Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto$CounselReadResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto.class new file mode 100644 index 0000000..149f3f5 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto$DiaryCreateRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto$DiaryCreateRequestDtoBuilder.class new file mode 100644 index 0000000..ae85a35 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto$DiaryCreateRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto.class new file mode 100644 index 0000000..32fef37 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto$DiaryDeleteRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto$DiaryDeleteRequestDtoBuilder.class new file mode 100644 index 0000000..3c855c2 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto$DiaryDeleteRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto.class new file mode 100644 index 0000000..8e806bf Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto$DiaryReadListResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto$DiaryReadListResponseDtoBuilder.class new file mode 100644 index 0000000..6e35c08 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto$DiaryReadListResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto.class new file mode 100644 index 0000000..091f663 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto$DiaryReadResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto$DiaryReadResponseDtoBuilder.class new file mode 100644 index 0000000..cbfd3a1 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto$DiaryReadResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto.class new file mode 100644 index 0000000..0b2bc3e Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryController.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryController.class new file mode 100644 index 0000000..e841396 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryController.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryDocument$DiaryDocumentBuilder.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryDocument$DiaryDocumentBuilder.class new file mode 100644 index 0000000..c443787 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryDocument$DiaryDocumentBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryDocument.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryDocument.class new file mode 100644 index 0000000..671e109 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryDocument.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryImageIOException.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryImageIOException.class new file mode 100644 index 0000000..d654459 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryImageIOException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryMapper.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryMapper.class new file mode 100644 index 0000000..32dc920 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryMapper.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryNotFoundException.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryNotFoundException.class new file mode 100644 index 0000000..c6e47b6 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryNotFoundException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryRepository.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryRepository.class new file mode 100644 index 0000000..d97c671 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryRepository.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryService.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryService.class new file mode 100644 index 0000000..bfccd51 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Diary/DiaryServiceImpl.class b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryServiceImpl.class new file mode 100644 index 0000000..c9e6c5d Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Diary/DiaryServiceImpl.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/GdgbackApplication.class b/build/classes/java/main/com/gdg/gdgback/GdgbackApplication.class new file mode 100644 index 0000000..ee82175 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/GdgbackApplication.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Global/ExceptionController.class b/build/classes/java/main/com/gdg/gdgback/Global/ExceptionController.class new file mode 100644 index 0000000..9418d43 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Global/ExceptionController.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Global/Validator.class b/build/classes/java/main/com/gdg/gdgback/Global/Validator.class new file mode 100644 index 0000000..527c9fa Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Global/Validator.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Global/ValidatorImpl.class b/build/classes/java/main/com/gdg/gdgback/Global/ValidatorImpl.class new file mode 100644 index 0000000..9880dd0 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Global/ValidatorImpl.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Global/WebConfig.class b/build/classes/java/main/com/gdg/gdgback/Global/WebConfig.class new file mode 100644 index 0000000..7720ef5 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Global/WebConfig.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto$MessageCreateRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto$MessageCreateRequestDtoBuilder.class new file mode 100644 index 0000000..4e9aaf1 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto$MessageCreateRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto.class b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto.class new file mode 100644 index 0000000..9e22e8d Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto$MessageReadListResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto$MessageReadListResponseDtoBuilder.class new file mode 100644 index 0000000..fcc54d4 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto$MessageReadListResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto.class new file mode 100644 index 0000000..c46f5af Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto$MessageReadResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto$MessageReadResponseDtoBuilder.class new file mode 100644 index 0000000..c66ab93 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto$MessageReadResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto.class b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto.class new file mode 100644 index 0000000..a357962 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageController.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageController.class new file mode 100644 index 0000000..f4f41c6 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageController.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageDocument$MessageDocumentBuilder.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageDocument$MessageDocumentBuilder.class new file mode 100644 index 0000000..e881a17 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageDocument$MessageDocumentBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageDocument.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageDocument.class new file mode 100644 index 0000000..2609b47 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageDocument.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageMapper.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageMapper.class new file mode 100644 index 0000000..dfcf6eb Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageMapper.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageNotExistsException.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageNotExistsException.class new file mode 100644 index 0000000..c412699 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageNotExistsException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageRepository.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageRepository.class new file mode 100644 index 0000000..288dc1c Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageRepository.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageService.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageService.class new file mode 100644 index 0000000..c1b3213 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/Message/MessageServiceImpl.class b/build/classes/java/main/com/gdg/gdgback/Message/MessageServiceImpl.class new file mode 100644 index 0000000..27424dd Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/Message/MessageServiceImpl.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto$UserCreateRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto$UserCreateRequestDtoBuilder.class new file mode 100644 index 0000000..f4f4a9e Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto$UserCreateRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto.class new file mode 100644 index 0000000..8ee0bda Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto$UserDeleteRequestDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto$UserDeleteRequestDtoBuilder.class new file mode 100644 index 0000000..895bffd Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto$UserDeleteRequestDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto.class new file mode 100644 index 0000000..4d17186 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto$UserReadListResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto$UserReadListResponseDtoBuilder.class new file mode 100644 index 0000000..39471af Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto$UserReadListResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto.class new file mode 100644 index 0000000..64e1f94 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto$UserReadResponseDtoBuilder.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto$UserReadResponseDtoBuilder.class new file mode 100644 index 0000000..c5bdab0 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto$UserReadResponseDtoBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto.class b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto.class new file mode 100644 index 0000000..1c2c078 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/Exception/UserAlreadyExistsException.class b/build/classes/java/main/com/gdg/gdgback/User/Exception/UserAlreadyExistsException.class new file mode 100644 index 0000000..ec3b462 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/Exception/UserAlreadyExistsException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/Exception/UserNotExistsException.class b/build/classes/java/main/com/gdg/gdgback/User/Exception/UserNotExistsException.class new file mode 100644 index 0000000..96060f3 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/Exception/UserNotExistsException.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserController.class b/build/classes/java/main/com/gdg/gdgback/User/UserController.class new file mode 100644 index 0000000..5d2e9af Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserController.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserDocument$UserDocumentBuilder.class b/build/classes/java/main/com/gdg/gdgback/User/UserDocument$UserDocumentBuilder.class new file mode 100644 index 0000000..794a0f3 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserDocument$UserDocumentBuilder.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserDocument.class b/build/classes/java/main/com/gdg/gdgback/User/UserDocument.class new file mode 100644 index 0000000..a007118 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserDocument.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserMapper.class b/build/classes/java/main/com/gdg/gdgback/User/UserMapper.class new file mode 100644 index 0000000..0542823 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserMapper.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserRepository.class b/build/classes/java/main/com/gdg/gdgback/User/UserRepository.class new file mode 100644 index 0000000..8463984 Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserRepository.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserService.class b/build/classes/java/main/com/gdg/gdgback/User/UserService.class new file mode 100644 index 0000000..65b6e8d Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserService.class differ diff --git a/build/classes/java/main/com/gdg/gdgback/User/UserServiceImpl.class b/build/classes/java/main/com/gdg/gdgback/User/UserServiceImpl.class new file mode 100644 index 0000000..c27ad4a Binary files /dev/null and b/build/classes/java/main/com/gdg/gdgback/User/UserServiceImpl.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Agent/AgentServiceTest.class b/build/classes/java/test/com/gdg/gdgback/Agent/AgentServiceTest.class new file mode 100644 index 0000000..dede0ac Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Agent/AgentServiceTest.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Counsel/CounselServiceTest.class b/build/classes/java/test/com/gdg/gdgback/Counsel/CounselServiceTest.class new file mode 100644 index 0000000..dfd8d9a Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Counsel/CounselServiceTest.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Counsel/CounselTestRepository.class b/build/classes/java/test/com/gdg/gdgback/Counsel/CounselTestRepository.class new file mode 100644 index 0000000..e688d89 Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Counsel/CounselTestRepository.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Diary/DiaryServiceTest.class b/build/classes/java/test/com/gdg/gdgback/Diary/DiaryServiceTest.class new file mode 100644 index 0000000..91b981f Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Diary/DiaryServiceTest.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Diary/DiaryTestRepository.class b/build/classes/java/test/com/gdg/gdgback/Diary/DiaryTestRepository.class new file mode 100644 index 0000000..2b0ddcc Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Diary/DiaryTestRepository.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/GdgbackApplicationTests.class b/build/classes/java/test/com/gdg/gdgback/GdgbackApplicationTests.class new file mode 100644 index 0000000..cae184b Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/GdgbackApplicationTests.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/General/TestValidator.class b/build/classes/java/test/com/gdg/gdgback/General/TestValidator.class new file mode 100644 index 0000000..9623f53 Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/General/TestValidator.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Message/MessageServiceTest.class b/build/classes/java/test/com/gdg/gdgback/Message/MessageServiceTest.class new file mode 100644 index 0000000..9514582 Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Message/MessageServiceTest.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/Message/MessageTestRepository.class b/build/classes/java/test/com/gdg/gdgback/Message/MessageTestRepository.class new file mode 100644 index 0000000..f473a4a Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/Message/MessageTestRepository.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/User/UserServiceTest.class b/build/classes/java/test/com/gdg/gdgback/User/UserServiceTest.class new file mode 100644 index 0000000..33916bd Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/User/UserServiceTest.class differ diff --git a/build/classes/java/test/com/gdg/gdgback/User/UserTestRepository.class b/build/classes/java/test/com/gdg/gdgback/User/UserTestRepository.class new file mode 100644 index 0000000..726a151 Binary files /dev/null and b/build/classes/java/test/com/gdg/gdgback/User/UserTestRepository.class differ diff --git a/build/libs/gdgback-latest.jar b/build/libs/gdgback-latest.jar new file mode 100644 index 0000000..9896c09 Binary files /dev/null and b/build/libs/gdgback-latest.jar differ diff --git a/build/reports/problems/problems-report.html b/build/reports/problems/problems-report.html new file mode 100644 index 0000000..23636cf --- /dev/null +++ b/build/reports/problems/problems-report.html @@ -0,0 +1,663 @@ + + + + + + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/build/reports/tests/test/css/base-style.css b/build/reports/tests/test/css/base-style.css new file mode 100644 index 0000000..4afa73e --- /dev/null +++ b/build/reports/tests/test/css/base-style.css @@ -0,0 +1,179 @@ + +body { + margin: 0; + padding: 0; + font-family: sans-serif; + font-size: 12pt; +} + +body, a, a:visited { + color: #303030; +} + +#content { + padding-left: 50px; + padding-right: 50px; + padding-top: 30px; + padding-bottom: 30px; +} + +#content h1 { + font-size: 160%; + margin-bottom: 10px; +} + +#footer { + margin-top: 100px; + font-size: 80%; + white-space: nowrap; +} + +#footer, #footer a { + color: #a0a0a0; +} + +#line-wrapping-toggle { + vertical-align: middle; +} + +#label-for-line-wrapping-toggle { + vertical-align: middle; +} + +ul { + margin-left: 0; +} + +h1, h2, h3 { + white-space: nowrap; +} + +h2 { + font-size: 120%; +} + +ul.tabLinks { + padding-left: 0; + padding-top: 10px; + padding-bottom: 10px; + overflow: auto; + min-width: 800px; + width: auto !important; + width: 800px; +} + +ul.tabLinks li { + float: left; + height: 100%; + list-style: none; + padding-left: 10px; + padding-right: 10px; + padding-top: 5px; + padding-bottom: 5px; + margin-bottom: 0; + -moz-border-radius: 7px; + border-radius: 7px; + margin-right: 25px; + border: solid 1px #d4d4d4; + background-color: #f0f0f0; +} + +ul.tabLinks li:hover { + background-color: #fafafa; +} + +ul.tabLinks li.selected { + background-color: #c5f0f5; + border-color: #c5f0f5; +} + +ul.tabLinks a { + font-size: 120%; + display: block; + outline: none; + text-decoration: none; + margin: 0; + padding: 0; +} + +ul.tabLinks li h2 { + margin: 0; + padding: 0; +} + +div.tab { +} + +div.selected { + display: block; +} + +div.deselected { + display: none; +} + +div.tab table { + min-width: 350px; + width: auto !important; + width: 350px; + border-collapse: collapse; +} + +div.tab th, div.tab table { + border-bottom: solid #d0d0d0 1px; +} + +div.tab th { + text-align: left; + white-space: nowrap; + padding-left: 6em; +} + +div.tab th:first-child { + padding-left: 0; +} + +div.tab td { + white-space: nowrap; + padding-left: 6em; + padding-top: 5px; + padding-bottom: 5px; +} + +div.tab td:first-child { + padding-left: 0; +} + +div.tab td.numeric, div.tab th.numeric { + text-align: right; +} + +span.code { + display: inline-block; + margin-top: 0em; + margin-bottom: 1em; +} + +span.code pre { + font-size: 11pt; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 10px; + padding-right: 10px; + margin: 0; + background-color: #f7f7f7; + border: solid 1px #d0d0d0; + min-width: 700px; + width: auto !important; + width: 700px; +} + +span.wrapped pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: break-all; +} + +label.hidden { + display: none; +} \ No newline at end of file diff --git a/build/reports/tests/test/css/style.css b/build/reports/tests/test/css/style.css new file mode 100644 index 0000000..3dc4913 --- /dev/null +++ b/build/reports/tests/test/css/style.css @@ -0,0 +1,84 @@ + +#summary { + margin-top: 30px; + margin-bottom: 40px; +} + +#summary table { + border-collapse: collapse; +} + +#summary td { + vertical-align: top; +} + +.breadcrumbs, .breadcrumbs a { + color: #606060; +} + +.infoBox { + width: 110px; + padding-top: 15px; + padding-bottom: 15px; + text-align: center; +} + +.infoBox p { + margin: 0; +} + +.counter, .percent { + font-size: 120%; + font-weight: bold; + margin-bottom: 8px; +} + +#duration { + width: 125px; +} + +#successRate, .summaryGroup { + border: solid 2px #d0d0d0; + -moz-border-radius: 10px; + border-radius: 10px; +} + +#successRate { + width: 140px; + margin-left: 35px; +} + +#successRate .percent { + font-size: 180%; +} + +.success, .success a { + color: #008000; +} + +div.success, #successRate.success { + background-color: #bbd9bb; + border-color: #008000; +} + +.failures, .failures a { + color: #b60808; +} + +.skipped, .skipped a { + color: #c09853; +} + +div.failures, #successRate.failures { + background-color: #ecdada; + border-color: #b60808; +} + +ul.linkList { + padding-left: 0; +} + +ul.linkList li { + list-style: none; + margin-bottom: 5px; +} diff --git a/build/reports/tests/test/index.html b/build/reports/tests/test/index.html new file mode 100644 index 0000000..c02366b --- /dev/null +++ b/build/reports/tests/test/index.html @@ -0,0 +1,133 @@ + + + + + +Test results - Test Summary + + + + + +
+

Test Summary

+
+ + + + + +
+
+ + + + + + + +
+
+
2
+

tests

+
+
+
+
0
+

failures

+
+
+
+
0
+

ignored

+
+
+
+
0.353s
+

duration

+
+
+
+
+
+
100%
+

successful

+
+
+
+
+ +
+

Packages

+ + + + + + + + + + + + + + + + + + + + + +
PackageTestsFailuresIgnoredDurationSuccess rate
+com.gdg.gdgback.Diary +2000.353s100%
+
+
+

Classes

+ + + + + + + + + + + + + + + + + + + + + +
ClassTestsFailuresIgnoredDurationSuccess rate
+com.gdg.gdgback.Diary.DiaryServiceTest +2000.353s100%
+
+
+ +
+ + diff --git a/build/reports/tests/test/js/report.js b/build/reports/tests/test/js/report.js new file mode 100644 index 0000000..83bab4a --- /dev/null +++ b/build/reports/tests/test/js/report.js @@ -0,0 +1,194 @@ +(function (window, document) { + "use strict"; + + var tabs = {}; + + function changeElementClass(element, classValue) { + if (element.getAttribute("className")) { + element.setAttribute("className", classValue); + } else { + element.setAttribute("class", classValue); + } + } + + function getClassAttribute(element) { + if (element.getAttribute("className")) { + return element.getAttribute("className"); + } else { + return element.getAttribute("class"); + } + } + + function addClass(element, classValue) { + changeElementClass(element, getClassAttribute(element) + " " + classValue); + } + + function removeClass(element, classValue) { + changeElementClass(element, getClassAttribute(element).replace(classValue, "")); + } + + function initTabs() { + var container = document.getElementById("tabs"); + + tabs.tabs = findTabs(container); + tabs.titles = findTitles(tabs.tabs); + tabs.headers = findHeaders(container); + tabs.select = select; + tabs.deselectAll = deselectAll; + tabs.select(0); + + return true; + } + + function getCheckBox() { + return document.getElementById("line-wrapping-toggle"); + } + + function getLabelForCheckBox() { + return document.getElementById("label-for-line-wrapping-toggle"); + } + + function findCodeBlocks() { + var spans = document.getElementById("tabs").getElementsByTagName("span"); + var codeBlocks = []; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].className.indexOf("code") >= 0) { + codeBlocks.push(spans[i]); + } + } + return codeBlocks; + } + + function forAllCodeBlocks(operation) { + var codeBlocks = findCodeBlocks(); + + for (var i = 0; i < codeBlocks.length; ++i) { + operation(codeBlocks[i], "wrapped"); + } + } + + function toggleLineWrapping() { + var checkBox = getCheckBox(); + + if (checkBox.checked) { + forAllCodeBlocks(addClass); + } else { + forAllCodeBlocks(removeClass); + } + } + + function initControls() { + if (findCodeBlocks().length > 0) { + var checkBox = getCheckBox(); + var label = getLabelForCheckBox(); + + checkBox.onclick = toggleLineWrapping; + checkBox.checked = false; + + removeClass(label, "hidden"); + } + } + + function switchTab() { + var id = this.id.substr(1); + + for (var i = 0; i < tabs.tabs.length; i++) { + if (tabs.tabs[i].id === id) { + tabs.select(i); + break; + } + } + + return false; + } + + function select(i) { + this.deselectAll(); + + changeElementClass(this.tabs[i], "tab selected"); + changeElementClass(this.headers[i], "selected"); + + while (this.headers[i].firstChild) { + this.headers[i].removeChild(this.headers[i].firstChild); + } + + var h2 = document.createElement("H2"); + + h2.appendChild(document.createTextNode(this.titles[i])); + this.headers[i].appendChild(h2); + } + + function deselectAll() { + for (var i = 0; i < this.tabs.length; i++) { + changeElementClass(this.tabs[i], "tab deselected"); + changeElementClass(this.headers[i], "deselected"); + + while (this.headers[i].firstChild) { + this.headers[i].removeChild(this.headers[i].firstChild); + } + + var a = document.createElement("A"); + + a.setAttribute("id", "ltab" + i); + a.setAttribute("href", "#tab" + i); + a.onclick = switchTab; + a.appendChild(document.createTextNode(this.titles[i])); + + this.headers[i].appendChild(a); + } + } + + function findTabs(container) { + return findChildElements(container, "DIV", "tab"); + } + + function findHeaders(container) { + var owner = findChildElements(container, "UL", "tabLinks"); + return findChildElements(owner[0], "LI", null); + } + + function findTitles(tabs) { + var titles = []; + + for (var i = 0; i < tabs.length; i++) { + var tab = tabs[i]; + var header = findChildElements(tab, "H2", null)[0]; + + header.parentNode.removeChild(header); + + if (header.innerText) { + titles.push(header.innerText); + } else { + titles.push(header.textContent); + } + } + + return titles; + } + + function findChildElements(container, name, targetClass) { + var elements = []; + var children = container.childNodes; + + for (var i = 0; i < children.length; i++) { + var child = children.item(i); + + if (child.nodeType === 1 && child.nodeName === name) { + if (targetClass && child.className.indexOf(targetClass) < 0) { + continue; + } + + elements.push(child); + } + } + + return elements; + } + + // Entry point. + + window.onload = function() { + initTabs(); + initControls(); + }; +} (window, window.document)); \ No newline at end of file diff --git a/build/resolvedMainClassName b/build/resolvedMainClassName new file mode 100644 index 0000000..f00bb85 --- /dev/null +++ b/build/resolvedMainClassName @@ -0,0 +1 @@ +com.gdg.gdgback.GdgbackApplication \ No newline at end of file diff --git a/build/resources/main/application.properties b/build/resources/main/application.properties new file mode 100644 index 0000000..72233fd --- /dev/null +++ b/build/resources/main/application.properties @@ -0,0 +1,2 @@ +spring.application.name=gdgback +spring.web.resources.static-locations=classpath:/static/,file:/app/images/ \ No newline at end of file diff --git a/build/resources/main/application.yml b/build/resources/main/application.yml new file mode 100644 index 0000000..257cdce --- /dev/null +++ b/build/resources/main/application.yml @@ -0,0 +1,20 @@ +server: + servlet: + session: + timeout: 5m + +spring: + profiles: + active: default + data: + mongodb: + uri: mongodb+srv://pupajusang01:1234@gdgback.rbtvd.mongodb.net/?retryWrites=true&w=majority&appName=gdgback + database: gdgback + web: + resources: + static-locations: classpath:/static/, file:/app/images/ + +gemini: + api: + url: ${GEMINI_URL} + key: ${GEMINI_KEY} \ No newline at end of file diff --git a/build/test-results/test/binary/output.bin b/build/test-results/test/binary/output.bin new file mode 100644 index 0000000..c6a8515 Binary files /dev/null and b/build/test-results/test/binary/output.bin differ diff --git a/build/test-results/test/binary/output.bin.idx b/build/test-results/test/binary/output.bin.idx new file mode 100644 index 0000000..beba215 Binary files /dev/null and b/build/test-results/test/binary/output.bin.idx differ diff --git a/build/test-results/test/binary/results.bin b/build/test-results/test/binary/results.bin new file mode 100644 index 0000000..0897161 Binary files /dev/null and b/build/test-results/test/binary/results.bin differ diff --git a/build/tmp/bootJar/MANIFEST.MF b/build/tmp/bootJar/MANIFEST.MF new file mode 100644 index 0000000..08cd7da --- /dev/null +++ b/build/tmp/bootJar/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Main-Class: org.springframework.boot.loader.launch.JarLauncher +Start-Class: com.gdg.gdgback.GdgbackApplication +Spring-Boot-Version: 3.4.2 +Spring-Boot-Classes: BOOT-INF/classes/ +Spring-Boot-Lib: BOOT-INF/lib/ +Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx +Spring-Boot-Layers-Index: BOOT-INF/layers.idx +Build-Jdk-Spec: 21 +Implementation-Title: gdgback +Implementation-Version: latest + diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/AgentController.class.uniqueId0 b/build/tmp/compileJava/compileTransaction/stash-dir/AgentController.class.uniqueId0 new file mode 100644 index 0000000..1e682bf Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/AgentController.class.uniqueId0 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/ApiConfig.class.uniqueId1 b/build/tmp/compileJava/compileTransaction/stash-dir/ApiConfig.class.uniqueId1 new file mode 100644 index 0000000..b0f4793 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/ApiConfig.class.uniqueId1 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/CounselingServiceImpl.class.uniqueId3 b/build/tmp/compileJava/compileTransaction/stash-dir/CounselingServiceImpl.class.uniqueId3 new file mode 100644 index 0000000..e0ce851 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/CounselingServiceImpl.class.uniqueId3 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/GoogleAgentService.class.uniqueId2 b/build/tmp/compileJava/compileTransaction/stash-dir/GoogleAgentService.class.uniqueId2 new file mode 100644 index 0000000..57df188 Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/GoogleAgentService.class.uniqueId2 differ diff --git a/build/tmp/compileJava/compileTransaction/stash-dir/GoogleSpeechService.class.uniqueId0 b/build/tmp/compileJava/compileTransaction/stash-dir/GoogleSpeechService.class.uniqueId0 new file mode 100644 index 0000000..09bc4fe Binary files /dev/null and b/build/tmp/compileJava/compileTransaction/stash-dir/GoogleSpeechService.class.uniqueId0 differ diff --git a/build/tmp/compileJava/previous-compilation-data.bin b/build/tmp/compileJava/previous-compilation-data.bin new file mode 100644 index 0000000..05abebc Binary files /dev/null and b/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/build/tmp/compileTestJava/compileTransaction/stash-dir/GdgbackApplicationTests.class.uniqueId0 b/build/tmp/compileTestJava/compileTransaction/stash-dir/GdgbackApplicationTests.class.uniqueId0 new file mode 100644 index 0000000..6bbc272 Binary files /dev/null and b/build/tmp/compileTestJava/compileTransaction/stash-dir/GdgbackApplicationTests.class.uniqueId0 differ diff --git a/build/tmp/compileTestJava/previous-compilation-data.bin b/build/tmp/compileTestJava/previous-compilation-data.bin new file mode 100644 index 0000000..85879c6 Binary files /dev/null and b/build/tmp/compileTestJava/previous-compilation-data.bin differ diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/build/tmp/jar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e18bc25..479489e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index f5feea6..ec19934 100644 --- a/gradlew +++ b/gradlew @@ -1,252 +1,252 @@ -#!/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. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# 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/HEAD/platforms/jvm/plugins-application/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 - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit - -# 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 - if ! command -v java >/dev/null 2>&1 - then - 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 -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - 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 - - -# 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"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# 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" "$@" +#!/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. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# 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/HEAD/platforms/jvm/plugins-application/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 + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# 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 + if ! command -v java >/dev/null 2>&1 + then + 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 +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + 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 + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# 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/settings.gradle b/settings.gradle index b50931e..bbd50e9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'gdgback' +rootProject.name = 'gdgback' diff --git a/src/main/java/com/gdg/gdgback/Agent/AgentController.java b/src/main/java/com/gdg/gdgback/Agent/AgentController.java new file mode 100644 index 0000000..8a68f9a --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/AgentController.java @@ -0,0 +1,45 @@ +package com.gdg.gdgback.Agent; + +import com.gdg.gdgback.Agent.DTO.Request.AgentAudioRequestDto; +import com.gdg.gdgback.Agent.DTO.Request.AgentTextRequestDto; +import com.gdg.gdgback.Agent.Service.AgentService; +import com.google.api.Context; +import jakarta.servlet.http.HttpSession; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Profile("!test") +@RestController +@RequestMapping("/counsel/agent") +public class AgentController { + private final AgentService agentService; + + @Autowired + AgentController(AgentService agentService) { + this.agentService = agentService; + } + + @PostMapping("/text") + ResponseEntity getTextResponse(HttpSession session, @Valid @RequestBody AgentTextRequestDto agentTextRequestDto) { + return ResponseEntity.ok().body(agentService.replyByText(session, agentTextRequestDto)); + } + @PostMapping("/voice") + ResponseEntity getVoiceResponse(HttpSession session, @Valid @RequestBody AgentTextRequestDto agentTextRequestDto) { + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_TYPE, "audio/mpeg") + .body(agentService.replyByAudio(session, agentTextRequestDto)); + } + @PostMapping("/call") + ResponseEntity getVoiceResponse(HttpSession session, @Valid @RequestBody AgentAudioRequestDto agentAudioRequestDto) { + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_TYPE, "audio/mpeg") + .body(agentService.replyByAudio(session, agentAudioRequestDto)); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Context/Context.java b/src/main/java/com/gdg/gdgback/Agent/Context/Context.java new file mode 100644 index 0000000..7a0a2bc --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Context/Context.java @@ -0,0 +1,36 @@ +package com.gdg.gdgback.Agent.Context; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Builder +@Data +public class Context { + String summary; + List history; + + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("[PAST CONTEXT]\n"); + if (summary.isEmpty()) { + sb.append("(No summary yet)"); + } else { + sb.append(summary); + } + sb.append("\n\n"); + + sb.append("[RECENT HISTORY]\n"); + if (history.isEmpty()) { + sb.append("(No dialogue history)"); + } else { + for (DialogueEntry entry : history) { + sb.append("User: ").append(entry.getUser()).append("\n"); + sb.append("Therapist: ").append(entry.getModel()).append("\n"); + } + } + return sb.toString(); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Context/ContextService.java b/src/main/java/com/gdg/gdgback/Agent/Context/ContextService.java new file mode 100644 index 0000000..a2bc3a2 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Context/ContextService.java @@ -0,0 +1,9 @@ +package com.gdg.gdgback.Agent.Context; + +import jakarta.servlet.http.HttpSession; + +public interface ContextService { + Context getContext(HttpSession session); + void updateContext(HttpSession session, DialogueEntry dialogue); + String generateUpdatedSummary(String summary, DialogueEntry dialogue); +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Context/DialogueEntry.java b/src/main/java/com/gdg/gdgback/Agent/Context/DialogueEntry.java new file mode 100644 index 0000000..02a9bd8 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Context/DialogueEntry.java @@ -0,0 +1,14 @@ +package com.gdg.gdgback.Agent.Context; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class DialogueEntry { + public static DialogueEntry of(String user, String model) { + return new DialogueEntry(user, model); + } + String user; + String model; +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Context/SessionContextService.java b/src/main/java/com/gdg/gdgback/Agent/Context/SessionContextService.java new file mode 100644 index 0000000..494fae0 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Context/SessionContextService.java @@ -0,0 +1,68 @@ +package com.gdg.gdgback.Agent.Context; + +import com.gdg.gdgback.Agent.Core.GenerativeModelApi; +import jakarta.servlet.http.HttpSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; + +@Service +public class SessionContextService implements ContextService { + private final GenerativeModelApi model; + + @Autowired + SessionContextService(GenerativeModelApi model) { + this.model = model; + } + + @Override + public Context getContext(HttpSession session) { + Context context = (Context)session.getAttribute("context"); + if(context == null) { + context = Context.builder() + .summary("") + .history(new ArrayList<>()) + .build(); + session.setAttribute("context", context); + } + return context; + } + + @Override + public void updateContext(HttpSession session, DialogueEntry dialogue) { + final int HISTORY_LIMIT = 2; + + Context context = (Context)session.getAttribute("context"); + context.history.add(dialogue); + + if(context.history.size() > HISTORY_LIMIT) { + context.summary = generateUpdatedSummary(context.summary, context.history.getFirst()); + context.history = new ArrayList<>(context.history.subList(1, HISTORY_LIMIT + 1)); + } + + session.setAttribute("context", context); + } + + @Override + public String generateUpdatedSummary(String summary, DialogueEntry dialogue) { + final String DIRECTION = """ + [Direction of summarization] + - Summarize the core content of the preceding dialogue. + - Emphasize any **changes or trends** in the user's emotional or physical state. + - Clearly present the relationship between the user's concerns and the counselor's interventions. + - The summary must not exceed 3 sentences. + + [Example] + User: {Initial emotions/symptoms → recent changes} + Counselor: {Follow-up questions, emotional validation, or coping strategies} + """; + + String prompt = DIRECTION + + "\n\n[Previous summary]\n" + summary + + "\n\n[New dialogue]\n" + dialogue.toString() + + "\n\n[Result of summarization]\n"; + + return model.generateResponseInJapan(prompt); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Core/GenerativeModelApi.java b/src/main/java/com/gdg/gdgback/Agent/Core/GenerativeModelApi.java new file mode 100644 index 0000000..593b07e --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Core/GenerativeModelApi.java @@ -0,0 +1,49 @@ +package com.gdg.gdgback.Agent.Core; + +import com.gdg.gdgback.Agent.Exception.AgentFailedToRespondException; +import com.google.cloud.vertexai.VertexAI; +import com.google.cloud.vertexai.api.HarmCategory; +import com.google.cloud.vertexai.api.SafetySetting; +import com.google.cloud.vertexai.generativeai.GenerativeModel; +import com.google.cloud.vertexai.generativeai.ResponseHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.Collections; + +@Component +@Profile("!test") +public class GenerativeModelApi { + private final GenerativeModel generativeModel; + private final GenerativeModel generativeModelInJapan; + + @Autowired + GenerativeModelApi() { + String projectId = "fair-backbone-449407-u7"; + this.generativeModel = new GenerativeModel("gemini-1.5-flash-001", new VertexAI(projectId, "asia-northeast3")); + this.generativeModel.withSafetySettings(Collections.singletonList( + SafetySetting.newBuilder() + .setCategory(HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT) + .setThreshold(SafetySetting.HarmBlockThreshold.BLOCK_NONE).build()) + ); + this.generativeModelInJapan = new GenerativeModel("gemini-1.5-flash-001", new VertexAI(projectId, "asia-northeast1")); + } + + public String generateResponse(String prompt) { + try { + return ResponseHandler.getText(generativeModel.generateContent(prompt)); + } catch (IOException e) { + throw new AgentFailedToRespondException(prompt); + } + } + + public String generateResponseInJapan(String prompt) { + try { + return ResponseHandler.getText(generativeModelInJapan.generateContent(prompt)); + } catch (IOException e) { + throw new AgentFailedToRespondException(prompt); + } + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto.java b/src/main/java/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto.java new file mode 100644 index 0000000..5a9b737 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/DTO/Request/AgentAudioRequestDto.java @@ -0,0 +1,10 @@ +package com.gdg.gdgback.Agent.DTO.Request; + +import lombok.*; + +@Data +@Builder +public class AgentAudioRequestDto { + private String counselId; + private byte[] content; +} diff --git a/src/main/java/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto.java b/src/main/java/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto.java new file mode 100644 index 0000000..ffb0e49 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/DTO/Request/AgentTextRequestDto.java @@ -0,0 +1,13 @@ +package com.gdg.gdgback.Agent.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.*; + +@Data +@Builder +public class AgentTextRequestDto { + private String counselId; + + @NotNull(message = "content는 필수 입력 값입니다.") + private String content; +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateSTTError.java b/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateSTTError.java new file mode 100644 index 0000000..6f3fc3f --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateSTTError.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Agent.Exception; + +public class AgentFailedToCreateSTTError extends ExceptionInInitializerError { + public AgentFailedToCreateSTTError() { + super("Agent failed to create STT."); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateTTSError.java b/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateTTSError.java new file mode 100644 index 0000000..9373fcc --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToCreateTTSError.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Agent.Exception; + +public class AgentFailedToCreateTTSError extends ExceptionInInitializerError { + public AgentFailedToCreateTTSError() { + super("Agent failed to create TTS."); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToRespondException.java b/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToRespondException.java new file mode 100644 index 0000000..2ee8e83 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Exception/AgentFailedToRespondException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Agent.Exception; + +public class AgentFailedToRespondException extends RuntimeException { + public AgentFailedToRespondException(String message) { + super("Agent failed to respond from : " + message); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Service/AgentService.java b/src/main/java/com/gdg/gdgback/Agent/Service/AgentService.java new file mode 100644 index 0000000..27864d4 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Service/AgentService.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Agent.Service; + +import com.gdg.gdgback.Agent.DTO.Request.AgentAudioRequestDto; +import com.gdg.gdgback.Agent.DTO.Request.AgentTextRequestDto; +import jakarta.servlet.http.HttpSession; + +public interface AgentService { + String replyByText(HttpSession session, AgentTextRequestDto agentTextRequestDto); + byte[] replyByAudio(HttpSession session, AgentTextRequestDto agentTextRequestDto); + byte[] replyByAudio(HttpSession session, AgentAudioRequestDto agentAudioRequestDto); +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Service/GoogleAgentService.java b/src/main/java/com/gdg/gdgback/Agent/Service/GoogleAgentService.java new file mode 100644 index 0000000..31ac565 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Service/GoogleAgentService.java @@ -0,0 +1,104 @@ +package com.gdg.gdgback.Agent.Service; + +import com.gdg.gdgback.Agent.Context.ContextService; +import com.gdg.gdgback.Agent.Context.DialogueEntry; +import com.gdg.gdgback.Agent.Core.GenerativeModelApi; +import com.gdg.gdgback.Agent.Context.Context; +import com.gdg.gdgback.Agent.DTO.Request.AgentAudioRequestDto; +import com.gdg.gdgback.Agent.DTO.Request.AgentTextRequestDto; +import com.gdg.gdgback.Agent.Speech.SpeechService; +import com.gdg.gdgback.Message.DTO.Request.MessageCreateRequestDto; +import com.gdg.gdgback.Message.MessageService; +import jakarta.servlet.http.HttpSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Profile("!test") +public class GoogleAgentService implements AgentService { + private final GenerativeModelApi model; + private final SpeechService speechService; + private final ContextService contextService; + private final MessageService messageService; + + private final String DIRECTION = """ + [ROLE] + You are a calm, emotionally-attuned therapist trained in CBT for panic disorder. Your purpose is to provide emotional safety, co-regulation, and grounding. Let the conversation follow the user’s rhythm — never lead it with pressure. + + [DIRECTION] + - Speak naturally using short, varied-length sentences. Avoid mechanical tone or sentence structure. + - Do not mention professional help unless the user expresses self-harm or danger. + - Validate emotions using metaphor, soft imagery, or personalized reflection. Vary language to maintain attunement. + - Explain symptoms only if the user expresses confusion, fear, or asks directly. Use metaphors like "false alarms" or "waves" to reduce fear. + - Use simplified CBT tools like breath anchoring, posture awareness, or sensory prompts (touch, sight, sound). Normalize common panic responses without pathologizing. + + - Do **not** ask a question in every reply. + Ask a gentle, open-ended follow-up question **only if**: + - The user shows emotional openness + - The user expresses something incomplete or uncertain + - The user asks for explanation or help + + - **Avoid all questions** if the user shows overwhelm, silence, or shutdown. In those moments, instead: + - Mirror the emotional tone softly: "That must’ve felt intense." + - Acknowledge inner experience: "It’s okay to not have words right now." + - Offer gentle sensory prompts: "Can you feel your back touching the chair?" + - Use warm silence: "Take your time. I’m here." + + - Vary your endings: use emotional reflections, grounding suggestions, or soft pauses. Avoid overuse of questions as endings. + + - Use supportive transitions like: + - "You’re not alone in this right now." + - "We can go slowly." + - "Even now, you’re doing something brave by staying with this moment." + + - Keep replies concise, typically 1-3 focused sentences, adjusting the length to sensitively match the user's input and their expressed need for support."""; + + @Autowired + GoogleAgentService(GenerativeModelApi model, SpeechService speechService, ContextService contextService, MessageService messageService) { + this.model = model; + this.speechService = speechService; + this.contextService = contextService; + this.messageService = messageService; + } + + @Override + @Transactional + public String replyByText(HttpSession session, AgentTextRequestDto agentTextRequestDto) { + String counselId = agentTextRequestDto.getCounselId(); + String userMessage = agentTextRequestDto.getContent(); + + Context context = contextService.getContext(session); + String prompt = DIRECTION + "\n\n" + context.toString() + "\n\n" + userMessage; + + String response = model.generateResponse(prompt); + + messageService.createMessage(MessageCreateRequestDto.of(counselId, "user", userMessage)); + messageService.createMessage(MessageCreateRequestDto.of(counselId, "model", response)); + + contextService.updateContext(session, DialogueEntry.of(userMessage, response)); + + return response; + } + + @Override + public byte[] replyByAudio(HttpSession session, AgentTextRequestDto agentTextRequestDto) { + String textResponse = replyByText(session, agentTextRequestDto); + + return speechService.textToSpeech(textResponse); + } + + @Override + public byte[] replyByAudio(HttpSession session, AgentAudioRequestDto agentAudioRequestDto) { + String textContent = speechService.speechToText(agentAudioRequestDto.getContent()); + AgentTextRequestDto agentTextRequestDto = AgentTextRequestDto.builder() + .counselId(agentAudioRequestDto.getCounselId()) + .content(textContent) + .build(); + + String textResponse = replyByText(session, agentTextRequestDto); + + return speechService.textToSpeech(textResponse); + } +} \ No newline at end of file diff --git a/src/main/java/com/gdg/gdgback/Agent/Speech/GoogleSpeechService.java b/src/main/java/com/gdg/gdgback/Agent/Speech/GoogleSpeechService.java new file mode 100644 index 0000000..44a0632 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Speech/GoogleSpeechService.java @@ -0,0 +1,28 @@ +package com.gdg.gdgback.Agent.Speech; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Service +@Profile("!test") +public class GoogleSpeechService implements SpeechService { + private final TextToSpeechApi textToSpeechApi; + private final SpeechToTextApi speechToTextApi; + + @Autowired + GoogleSpeechService(TextToSpeechApi textToSpeechApi, SpeechToTextApi speechToTextApi) { + this.textToSpeechApi = textToSpeechApi; + this.speechToTextApi = speechToTextApi; + } + + @Override + public byte[] textToSpeech(String text) { + return textToSpeechApi.textToSpeech(text); + } + + @Override + public String speechToText(byte[] speech) { + return speechToTextApi.speechToText(speech); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Speech/SpeechService.java b/src/main/java/com/gdg/gdgback/Agent/Speech/SpeechService.java new file mode 100644 index 0000000..5615090 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Speech/SpeechService.java @@ -0,0 +1,6 @@ +package com.gdg.gdgback.Agent.Speech; + +public interface SpeechService { + byte[] textToSpeech(String text); + String speechToText(byte[] speech); +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Speech/SpeechToTextApi.java b/src/main/java/com/gdg/gdgback/Agent/Speech/SpeechToTextApi.java new file mode 100644 index 0000000..e3016f7 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Speech/SpeechToTextApi.java @@ -0,0 +1,33 @@ +package com.gdg.gdgback.Agent.Speech; + +import com.gdg.gdgback.Agent.Exception.AgentFailedToCreateSTTError; +import com.google.cloud.speech.v2.*; +import com.google.protobuf.ByteString; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Profile("!test") +public class SpeechToTextApi { + static final private String recognizer = "gdg-recognizer"; + static private SpeechClient speechClient; + + SpeechToTextApi() { + try { + speechClient = SpeechClient.create(); + } catch (IOException e) { + throw new AgentFailedToCreateSTTError(); + } + } + + public String speechToText(byte[] speech) { + RecognizeRequest request = RecognizeRequest.newBuilder() + .setRecognizer(recognizer) + .setContent(ByteString.copyFrom(speech)) + .build(); + + return speechClient.recognize(request).getResults(0).getAlternatives(0).getTranscript(); + } +} diff --git a/src/main/java/com/gdg/gdgback/Agent/Speech/TextToSpeechApi.java b/src/main/java/com/gdg/gdgback/Agent/Speech/TextToSpeechApi.java new file mode 100644 index 0000000..37588cd --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Agent/Speech/TextToSpeechApi.java @@ -0,0 +1,33 @@ +package com.gdg.gdgback.Agent.Speech; + +import com.gdg.gdgback.Agent.Exception.AgentFailedToCreateTTSError; +import com.google.cloud.texttospeech.v1.*; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Profile("!test") +public class TextToSpeechApi { + private final VoiceSelectionParams voice; + private final AudioConfig audioConfig; + private final TextToSpeechClient textToSpeechClient; + + TextToSpeechApi() { + this.voice = VoiceSelectionParams.newBuilder().setLanguageCode("ko-KR").setSsmlGender(SsmlVoiceGender.FEMALE).build(); + this.audioConfig = AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build(); + try { + this.textToSpeechClient = TextToSpeechClient.create(); + } catch (IOException e) { + throw new AgentFailedToCreateTTSError(); + } + } + + public byte[] textToSpeech(String text) { + SynthesisInput input = SynthesisInput.newBuilder() + .setText(text) + .build(); + return textToSpeechClient.synthesizeSpeech(input, voice, audioConfig).toByteArray(); + } +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/AnalysisController.java b/src/main/java/com/gdg/gdgback/Analysis/AnalysisController.java new file mode 100644 index 0000000..b54eeae --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/AnalysisController.java @@ -0,0 +1,27 @@ +package com.gdg.gdgback.Analysis; + +import com.gdg.gdgback.Analysis.DTO.AnalysisResponseDto; +import org.springframework.context.annotation.Profile; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.YearMonth; + +@Profile("!test") +@RestController +@RequestMapping("/analysis") +public class AnalysisController { + AnalysisService analysisService; + + AnalysisController(AnalysisService analysisService) { + this.analysisService = analysisService; + } + + @GetMapping + ResponseEntity getAnalysisByUserIdAndYearMonth(@RequestParam("id") String id, @RequestParam("yearMonth") String yearMonth) { + return ResponseEntity.ok().body(analysisService.analyzeByUserIdAndYearMonth(id, YearMonth.parse(yearMonth))); + } +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/AnalysisService.java b/src/main/java/com/gdg/gdgback/Analysis/AnalysisService.java new file mode 100644 index 0000000..0d8f83c --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/AnalysisService.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Analysis; + +import com.gdg.gdgback.Analysis.DTO.AnalysisResponseDto; +import org.springframework.stereotype.Service; + +import java.time.YearMonth; + +@Service +public interface AnalysisService { + AnalysisResponseDto analyzeByUserIdAndYearMonth(String id, YearMonth yearMonth); +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/AnalysisServiceImpl.java b/src/main/java/com/gdg/gdgback/Analysis/AnalysisServiceImpl.java new file mode 100644 index 0000000..db4b96b --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/AnalysisServiceImpl.java @@ -0,0 +1,75 @@ +package com.gdg.gdgback.Analysis; + +import com.gdg.gdgback.Analysis.DTO.AnalysisResponseDto; +import com.gdg.gdgback.Counsel.CounselService; +import com.gdg.gdgback.Diary.DTO.Response.DiaryReadResponseDto; +import com.gdg.gdgback.Diary.DiaryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.YearMonth; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service +public class AnalysisServiceImpl implements AnalysisService { + CounselService counselService; + DiaryService diaryService; + + @Autowired + AnalysisServiceImpl(CounselService counselService, DiaryService diaryService) { + this.counselService = counselService; + this.diaryService = diaryService; + } + + @Override + public AnalysisResponseDto analyzeByUserIdAndYearMonth(String userId, YearMonth yearMonth) { + List diaries = diaryService.readDiaryListByUserIdAndYearMonth(userId, yearMonth).getDiaries(); + + return AnalysisResponseDto.builder() + .diaryNum(diaries.size()) + .symptomStats(getSymptomStats(diaries)) + .expectationStat(getExpectationStat(diaries)) + .scoreStats(getScoreStats(diaries)) + .build(); + } + + private ArrayList getSymptomStats(List diaries) { + return countCategoryFrequency(diaries).entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .map(entry -> new SymptomStat(entry.getKey(), entry.getValue())) + .collect(Collectors.toCollection(ArrayList::new)); + } + + private Map countCategoryFrequency(List diaries) { + return diaries.stream() + .filter(diary -> diary.getCategory() != null) + .flatMap(diary -> Arrays.stream(diary.getCategory())) + .collect(Collectors.toMap( + Function.identity(), + v -> 1, + Integer::sum + )); + } + + private ExpectationStat getExpectationStat(List diaries) { + int predicted = 0, nonPredicted = 0; + + for (DiaryReadResponseDto diary : diaries) { + if(diary.getExpected() == null) continue; + + if(diary.getExpected()) predicted++; + else nonPredicted++; + } + return ExpectationStat.builder().O(predicted).X(nonPredicted).build(); + } + + private ArrayList getScoreStats(List diaries) { + return diaries.stream() + .filter(diary -> diary.getScore() != null) + .map(diary -> new ScoreStat(diary.getDate(), diary.getScore())) + .sorted(Comparator.comparing(ScoreStat::getDate).reversed()) + .collect(Collectors.toCollection(ArrayList::new)); + } +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/DTO/AnalysisResponseDto.java b/src/main/java/com/gdg/gdgback/Analysis/DTO/AnalysisResponseDto.java new file mode 100644 index 0000000..f9a375d --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/DTO/AnalysisResponseDto.java @@ -0,0 +1,18 @@ +package com.gdg.gdgback.Analysis.DTO; + +import com.gdg.gdgback.Analysis.ExpectationStat; +import com.gdg.gdgback.Analysis.ScoreStat; +import com.gdg.gdgback.Analysis.SymptomStat; +import lombok.Builder; +import lombok.Data; + +import java.util.ArrayList; + +@Builder +@Data +public class AnalysisResponseDto { + int diaryNum; + ArrayList symptomStats; + ExpectationStat expectationStat; + ArrayList scoreStats; +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/ExpectationStat.java b/src/main/java/com/gdg/gdgback/Analysis/ExpectationStat.java new file mode 100644 index 0000000..fc56a18 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/ExpectationStat.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Analysis; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class ExpectationStat { + Integer O; + Integer X; +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/ScoreStat.java b/src/main/java/com/gdg/gdgback/Analysis/ScoreStat.java new file mode 100644 index 0000000..321f478 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/ScoreStat.java @@ -0,0 +1,13 @@ +package com.gdg.gdgback.Analysis; + +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Builder +@Data +public class ScoreStat { + private LocalDateTime date; + private int score; +} diff --git a/src/main/java/com/gdg/gdgback/Analysis/SymptomStat.java b/src/main/java/com/gdg/gdgback/Analysis/SymptomStat.java new file mode 100644 index 0000000..285e36a --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Analysis/SymptomStat.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Analysis; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class SymptomStat { + private String name; + private int count; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselController.java b/src/main/java/com/gdg/gdgback/Counsel/CounselController.java new file mode 100644 index 0000000..516d3c8 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselController.java @@ -0,0 +1,58 @@ +package com.gdg.gdgback.Counsel; + +import com.gdg.gdgback.Counsel.DTO.Request.CounselCreateRequestDto; +import com.gdg.gdgback.Counsel.DTO.Request.CounselDeleteRequestDto; +import com.gdg.gdgback.Counsel.DTO.Request.CounselEndRequestDto; +import com.gdg.gdgback.Counsel.DTO.Response.CounselCreateResponseDto; +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadListResponseDto; +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadResponseDto; +import jakarta.servlet.http.HttpSession; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@Profile("!test") +@RestController +@RequestMapping("/counsel") +public class CounselController { + CounselService counselService; + + @Autowired + CounselController(CounselService counselService) { + this.counselService = counselService; + } + + @GetMapping + ResponseEntity readCounsel(@RequestParam String id) { + return ResponseEntity.ok().body(counselService.readCounsel(id)); + } + + @GetMapping("/list") + ResponseEntity readCounselList() { + return ResponseEntity.ok().body(counselService.readCounselList()); + } + + @GetMapping("/user") + ResponseEntity readCounselByUserId(@RequestParam String id) { + return ResponseEntity.ok().body(counselService.readCounselByUserId(id)); + } + + @PostMapping + ResponseEntity createCounsel(HttpSession session, @Valid @RequestBody CounselCreateRequestDto createRequestDto) { + return ResponseEntity.ok().body(counselService.createCounsel(session, createRequestDto)); + } + + @PostMapping("/end") + ResponseEntity endCounsel(@Valid @RequestBody CounselEndRequestDto counselEndRequestDto) { + counselService.endCounsel(counselEndRequestDto); + return ResponseEntity.ok().body("정상적으로 상담이 종료되었습니다."); + } + + @PostMapping("/delete") + ResponseEntity deleteCounsel(@Valid @RequestBody CounselDeleteRequestDto deleteRequestDto) { + counselService.deleteCounsel(deleteRequestDto); + return ResponseEntity.ok().body("정상적으로 삭제되었습니다."); + } +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselDocument.java b/src/main/java/com/gdg/gdgback/Counsel/CounselDocument.java new file mode 100644 index 0000000..e8d79ed --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselDocument.java @@ -0,0 +1,24 @@ +package com.gdg.gdgback.Counsel; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.time.LocalDateTime; + +@Builder +@Getter +@Document("counsel") +public class CounselDocument { + @Id + String id; + @Indexed + String userId; + @Indexed + LocalDateTime startTime; + @Indexed + LocalDateTime endTime; + String summation; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselMapper.java b/src/main/java/com/gdg/gdgback/Counsel/CounselMapper.java new file mode 100644 index 0000000..4103aed --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselMapper.java @@ -0,0 +1,47 @@ +package com.gdg.gdgback.Counsel; + +import com.gdg.gdgback.Counsel.DTO.Request.CounselCreateRequestDto; +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadListResponseDto; +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadResponseDto; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class CounselMapper { + public static CounselReadResponseDto map(CounselDocument counselDocument) { + LocalDateTime startTime = counselDocument.getStartTime(); + LocalDateTime endTime = counselDocument.getEndTime(); + if(endTime == null) { + endTime = LocalDateTime.now(); + } + + return CounselReadResponseDto.builder() + .id(counselDocument.getId()) + .userId(counselDocument.getUserId()) + .startTime(counselDocument.getStartTime()) + .endTime(endTime) + .seconds(Duration.between(startTime, endTime).toSeconds()) + .summation(counselDocument.getSummation()) + .build(); + } + + public static CounselReadListResponseDto map(List counselDocumentList) { + ArrayList counsels = counselDocumentList.stream() + .map(CounselMapper::map) + .collect(Collectors.toCollection(ArrayList::new)); + + return CounselReadListResponseDto.builder() + .counsels(counsels) + .build(); + } + + public static CounselDocument map(CounselCreateRequestDto dto) { + return CounselDocument.builder() + .userId(dto.getUserId()) + .startTime(LocalDateTime.now()) + .build(); + } +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselNotExistsException.java b/src/main/java/com/gdg/gdgback/Counsel/CounselNotExistsException.java new file mode 100644 index 0000000..7914584 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselNotExistsException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Counsel; + +public class CounselNotExistsException extends RuntimeException { + public CounselNotExistsException(String message) { + super("Counsel does not exist: " + message); + } +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselRepository.java b/src/main/java/com/gdg/gdgback/Counsel/CounselRepository.java new file mode 100644 index 0000000..ddbb6fc --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselRepository.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Counsel; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface CounselRepository extends MongoRepository { + List findAllByUserId(String id); +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselService.java b/src/main/java/com/gdg/gdgback/Counsel/CounselService.java new file mode 100644 index 0000000..c368f6b --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselService.java @@ -0,0 +1,21 @@ +package com.gdg.gdgback.Counsel; + +import com.gdg.gdgback.Counsel.DTO.Request.*; +import com.gdg.gdgback.Counsel.DTO.Response.*; +import jakarta.servlet.http.HttpSession; +import org.springframework.stereotype.Service; + +import java.time.YearMonth; + +@Service +public interface CounselService { + CounselReadResponseDto readCounsel(String id); + CounselReadListResponseDto readCounselList(); + CounselReadListResponseDto readCounselByUserId(String id); + CounselReadListResponseDto readCounselByUserIdAndYearMonth(String id, YearMonth yearMonth); + CounselCreateResponseDto createCounsel(HttpSession session, CounselCreateRequestDto createRequestDto); + void deleteCounselsOverTimeLimit(); + void endCounsel(CounselEndRequestDto counselEndRequestDto); + void deleteCounsel(CounselDeleteRequestDto deleteRequestDto); + void validateCounselExists(String id); +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/CounselServiceImpl.java b/src/main/java/com/gdg/gdgback/Counsel/CounselServiceImpl.java new file mode 100644 index 0000000..1cd183e --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/CounselServiceImpl.java @@ -0,0 +1,127 @@ +package com.gdg.gdgback.Counsel; + +import com.gdg.gdgback.Agent.DTO.Request.AgentTextRequestDto; +import com.gdg.gdgback.Agent.Service.AgentService; +import com.gdg.gdgback.Counsel.DTO.Request.*; +import com.gdg.gdgback.Counsel.DTO.Response.*; +import com.gdg.gdgback.Global.Validator; +import jakarta.servlet.http.HttpSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.List; + +@Service +@EnableScheduling +public class CounselServiceImpl implements CounselService { + private final CounselRepository counselRepository; + private final AgentService agentService; + + private final Validator validator; + + @Autowired + private MongoTemplate mongoTemplate; + + @Autowired + CounselServiceImpl(CounselRepository counselRepository, AgentService agentService, Validator validator) { + this.counselRepository = counselRepository; + this.agentService = agentService; + this.validator = validator; + } + + @Override + public CounselCreateResponseDto createCounsel(HttpSession session, CounselCreateRequestDto createRequestDto) { + validator.validateUserExists(createRequestDto.getUserId()); + + session.setAttribute("Dialogue", "[Dialogue]"); + CounselDocument counselDocument = CounselMapper.map(createRequestDto); + + String id = counselRepository.save(counselDocument).getId(); + String response = agentService.replyByText(session, AgentTextRequestDto.builder().counselId(id).content("지금 공황이 오는 것 같아요. 최대한 짧게 뭐라도 말해주세요.").build()); + return CounselCreateResponseDto.builder() + .id(id) + .content(response) + .build(); + } + + @Override + public CounselReadResponseDto readCounsel(String id) { + CounselDocument counselDocument = counselRepository.findById(id) + .orElseThrow(() -> new CounselNotExistsException(id)); + + return CounselMapper.map(counselDocument); + } + + @Override + public CounselReadListResponseDto readCounselList() { + List counselDocumentList = counselRepository.findAll(); + + return CounselMapper.map(counselDocumentList); + } + + @Override + public CounselReadListResponseDto readCounselByUserId(String id) { + validator.validateUserExists(id); + + List counselDocumentList = counselRepository.findAllByUserId(id); + return CounselMapper.map(counselDocumentList); + } + + @Override + public CounselReadListResponseDto readCounselByUserIdAndYearMonth(String id, YearMonth yearMonth) { + validator.validateUserExists(id); + LocalDate start = yearMonth.atDay(1); + LocalDate end = yearMonth.atEndOfMonth(); + + Query query = new Query() + .addCriteria(Criteria.where("userId").is(id)) + .addCriteria(Criteria.where("createdAt").gte(start).lte(end)); + + List counselDocumentList = mongoTemplate.find(query, CounselDocument.class); + return CounselMapper.map(counselDocumentList); + } + + @Override + public void deleteCounsel(CounselDeleteRequestDto deleteRequestDto) { + CounselDocument counselDocument = counselRepository.findById(deleteRequestDto.getId()) + .orElseThrow(() -> new CounselNotExistsException(deleteRequestDto.getId())); + + counselRepository.delete(counselDocument); + } + + @Scheduled(cron = "0 0 2 * * ?") + @Override + public void deleteCounselsOverTimeLimit() { + LocalDateTime threshold = LocalDateTime.now().minusMinutes(30); + + Query query = new Query(Criteria.where("endTime").is(null).and("startTime").lt(threshold)); + + mongoTemplate.remove(query, CounselDocument.class); + } + + @Override + public void endCounsel(CounselEndRequestDto counselEndRequestDto) { + validateCounselExists(counselEndRequestDto.getId()); + + Query query = new Query(Criteria.where("id").is(counselEndRequestDto.getId())); + Update update = new Update().set("endTime", LocalDateTime.now()); + + mongoTemplate.updateFirst(query, update, CounselDocument.class); + } + + @Override + public void validateCounselExists(String id) { + if(!counselRepository.existsById(id)) { + throw new CounselNotExistsException(id); + } + } +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto.java b/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto.java new file mode 100644 index 0000000..10151ea --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselCreateRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Counsel.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class CounselCreateRequestDto { + @NotNull(message="userId는 필수 값입니다.") + private String userId; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto.java b/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto.java new file mode 100644 index 0000000..84eea91 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselDeleteRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Counsel.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class CounselDeleteRequestDto { + @NotNull(message="id는 필수 값입니다.") + private String id; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto.java b/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto.java new file mode 100644 index 0000000..4e1c81e --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/DTO/Request/CounselEndRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Counsel.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class CounselEndRequestDto { + @NotNull(message = "id는 필수 값입니다.") + private String id; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto.java b/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto.java new file mode 100644 index 0000000..b7bdb73 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselCreateResponseDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Counsel.DTO.Response; + + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class CounselCreateResponseDto { + String id; + String content; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto.java b/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto.java new file mode 100644 index 0000000..79c897d --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselReadListResponseDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Counsel.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.util.ArrayList; + +@Builder +@Data +public class CounselReadListResponseDto { + ArrayList counsels; +} diff --git a/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto.java b/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto.java new file mode 100644 index 0000000..e4ab3c3 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Counsel/DTO/Response/CounselReadResponseDto.java @@ -0,0 +1,18 @@ +package com.gdg.gdgback.Counsel.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Builder +@Data +public class CounselReadResponseDto { + String id; + String userId; + + LocalDateTime startTime; + LocalDateTime endTime; + long seconds; + String summation; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto.java b/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto.java new file mode 100644 index 0000000..badac10 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryCreateRequestDto.java @@ -0,0 +1,24 @@ +package com.gdg.gdgback.Diary.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Builder +@Data +public class DiaryCreateRequestDto { + @NotNull(message = "userId는 필수 입력 값입니다.") + private String userId; + private String counselId; + + private MultipartFile picture; + private String[] category; + private Integer score; + private Boolean expected; + + @NotNull(message = "title 은 필수 입력 값입니다.") + private String title; + @NotNull(message = "content 는 필수 입력 값입니다.") + private String content; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto.java b/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto.java new file mode 100644 index 0000000..8599b57 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryDeleteRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Diary.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class DiaryDeleteRequestDto { + @NotNull(message = "id는 필수 입력 값입니다.") + private String id; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryImageUploadRequestDto.java b/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryImageUploadRequestDto.java new file mode 100644 index 0000000..d651380 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DTO/Request/DiaryImageUploadRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Diary.DTO.Request; + +import lombok.Builder; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Builder +@Data +public class DiaryImageUploadRequestDto { + String id; + MultipartFile image; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto.java b/src/main/java/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto.java new file mode 100644 index 0000000..a295ab3 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DTO/Response/DiaryReadListResponseDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Diary.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.util.ArrayList; + +@Builder +@Data +public class DiaryReadListResponseDto { + ArrayList diaries; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto.java b/src/main/java/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto.java new file mode 100644 index 0000000..1477000 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DTO/Response/DiaryReadResponseDto.java @@ -0,0 +1,24 @@ +package com.gdg.gdgback.Diary.DTO.Response; + +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadResponseDto; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Builder +@Data +public class DiaryReadResponseDto { + String id; + String userId; + + CounselReadResponseDto counsel; + + LocalDateTime date; + String imageUrl; + Boolean expected; + String[] category; + Integer score; + String title; + String content; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryController.java b/src/main/java/com/gdg/gdgback/Diary/DiaryController.java new file mode 100644 index 0000000..4b60cc4 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryController.java @@ -0,0 +1,53 @@ +package com.gdg.gdgback.Diary; + +import com.gdg.gdgback.Diary.DTO.Request.*; +import com.gdg.gdgback.Diary.DTO.Response.*; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.concurrent.CompletableFuture; + +@RestController +@RequestMapping("/diary") +public class DiaryController { + DiaryService diaryService; + + @Autowired + DiaryController(DiaryService diaryService) { + this.diaryService = diaryService; + } + + @GetMapping + ResponseEntity readDiary(@RequestParam String id) { + return ResponseEntity.ok().body(diaryService.readDiary(id)); + } + + @GetMapping("/list") + ResponseEntity readDiaryList() { + return ResponseEntity.ok().body(diaryService.readDiaryList()); + } + + @GetMapping("/user") + ResponseEntity readDiaryListByUserId(@RequestParam String id) { + return ResponseEntity.ok().body(diaryService.readDiaryListByUserId(id)); + } + + @PostMapping + ResponseEntity createDiary(@Valid @RequestBody DiaryCreateRequestDto createRequestDto) { + return ResponseEntity.ok().body(diaryService.createDiary(createRequestDto)); + } + + @PostMapping("/delete") + ResponseEntity deleteDiary(@Valid @RequestBody DiaryDeleteRequestDto deleteRequestDto) { + this.diaryService.deleteDiary(deleteRequestDto); + return ResponseEntity.ok().body("정상적으로 일지가 삭제되었습니다."); + } + + @PostMapping("/image") + ResponseEntity> uploadDiaryImage(@Valid @ModelAttribute DiaryImageUploadRequestDto imageUploadRequestDto) { + return ResponseEntity.ok().body(this.diaryService.uploadDiaryImage(imageUploadRequestDto)); + } +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryDocument.java b/src/main/java/com/gdg/gdgback/Diary/DiaryDocument.java new file mode 100644 index 0000000..67b5987 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryDocument.java @@ -0,0 +1,30 @@ +package com.gdg.gdgback.Diary; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.time.LocalDateTime; + +@Builder +@Getter +@Setter +@Document("diary") +public class DiaryDocument { + @Id + String id; + @Indexed + String userId; + String counselId; + + LocalDateTime date; + String imageUrl; + String[] category; + Integer score; + Boolean expected; + String title; + String content; +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryImageIOException.java b/src/main/java/com/gdg/gdgback/Diary/DiaryImageIOException.java new file mode 100644 index 0000000..98dc145 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryImageIOException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Diary; + +public class DiaryImageIOException extends RuntimeException { + public DiaryImageIOException(String message) { + super("IO Exception of Diary Image: " + message); + } +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryMapper.java b/src/main/java/com/gdg/gdgback/Diary/DiaryMapper.java new file mode 100644 index 0000000..06d21c7 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryMapper.java @@ -0,0 +1,36 @@ +package com.gdg.gdgback.Diary; + +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadResponseDto; +import com.gdg.gdgback.Diary.DTO.Request.DiaryCreateRequestDto; +import com.gdg.gdgback.Diary.DTO.Response.DiaryReadResponseDto; + +import java.time.LocalDateTime; +public class DiaryMapper { + public static DiaryDocument map(DiaryCreateRequestDto createRequestDto) { + return DiaryDocument.builder() + .userId(createRequestDto.getUserId()) + .counselId(createRequestDto.getCounselId()) + .expected(createRequestDto.getExpected()) + .category(createRequestDto.getCategory()) + .score(createRequestDto.getScore()) + .date(LocalDateTime.now()) + .title(createRequestDto.getTitle()) + .content(createRequestDto.getContent()) + .build(); + } + + public static DiaryReadResponseDto map(DiaryDocument diaryDocument, CounselReadResponseDto counsel) { + return DiaryReadResponseDto.builder() + .id(diaryDocument.getId()) + .userId(diaryDocument.getUserId()) + .counsel(counsel) + .expected(diaryDocument.getExpected()) + .date(diaryDocument.getDate()) + .imageUrl(diaryDocument.getImageUrl()) + .category(diaryDocument.getCategory()) + .score(diaryDocument.getScore()) + .title(diaryDocument.getTitle()) + .content(diaryDocument.getContent()) + .build(); + } +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryNotFoundException.java b/src/main/java/com/gdg/gdgback/Diary/DiaryNotFoundException.java new file mode 100644 index 0000000..928dfbe --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryNotFoundException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Diary; + +public class DiaryNotFoundException extends RuntimeException { + public DiaryNotFoundException(String message) { + super("Diary does not exist: " + message); + } +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryRepository.java b/src/main/java/com/gdg/gdgback/Diary/DiaryRepository.java new file mode 100644 index 0000000..f283f11 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryRepository.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Diary; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface DiaryRepository extends MongoRepository { + List findAllByUserIdOrderByDateDesc(String id); +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryService.java b/src/main/java/com/gdg/gdgback/Diary/DiaryService.java new file mode 100644 index 0000000..8315504 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryService.java @@ -0,0 +1,24 @@ +package com.gdg.gdgback.Diary; + +import com.gdg.gdgback.Diary.DTO.Request.DiaryCreateRequestDto; +import com.gdg.gdgback.Diary.DTO.Request.DiaryDeleteRequestDto; +import com.gdg.gdgback.Diary.DTO.Request.DiaryImageUploadRequestDto; +import com.gdg.gdgback.Diary.DTO.Response.DiaryReadListResponseDto; +import com.gdg.gdgback.Diary.DTO.Response.DiaryReadResponseDto; +import com.gdg.gdgback.User.Exception.UserNotExistsException; +import org.springframework.stereotype.Service; + +import java.time.YearMonth; +import java.util.concurrent.CompletableFuture; + +@Service +public interface DiaryService { + String createDiary(DiaryCreateRequestDto createRequestDto) throws UserNotExistsException; + DiaryReadResponseDto readDiary(String id) throws DiaryNotFoundException; + DiaryReadListResponseDto readDiaryList(); + DiaryReadListResponseDto readDiaryListByUserId(String id) throws UserNotExistsException; + DiaryReadListResponseDto readDiaryListByUserIdAndYearMonth(String id, YearMonth yearMonth); + void deleteDiary(DiaryDeleteRequestDto deleteRequestDto) throws DiaryNotFoundException; + + CompletableFuture uploadDiaryImage(DiaryImageUploadRequestDto imageUploadRequestDto); +} diff --git a/src/main/java/com/gdg/gdgback/Diary/DiaryServiceImpl.java b/src/main/java/com/gdg/gdgback/Diary/DiaryServiceImpl.java new file mode 100644 index 0000000..b81d711 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Diary/DiaryServiceImpl.java @@ -0,0 +1,146 @@ +package com.gdg.gdgback.Diary; + +import com.gdg.gdgback.Counsel.CounselNotExistsException; +import com.gdg.gdgback.Counsel.CounselService; +import com.gdg.gdgback.Diary.DTO.Request.*; +import com.gdg.gdgback.Diary.DTO.Response.*; +import com.gdg.gdgback.Global.Validator; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +@Service +public class DiaryServiceImpl implements DiaryService { + + private final DiaryRepository diaryRepository; + + private final CounselService counselService; + + private final Validator validator; + + @Autowired + private MongoTemplate mongoTemplate; + + @Autowired + DiaryServiceImpl(CounselService counselService, DiaryRepository diaryRepository, Validator validator) { + this.diaryRepository = diaryRepository; + + this.counselService = counselService; + + this.validator = validator; + } + + @Override + public String createDiary(DiaryCreateRequestDto createRequestDto) { + validator.validateUserExists(createRequestDto.getUserId()); + return diaryRepository.save(DiaryMapper.map(createRequestDto)).getId(); + } + + @Override + public DiaryReadResponseDto readDiary(String id) { + DiaryDocument diaryDocument = diaryRepository.findById(id) + .orElseThrow(() -> new DiaryNotFoundException(id)); + return convertDocumentToDto(diaryDocument); + } + + @Override + public DiaryReadListResponseDto readDiaryList() { + List diaryDocumentList = diaryRepository.findAll(); + return convertDocumentListToListDto(diaryDocumentList); + } + + @Override + public DiaryReadListResponseDto readDiaryListByUserId(String id) { + validator.validateUserExists(id); + + List diaryDocumentList = diaryRepository.findAllByUserIdOrderByDateDesc(id); + return convertDocumentListToListDto(diaryDocumentList); + } + + @Override + public DiaryReadListResponseDto readDiaryListByUserIdAndYearMonth(String id, YearMonth yearMonth) { + validator.validateUserExists(id); + + LocalDate start = yearMonth.atDay(1); + LocalDate end = yearMonth.atEndOfMonth(); + + Query query = new Query() + .addCriteria(Criteria.where("userId").is(id)) + .addCriteria(Criteria.where("date").gte(start).lte(end)); + + return convertDocumentListToListDto(mongoTemplate.find(query, DiaryDocument.class)); + } + + @Override + public void deleteDiary(DiaryDeleteRequestDto deleteRequestDto) { + DiaryDocument diaryDocument = diaryRepository.findById(deleteRequestDto.getId()) + .orElseThrow(() -> new DiaryNotFoundException(deleteRequestDto.getId())); + diaryRepository.delete(diaryDocument); + } + + @Async + @Override + public CompletableFuture uploadDiaryImage(DiaryImageUploadRequestDto imageUploadRequestDto) { + DiaryDocument diaryDocument = diaryRepository.findById(imageUploadRequestDto.getId()) + .orElseThrow(() -> new DiaryNotFoundException(imageUploadRequestDto.getId())); + + String imageUrl = saveImage(imageUploadRequestDto.getImage()); + + diaryDocument.setImageUrl(imageUrl); + diaryRepository.save(diaryDocument); + return CompletableFuture.completedFuture(imageUrl); + } + + private String saveImage(MultipartFile image) { + try { + String UPLOAD_PATH = "/app/images"; + String fileName = Paths.get(UUID.randomUUID() + "_" + image.getOriginalFilename()).getFileName().toString(); + Path path = Paths.get(UPLOAD_PATH, fileName); + Files.createDirectories(path.getParent()); + Files.copy(image.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING); + return "/images/" + fileName; + } catch (IOException e) { + throw new DiaryImageIOException("Failed to save image file."); + } + } + + private DiaryReadResponseDto convertDocumentToDto(DiaryDocument document) { + try { + String counselId = document.getCounselId(); + if (counselId == null) { + return DiaryMapper.map(document, null); + } else { + return DiaryMapper.map(document, counselService.readCounsel(counselId)); + } + } catch (CounselNotExistsException e) { + return DiaryMapper.map(document, null); // 얘가 범인인가? + } + } + + private DiaryReadListResponseDto convertDocumentListToListDto(List documentList) { + ArrayList dtoArrayList = documentList.stream() + .map(this::convertDocumentToDto) + .collect(Collectors.toCollection(ArrayList::new)); + + return DiaryReadListResponseDto.builder() + .diaries(dtoArrayList) + .build(); + } +} diff --git a/src/main/java/com/gdg/gdgback/GdgbackApplication.java b/src/main/java/com/gdg/gdgback/GdgbackApplication.java index d7a828b..afd5ad3 100644 --- a/src/main/java/com/gdg/gdgback/GdgbackApplication.java +++ b/src/main/java/com/gdg/gdgback/GdgbackApplication.java @@ -1,13 +1,18 @@ -package com.gdg.gdgback; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class GdgbackApplication { - - public static void main(String[] args) { - SpringApplication.run(GdgbackApplication.class, args); - } - -} +package com.gdg.gdgback; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.data.mongodb.config.EnableMongoAuditing; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; +import org.springframework.scheduling.annotation.EnableAsync; + +@EnableMongoRepositories +@EnableMongoAuditing +@EnableAsync +@SpringBootApplication(exclude = SecurityAutoConfiguration.class) +public class GdgbackApplication { + public static void main(String[] args) { + SpringApplication.run(GdgbackApplication.class, args); + } +} diff --git a/src/main/java/com/gdg/gdgback/Global/ExceptionController.java b/src/main/java/com/gdg/gdgback/Global/ExceptionController.java new file mode 100644 index 0000000..090a66e --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Global/ExceptionController.java @@ -0,0 +1,26 @@ +package com.gdg.gdgback.Global; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class ExceptionController { + @ExceptionHandler(RuntimeException.class) + public ResponseEntity handleRuntimeException(RuntimeException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidationExceptions(MethodArgumentNotValidException ex) { + Map errors = new HashMap<>(); + ex.getBindingResult().getFieldErrors().forEach(error -> + errors.put(error.getField(), error.getDefaultMessage()) + ); + return ResponseEntity.badRequest().body(errors); + } +} diff --git a/src/main/java/com/gdg/gdgback/Global/Validator.java b/src/main/java/com/gdg/gdgback/Global/Validator.java new file mode 100644 index 0000000..a954a9f --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Global/Validator.java @@ -0,0 +1,6 @@ +package com.gdg.gdgback.Global; + +public interface Validator { + void validateUserExists(String id); + void validateCounselExists(String id); +} diff --git a/src/main/java/com/gdg/gdgback/Global/ValidatorImpl.java b/src/main/java/com/gdg/gdgback/Global/ValidatorImpl.java new file mode 100644 index 0000000..29b1176 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Global/ValidatorImpl.java @@ -0,0 +1,34 @@ +package com.gdg.gdgback.Global; + +import com.gdg.gdgback.Counsel.CounselNotExistsException; +import com.gdg.gdgback.Counsel.CounselRepository; +import com.gdg.gdgback.User.Exception.UserNotExistsException; +import com.gdg.gdgback.User.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ValidatorImpl implements Validator { + private final UserRepository userRepository; + private final CounselRepository counselRepository; + + @Autowired + ValidatorImpl(UserRepository userRepository, CounselRepository counselRepository) { + this.userRepository = userRepository; + this.counselRepository = counselRepository; + } + + @Override + public void validateUserExists(String id) { + if(!userRepository.existsById(id)) { + throw new UserNotExistsException(id); + } + } + + @Override + public void validateCounselExists(String id) { + if(!counselRepository.existsById(id)) { + throw new CounselNotExistsException(id); + } + } +} diff --git a/src/main/java/com/gdg/gdgback/Global/WebConfig.java b/src/main/java/com/gdg/gdgback/Global/WebConfig.java new file mode 100644 index 0000000..e5cadbe --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Global/WebConfig.java @@ -0,0 +1,24 @@ +package com.gdg.gdgback.Global; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") // 모든 경로에 대해 + .allowedOriginPatterns("*") // 특정 Origin 허용 + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 허용할 HTTP 메서드 지정 + .allowedHeaders("*") // 모든 헤더 허용 + .allowCredentials(true); // 쿠키 및 인증정보 포함 허용 + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/images/**") + .addResourceLocations("file:/app/images/"); + } +} diff --git a/src/main/java/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto.java b/src/main/java/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto.java new file mode 100644 index 0000000..35c6519 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/DTO/Request/MessageCreateRequestDto.java @@ -0,0 +1,16 @@ +package com.gdg.gdgback.Message.DTO.Request; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class MessageCreateRequestDto { + public static MessageCreateRequestDto of(String counselId, String role, String content) { + return new MessageCreateRequestDto(counselId, role, content); + } + + String counselId; + String role; + String content; +} diff --git a/src/main/java/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto.java b/src/main/java/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto.java new file mode 100644 index 0000000..4cded11 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/DTO/Response/MessageReadListResponseDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.Message.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.util.ArrayList; + +@Builder +@Data +public class MessageReadListResponseDto { + ArrayList messages; +} diff --git a/src/main/java/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto.java b/src/main/java/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto.java new file mode 100644 index 0000000..22bd11c --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/DTO/Response/MessageReadResponseDto.java @@ -0,0 +1,16 @@ +package com.gdg.gdgback.Message.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Builder +@Data +public class MessageReadResponseDto { + String id; + String counselId; + String role; + String content; + LocalDateTime date; +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageController.java b/src/main/java/com/gdg/gdgback/Message/MessageController.java new file mode 100644 index 0000000..4d09dcc --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageController.java @@ -0,0 +1,35 @@ +package com.gdg.gdgback.Message; + +import com.gdg.gdgback.Message.DTO.Response.MessageReadListResponseDto; +import com.gdg.gdgback.Message.DTO.Response.MessageReadResponseDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@Profile("!test") +@RestController +@RequestMapping("/counsel/message") +public class MessageController { + private final MessageService messageService; + + @Autowired + MessageController(MessageService messageService) { + this.messageService = messageService; + } + + @GetMapping + public ResponseEntity readMessageByCounselId(@RequestParam String counselId) { + return ResponseEntity.ok().body(messageService.readMessageByCounselId(counselId)); + } + + @GetMapping("/id") + public ResponseEntity readMessage(@RequestParam String id) { + return ResponseEntity.ok().body(messageService.readMessage(id)); + } + + @GetMapping("/list") + public ResponseEntity readListMessage() { + return ResponseEntity.ok().body(messageService.readListMessage()); + } +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageDocument.java b/src/main/java/com/gdg/gdgback/Message/MessageDocument.java new file mode 100644 index 0000000..e3acdbb --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageDocument.java @@ -0,0 +1,26 @@ +package com.gdg.gdgback.Message; + +import lombok.Builder; +import lombok.Data; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.time.LocalDateTime; + +@Builder +@Data +@Document(collection = "message") +public class MessageDocument { + @Id + String id; + @Indexed + String counselId; + + String role; + String content; + + @CreatedDate + LocalDateTime date; +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageMapper.java b/src/main/java/com/gdg/gdgback/Message/MessageMapper.java new file mode 100644 index 0000000..6a4a94a --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageMapper.java @@ -0,0 +1,36 @@ +package com.gdg.gdgback.Message; + +import com.gdg.gdgback.Message.DTO.Request.MessageCreateRequestDto; +import com.gdg.gdgback.Message.DTO.Response.MessageReadListResponseDto; +import com.gdg.gdgback.Message.DTO.Response.MessageReadResponseDto; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class MessageMapper { + public static MessageDocument map(MessageCreateRequestDto messageCreateRequestDto) { + return MessageDocument.builder() + .counselId(messageCreateRequestDto.getCounselId()) + .role(messageCreateRequestDto.getRole()) + .content(messageCreateRequestDto.getContent()) + .build(); + } + public static MessageReadResponseDto map(MessageDocument messageDocument) { + return MessageReadResponseDto.builder() + .id(messageDocument.getId()) + .counselId(messageDocument.getCounselId()) + .role(messageDocument.getRole()) + .content(messageDocument.getContent()) + .date(messageDocument.getDate()) + .build(); + } + + public static MessageReadListResponseDto map(List messageDocumentList) { + ArrayList messages = messageDocumentList.stream().map(MessageMapper::map).collect(Collectors.toCollection(ArrayList::new)); + + return MessageReadListResponseDto.builder() + .messages(messages) + .build(); + } +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageNotExistsException.java b/src/main/java/com/gdg/gdgback/Message/MessageNotExistsException.java new file mode 100644 index 0000000..8a04e6a --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageNotExistsException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.Message; + +public class MessageNotExistsException extends RuntimeException { + public MessageNotExistsException() { + super("Message does not exist."); + } +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageRepository.java b/src/main/java/com/gdg/gdgback/Message/MessageRepository.java new file mode 100644 index 0000000..f9f0e8a --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageRepository.java @@ -0,0 +1,11 @@ +package com.gdg.gdgback.Message; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface MessageRepository extends MongoRepository { + List findAllByCounselId(String id); +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageService.java b/src/main/java/com/gdg/gdgback/Message/MessageService.java new file mode 100644 index 0000000..f12782c --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageService.java @@ -0,0 +1,14 @@ +package com.gdg.gdgback.Message; + +import com.gdg.gdgback.Message.DTO.Request.MessageCreateRequestDto; +import com.gdg.gdgback.Message.DTO.Response.MessageReadListResponseDto; +import com.gdg.gdgback.Message.DTO.Response.MessageReadResponseDto; +import org.springframework.stereotype.Service; + +@Service +public interface MessageService { + void createMessage(MessageCreateRequestDto messageCreateRequestDto); + MessageReadListResponseDto readMessageByCounselId(String id); + MessageReadResponseDto readMessage(String id); + MessageReadListResponseDto readListMessage(); +} diff --git a/src/main/java/com/gdg/gdgback/Message/MessageServiceImpl.java b/src/main/java/com/gdg/gdgback/Message/MessageServiceImpl.java new file mode 100644 index 0000000..b721a31 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/Message/MessageServiceImpl.java @@ -0,0 +1,57 @@ +package com.gdg.gdgback.Message; + +import com.gdg.gdgback.Global.Validator; +import com.gdg.gdgback.Message.DTO.Request.*; +import com.gdg.gdgback.Message.DTO.Response.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Profile("!test") +@Service +public class MessageServiceImpl implements MessageService { + private final MessageRepository messageRepository; + + private final Validator validator; + + @Autowired + MessageServiceImpl(MessageRepository messageRepository, Validator validator) { + this.messageRepository = messageRepository; + this.validator = validator; + } + + @Async + @Override + public void createMessage(MessageCreateRequestDto messageCreateRequestDto) { + MessageDocument messageDocument = MessageMapper.map(messageCreateRequestDto); + + messageRepository.save(messageDocument); + } + + @Override + public MessageReadListResponseDto readMessageByCounselId(String id) { + validator.validateCounselExists(id); + + List messages = messageRepository.findAllByCounselId(id); + + return MessageMapper.map(messages); + } + + @Override + public MessageReadResponseDto readMessage(String id) { + MessageDocument messageDocument = messageRepository.findById(id) + .orElseThrow(MessageNotExistsException::new); + + return MessageMapper.map(messageDocument); + } + + @Override + public MessageReadListResponseDto readListMessage() { + List messages = messageRepository.findAll(); + + return MessageMapper.map(messages); + } +} diff --git a/src/main/java/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto.java b/src/main/java/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto.java new file mode 100644 index 0000000..5991f50 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/DTO/Request/UserCreateRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.User.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.*; + +@Builder +@Data +public class UserCreateRequestDto { + @NotNull(message = "id는 필수 입력 값입니다.") + private String id; + private String name; +} diff --git a/src/main/java/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto.java b/src/main/java/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto.java new file mode 100644 index 0000000..dad4465 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/DTO/Request/UserDeleteRequestDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.User.DTO.Request; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class UserDeleteRequestDto { + @NotNull(message = "id는 필수 입력 값입니다.") + private String id; +} diff --git a/src/main/java/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto.java b/src/main/java/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto.java new file mode 100644 index 0000000..3d106b5 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/DTO/Response/UserReadListResponseDto.java @@ -0,0 +1,12 @@ +package com.gdg.gdgback.User.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.util.ArrayList; + +@Builder +@Data +public class UserReadListResponseDto { + ArrayList users; +} diff --git a/src/main/java/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto.java b/src/main/java/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto.java new file mode 100644 index 0000000..dc6f6f2 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/DTO/Response/UserReadResponseDto.java @@ -0,0 +1,14 @@ +package com.gdg.gdgback.User.DTO.Response; + +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Builder +@Data +public class UserReadResponseDto { + private String id; + private String name; + private LocalDateTime date; +} diff --git a/src/main/java/com/gdg/gdgback/User/Exception/UserAlreadyExistsException.java b/src/main/java/com/gdg/gdgback/User/Exception/UserAlreadyExistsException.java new file mode 100644 index 0000000..258f5de --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/Exception/UserAlreadyExistsException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.User.Exception; + +public class UserAlreadyExistsException extends RuntimeException { + public UserAlreadyExistsException() { + super("User already exists."); + } +} diff --git a/src/main/java/com/gdg/gdgback/User/Exception/UserNotExistsException.java b/src/main/java/com/gdg/gdgback/User/Exception/UserNotExistsException.java new file mode 100644 index 0000000..d7d2639 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/Exception/UserNotExistsException.java @@ -0,0 +1,7 @@ +package com.gdg.gdgback.User.Exception; + +public class UserNotExistsException extends RuntimeException { + public UserNotExistsException(String message) { + super("User does not exist: " + message); + } +} diff --git a/src/main/java/com/gdg/gdgback/User/UserController.java b/src/main/java/com/gdg/gdgback/User/UserController.java new file mode 100644 index 0000000..34e690f --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/UserController.java @@ -0,0 +1,39 @@ +package com.gdg.gdgback.User; + +import com.gdg.gdgback.User.DTO.Request.UserCreateRequestDto; +import com.gdg.gdgback.User.DTO.Request.UserDeleteRequestDto; +import com.gdg.gdgback.User.DTO.Response.UserReadListResponseDto; +import com.gdg.gdgback.User.DTO.Response.UserReadResponseDto; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/user") +public class UserController { + UserService userService; + + @Autowired + UserController(UserService userService) { + this.userService = userService; + } + @GetMapping("/list") + public ResponseEntity readUserList() { + return ResponseEntity.ok(userService.readUserList()); + } + @GetMapping + public ResponseEntity readUser(String id) { + return ResponseEntity.ok(userService.readUser(id)); + } + @PostMapping + public ResponseEntity createUser(@Valid @RequestBody UserCreateRequestDto userCreateRequestDto) { + userService.createUser(userCreateRequestDto); + return ResponseEntity.ok("회원가입 되었습니다."); + } + @PostMapping("/delete") + public ResponseEntity deleteUser(@Valid @RequestBody UserDeleteRequestDto deleteRequestDto) { + userService.deleteUser(deleteRequestDto); + return ResponseEntity.ok("정상적으로 삭제되었습니다."); + } +} diff --git a/src/main/java/com/gdg/gdgback/User/UserDocument.java b/src/main/java/com/gdg/gdgback/User/UserDocument.java new file mode 100644 index 0000000..0eac9b4 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/UserDocument.java @@ -0,0 +1,21 @@ +package com.gdg.gdgback.User; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.time.LocalDateTime; + +@Builder +@Getter +@Document("user") +public class UserDocument { + @Id + @Indexed + String id; + String name; + + LocalDateTime date; +} diff --git a/src/main/java/com/gdg/gdgback/User/UserMapper.java b/src/main/java/com/gdg/gdgback/User/UserMapper.java new file mode 100644 index 0000000..98434f8 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/UserMapper.java @@ -0,0 +1,34 @@ +package com.gdg.gdgback.User; + +import com.gdg.gdgback.User.DTO.Request.UserCreateRequestDto; +import com.gdg.gdgback.User.DTO.Response.UserReadListResponseDto; +import com.gdg.gdgback.User.DTO.Response.UserReadResponseDto; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class UserMapper { + public static UserReadResponseDto map(UserDocument userDocument) { + return UserReadResponseDto.builder() + .id(userDocument.getId()) + .name(userDocument.getName()) + .date(userDocument.getDate()) + .build(); + } + public static UserReadListResponseDto map(List userDocumentList) { + ArrayList users = userDocumentList.stream().map(UserMapper::map).collect(Collectors.toCollection(ArrayList::new)); + return UserReadListResponseDto.builder() + .users(users) + .build(); + } + + public static UserDocument map(UserCreateRequestDto userCreateRequestDto) { + return UserDocument.builder() + .id(userCreateRequestDto.getId()) + .name(userCreateRequestDto.getName()) + .date(LocalDateTime.now()) + .build(); + } +} diff --git a/src/main/java/com/gdg/gdgback/User/UserRepository.java b/src/main/java/com/gdg/gdgback/User/UserRepository.java new file mode 100644 index 0000000..4de3c51 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/UserRepository.java @@ -0,0 +1,8 @@ +package com.gdg.gdgback.User; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends MongoRepository { +} diff --git a/src/main/java/com/gdg/gdgback/User/UserService.java b/src/main/java/com/gdg/gdgback/User/UserService.java new file mode 100644 index 0000000..61dc604 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/UserService.java @@ -0,0 +1,14 @@ +package com.gdg.gdgback.User; + +import com.gdg.gdgback.User.DTO.Request.UserCreateRequestDto; +import com.gdg.gdgback.User.DTO.Request.UserDeleteRequestDto; +import com.gdg.gdgback.User.DTO.Response.UserReadListResponseDto; +import com.gdg.gdgback.User.DTO.Response.UserReadResponseDto; + +public interface UserService { + void createUser(UserCreateRequestDto userCreateRequestDto); + UserReadResponseDto readUser(String id); + UserReadListResponseDto readUserList(); + void deleteUser(UserDeleteRequestDto deleteRequestDto); + void validateUserNotExists(String id); +} diff --git a/src/main/java/com/gdg/gdgback/User/UserServiceImpl.java b/src/main/java/com/gdg/gdgback/User/UserServiceImpl.java new file mode 100644 index 0000000..c64a218 --- /dev/null +++ b/src/main/java/com/gdg/gdgback/User/UserServiceImpl.java @@ -0,0 +1,58 @@ +package com.gdg.gdgback.User; + +import com.gdg.gdgback.User.DTO.Request.*; +import com.gdg.gdgback.User.DTO.Response.*; +import com.gdg.gdgback.User.Exception.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + + @Autowired + UserServiceImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public void createUser(UserCreateRequestDto userCreateRequestDto) { + validateUserNotExists(userCreateRequestDto.getId()); + + UserDocument userDocument = UserMapper.map(userCreateRequestDto); + + userRepository.save(userDocument); + } + + @Override + public UserReadResponseDto readUser(String id) { + UserDocument userDocument = userRepository.findById(id) + .orElseThrow(() -> new UserNotExistsException(id)); + + return UserMapper.map(userDocument); + } + + @Override + public UserReadListResponseDto readUserList() { + List userDocumentList = userRepository.findAll(); + + return UserMapper.map(userDocumentList); + } + + @Override + public void deleteUser(UserDeleteRequestDto deleteRequestDto) { + UserDocument userDocument = userRepository.findById(deleteRequestDto.getId()) + .orElseThrow(() -> new UserNotExistsException(deleteRequestDto.getId())); + + userRepository.delete(userDocument); + } + + @Override + public void validateUserNotExists(String id) { + if(userRepository.existsById(id)) { + throw new UserAlreadyExistsException(); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c329bab..72233fd 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ -spring.application.name=gdgback +spring.application.name=gdgback +spring.web.resources.static-locations=classpath:/static/,file:/app/images/ \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..257cdce --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,20 @@ +server: + servlet: + session: + timeout: 5m + +spring: + profiles: + active: default + data: + mongodb: + uri: mongodb+srv://pupajusang01:1234@gdgback.rbtvd.mongodb.net/?retryWrites=true&w=majority&appName=gdgback + database: gdgback + web: + resources: + static-locations: classpath:/static/, file:/app/images/ + +gemini: + api: + url: ${GEMINI_URL} + key: ${GEMINI_KEY} \ No newline at end of file diff --git a/src/test/java/com/gdg/gdgback/Agent/AgentServiceTest.java b/src/test/java/com/gdg/gdgback/Agent/AgentServiceTest.java new file mode 100644 index 0000000..8b34cec --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Agent/AgentServiceTest.java @@ -0,0 +1,74 @@ +package com.gdg.gdgback.Agent; + +import com.gdg.gdgback.Agent.Context.Context; +import com.gdg.gdgback.Agent.Context.ContextService; +import com.gdg.gdgback.Agent.Core.GenerativeModelApi; +import com.gdg.gdgback.Agent.DTO.Request.AgentAudioRequestDto; +import com.gdg.gdgback.Agent.DTO.Request.AgentTextRequestDto; +import com.gdg.gdgback.Agent.Service.GoogleAgentService; +import com.gdg.gdgback.Agent.Speech.GoogleSpeechService; +import com.gdg.gdgback.Agent.Speech.SpeechService; +import com.gdg.gdgback.Message.MessageService; +import com.gdg.gdgback.Message.MessageServiceImpl; +import jakarta.servlet.http.HttpSession; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +@ExtendWith(MockitoExtension.class) +public class AgentServiceTest { + GenerativeModelApi generativeModelApi = mock(GenerativeModelApi.class); + SpeechService speechService = mock(GoogleSpeechService.class); + MessageService messageService = mock(MessageServiceImpl.class); + ContextService contextService = mock(ContextService.class); + HttpSession session = mock(HttpSession.class); + + @InjectMocks + GoogleAgentService agentService; + + @BeforeEach + void setUp() { + doReturn("test").when(generativeModelApi).generateResponse(anyString()); + doReturn("test").when(speechService).speechToText(any(byte[].class)); + doReturn(new byte[5]).when(speechService).textToSpeech(anyString()); + Context testContext = Context.builder() + .summary("") + .history(new ArrayList<>()) + .build(); + doReturn(testContext).when(contextService).getContext(session); + } + + @Test + void replyByText() { + AgentTextRequestDto dto = AgentTextRequestDto.builder() + .counselId("test") + .content("test") + .build(); + Assertions.assertDoesNotThrow(()->agentService.replyByText(session, dto)); + } + @Test + void replyByAudioFromText() { + AgentTextRequestDto dto = AgentTextRequestDto.builder() + .counselId("test") + .content("test") + .build(); + Assertions.assertDoesNotThrow(()->agentService.replyByAudio(session, dto)); + } + @Test + void replyByAudioResponseFromAudio() { + AgentAudioRequestDto dto = AgentAudioRequestDto.builder() + .counselId("test") + .content(new byte[5]) + .build(); + Assertions.assertDoesNotThrow(()->agentService.replyByAudio(session, dto)); + } +} diff --git a/src/test/java/com/gdg/gdgback/Counsel/CounselServiceTest.java b/src/test/java/com/gdg/gdgback/Counsel/CounselServiceTest.java new file mode 100644 index 0000000..5227bfb --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Counsel/CounselServiceTest.java @@ -0,0 +1,82 @@ +package com.gdg.gdgback.Counsel; + +import com.gdg.gdgback.Agent.DTO.Request.AgentTextRequestDto; +import com.gdg.gdgback.Agent.Service.AgentService; +import com.gdg.gdgback.Counsel.DTO.Request.CounselCreateRequestDto; +import com.gdg.gdgback.Counsel.DTO.Request.CounselDeleteRequestDto; +import com.gdg.gdgback.Global.Validator; +import com.gdg.gdgback.General.TestValidator; +import com.gdg.gdgback.User.Exception.UserNotExistsException; +import jakarta.servlet.http.HttpSession; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class CounselServiceTest { + @Spy + CounselRepository counselRepository = new CounselTestRepository(); + AgentService agentService = mock(AgentService.class); + HttpSession session = mock(HttpSession.class); + @Spy + Validator validator = new TestValidator(); + + @InjectMocks + CounselServiceImpl counselService; + + @BeforeEach + void setUp() { + doReturn("testResponse").when(agentService).replyByText(any(HttpSession.class), any(AgentTextRequestDto.class)); + } + + @Test + void createCounsel() { + CounselCreateRequestDto dto = CounselCreateRequestDto.builder() + .userId("test") + .build(); + + Assertions.assertDoesNotThrow(()->counselService.createCounsel(session, dto)); + } + @Test + void createCounselNotExistUser() { + CounselCreateRequestDto dto = CounselCreateRequestDto.builder() + .userId("id_not_exists") + .build(); + + Assertions.assertThrows(UserNotExistsException.class, ()->counselService.createCounsel(session, dto)); + } + @Test + void readCounsel() { + Assertions.assertDoesNotThrow(()->counselService.readCounsel("test")); + } + @Test + void readCounselNotExists() { + String id = "not_exist_id"; + Assertions.assertThrows(CounselNotExistsException.class, ()->counselService.readCounsel(id)); + } + @Test + void readCounselList() { + Assertions.assertDoesNotThrow(()->counselService.readCounselList()); + } + @Test + void deleteCounsel() { + CounselDeleteRequestDto dto = CounselDeleteRequestDto.builder() + .id("test") + .build(); + Assertions.assertDoesNotThrow(()->counselService.deleteCounsel(dto)); + } + @Test + void deleteCounselNotExists() { + CounselDeleteRequestDto dto = CounselDeleteRequestDto.builder() + .id("not_exist_id") + .build(); + Assertions.assertThrows(CounselNotExistsException.class, ()->counselService.deleteCounsel(dto)); + } +} diff --git a/src/test/java/com/gdg/gdgback/Counsel/CounselTestRepository.java b/src/test/java/com/gdg/gdgback/Counsel/CounselTestRepository.java new file mode 100644 index 0000000..7f1fded --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Counsel/CounselTestRepository.java @@ -0,0 +1,147 @@ +package com.gdg.gdgback.Counsel; + +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.query.FluentQuery; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class CounselTestRepository implements CounselRepository{ + private CounselDocument testDocument; + + CounselTestRepository() { + this.testDocument = CounselDocument.builder() + .id("test") + .userId("test") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now()) + .summation("test") + .build(); + } + + @Override + public List findAllByUserId(String id) { + if(!id.equals(testDocument.userId)) throw new NullPointerException(); + return List.of(testDocument); + } + + @Override + public S insert(S entity) { + return null; + } + + @Override + public List insert(Iterable entities) { + return List.of(); + } + + @Override + public Optional findOne(Example example) { + return Optional.empty(); + } + + @Override + public List findAll(Example example) { + return List.of(); + } + + @Override + public List findAll(Example example, Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Example example, Pageable pageable) { + return null; + } + + @Override + public long count(Example example) { + return 0; + } + + @Override + public boolean exists(Example example) { + return false; + } + + @Override + public R findBy(Example example, Function, R> queryFunction) { + return null; + } + + @Override + public S save(S entity) { + return entity; + } + + @Override + public List saveAll(Iterable entities) { + return List.of(); + } + + @Override + public Optional findById(String s) { + if (s.equals(testDocument.id)) return Optional.of(testDocument); + return Optional.empty(); + } + + @Override + public boolean existsById(String s) { + return s.equals(testDocument.id); + } + + @Override + public List findAll() { + return List.of(); + } + + @Override + public List findAllById(Iterable strings) { + return List.of(); + } + + @Override + public long count() { + return 0; + } + + @Override + public void deleteById(String s) { + if (!s.equals(testDocument.id)) throw new RuntimeException(); + } + + @Override + public void delete(CounselDocument entity) { + } + + @Override + public void deleteAllById(Iterable strings) { + + } + + @Override + public void deleteAll(Iterable entities) { + + } + + @Override + public void deleteAll() { + + } + + @Override + public List findAll(Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Pageable pageable) { + return null; + } +} diff --git a/src/test/java/com/gdg/gdgback/Diary/DiaryServiceTest.java b/src/test/java/com/gdg/gdgback/Diary/DiaryServiceTest.java new file mode 100644 index 0000000..162e648 --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Diary/DiaryServiceTest.java @@ -0,0 +1,65 @@ +package com.gdg.gdgback.Diary; + +import com.gdg.gdgback.Counsel.CounselService; +import com.gdg.gdgback.Counsel.DTO.Response.CounselReadResponseDto; +import com.gdg.gdgback.Diary.DTO.Request.DiaryCreateRequestDto; +import com.gdg.gdgback.Global.Validator; +import com.gdg.gdgback.General.TestValidator; +import com.gdg.gdgback.User.Exception.UserNotExistsException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class DiaryServiceTest { + @Spy + DiaryRepository diaryRepository = new DiaryTestRepository(); + CounselService counselService = mock(CounselService.class); + + @Spy + Validator validator = new TestValidator(); + + @InjectMocks + DiaryServiceImpl diaryService; + + @BeforeEach + void setUp() { + CounselReadResponseDto counselReadResponseDto = CounselReadResponseDto.builder().build(); + doReturn(counselReadResponseDto).when(counselService).readCounsel("test"); + } + + @Test + void createDiary() { + DiaryCreateRequestDto dto = DiaryCreateRequestDto.builder() + .userId("test") + .counselId("test") + .category(new String[3]) + .score(5) + .expected(true) + .picture(null) + .title("test") + .content("test") + .build(); + Assertions.assertDoesNotThrow(()->diaryService.createDiary(dto)); + } + @Test + void createDiaryWithNotExistingUser() { + DiaryCreateRequestDto dto = DiaryCreateRequestDto.builder() + .userId("I want to go home") + .counselId("test") + .category(new String[3]) + .score(5) + .expected(true) + .picture(null) + .title("test") + .content("test") + .build(); + Assertions.assertThrows(UserNotExistsException.class, ()->diaryService.createDiary(dto)); + } +} diff --git a/src/test/java/com/gdg/gdgback/Diary/DiaryTestRepository.java b/src/test/java/com/gdg/gdgback/Diary/DiaryTestRepository.java new file mode 100644 index 0000000..e87bbac --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Diary/DiaryTestRepository.java @@ -0,0 +1,154 @@ +package com.gdg.gdgback.Diary; + +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.query.FluentQuery; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class DiaryTestRepository implements DiaryRepository { + DiaryDocument testDocument; + + DiaryTestRepository() { + testDocument = DiaryDocument.builder() + .id("test") + .counselId("test") + .userId("test") + .score(0) + .date(LocalDateTime.now()) + .imageUrl(null) + .expected(null) + .category(null) + .title("test") + .content("test") + .build(); + } + + @Override + public List findAllByUserIdOrderByDateDesc(String id) { + if (!id.equals("test")) throw new NullPointerException(); + return List.of(testDocument); + } + + @Override + public S insert(S entity) { + return null; + } + + @Override + public List insert(Iterable entities) { + return List.of(); + } + + @Override + public Optional findOne(Example example) { + return Optional.empty(); + } + + @Override + public List findAll(Example example) { + return List.of(); + } + + @Override + public List findAll(Example example, Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Example example, Pageable pageable) { + return null; + } + + @Override + public long count(Example example) { + return 0; + } + + @Override + public boolean exists(Example example) { + return false; + } + + @Override + public R findBy(Example example, Function, R> queryFunction) { + return null; + } + + @Override + public S save(S entity) { + entity.id = "test"; + return entity; + } + + @Override + public List saveAll(Iterable entities) { + return List.of(); + } + + @Override + public Optional findById(String s) { + if (!s.equals(testDocument.id)) throw new NullPointerException(); + return Optional.of(testDocument); + } + + @Override + public boolean existsById(String s) { + return s.equals(testDocument.id); + } + + @Override + public List findAll() { + return List.of(); + } + + @Override + public List findAllById(Iterable strings) { + return List.of(); + } + + @Override + public long count() { + return 0; + } + + @Override + public void deleteById(String s) { + if (!s.equals(testDocument.id)) throw new NullPointerException(); + } + + @Override + public void delete(DiaryDocument entity) { + if (!entity.equals(testDocument)) throw new NullPointerException(); + } + + @Override + public void deleteAllById(Iterable strings) { + + } + + @Override + public void deleteAll(Iterable entities) { + + } + + @Override + public void deleteAll() { + + } + + @Override + public List findAll(Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Pageable pageable) { + return null; + } +} diff --git a/src/test/java/com/gdg/gdgback/GdgbackApplicationTests.java b/src/test/java/com/gdg/gdgback/GdgbackApplicationTests.java index 95a57dc..32ec584 100644 --- a/src/test/java/com/gdg/gdgback/GdgbackApplicationTests.java +++ b/src/test/java/com/gdg/gdgback/GdgbackApplicationTests.java @@ -1,13 +1,21 @@ -package com.gdg.gdgback; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class GdgbackApplicationTests { - - @Test - void contextLoads() { - } - -} +package com.gdg.gdgback; + +import com.gdg.gdgback.User.UserServiceImpl; +import com.gdg.gdgback.User.UserDocument; +import com.gdg.gdgback.User.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.util.Optional; + +import static org.mockito.Mockito.*; + + +// "test" 프로필 - ADC 인증 필요한 서비스는 제외하고 테스트. +@SpringBootTest +@ActiveProfiles("test") +public class GdgbackApplicationTests { +} \ No newline at end of file diff --git a/src/test/java/com/gdg/gdgback/General/TestValidator.java b/src/test/java/com/gdg/gdgback/General/TestValidator.java new file mode 100644 index 0000000..e3ceb51 --- /dev/null +++ b/src/test/java/com/gdg/gdgback/General/TestValidator.java @@ -0,0 +1,19 @@ +package com.gdg.gdgback.General; + +import com.gdg.gdgback.Counsel.CounselNotExistsException; +import com.gdg.gdgback.Global.Validator; +import com.gdg.gdgback.User.Exception.UserNotExistsException; + +public class TestValidator implements Validator { + public void validateUserExists(String id) { + if(!id.equals("test")) { + throw new UserNotExistsException(id); + } + } + + public void validateCounselExists(String id) { + if(!id.equals("test")) { + throw new CounselNotExistsException(id); + } + } +} diff --git a/src/test/java/com/gdg/gdgback/Message/MessageServiceTest.java b/src/test/java/com/gdg/gdgback/Message/MessageServiceTest.java new file mode 100644 index 0000000..8725653 --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Message/MessageServiceTest.java @@ -0,0 +1,27 @@ +package com.gdg.gdgback.Message; + +import com.gdg.gdgback.General.TestValidator; +import com.gdg.gdgback.Global.Validator; +import com.gdg.gdgback.Message.DTO.Request.MessageCreateRequestDto; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class MessageServiceTest { + MessageRepository messageRepository = new MessageTestRepository(); + Validator validator = new TestValidator(); + MessageService messageService = new MessageServiceImpl(messageRepository, validator); + + @Test + void createMessage() { + MessageCreateRequestDto dto = MessageCreateRequestDto.builder() + .counselId("test") + .role("test") + .content("test") + .build(); + Assertions.assertDoesNotThrow(()->messageService.createMessage(dto)); + } + +} diff --git a/src/test/java/com/gdg/gdgback/Message/MessageTestRepository.java b/src/test/java/com/gdg/gdgback/Message/MessageTestRepository.java new file mode 100644 index 0000000..30f753d --- /dev/null +++ b/src/test/java/com/gdg/gdgback/Message/MessageTestRepository.java @@ -0,0 +1,148 @@ +package com.gdg.gdgback.Message; + +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.query.FluentQuery; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class MessageTestRepository implements MessageRepository { + MessageDocument testDocument; + + MessageTestRepository() { + testDocument = MessageDocument.builder() + .id("test") + .counselId("test") + .role("test") + .content("test") + .date(LocalDateTime.now()) + .build(); + } + + @Override + public List findAllByCounselId(String id) { + if(!id.equals(testDocument.counselId)) throw new NullPointerException(); + return List.of(testDocument); + } + + @Override + public S insert(S entity) { + return null; + } + + @Override + public List insert(Iterable entities) { + return List.of(); + } + + @Override + public Optional findOne(Example example) { + return Optional.empty(); + } + + @Override + public List findAll(Example example) { + return List.of(); + } + + @Override + public List findAll(Example example, Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Example example, Pageable pageable) { + return null; + } + + @Override + public long count(Example example) { + return 0; + } + + @Override + public boolean exists(Example example) { + return false; + } + + @Override + public R findBy(Example example, Function, R> queryFunction) { + return null; + } + + @Override + public S save(S entity) { + return entity; + } + + @Override + public List saveAll(Iterable entities) { + return List.of(); + } + + @Override + public Optional findById(String s) { + if(!s.equals(testDocument.id)) throw new NullPointerException(); + return Optional.of(testDocument); + } + + @Override + public boolean existsById(String s) { + return s.equals(testDocument.id); + } + + @Override + public List findAll() { + return List.of(testDocument); + } + + @Override + public List findAllById(Iterable strings) { + return List.of(); + } + + @Override + public long count() { + return 0; + } + + @Override + public void deleteById(String s) { + if(!s.equals(testDocument.id)) throw new NullPointerException(); + } + + @Override + public void delete(MessageDocument entity) { + if(!entity.equals(testDocument)) throw new NullPointerException(); + } + + @Override + public void deleteAllById(Iterable strings) { + + } + + @Override + public void deleteAll(Iterable entities) { + + } + + @Override + public void deleteAll() { + + } + + @Override + public List findAll(Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Pageable pageable) { + return null; + } +} diff --git a/src/test/java/com/gdg/gdgback/User/UserServiceTest.java b/src/test/java/com/gdg/gdgback/User/UserServiceTest.java new file mode 100644 index 0000000..3e32038 --- /dev/null +++ b/src/test/java/com/gdg/gdgback/User/UserServiceTest.java @@ -0,0 +1,67 @@ +package com.gdg.gdgback.User; + +import com.gdg.gdgback.User.DTO.Request.UserCreateRequestDto; +import com.gdg.gdgback.User.DTO.Request.UserDeleteRequestDto; +import com.gdg.gdgback.User.Exception.UserAlreadyExistsException; +import com.gdg.gdgback.User.Exception.UserNotExistsException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(MockitoExtension.class) +public class UserServiceTest { + @Spy + UserRepository userRepository = new UserTestRepository(); + + @InjectMocks + UserServiceImpl userService; + + @Test + void createUser() { + UserCreateRequestDto userCreateRequestDto = UserCreateRequestDto.builder() + .id("id_not_exist") + .name("빵빵이") + .build(); + assertDoesNotThrow(() -> userService.createUser(userCreateRequestDto)); + } + + @Test + void createExistingUser() { + UserCreateRequestDto userCreateRequestDto = UserCreateRequestDto.builder() + .id("test") + .name("버그 터지지 마라 제발") + .build(); + assertThrows(UserAlreadyExistsException.class, () -> userService.createUser(userCreateRequestDto)); + } + + @Test + void readUser() { + assertDoesNotThrow(() -> userService.readUser("test")); + } + + @Test + void readNotExistingUser() { + String id = "id_not_exist"; + assertThrows(UserNotExistsException.class, () -> userService.readUser(id)); + } + @Test + void deleteUser() { + UserDeleteRequestDto dto = UserDeleteRequestDto.builder() + .id("test") + .build(); + assertDoesNotThrow(()->userService.deleteUser(dto)); + } + @Test + void deleteUserNotExists() { + UserDeleteRequestDto dto = UserDeleteRequestDto.builder() + .id("not_exist_id") + .build(); + Assertions.assertThrows(UserNotExistsException.class, ()->userService.deleteUser(dto)); + } +} diff --git a/src/test/java/com/gdg/gdgback/User/UserTestRepository.java b/src/test/java/com/gdg/gdgback/User/UserTestRepository.java new file mode 100644 index 0000000..d42dc08 --- /dev/null +++ b/src/test/java/com/gdg/gdgback/User/UserTestRepository.java @@ -0,0 +1,140 @@ +package com.gdg.gdgback.User; + +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.query.FluentQuery; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class UserTestRepository implements UserRepository { + private UserDocument testDocument; + + UserTestRepository() { + this.testDocument = UserDocument.builder() + .id("test") + .name("test") + .date(LocalDateTime.now()) + .build(); + } + + @Override + public S insert(S entity) { + return null; + } + + @Override + public List insert(Iterable entities) { + return List.of(); + } + + @Override + public Optional findOne(Example example) { + return Optional.empty(); + } + + @Override + public List findAll(Example example) { + return List.of(); + } + + @Override + public List findAll(Example example, Sort sort) { + return List.of(); + } + + @Override + public Page findAll(Example example, Pageable pageable) { + return null; + } + + @Override + public long count(Example example) { + return 0; + } + + @Override + public boolean exists(Example example) { + return false; + } + + @Override + public R findBy(Example example, Function, R> queryFunction) { + return null; + } + + @Override + public S save(S entity) { + return entity; + } + + @Override + public List saveAll(Iterable entities) { + return List.of(); + } + + @Override + public Optional findById(String s) { + if (s.equals(testDocument.id)) return Optional.of(testDocument); + return Optional.empty(); + } + + @Override + public boolean existsById(String s) { + return s.equals(testDocument.id); + } + + @Override + public List findAll() { + return List.of(); + } + + @Override + public List findAllById(Iterable strings) { + return List.of(); + } + + @Override + public long count() { + return 0; + } + + @Override + public void deleteById(String s) { + if (!s.equals(testDocument.id)) throw new NullPointerException(); + } + + @Override + public void delete(UserDocument entity) { + if (!entity.equals(testDocument)) throw new NullPointerException(); + } + + @Override + public void deleteAllById(Iterable strings) { + + } + + @Override + public void deleteAll(Iterable entities) { + + } + + @Override + public void deleteAll() { + + } + + @Override + public List findAll(Sort sort) { + return List.of(testDocument); + } + + @Override + public Page findAll(Pageable pageable) { + return null; + } +}