-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BE] refactor: 도메인을 활용한 하이라이트 추가 및 수정 로직 리팩토링 #859
Changes from 21 commits
d7bcdb1
d689cd6
588c2ee
8046c1a
131304e
bf64ea9
d68451e
7e84d45
0efcc43
7557ce9
a807959
206f712
1df8f12
65dd10e
1e053d8
6c98099
30c9518
52f9e1a
4a515c8
a243d24
e060289
26428e3
9eac3bc
b757b0d
51654c4
e49734b
d9a2228
7dcc5e2
80479d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package reviewme.highlight.domain; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import lombok.Getter; | ||
import reviewme.highlight.domain.exception.InvalidHighlightLineIndexException; | ||
import reviewme.highlight.domain.exception.NegativeHighlightLineIndexException; | ||
|
||
@Getter | ||
public class HighlightLines { | ||
|
||
public static final String LINE_SEPARATOR = "\n"; | ||
|
||
private final List<HighlightedLine> lines; | ||
|
||
public HighlightLines(String content) { | ||
this.lines = Arrays.stream(content.split(LINE_SEPARATOR)) | ||
.map(HighlightedLine::new) | ||
.toList(); | ||
} | ||
|
||
public void addRange(int lineIndex, int startIndex, int endIndex) { | ||
validateNonNegativeLineIndexNumber(lineIndex); | ||
validateLineIndexRange(lineIndex); | ||
HighlightedLine line = lines.get(lineIndex); | ||
line.addRange(startIndex, endIndex); | ||
} | ||
|
||
private void validateNonNegativeLineIndexNumber(int lineIndex) { | ||
if (lineIndex < 0) { | ||
throw new NegativeHighlightLineIndexException(lineIndex); | ||
} | ||
} | ||
|
||
private void validateLineIndexRange(int lineIndex) { | ||
if (lineIndex >= lines.size()) { | ||
throw new InvalidHighlightLineIndexException(lineIndex, lines.size()); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package reviewme.highlight.domain; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import reviewme.highlight.domain.exception.HighlightIndexExceedLineLengthException; | ||
import reviewme.highlight.entity.HighlightRange; | ||
|
||
@Getter | ||
@EqualsAndHashCode | ||
public class HighlightedLine { | ||
|
||
private final String content; | ||
private final Set<HighlightRange> ranges; | ||
|
||
public HighlightedLine(String content) { | ||
this.content = content; | ||
this.ranges = new HashSet<>(); | ||
} | ||
|
||
public void addRange(int startIndex, int endIndex) { | ||
validateRangeByContentLength(startIndex, endIndex); | ||
ranges.add(new HighlightRange(startIndex, endIndex)); | ||
} | ||
|
||
private void validateRangeByContentLength(int startIndex, int endIndex) { | ||
int contentLength = content.length(); | ||
if (startIndex >= contentLength || endIndex >= contentLength) { | ||
throw new HighlightIndexExceedLineLengthException(content.length(), startIndex, endIndex); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package reviewme.highlight.domain.exception; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class HighlightIndexExceedLineLengthException extends BadRequestException { | ||
|
||
public HighlightIndexExceedLineLengthException(int lineLength, int startIndex, int endIndex) { | ||
super("하이라이트 위치가 텍스트의 범위를 벗어났어요."); | ||
log.info("Highlight index exceed line length - lineLength: {}, startIndex: {}, endIndex: {}", | ||
lineLength, startIndex, endIndex); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package reviewme.highlight.domain.exception; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class InvalidHighlightIndexRangeException extends BadRequestException { | ||
|
||
public InvalidHighlightIndexRangeException(int startIndex, int endIndex) { | ||
super("유효하지 않은 하이라이트 위치에요. 하이라이트 시작 위치: %d, 종료 위치: %d".formatted(startIndex, endIndex)); | ||
log.info("Highlight index is a negative number - startIndex: {}, endIndex: {}", startIndex, endIndex); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package reviewme.highlight.domain.exception; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import reviewme.global.exception.BadRequestException; | ||
|
||
@Slf4j | ||
public class NegativeHighlightLineIndexException extends BadRequestException { | ||
|
||
public NegativeHighlightLineIndexException(int lineIndex) { | ||
super("하이라이트 할 라인의 위치는 0 이상의 수이어야 해요."); | ||
log.info("Highlight index is a negative number - lineIndex: {}", lineIndex); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package reviewme.highlight.domain; | ||
package reviewme.highlight.entity; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Embedded; | ||
|
@@ -26,11 +26,19 @@ public class Highlight { | |
@Column(name = "answer_id", nullable = false) | ||
private long answerId; | ||
|
||
@Column(name = "line_index", nullable = false) | ||
private int lineIndex; | ||
|
||
@Embedded | ||
private HighlightPosition highlightPosition; | ||
private HighlightRange highlightRange; | ||
|
||
public Highlight(long answerId, int lineIndex, int startIndex, int endIndex) { | ||
public Highlight(long answerId, int lineIndex, HighlightRange range) { | ||
this.answerId = answerId; | ||
this.highlightPosition = new HighlightPosition(lineIndex, startIndex, endIndex); | ||
this.lineIndex = lineIndex; | ||
this.highlightRange = range; | ||
} | ||
|
||
public Highlight(long answerId, int lineIndex, int startIndex, int endIndex) { | ||
this(answerId, lineIndex, new HighlightRange(startIndex, endIndex)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 안 쓰는 생성자입니다~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반완! |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,41 @@ | ||
package reviewme.highlight.domain; | ||
package reviewme.highlight.entity; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Embeddable; | ||
import lombok.AccessLevel; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import reviewme.highlight.domain.exception.HighlightStartIndexExceedEndIndexException; | ||
import reviewme.highlight.domain.exception.NegativeHighlightIndexException; | ||
import reviewme.highlight.domain.exception.InvalidHighlightIndexRangeException; | ||
|
||
@Embeddable | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Getter | ||
@EqualsAndHashCode | ||
public class HighlightPosition { | ||
|
||
@Column(name = "line_index", nullable = false) | ||
private int lineIndex; | ||
public class HighlightRange { | ||
|
||
@Column(name = "start_index", nullable = false) | ||
private int startIndex; | ||
|
||
@Column(name = "end_index", nullable = false) | ||
private int endIndex; | ||
|
||
public HighlightPosition(int lineIndex, int startIndex, int endIndex) { | ||
public HighlightRange(int startIndex, int endIndex) { | ||
validateNonNegativeIndexNumber(startIndex, endIndex); | ||
validateEndIndexOverStartIndex(startIndex, endIndex); | ||
this.lineIndex = lineIndex; | ||
this.startIndex = startIndex; | ||
this.endIndex = endIndex; | ||
} | ||
|
||
private void validateNonNegativeIndexNumber(long startIndex, long endIndex) { | ||
private void validateNonNegativeIndexNumber(int startIndex, int endIndex) { | ||
if (startIndex < 0 || endIndex < 0) { | ||
throw new NegativeHighlightIndexException(startIndex, endIndex); | ||
throw new InvalidHighlightIndexRangeException(startIndex, endIndex); | ||
} | ||
} | ||
|
||
private void validateEndIndexOverStartIndex(long startIndex, long endIndex) { | ||
private void validateEndIndexOverStartIndex(int startIndex, int endIndex) { | ||
if (startIndex > endIndex) { | ||
throw new HighlightStartIndexExceedEndIndexException(startIndex, endIndex); | ||
throw new InvalidHighlightIndexRangeException(startIndex, endIndex); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,17 @@ | ||
package reviewme.highlight.repository; | ||
|
||
import java.util.Collection; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import reviewme.highlight.domain.Highlight; | ||
import org.springframework.data.jpa.repository.Modifying; | ||
import org.springframework.data.jpa.repository.Query; | ||
import reviewme.highlight.entity.Highlight; | ||
|
||
public interface HighlightRepository extends JpaRepository<Highlight, Long> { | ||
|
||
@Modifying | ||
@Query(""" | ||
DELETE FROM Highlight h | ||
WHERE h.answerId IN :answerIds | ||
""") | ||
void deleteAllByAnswerIds(Collection<Long> answerIds); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,15 @@ | ||
package reviewme.highlight.service; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Set; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import reviewme.highlight.domain.Highlight; | ||
import reviewme.highlight.entity.Highlight; | ||
import reviewme.highlight.repository.HighlightRepository; | ||
import reviewme.highlight.service.dto.HighlightIndexRangeRequest; | ||
import reviewme.highlight.service.dto.HighlightRequest; | ||
import reviewme.highlight.service.dto.HighlightedLineRequest; | ||
import reviewme.highlight.service.dto.HighlightsRequest; | ||
import reviewme.highlight.service.mapper.HighlightMapper; | ||
import reviewme.highlight.service.validator.HighlightValidator; | ||
import reviewme.review.domain.Answer; | ||
import reviewme.review.repository.AnswerRepository; | ||
import reviewme.reviewgroup.domain.ReviewGroup; | ||
|
||
|
@@ -25,36 +21,16 @@ public class HighlightService { | |
private final AnswerRepository answerRepository; | ||
|
||
private final HighlightValidator highlightValidator; | ||
private final HighlightMapper highlightMapper; | ||
|
||
@Transactional | ||
public void highlight(HighlightsRequest request, ReviewGroup reviewGroup) { | ||
long reviewGroupId = reviewGroup.getId(); | ||
highlightValidator.validate(request, reviewGroupId); | ||
deleteOldHighlight(request.questionId(), reviewGroupId); | ||
saveNewHighlight(request); | ||
} | ||
|
||
private void deleteOldHighlight(long questionId, long reviewGroupId) { | ||
Set<Answer> answersByReviewGroup = answerRepository.findAllByReviewGroupId(reviewGroupId); | ||
List<Long> answersByReviewQuestion = answersByReviewGroup.stream() | ||
.filter(answer -> answer.getQuestionId() == questionId) | ||
.map(Answer::getId) | ||
.toList(); | ||
public void editHighlight(HighlightsRequest highlightsRequest, ReviewGroup reviewGroup) { | ||
highlightValidator.validate(highlightsRequest, reviewGroup); | ||
List<Highlight> highlights = highlightMapper.mapToHighlights(highlightsRequest); | ||
|
||
highlightRepository.deleteAllById(answersByReviewQuestion); | ||
} | ||
Set<Long> allAnswerIds = answerRepository.findIdsByQuestionId(highlightsRequest.questionId()); | ||
highlightRepository.deleteAllByAnswerIds(allAnswerIds); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [왕사소 & 취향이라 생각하면 반영 안해도 됨] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 고민했었는데 산초도 그렇게 생각했다니 반영 갑니다~~ |
||
|
||
private void saveNewHighlight(HighlightsRequest highlightsRequest) { | ||
List<Highlight> highlights = new ArrayList<>(); | ||
for (HighlightRequest highlight : highlightsRequest.highlights()) { | ||
for (HighlightedLineRequest line : highlight.lines()) { | ||
for (HighlightIndexRangeRequest range : line.ranges()) { | ||
Highlight highLight = new Highlight(highlight.answerId(), | ||
line.index(), range.startIndex(), range.endIndex()); | ||
highlights.add(highLight); | ||
} | ||
} | ||
} | ||
highlightRepository.saveAll(highlights); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,11 @@ public record HighlightsRequest( | |
@Valid @NotNull(message = "하이라이트할 부분을 입력해주세요.") | ||
List<HighlightRequest> highlights | ||
) { | ||
public List<Long> getUniqueAnswerIds() { | ||
return highlights() | ||
.stream() | ||
.map(HighlightRequest::answerId) | ||
.distinct() | ||
.toList(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [초간단🍰] |
||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
얘는 안 바뀌었어요~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lineIndex 말하는 거 맞을까요? 여기는 start, end 등 다른 인덱스도 함께 있어서 구분을 위해 lineIndex라고 명시하는 게 낫겠다 생각했어요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HighlightedLines
👀There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반완!