diff --git a/build.gradle b/build.gradle index a754346..bb6412a 100644 --- a/build.gradle +++ b/build.gradle @@ -45,8 +45,8 @@ dependencies { implementation 'org.mapstruct:mapstruct:1.5.5.Final' - annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0" + annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' implementation("org.flywaydb:flyway-core") implementation("org.flywaydb:flyway-mysql") diff --git a/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java b/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java index c9043eb..d2f4bde 100644 --- a/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java +++ b/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java @@ -2,7 +2,10 @@ import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -12,9 +15,11 @@ @Getter @MappedSuperclass @EntityListeners(AuditingEntityListener.class) +@SuperBuilder +@NoArgsConstructor(access = AccessLevel.PROTECTED) public abstract class BaseTimeEntity { @CreatedDate - private LocalDateTime createdAt; + protected LocalDateTime createdAt; @LastModifiedDate - private LocalDateTime modifiedAt; + protected LocalDateTime modifiedAt; } diff --git a/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java b/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java index 2237d8d..035c9e6 100644 --- a/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java +++ b/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java @@ -54,6 +54,7 @@ public void delete(Long id) { @Override public Post update(Post post) { + //FIXME need to refactor this code PostEntity entity = postJPARepository.findById(post.getId()).orElseThrow(() -> { throw new IllegalArgumentException("존재하지 않는 게시물입니다."); }); diff --git a/src/main/java/com/codecrafters/companity/adapter/user/UserController.java b/src/main/java/com/codecrafters/companity/adapter/user/UserController.java index c777b5c..9edae51 100644 --- a/src/main/java/com/codecrafters/companity/adapter/user/UserController.java +++ b/src/main/java/com/codecrafters/companity/adapter/user/UserController.java @@ -10,8 +10,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.Map; @RestController @RequestMapping("/users") diff --git a/src/main/java/com/codecrafters/companity/adapter/utility/ExceptionControllerAdvice.java b/src/main/java/com/codecrafters/companity/adapter/utility/ExceptionControllerAdvice.java index 3c08993..357c31e 100644 --- a/src/main/java/com/codecrafters/companity/adapter/utility/ExceptionControllerAdvice.java +++ b/src/main/java/com/codecrafters/companity/adapter/utility/ExceptionControllerAdvice.java @@ -1,7 +1,6 @@ package com.codecrafters.companity.adapter.utility; import com.codecrafters.companity.adapter.utility.dto.response.ExceptionResponse; -import com.codecrafters.companity.adapter.utility.dto.response.ResultCode; import com.codecrafters.companity.exception.CustomException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/codecrafters/companity/comment/adapter/CommentController.java b/src/main/java/com/codecrafters/companity/comment/adapter/CommentController.java index 01f51a6..86033a5 100644 --- a/src/main/java/com/codecrafters/companity/comment/adapter/CommentController.java +++ b/src/main/java/com/codecrafters/companity/comment/adapter/CommentController.java @@ -1,6 +1,7 @@ package com.codecrafters.companity.comment.adapter; import com.codecrafters.companity.comment.adapter.dto.request.AddCommentDto; +import com.codecrafters.companity.comment.adapter.dto.request.UpdatingCommentDto; import com.codecrafters.companity.comment.adapter.dto.response.ResponseComment; import com.codecrafters.companity.comment.application.port.in.CommentUseCase; import com.codecrafters.companity.application.in.post.PostUseCase; @@ -12,6 +13,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; + @RestController @RequestMapping("/comment") @RequiredArgsConstructor @@ -26,6 +28,12 @@ public ResponseEntity add(@RequestBody AddCommentDto request){ return new ResponseEntity<>(ResponseComment.toDto(result), HttpStatus.CREATED); } + @PutMapping + public ResponseEntity update(@RequestBody UpdatingCommentDto request){ + Comment result = commentUseCase.update(request.toCommentForUpdate(getUser())); + return new ResponseEntity<>(ResponseComment.toDto(result), HttpStatus.OK); + } + //FIXME need to implement about get user private User getUser(){ return User.builder().userId("shtjdrb").userName("노성규").nickName("안녕").build(); diff --git a/src/main/java/com/codecrafters/companity/comment/adapter/CommentMapper.java b/src/main/java/com/codecrafters/companity/comment/adapter/CommentMapper.java index 4dc25fc..4fa807b 100644 --- a/src/main/java/com/codecrafters/companity/comment/adapter/CommentMapper.java +++ b/src/main/java/com/codecrafters/companity/comment/adapter/CommentMapper.java @@ -5,12 +5,13 @@ import com.codecrafters.companity.comment.domain.Comment; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.MappingConstants; import org.mapstruct.control.DeepClone; import org.mapstruct.factory.Mappers; import java.util.List; -@Mapper(mappingControl = DeepClone.class) +@Mapper(mappingControl = DeepClone.class, componentModel = MappingConstants.ComponentModel.SPRING) public interface CommentMapper { CommentMapper COMMENT_MAPPER = Mappers.getMapper(CommentMapper.class); @Mapping(source = "owner", target = "user") diff --git a/src/main/java/com/codecrafters/companity/comment/adapter/dto/request/UpdatingCommentDto.java b/src/main/java/com/codecrafters/companity/comment/adapter/dto/request/UpdatingCommentDto.java new file mode 100644 index 0000000..e79b8ae --- /dev/null +++ b/src/main/java/com/codecrafters/companity/comment/adapter/dto/request/UpdatingCommentDto.java @@ -0,0 +1,19 @@ +package com.codecrafters.companity.comment.adapter.dto.request; + +import com.codecrafters.companity.comment.domain.CommentForUpdate; +import com.codecrafters.companity.domain.user.User; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class UpdatingCommentDto { + private Long id; + private String content; + + public CommentForUpdate toCommentForUpdate(User user){ + return CommentForUpdate.builder().id(id).user(user).content(content).build(); + } +} diff --git a/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/CommentRepositoryImpl.java b/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/CommentRepositoryImpl.java index b3a6a60..addeeef 100644 --- a/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/CommentRepositoryImpl.java +++ b/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/CommentRepositoryImpl.java @@ -23,8 +23,30 @@ public class CommentRepositoryImpl implements CommentRepository { private final String CREATED_AT = "createdAt"; @Override public Comment add(Comment comment) { - CommentEntity savedEntity = commentJPARepository.save(COMMENT_MAPPER.toEntity(comment)); - return COMMENT_MAPPER.toDomain(savedEntity); + CommentEntity savedEntity = commentJPARepository.save(toEntity(comment)); + return toDomain(savedEntity); + } + + @Override + public Comment getById(Long id) { + CommentEntity entity = commentJPARepository.findById(id).orElseThrow(() -> { + throw new IllegalArgumentException("존재하지 않는 댓글입니다."); + }); + return toDomain(entity); + } + + @Override + public Comment update(Comment comment) { + CommentEntity save = commentJPARepository.save(toEntity(comment)); + return toDomain(save); + } + + private Comment toDomain(CommentEntity entity){ + return COMMENT_MAPPER.toDomain(entity); + } + + private CommentEntity toEntity(Comment comment){ + return COMMENT_MAPPER.toEntity(comment); } @Override diff --git a/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/jpa/CommentEntity.java b/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/jpa/CommentEntity.java index 1a50e6a..bc19c75 100644 --- a/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/jpa/CommentEntity.java +++ b/src/main/java/com/codecrafters/companity/comment/adapter/infrastructure/jpa/CommentEntity.java @@ -5,12 +5,12 @@ import com.codecrafters.companity.adapter.user.infrastructure.jpa.UserEntity; import jakarta.persistence.*; import lombok.*; +import lombok.experimental.SuperBuilder; @Entity(name = "Comment") @Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor +@SuperBuilder +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class CommentEntity extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java b/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java index 9579d57..3281b71 100644 --- a/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java +++ b/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java @@ -4,6 +4,7 @@ import com.codecrafters.companity.comment.application.port.out.persistence.CommentRepository; import com.codecrafters.companity.comment.domain.CommentForCreate; import com.codecrafters.companity.comment.domain.Comment; +import com.codecrafters.companity.comment.domain.CommentForUpdate; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -15,7 +16,14 @@ public class CommentService implements CommentUseCase { private final CommentRepository commentRepository; @Override public Comment add(CommentForCreate commentForCreate) { + //TODO : change to use commentForCreate directly and validate here Comment comment = commentForCreate.toComment(); return commentRepository.add(comment); } + + @Override + public Comment update(CommentForUpdate commentForUpdate) { + Comment comment = commentRepository.getById(commentForUpdate.getId()); + return commentRepository.update(commentForUpdate.update(comment)); + } } diff --git a/src/main/java/com/codecrafters/companity/comment/application/port/in/CommentUseCase.java b/src/main/java/com/codecrafters/companity/comment/application/port/in/CommentUseCase.java index 72e00c1..e6826b6 100644 --- a/src/main/java/com/codecrafters/companity/comment/application/port/in/CommentUseCase.java +++ b/src/main/java/com/codecrafters/companity/comment/application/port/in/CommentUseCase.java @@ -2,7 +2,10 @@ import com.codecrafters.companity.comment.domain.CommentForCreate; import com.codecrafters.companity.comment.domain.Comment; +import com.codecrafters.companity.comment.domain.CommentForUpdate; public interface CommentUseCase { Comment add(CommentForCreate commentForCreate); + + Comment update(CommentForUpdate commentForUpdate); } diff --git a/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java b/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java index fe0077a..bcdde5a 100644 --- a/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java +++ b/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java @@ -6,6 +6,11 @@ import org.springframework.data.domain.Pageable; public interface CommentRepository { + //TODO : change to use commentForCreate directly Comment add(Comment comment); Page findAllByPost(Post post, Pageable pageable); + + Comment update(Comment comment); + + Comment getById(Long id); } diff --git a/src/main/java/com/codecrafters/companity/comment/domain/Comment.java b/src/main/java/com/codecrafters/companity/comment/domain/Comment.java index 354bcb0..4664596 100644 --- a/src/main/java/com/codecrafters/companity/comment/domain/Comment.java +++ b/src/main/java/com/codecrafters/companity/comment/domain/Comment.java @@ -4,13 +4,11 @@ import com.codecrafters.companity.domain.user.User; import lombok.Builder; import lombok.Getter; -import lombok.ToString; import java.time.LocalDateTime; @Getter @Builder -@ToString public class Comment { private Long id; private User owner; diff --git a/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java b/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java index 6c8b207..35b022d 100644 --- a/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java +++ b/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java @@ -13,6 +13,7 @@ public class CommentForCreate { private Post post; private User user; + //FIXME: This method is not used. Remove it. public Comment toComment(){ validate(); return Comment.builder().post(post.clone()).owner(user.clone()).content(content).build(); diff --git a/src/main/java/com/codecrafters/companity/comment/domain/CommentForUpdate.java b/src/main/java/com/codecrafters/companity/comment/domain/CommentForUpdate.java new file mode 100644 index 0000000..ed5a9a5 --- /dev/null +++ b/src/main/java/com/codecrafters/companity/comment/domain/CommentForUpdate.java @@ -0,0 +1,33 @@ +package com.codecrafters.companity.comment.domain; + +import com.codecrafters.companity.domain.user.User; +import lombok.Builder; +import lombok.Getter; +import org.springframework.util.StringUtils; + +@Getter +@Builder +public class CommentForUpdate { + private Long id; + private String content; + private User user; + + public Comment update(Comment original){ + validate(original); + return Comment.builder() + .id(id) + .post(original.getPost().clone()) + .owner(user.clone()) + .content(content) + .createdAt(original.getCreatedAt()) + .modifiedAt(original.getModifiedAt()) + .build(); + } + + private void validate(Comment comment){ + if(!StringUtils.hasText(content)) throw new IllegalArgumentException("Content must not be null"); + if(id == null) throw new IllegalArgumentException("Id must not be null"); + if(user == null) throw new IllegalArgumentException("User must not be null"); + if(!user.getUserId().equals(comment.getOwner().getUserId())) throw new IllegalArgumentException("User must be the same as the writer of the comment"); + } +} diff --git a/src/test/java/com/codecrafters/companity/adapter/user/dto/response/UserCreateResponseTest.java b/src/test/java/com/codecrafters/companity/adapter/user/dto/response/UserCreateResponseTest.java index 759694e..74bb104 100644 --- a/src/test/java/com/codecrafters/companity/adapter/user/dto/response/UserCreateResponseTest.java +++ b/src/test/java/com/codecrafters/companity/adapter/user/dto/response/UserCreateResponseTest.java @@ -2,11 +2,8 @@ import com.codecrafters.companity.adapter.user.dto.resposne.UserCreateResponse; import com.codecrafters.companity.domain.user.User; -import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static com.codecrafters.companity.static_reference.PostStatic.CITY; import static com.codecrafters.companity.static_reference.UserStatic.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; diff --git a/src/test/java/com/codecrafters/companity/domain/user/UserTest.java b/src/test/java/com/codecrafters/companity/domain/user/UserTest.java index 9a938f9..5b45d33 100644 --- a/src/test/java/com/codecrafters/companity/domain/user/UserTest.java +++ b/src/test/java/com/codecrafters/companity/domain/user/UserTest.java @@ -1,7 +1,6 @@ package com.codecrafters.companity.domain.user; import com.codecrafters.companity.adapter.user.dto.request.UserCreateRequest; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static com.codecrafters.companity.static_reference.UserStatic.*; diff --git a/src/test/java/com/codecrafters/companity/mock/repository/UserInMemoryImpl.java b/src/test/java/com/codecrafters/companity/mock/repository/UserInMemoryImpl.java index 40c6724..ee3fcc5 100644 --- a/src/test/java/com/codecrafters/companity/mock/repository/UserInMemoryImpl.java +++ b/src/test/java/com/codecrafters/companity/mock/repository/UserInMemoryImpl.java @@ -8,7 +8,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; public class UserInMemoryImpl implements UserRepository { private final Map repository = new ConcurrentHashMap<>();