-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
45 changed files
with
2,358 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
backend/emm-sale/src/main/java/com/emmsale/comment/api/CommentApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.emmsale.comment.api; | ||
|
||
import com.emmsale.comment.application.CommentCommandService; | ||
import com.emmsale.comment.application.CommentQueryService; | ||
import com.emmsale.comment.application.dto.CommentAddRequest; | ||
import com.emmsale.comment.application.dto.CommentHierarchyResponse; | ||
import com.emmsale.comment.application.dto.CommentModifyRequest; | ||
import com.emmsale.comment.application.dto.CommentResponse; | ||
import com.emmsale.member.domain.Member; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PatchMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.ResponseStatus; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
public class CommentApi { | ||
|
||
private final CommentCommandService commentCommandService; | ||
private final CommentQueryService commentQueryService; | ||
|
||
@PostMapping("/comments") | ||
public CommentResponse create( | ||
@RequestBody final CommentAddRequest commentAddRequest, | ||
final Member member | ||
) { | ||
return commentCommandService.create(commentAddRequest, member); | ||
} | ||
|
||
@GetMapping("/comments") | ||
public List<CommentHierarchyResponse> findAll(@RequestParam final Long eventId) { | ||
return commentQueryService.findAllCommentsByEventId(eventId); | ||
} | ||
|
||
@DeleteMapping("/comments/{comment-id}") | ||
@ResponseStatus(HttpStatus.NO_CONTENT) | ||
public void delete(@PathVariable("comment-id") final Long commentId, final Member member) { | ||
commentCommandService.delete(commentId, member); | ||
} | ||
|
||
@PatchMapping("/comments/{comment-id}") | ||
public CommentResponse modify( | ||
@PathVariable("comment-id") final Long commentId, | ||
final Member member, | ||
@RequestBody final CommentModifyRequest commentModifyRequest | ||
) { | ||
return commentCommandService.modify(commentId, member, commentModifyRequest); | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
backend/emm-sale/src/main/java/com/emmsale/comment/application/CommentCommandService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package com.emmsale.comment.application; | ||
|
||
import static com.emmsale.comment.exception.CommentExceptionType.FORBIDDEN_DELETE_COMMENT; | ||
import static com.emmsale.comment.exception.CommentExceptionType.FORBIDDEN_MODIFY_COMMENT; | ||
import static com.emmsale.comment.exception.CommentExceptionType.FORBIDDEN_MODIFY_DELETED_COMMENT; | ||
import static com.emmsale.comment.exception.CommentExceptionType.NOT_FOUND_COMMENT; | ||
|
||
import com.emmsale.comment.application.dto.CommentAddRequest; | ||
import com.emmsale.comment.application.dto.CommentModifyRequest; | ||
import com.emmsale.comment.application.dto.CommentResponse; | ||
import com.emmsale.comment.domain.Comment; | ||
import com.emmsale.comment.domain.CommentRepository; | ||
import com.emmsale.comment.exception.CommentException; | ||
import com.emmsale.comment.exception.CommentExceptionType; | ||
import com.emmsale.event.domain.Event; | ||
import com.emmsale.event.domain.repository.EventRepository; | ||
import com.emmsale.event.exception.EventException; | ||
import com.emmsale.event.exception.EventExceptionType; | ||
import com.emmsale.member.domain.Member; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional | ||
public class CommentCommandService { | ||
|
||
private final CommentRepository commentRepository; | ||
private final EventRepository eventRepository; | ||
|
||
public CommentResponse create( | ||
final CommentAddRequest commentAddRequest, | ||
final Member member | ||
) { | ||
final Event savedEvent = eventRepository.findById(commentAddRequest.getEventId()) | ||
.orElseThrow(() -> new EventException(EventExceptionType.NOT_FOUND_EVENT)); | ||
final String content = commentAddRequest.getContent(); | ||
|
||
final Comment comment = commentAddRequest.optionalParentId() | ||
.map(commentId -> Comment.createChild( | ||
savedEvent, | ||
findSavedComment(commentId), | ||
member, | ||
content) | ||
) | ||
.orElseGet(() -> Comment.createRoot(savedEvent, member, content)); | ||
|
||
return CommentResponse.from(commentRepository.save(comment)); | ||
} | ||
|
||
private Comment findSavedComment(final Long commentId) { | ||
return commentRepository.findById(commentId) | ||
.orElseThrow(() -> new CommentException(NOT_FOUND_COMMENT)); | ||
} | ||
|
||
public void delete(final Long commentId, final Member loginMember) { | ||
|
||
final Comment comment = findSavedComment(commentId); | ||
|
||
validateSameWriter(loginMember, comment, FORBIDDEN_DELETE_COMMENT); | ||
|
||
comment.delete(); | ||
} | ||
|
||
private void validateSameWriter( | ||
final Member loginMember, | ||
final Comment comment, | ||
final CommentExceptionType commentExceptionType | ||
) { | ||
if (loginMember.isNotMe(comment.getMember())) { | ||
throw new CommentException(commentExceptionType); | ||
} | ||
} | ||
|
||
public CommentResponse modify( | ||
final Long commentId, | ||
final Member loginMember, | ||
final CommentModifyRequest commentModifyRequest | ||
) { | ||
|
||
final Comment comment = findSavedComment(commentId); | ||
|
||
validateAlreadyDeleted(comment); | ||
validateSameWriter(loginMember, comment, FORBIDDEN_MODIFY_COMMENT); | ||
|
||
comment.modify(commentModifyRequest.getContent()); | ||
|
||
return CommentResponse.from(comment); | ||
} | ||
|
||
private void validateAlreadyDeleted(final Comment comment) { | ||
if (comment.isDeleted()) { | ||
throw new CommentException(FORBIDDEN_MODIFY_DELETED_COMMENT); | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
backend/emm-sale/src/main/java/com/emmsale/comment/application/CommentQueryService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.emmsale.comment.application; | ||
|
||
import com.emmsale.comment.application.dto.CommentHierarchyResponse; | ||
import com.emmsale.comment.domain.Comment; | ||
import com.emmsale.comment.domain.CommentRepository; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class CommentQueryService { | ||
|
||
private final CommentRepository commentRepository; | ||
|
||
public List<CommentHierarchyResponse> findAllCommentsByEventId(final Long eventId) { | ||
|
||
final List<Comment> comments = commentRepository.findByEventId(eventId); | ||
|
||
return CommentHierarchyResponse.from(comments); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
backend/emm-sale/src/main/java/com/emmsale/comment/application/dto/CommentAddRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.emmsale.comment.application.dto; | ||
|
||
import java.util.Optional; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RequiredArgsConstructor | ||
@Getter | ||
public class CommentAddRequest { | ||
|
||
private final String content; | ||
private final Long eventId; | ||
private final Long parentId; | ||
|
||
public Optional<Long> optionalParentId() { | ||
return Optional.ofNullable(parentId); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
.../emm-sale/src/main/java/com/emmsale/comment/application/dto/CommentHierarchyResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package com.emmsale.comment.application.dto; | ||
|
||
import com.emmsale.base.BaseEntity; | ||
import com.emmsale.comment.domain.Comment; | ||
import java.util.ArrayList; | ||
import java.util.Comparator; | ||
import java.util.LinkedHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.stream.Collectors; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RequiredArgsConstructor | ||
@Getter | ||
public class CommentHierarchyResponse { | ||
|
||
private final CommentResponse parentComment; | ||
private final List<CommentResponse> childComments; | ||
|
||
public static List<CommentHierarchyResponse> from(final List<Comment> comments) { | ||
|
||
final Map<Comment, List<Comment>> groupedByParent = | ||
groupingByParentAndSortedByCreatedAt(comments); | ||
|
||
final List<CommentHierarchyResponse> result = new ArrayList<>(); | ||
|
||
for (final Entry<Comment, List<Comment>> entry : groupedByParent.entrySet()) { | ||
final Comment parentComment = entry.getKey(); | ||
final List<CommentResponse> childCommentResponses = | ||
mapToCommentResponse(entry, parentComment); | ||
|
||
result.add( | ||
new CommentHierarchyResponse(CommentResponse.from(parentComment), childCommentResponses) | ||
); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private static LinkedHashMap<Comment, List<Comment>> groupingByParentAndSortedByCreatedAt( | ||
final List<Comment> comments | ||
) { | ||
return comments.stream() | ||
.sorted(Comparator.comparing(BaseEntity::getCreatedAt)) | ||
.collect(Collectors.groupingBy( | ||
it -> it.getParent().orElse(it), | ||
LinkedHashMap::new, Collectors.toList()) | ||
); | ||
} | ||
|
||
private static List<CommentResponse> mapToCommentResponse( | ||
final Entry<Comment, List<Comment>> entry, | ||
final Comment parentComment | ||
) { | ||
return entry.getValue().stream() | ||
.filter(it -> isNotSameKeyAndValue(parentComment, it)) | ||
.map(CommentResponse::from) | ||
.sorted(Comparator.comparing(CommentResponse::getCreatedAt)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static boolean isNotSameKeyAndValue(final Comment parentComment, final Comment target) { | ||
return !target.equals(parentComment); | ||
} | ||
} |
Oops, something went wrong.