refactor: Use Assembler to replace the original converter (#1724)

pull/1730/head
guqing 2022-03-09 14:19:05 +08:00 committed by GitHub
parent f733fbea7c
commit 7d4075eb3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 689 additions and 576 deletions

View File

@ -29,6 +29,7 @@ import run.halo.app.model.vo.BaseCommentWithParentVO;
import run.halo.app.model.vo.JournalCommentWithJournalVO;
import run.halo.app.service.JournalCommentService;
import run.halo.app.service.OptionService;
import run.halo.app.service.assembler.comment.JournalCommentAssembler;
/**
* Journal comment controller.
@ -40,13 +41,17 @@ import run.halo.app.service.OptionService;
@RestController
@RequestMapping("/api/admin/journals/comments")
public class JournalCommentController {
private final JournalCommentAssembler journalCommentAssembler;
private final JournalCommentService journalCommentService;
private final OptionService optionService;
public JournalCommentController(JournalCommentService journalCommentService,
public JournalCommentController(
JournalCommentAssembler journalCommentAssembler,
JournalCommentService journalCommentService,
OptionService optionService) {
this.journalCommentAssembler = journalCommentAssembler;
this.journalCommentService = journalCommentService;
this.optionService = optionService;
}
@ -59,7 +64,7 @@ public class JournalCommentController {
Page<JournalComment> journalCommentPage =
journalCommentService.pageBy(commentQuery, pageable);
return journalCommentService.convertToWithJournalVo(journalCommentPage);
return journalCommentAssembler.convertToWithJournalVo(journalCommentPage);
}
@GetMapping("latest")
@ -69,7 +74,7 @@ public class JournalCommentController {
@RequestParam(name = "status", required = false) CommentStatus status) {
List<JournalComment> latestComments =
journalCommentService.pageLatest(top, status).getContent();
return journalCommentService.convertToWithJournalVo(latestComments);
return journalCommentAssembler.convertToWithJournalVo(latestComments);
}
@GetMapping("{journalId:\\d+}/tree_view")
@ -94,7 +99,7 @@ public class JournalCommentController {
@ApiOperation("Creates a journal comment")
public BaseCommentDTO createCommentBy(@RequestBody JournalCommentParam journalCommentParam) {
JournalComment journalComment = journalCommentService.createBy(journalCommentParam);
return journalCommentService.convertTo(journalComment);
return journalCommentAssembler.convertTo(journalComment);
}
@PutMapping("{commentId:\\d+}/status/{status}")
@ -104,7 +109,7 @@ public class JournalCommentController {
// Update comment status
JournalComment updatedJournalComment =
journalCommentService.updateStatus(commentId, status);
return journalCommentService.convertTo(updatedJournalComment);
return journalCommentAssembler.convertTo(updatedJournalComment);
}
@PutMapping("/{commentId:\\d+}")
@ -114,13 +119,13 @@ public class JournalCommentController {
JournalComment commentToUpdate = journalCommentService.getById(commentId);
journalCommentParam.update(commentToUpdate);
return journalCommentService.convertTo(journalCommentService.update(commentToUpdate));
return journalCommentAssembler.convertTo(journalCommentService.update(commentToUpdate));
}
@DeleteMapping("{commentId:\\d+}")
@ApiOperation("Deletes comment permanently and recursively")
public BaseCommentDTO deleteBy(@PathVariable("commentId") Long commentId) {
JournalComment deletedJournalComment = journalCommentService.removeById(commentId);
return journalCommentService.convertTo(deletedJournalComment);
return journalCommentAssembler.convertTo(deletedJournalComment);
}
}

View File

@ -30,6 +30,7 @@ import run.halo.app.model.vo.BaseCommentWithParentVO;
import run.halo.app.model.vo.PostCommentWithPostVO;
import run.halo.app.service.OptionService;
import run.halo.app.service.PostCommentService;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
/**
* Post comment controller.
@ -42,12 +43,17 @@ import run.halo.app.service.PostCommentService;
@RequestMapping("/api/admin/posts/comments")
public class PostCommentController {
private final PostCommentAssembler postCommentAssembler;
private final PostCommentService postCommentService;
private final OptionService optionService;
public PostCommentController(PostCommentService postCommentService,
public PostCommentController(
PostCommentAssembler postCommentAssembler,
PostCommentService postCommentService,
OptionService optionService) {
this.postCommentAssembler = postCommentAssembler;
this.postCommentService = postCommentService;
this.optionService = optionService;
}
@ -58,7 +64,7 @@ public class PostCommentController {
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
CommentQuery commentQuery) {
Page<PostComment> commentPage = postCommentService.pageBy(commentQuery, pageable);
return postCommentService.convertToWithPostVo(commentPage);
return postCommentAssembler.convertToWithPostVo(commentPage);
}
@GetMapping("latest")
@ -70,7 +76,7 @@ public class PostCommentController {
List<PostComment> content = postCommentService.pageLatest(top, status).getContent();
// Convert and return
return postCommentService.convertToWithPostVo(content);
return postCommentAssembler.convertToWithPostVo(content);
}
@GetMapping("{postId:\\d+}/tree_view")
@ -95,7 +101,7 @@ public class PostCommentController {
@ApiOperation("Creates a post comment (new or reply)")
public BaseCommentDTO createBy(@RequestBody PostCommentParam postCommentParam) {
PostComment createdPostComment = postCommentService.createBy(postCommentParam);
return postCommentService.convertTo(createdPostComment);
return postCommentAssembler.convertTo(createdPostComment);
}
@PutMapping("{commentId:\\d+}/status/{status}")
@ -104,7 +110,7 @@ public class PostCommentController {
@PathVariable("status") CommentStatus status) {
// Update comment status
PostComment updatedPostComment = postCommentService.updateStatus(commentId, status);
return postCommentService.convertTo(updatedPostComment);
return postCommentAssembler.convertTo(updatedPostComment);
}
@PutMapping("status/{status}")
@ -113,14 +119,14 @@ public class PostCommentController {
@PathVariable(name = "status") CommentStatus status,
@RequestBody List<Long> ids) {
List<PostComment> comments = postCommentService.updateStatusByIds(ids, status);
return postCommentService.convertTo(comments);
return postCommentAssembler.convertTo(comments);
}
@DeleteMapping("{commentId:\\d+}")
@ApiOperation("Deletes post comment permanently and recursively")
public BaseCommentDTO deletePermanently(@PathVariable("commentId") Long commentId) {
PostComment deletedPostComment = postCommentService.removeById(commentId);
return postCommentService.convertTo(deletedPostComment);
return postCommentAssembler.convertTo(deletedPostComment);
}
@DeleteMapping
@ -133,7 +139,7 @@ public class PostCommentController {
@ApiOperation("Gets a post comment by comment id")
public PostCommentWithPostVO getBy(@PathVariable("commentId") Long commentId) {
PostComment comment = postCommentService.getById(commentId);
return postCommentService.convertToWithPostVo(comment);
return postCommentAssembler.convertToWithPostVo(comment);
}
@PutMapping("{commentId:\\d+}")
@ -144,6 +150,6 @@ public class PostCommentController {
commentParam.update(commentToUpdate);
return postCommentService.convertTo(postCommentService.update(commentToUpdate));
return postCommentAssembler.convertTo(postCommentService.update(commentToUpdate));
}
}

View File

@ -30,6 +30,7 @@ import run.halo.app.model.vo.BaseCommentWithParentVO;
import run.halo.app.model.vo.SheetCommentWithSheetVO;
import run.halo.app.service.OptionService;
import run.halo.app.service.SheetCommentService;
import run.halo.app.service.assembler.comment.SheetCommentAssembler;
/**
* Sheet comment controller.
@ -42,12 +43,17 @@ import run.halo.app.service.SheetCommentService;
@RequestMapping("/api/admin/sheets/comments")
public class SheetCommentController {
private final SheetCommentAssembler sheetCommentAssembler;
private final SheetCommentService sheetCommentService;
private final OptionService optionService;
public SheetCommentController(SheetCommentService sheetCommentService,
public SheetCommentController(
SheetCommentAssembler sheetCommentAssembler,
SheetCommentService sheetCommentService,
OptionService optionService) {
this.sheetCommentAssembler = sheetCommentAssembler;
this.sheetCommentService = sheetCommentService;
this.optionService = optionService;
}
@ -58,7 +64,7 @@ public class SheetCommentController {
@PageableDefault(sort = "createTime", direction = DESC) Pageable pageable,
CommentQuery commentQuery) {
Page<SheetComment> sheetCommentPage = sheetCommentService.pageBy(commentQuery, pageable);
return sheetCommentService.convertToWithSheetVo(sheetCommentPage);
return sheetCommentAssembler.convertToWithSheetVo(sheetCommentPage);
}
@GetMapping("latest")
@ -67,7 +73,7 @@ public class SheetCommentController {
@RequestParam(name = "top", defaultValue = "10") int top,
@RequestParam(name = "status", required = false) CommentStatus status) {
Page<SheetComment> sheetCommentPage = sheetCommentService.pageLatest(top, status);
return sheetCommentService.convertToWithSheetVo(sheetCommentPage.getContent());
return sheetCommentAssembler.convertToWithSheetVo(sheetCommentPage.getContent());
}
@GetMapping("{sheetId:\\d+}/tree_view")
@ -92,7 +98,7 @@ public class SheetCommentController {
@ApiOperation("Creates a sheet comment (new or reply)")
public BaseCommentDTO createBy(@RequestBody SheetCommentParam commentParam) {
SheetComment createdComment = sheetCommentService.createBy(commentParam);
return sheetCommentService.convertTo(createdComment);
return sheetCommentAssembler.convertTo(createdComment);
}
@PutMapping("{commentId:\\d+}/status/{status}")
@ -101,7 +107,7 @@ public class SheetCommentController {
@PathVariable("status") CommentStatus status) {
// Update comment status
SheetComment updatedSheetComment = sheetCommentService.updateStatus(commentId, status);
return sheetCommentService.convertTo(updatedSheetComment);
return sheetCommentAssembler.convertTo(updatedSheetComment);
}
@PutMapping("status/{status}")
@ -110,7 +116,7 @@ public class SheetCommentController {
@PathVariable(name = "status") CommentStatus status,
@RequestBody List<Long> ids) {
List<SheetComment> comments = sheetCommentService.updateStatusByIds(ids, status);
return sheetCommentService.convertTo(comments);
return sheetCommentAssembler.convertTo(comments);
}
@ -118,7 +124,7 @@ public class SheetCommentController {
@ApiOperation("Deletes sheet comment permanently and recursively")
public BaseCommentDTO deletePermanently(@PathVariable("commentId") Long commentId) {
SheetComment deletedSheetComment = sheetCommentService.removeById(commentId);
return sheetCommentService.convertTo(deletedSheetComment);
return sheetCommentAssembler.convertTo(deletedSheetComment);
}
@DeleteMapping
@ -131,7 +137,7 @@ public class SheetCommentController {
@ApiOperation("Gets a sheet comment by comment id")
public SheetCommentWithSheetVO getBy(@PathVariable("commentId") Long commentId) {
SheetComment comment = sheetCommentService.getById(commentId);
return sheetCommentService.convertToWithSheetVo(comment);
return sheetCommentAssembler.convertToWithSheetVo(comment);
}
@PutMapping("{commentId:\\d+}")
@ -142,6 +148,6 @@ public class SheetCommentController {
commentParam.update(commentToUpdate);
return sheetCommentService.convertTo(sheetCommentService.update(commentToUpdate));
return sheetCommentAssembler.convertTo(sheetCommentService.update(commentToUpdate));
}
}

View File

@ -22,7 +22,6 @@ import org.springframework.web.util.HtmlUtils;
import run.halo.app.cache.lock.CacheLock;
import run.halo.app.cache.lock.CacheParam;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.dto.JournalDTO;
import run.halo.app.model.dto.JournalWithCmtCountDTO;
import run.halo.app.model.entity.Journal;
import run.halo.app.model.entity.JournalComment;
@ -35,6 +34,7 @@ import run.halo.app.model.vo.CommentWithHasChildrenVO;
import run.halo.app.service.JournalCommentService;
import run.halo.app.service.JournalService;
import run.halo.app.service.OptionService;
import run.halo.app.service.assembler.comment.JournalCommentAssembler;
/**
* Content journal controller.
@ -49,14 +49,18 @@ public class JournalController {
private final JournalService journalService;
private final JournalCommentAssembler journalCommentAssembler;
private final JournalCommentService journalCommentService;
private final OptionService optionService;
public JournalController(JournalService journalService,
JournalCommentAssembler journalCommentAssembler,
JournalCommentService journalCommentService,
OptionService optionService) {
this.journalService = journalService;
this.journalCommentAssembler = journalCommentAssembler;
this.journalCommentService = journalCommentService;
this.optionService = optionService;
}
@ -93,7 +97,7 @@ public class JournalController {
List<JournalComment> postComments = journalCommentService
.listChildrenBy(journalId, commentParentId, CommentStatus.PUBLISHED, sort);
// Convert to base comment dto
return journalCommentService.convertTo(postComments);
return journalCommentAssembler.convertTo(postComments);
}
@GetMapping("{journalId:\\d+}/comments/tree_view")
@ -122,7 +126,8 @@ public class JournalController {
// Escape content
journalCommentParam.setContent(HtmlUtils
.htmlEscape(journalCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
return journalCommentService.convertTo(journalCommentService.createBy(journalCommentParam));
return journalCommentAssembler.convertTo(
journalCommentService.createBy(journalCommentParam));
}
@PostMapping("{id:\\d+}/likes")

View File

@ -42,6 +42,7 @@ import run.halo.app.service.OptionService;
import run.halo.app.service.PostCommentService;
import run.halo.app.service.PostService;
import run.halo.app.service.assembler.PostRenderAssembler;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
/**
* Content post controller.
@ -57,6 +58,8 @@ public class PostController {
private final PostService postService;
private final PostCommentAssembler postCommentAssembler;
private final PostCommentService postCommentService;
private final OptionService optionService;
@ -66,10 +69,12 @@ public class PostController {
private final PostAuthentication postAuthentication;
public PostController(PostService postService,
PostCommentAssembler postCommentAssembler,
PostCommentService postCommentService,
OptionService optionService, PostRenderAssembler postRenderAssembler,
PostAuthentication postAuthentication) {
this.postService = postService;
this.postCommentAssembler = postCommentAssembler;
this.postCommentService = postCommentService;
this.optionService = optionService;
this.postRenderAssembler = postRenderAssembler;
@ -203,7 +208,7 @@ public class PostController {
.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort);
// Convert to base comment dto
return postCommentService.convertTo(postComments);
return postCommentAssembler.convertTo(postComments);
}
@GetMapping("{postId:\\d+}/comments/tree_view")
@ -236,7 +241,7 @@ public class PostController {
// Escape content
postCommentParam.setContent(HtmlUtils
.htmlEscape(postCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
return postCommentService.convertTo(postCommentService.createBy(postCommentParam));
return postCommentAssembler.convertTo(postCommentService.createBy(postCommentParam));
}
@PostMapping("{postId:\\d+}/likes")

View File

@ -35,6 +35,7 @@ import run.halo.app.service.OptionService;
import run.halo.app.service.SheetCommentService;
import run.halo.app.service.SheetService;
import run.halo.app.service.assembler.SheetRenderAssembler;
import run.halo.app.service.assembler.comment.SheetCommentAssembler;
/**
* Content sheet controller.
@ -47,6 +48,8 @@ import run.halo.app.service.assembler.SheetRenderAssembler;
@RequestMapping("/api/content/sheets")
public class SheetController {
private final SheetCommentAssembler sheetCommentAssembler;
private final SheetService sheetService;
private final SheetRenderAssembler sheetRenderAssembler;
@ -55,10 +58,13 @@ public class SheetController {
private final OptionService optionService;
public SheetController(SheetService sheetService,
public SheetController(
SheetCommentAssembler sheetCommentAssembler,
SheetService sheetService,
SheetRenderAssembler sheetRenderAssembler,
SheetCommentService sheetCommentService,
OptionService optionService) {
this.sheetCommentAssembler = sheetCommentAssembler;
this.sheetService = sheetService;
this.sheetRenderAssembler = sheetRenderAssembler;
this.sheetCommentService = sheetCommentService;
@ -140,7 +146,7 @@ public class SheetController {
List<SheetComment> sheetComments = sheetCommentService
.listChildrenBy(sheetId, commentParentId, CommentStatus.PUBLISHED, sort);
// Convert to base comment dto
return sheetCommentService.convertTo(sheetComments);
return sheetCommentAssembler.convertTo(sheetComments);
}
@ -170,6 +176,6 @@ public class SheetController {
// Escape content
sheetCommentParam.setContent(HtmlUtils
.htmlEscape(sheetCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
return sheetCommentService.convertTo(sheetCommentService.createBy(sheetCommentParam));
return sheetCommentAssembler.convertTo(sheetCommentService.createBy(sheetCommentParam));
}
}

View File

@ -15,6 +15,7 @@ import run.halo.app.model.entity.PostComment;
import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.support.HaloConst;
import run.halo.app.service.PostCommentService;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
/**
* Freemarker custom tag of comment.
@ -27,8 +28,12 @@ public class CommentTagDirective implements TemplateDirectiveModel {
private final PostCommentService postCommentService;
public CommentTagDirective(Configuration configuration, PostCommentService postCommentService) {
private final PostCommentAssembler postCommentAssembler;
public CommentTagDirective(Configuration configuration, PostCommentService postCommentService,
PostCommentAssembler postCommentAssembler) {
this.postCommentService = postCommentService;
this.postCommentAssembler = postCommentAssembler;
configuration.setSharedVariable("commentTag", this);
}
@ -46,7 +51,8 @@ public class CommentTagDirective implements TemplateDirectiveModel {
Page<PostComment> postComments =
postCommentService.pageLatest(top, CommentStatus.PUBLISHED);
env.setVariable("comments",
builder.build().wrap(postCommentService.convertToWithPostVo(postComments)));
builder.build()
.wrap(postCommentAssembler.convertToWithPostVo(postComments)));
break;
case "count":
env.setVariable("count", builder.build().wrap(postCommentService.count()));

View File

@ -1,26 +1,15 @@
package run.halo.app.service;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import run.halo.app.model.entity.JournalComment;
import run.halo.app.model.vo.JournalCommentWithJournalVO;
import run.halo.app.service.base.BaseCommentService;
/**
* Journal comment service interface.
*
* @author johnniang
* @author guqing
* @date 2019-04-25
*/
public interface JournalCommentService extends BaseCommentService<JournalComment> {
@NonNull
List<JournalCommentWithJournalVO> convertToWithJournalVo(
@Nullable List<JournalComment> journalComments);
@NonNull
Page<JournalCommentWithJournalVO> convertToWithJournalVo(
@NonNull Page<JournalComment> journalCommentPage);
}

View File

@ -1,11 +1,6 @@
package run.halo.app.service;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import run.halo.app.model.entity.PostComment;
import run.halo.app.model.vo.PostCommentWithPostVO;
import run.halo.app.service.base.BaseCommentService;
/**
@ -13,39 +8,13 @@ import run.halo.app.service.base.BaseCommentService;
*
* @author johnniang
* @author ryanwang
* @author guqing
* @date 2019-03-14
*/
public interface PostCommentService extends BaseCommentService<PostComment> {
/**
* Converts to with post vo.
*
* @param commentPage comment page must not be null
* @return a page of comment with post vo
*/
@NonNull
Page<PostCommentWithPostVO> convertToWithPostVo(@NonNull Page<PostComment> commentPage);
/**
* Converts to with post vo
*
* @param comment comment
* @return a comment with post vo
*/
@NonNull
PostCommentWithPostVO convertToWithPostVo(@NonNull PostComment comment);
/**
* Converts to with post vo
*
* @param postComments comment list
* @return a list of comment with post vo
*/
@NonNull
List<PostCommentWithPostVO> convertToWithPostVo(@Nullable List<PostComment> postComments);
/**
* Validate CommentBlackList Status
* Validate CommentBlackList Status.
*/
void validateCommentBlackListStatus();
}

View File

@ -1,11 +1,6 @@
package run.halo.app.service;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import run.halo.app.model.entity.SheetComment;
import run.halo.app.model.vo.SheetCommentWithSheetVO;
import run.halo.app.service.base.BaseCommentService;
/**
@ -17,31 +12,4 @@ import run.halo.app.service.base.BaseCommentService;
*/
public interface SheetCommentService extends BaseCommentService<SheetComment> {
/**
* Converts to with sheet vo
*
* @param comment comment
* @return a comment with sheet vo
*/
@NonNull
SheetCommentWithSheetVO convertToWithSheetVo(@NonNull SheetComment comment);
/**
* Converts to with sheet vo
*
* @param sheetComments sheet comments
* @return a sheet comments with sheet vo
*/
@NonNull
List<SheetCommentWithSheetVO> convertToWithSheetVo(@Nullable List<SheetComment> sheetComments);
/**
* Converts to with sheet vo
*
* @param sheetCommentPage sheet comments
* @return a page of sheet comments with sheet vo
*/
@NonNull
Page<SheetCommentWithSheetVO> convertToWithSheetVo(
@NonNull Page<SheetComment> sheetCommentPage);
}

View File

@ -0,0 +1,168 @@
package run.halo.app.service.assembler.comment;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.BaseComment;
import run.halo.app.model.properties.CommentProperties;
import run.halo.app.model.vo.BaseCommentVO;
import run.halo.app.service.OptionService;
/**
* Base comment assembler.
*
* @author guqing
* @date 2022-03-08
*/
public abstract class BaseCommentAssembler<COMMENT extends BaseComment> {
private final OptionService optionService;
public BaseCommentAssembler(OptionService optionService) {
this.optionService = optionService;
}
/**
* Converts to base comment dto.
*
* @param comment comment must not be null
* @return base comment dto
*/
@NonNull
public BaseCommentDTO convertTo(@NonNull COMMENT comment) {
Assert.notNull(comment, "Comment must not be null");
BaseCommentDTO baseCommentDto = new BaseCommentDTO().convertFrom(comment);
baseCommentDto.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return baseCommentDto;
}
/**
* Converts to base comment dto list.
*
* @param comments comment list must not be null
* @return a list of base comment dto
*/
@NonNull
public List<BaseCommentDTO> convertTo(@NonNull List<COMMENT> comments) {
if (CollectionUtils.isEmpty(comments)) {
return Collections.emptyList();
}
return comments.stream()
.map(this::convertTo)
.collect(Collectors.toList());
}
/**
* Converts to base comment dto page.
*
* @param commentPage comment page must not be null
* @return a page of base comment dto
*/
@NonNull
public Page<BaseCommentDTO> convertTo(@NonNull Page<COMMENT> commentPage) {
Assert.notNull(commentPage, "Comment page must not be null");
return commentPage.map(this::convertTo);
}
/**
* Converts to base comment vo tree.
*
* @param comments comments list could be null
* @param comparator comment comparator could be null
* @return a comment vo tree
*/
public List<BaseCommentVO> convertToVo(@Nullable List<COMMENT> comments,
@Nullable Comparator<BaseCommentVO> comparator) {
if (CollectionUtils.isEmpty(comments)) {
return Collections.emptyList();
}
// Init the top virtual comment
BaseCommentVO topVirtualComment = new BaseCommentVO();
topVirtualComment.setId(0L);
topVirtualComment.setChildren(new LinkedList<>());
// Concrete the comment tree
concreteTree(topVirtualComment, new LinkedList<>(comments), comparator);
return topVirtualComment.getChildren();
}
/**
* Concretes comment tree.
*
* @param parentComment parent comment vo must not be null
* @param comments comment list must not null
* @param commentComparator comment vo comparator
*/
public void concreteTree(@NonNull BaseCommentVO parentComment,
@Nullable Collection<COMMENT> comments,
@Nullable Comparator<BaseCommentVO> commentComparator) {
Assert.notNull(parentComment, "Parent comment must not be null");
if (CollectionUtils.isEmpty(comments)) {
return;
}
// Get children
List<COMMENT> children = comments.stream()
.filter(comment -> Objects.equals(parentComment.getId(), comment.getParentId()))
.collect(Collectors.toList());
// Add children
children.forEach(comment -> {
// Convert to comment vo
BaseCommentVO commentVo = new BaseCommentVO().convertFrom(comment);
commentVo.setAvatar(buildAvatarUrl(commentVo.getGravatarMd5()));
if (parentComment.getChildren() == null) {
parentComment.setChildren(new LinkedList<>());
}
parentComment.getChildren().add(commentVo);
});
// Remove children
comments.removeAll(children);
if (!CollectionUtils.isEmpty(parentComment.getChildren())) {
// Recursively concrete the children
parentComment.getChildren()
.forEach(childComment -> concreteTree(childComment, comments, commentComparator));
// Sort the children
if (commentComparator != null) {
parentComment.getChildren().sort(commentComparator);
}
}
}
/**
* Build avatar url by gravatarMd5.
*
* @param gravatarMd5 gravatarMd5
* @return avatar url
*/
public String buildAvatarUrl(String gravatarMd5) {
final String gravatarSource =
optionService.getByPropertyOrDefault(CommentProperties.GRAVATAR_SOURCE, String.class);
final String gravatarDefault =
optionService.getByPropertyOrDefault(CommentProperties.GRAVATAR_DEFAULT, String.class);
return gravatarSource + gravatarMd5 + "?s=256&d=" + gravatarDefault;
}
}

View File

@ -0,0 +1,81 @@
package run.halo.app.service.assembler.comment;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.JournalDTO;
import run.halo.app.model.entity.Journal;
import run.halo.app.model.entity.JournalComment;
import run.halo.app.model.vo.JournalCommentWithJournalVO;
import run.halo.app.repository.JournalRepository;
import run.halo.app.service.OptionService;
import run.halo.app.utils.ServiceUtils;
/**
* Journal comment assembler.
*
* @author guqing
* @date 2022-03-08
*/
@Component
public class JournalCommentAssembler extends BaseCommentAssembler<JournalComment> {
private final JournalRepository journalRepository;
public JournalCommentAssembler(OptionService optionService,
JournalRepository journalRepository) {
super(optionService);
this.journalRepository = journalRepository;
}
@NonNull
public List<JournalCommentWithJournalVO> convertToWithJournalVo(
List<JournalComment> journalComments) {
if (CollectionUtils.isEmpty(journalComments)) {
return Collections.emptyList();
}
Set<Integer> journalIds =
ServiceUtils.fetchProperty(journalComments, JournalComment::getPostId);
// Get all journals
List<Journal> journals = journalRepository.findAllById(journalIds);
Map<Integer, Journal> journalMap = ServiceUtils.convertToMap(journals, Journal::getId);
return journalComments.stream()
.filter(journalComment -> journalMap.containsKey(journalComment.getPostId()))
.map(journalComment -> {
JournalCommentWithJournalVO journalCmtWithJournalVo =
new JournalCommentWithJournalVO().convertFrom(journalComment);
journalCmtWithJournalVo.setJournal(
new JournalDTO().convertFrom(journalMap.get(journalComment.getPostId())));
journalCmtWithJournalVo.setAvatar(buildAvatarUrl(journalComment.getGravatarMd5()));
return journalCmtWithJournalVo;
})
.collect(Collectors.toList());
}
@NonNull
public Page<JournalCommentWithJournalVO> convertToWithJournalVo(
@NonNull Page<JournalComment> journalCommentPage) {
Assert.notNull(journalCommentPage, "Journal comment page must not be null");
// Convert the list
List<JournalCommentWithJournalVO> journalCmtWithJournalVos =
convertToWithJournalVo(journalCommentPage.getContent());
// Build and return
return new PageImpl<>(journalCmtWithJournalVos, journalCommentPage.getPageable(),
journalCommentPage.getTotalElements());
}
}

View File

@ -0,0 +1,183 @@
package run.halo.app.service.assembler.comment;
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.post.BasePostMinimalDTO;
import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostComment;
import run.halo.app.model.enums.PostPermalinkType;
import run.halo.app.model.vo.PostCommentWithPostVO;
import run.halo.app.repository.PostRepository;
import run.halo.app.service.OptionService;
import run.halo.app.utils.DateUtils;
import run.halo.app.utils.ServiceUtils;
/**
* Post comment assembler.
*
* @author guqing
* @date 2022-03-08
*/
@Component
public class PostCommentAssembler extends BaseCommentAssembler<PostComment> {
private final OptionService optionService;
private final PostRepository postRepository;
public PostCommentAssembler(OptionService optionService,
PostRepository postRepository) {
super(optionService);
this.postRepository = postRepository;
this.optionService = optionService;
}
/**
* Converts to with post vo.
*
* @param commentPage comment page must not be null
* @return a page of comment with post vo
*/
@NonNull
public Page<PostCommentWithPostVO> convertToWithPostVo(@NonNull Page<PostComment> commentPage) {
Assert.notNull(commentPage, "PostComment page must not be null");
return new PageImpl<>(convertToWithPostVo(commentPage.getContent()),
commentPage.getPageable(), commentPage.getTotalElements());
}
/**
* Converts to with post vo
*
* @param comment comment
* @return a comment with post vo
*/
@NonNull
public PostCommentWithPostVO convertToWithPostVo(@NonNull PostComment comment) {
Assert.notNull(comment, "PostComment must not be null");
PostCommentWithPostVO postCommentWithPostVo =
new PostCommentWithPostVO().convertFrom(comment);
BasePostMinimalDTO basePostMinimalDto =
new BasePostMinimalDTO().convertFrom(postRepository.getById(comment.getPostId()));
postCommentWithPostVo.setPost(buildPostFullPath(basePostMinimalDto));
postCommentWithPostVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return postCommentWithPostVo;
}
/**
* Converts to with post vo
*
* @param postComments comment list
* @return a list of comment with post vo
*/
@NonNull
public List<PostCommentWithPostVO> convertToWithPostVo(List<PostComment> postComments) {
if (CollectionUtils.isEmpty(postComments)) {
return Collections.emptyList();
}
// Fetch goods ids
Set<Integer> postIds = ServiceUtils.fetchProperty(postComments, PostComment::getPostId);
// Get all posts
Map<Integer, Post> postMap =
ServiceUtils.convertToMap(postRepository.findAllById(postIds), Post::getId);
return postComments.stream()
.filter(comment -> postMap.containsKey(comment.getPostId()))
.map(comment -> {
// Convert to vo
PostCommentWithPostVO postCommentWithPostVo =
new PostCommentWithPostVO().convertFrom(comment);
BasePostMinimalDTO basePostMinimalDto =
new BasePostMinimalDTO().convertFrom(postMap.get(comment.getPostId()));
postCommentWithPostVo.setPost(buildPostFullPath(basePostMinimalDto));
postCommentWithPostVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return postCommentWithPostVo;
}).collect(Collectors.toList());
}
private BasePostMinimalDTO buildPostFullPath(BasePostMinimalDTO post) {
PostPermalinkType permalinkType = optionService.getPostPermalinkType();
String pathSuffix = optionService.getPathSuffix();
String archivesPrefix = optionService.getArchivesPrefix();
int month = DateUtils.month(post.getCreateTime()) + 1;
String monthString = month < 10 ? "0" + month : String.valueOf(month);
int day = DateUtils.dayOfMonth(post.getCreateTime());
String dayString = day < 10 ? "0" + day : String.valueOf(day);
StringBuilder fullPath = new StringBuilder();
if (optionService.isEnabledAbsolutePath()) {
fullPath.append(optionService.getBlogBaseUrl());
}
fullPath.append(URL_SEPARATOR);
if (permalinkType.equals(PostPermalinkType.DEFAULT)) {
fullPath.append(archivesPrefix)
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.ID)) {
fullPath.append("?p=")
.append(post.getId());
} else if (permalinkType.equals(PostPermalinkType.DATE)) {
fullPath.append(DateUtils.year(post.getCreateTime()))
.append(URL_SEPARATOR)
.append(monthString)
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.DAY)) {
fullPath.append(DateUtils.year(post.getCreateTime()))
.append(URL_SEPARATOR)
.append(monthString)
.append(URL_SEPARATOR)
.append(dayString)
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.YEAR)) {
fullPath.append(DateUtils.year(post.getCreateTime()))
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.ID_SLUG)) {
fullPath.append(archivesPrefix)
.append(URL_SEPARATOR)
.append(post.getId())
.append(pathSuffix);
}
post.setFullPath(fullPath.toString());
return post;
}
}

View File

@ -0,0 +1,141 @@
package run.halo.app.service.assembler.comment;
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.post.BasePostMinimalDTO;
import run.halo.app.model.entity.Sheet;
import run.halo.app.model.entity.SheetComment;
import run.halo.app.model.enums.SheetPermalinkType;
import run.halo.app.model.vo.SheetCommentWithSheetVO;
import run.halo.app.repository.SheetRepository;
import run.halo.app.service.OptionService;
import run.halo.app.utils.ServiceUtils;
/**
* Sheet comment assembler.
*
* @author guqing
* @date 2022-03-08
*/
@Component
public class SheetCommentAssembler extends BaseCommentAssembler<SheetComment> {
private final SheetRepository sheetRepository;
private final OptionService optionService;
public SheetCommentAssembler(OptionService optionService,
SheetRepository sheetRepository) {
super(optionService);
this.sheetRepository = sheetRepository;
this.optionService = optionService;
}
/**
* Converts to with sheet vo
*
* @param comment comment
* @return a comment with sheet vo
*/
@NonNull
public SheetCommentWithSheetVO convertToWithSheetVo(@NonNull SheetComment comment) {
Assert.notNull(comment, "SheetComment must not be null");
SheetCommentWithSheetVO sheetCommentWithSheetVo =
new SheetCommentWithSheetVO().convertFrom(comment);
BasePostMinimalDTO basePostMinimalDto =
new BasePostMinimalDTO().convertFrom(sheetRepository.getOne(comment.getPostId()));
sheetCommentWithSheetVo.setSheet(buildSheetFullPath(basePostMinimalDto));
sheetCommentWithSheetVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return sheetCommentWithSheetVo;
}
/**
* Converts to with sheet vo
*
* @param sheetComments sheet comments
* @return a sheet comments with sheet vo
*/
@NonNull
public List<SheetCommentWithSheetVO> convertToWithSheetVo(List<SheetComment> sheetComments) {
if (CollectionUtils.isEmpty(sheetComments)) {
return Collections.emptyList();
}
Set<Integer> sheetIds = ServiceUtils.fetchProperty(sheetComments, SheetComment::getPostId);
Map<Integer, Sheet> sheetMap =
ServiceUtils.convertToMap(sheetRepository.findAllById(sheetIds), Sheet::getId);
return sheetComments.stream()
.filter(comment -> sheetMap.containsKey(comment.getPostId()))
.map(comment -> {
SheetCommentWithSheetVO sheetCmtWithPostVo =
new SheetCommentWithSheetVO().convertFrom(comment);
BasePostMinimalDTO postMinimalDto =
new BasePostMinimalDTO().convertFrom(sheetMap.get(comment.getPostId()));
sheetCmtWithPostVo.setSheet(buildSheetFullPath(postMinimalDto));
sheetCmtWithPostVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return sheetCmtWithPostVo;
})
.collect(Collectors.toList());
}
/**
* Converts to with sheet vo
*
* @param sheetCommentPage sheet comments
* @return a page of sheet comments with sheet vo
*/
@NonNull
public Page<SheetCommentWithSheetVO> convertToWithSheetVo(
@NonNull Page<SheetComment> sheetCommentPage) {
Assert.notNull(sheetCommentPage, "Sheet comment page must not be null");
return new PageImpl<>(convertToWithSheetVo(sheetCommentPage.getContent()),
sheetCommentPage.getPageable(), sheetCommentPage.getTotalElements());
}
private BasePostMinimalDTO buildSheetFullPath(BasePostMinimalDTO basePostMinimalDto) {
StringBuilder fullPath = new StringBuilder();
SheetPermalinkType permalinkType = optionService.getSheetPermalinkType();
if (optionService.isEnabledAbsolutePath()) {
fullPath.append(optionService.getBlogBaseUrl());
}
if (permalinkType.equals(SheetPermalinkType.SECONDARY)) {
fullPath.append(URL_SEPARATOR)
.append(optionService.getSheetPrefix())
.append(URL_SEPARATOR)
.append(basePostMinimalDto.getSlug())
.append(optionService.getPathSuffix());
} else if (permalinkType.equals(SheetPermalinkType.ROOT)) {
fullPath.append(URL_SEPARATOR)
.append(basePostMinimalDto.getSlug())
.append(optionService.getPathSuffix());
}
basePostMinimalDto.setFullPath(fullPath.toString());
return basePostMinimalDto;
}
}

View File

@ -1,7 +1,6 @@
package run.halo.app.service.base;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
@ -9,7 +8,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.BaseComment;
import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.BaseCommentParam;
@ -27,7 +25,7 @@ import run.halo.app.model.vo.CommentWithHasChildrenVO;
*/
public interface BaseCommentService<COMMENT extends BaseComment>
extends CrudService<COMMENT, Long> {
/**
* Lists comments by post id.
*
@ -217,42 +215,6 @@ public interface BaseCommentService<COMMENT extends BaseComment>
@NonNull
List<COMMENT> removeByIds(@NonNull Collection<Long> ids);
/**
* Converts to base comment dto.
*
* @param comment comment must not be null
* @return base comment dto
*/
@NonNull
BaseCommentDTO convertTo(@NonNull COMMENT comment);
/**
* Converts to base comment dto list.
*
* @param comments comment list must not be null
* @return a list of base comment dto
*/
@NonNull
List<BaseCommentDTO> convertTo(@NonNull List<COMMENT> comments);
/**
* Converts to base comment dto page.
*
* @param commentPage comment page must not be null
* @return a page of base comment dto
*/
@NonNull
Page<BaseCommentDTO> convertTo(@NonNull Page<COMMENT> commentPage);
/**
* Converts to base comment vo tree.
*
* @param comments comments list could be null
* @param comparator comment comparator could be null
* @return a comment vo tree
*/
List<BaseCommentVO> convertToVo(@Nullable List<COMMENT> comments,
@Nullable Comparator<BaseCommentVO> comparator);
/**
* Target validation.

View File

@ -11,7 +11,6 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -34,7 +33,6 @@ import run.halo.app.event.comment.CommentNewEvent;
import run.halo.app.event.comment.CommentReplyEvent;
import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.BaseComment;
import run.halo.app.model.entity.User;
import run.halo.app.model.enums.CommentStatus;
@ -53,6 +51,7 @@ import run.halo.app.security.authentication.Authentication;
import run.halo.app.security.context.SecurityContextHolder;
import run.halo.app.service.OptionService;
import run.halo.app.service.UserService;
import run.halo.app.service.assembler.comment.BaseCommentAssembler;
import run.halo.app.service.base.AbstractCrudService;
import run.halo.app.service.base.BaseCommentService;
import run.halo.app.utils.HaloUtils;
@ -75,15 +74,18 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
protected final UserService userService;
protected final ApplicationEventPublisher eventPublisher;
private final BaseCommentRepository<COMMENT> baseCommentRepository;
private final BaseCommentAssembler<COMMENT> commentAssembler;
public BaseCommentServiceImpl(BaseCommentRepository<COMMENT> baseCommentRepository,
OptionService optionService,
UserService userService, ApplicationEventPublisher eventPublisher) {
UserService userService, ApplicationEventPublisher eventPublisher,
BaseCommentAssembler<COMMENT> commentAssembler) {
super(baseCommentRepository);
this.baseCommentRepository = baseCommentRepository;
this.optionService = optionService;
this.userService = userService;
this.eventPublisher = eventPublisher;
this.commentAssembler = commentAssembler;
}
@Override
@ -154,7 +156,7 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
buildCommentComparator(pageable.getSortOr(Sort.by(Sort.Direction.DESC, "createTime")));
// Convert to vo
List<BaseCommentVO> topComments = convertToVo(comments, commentComparator);
List<BaseCommentVO> topComments = commentAssembler.convertToVo(comments, commentComparator);
List<BaseCommentVO> pageContent;
@ -229,7 +231,8 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
BaseCommentWithParentVO commentWithParentVo =
new BaseCommentWithParentVO().convertFrom(comment);
commentWithParentVo.setAvatar(buildAvatarUrl(commentWithParentVo.getGravatarMd5()));
commentWithParentVo.setAvatar(
commentAssembler.buildAvatarUrl(commentWithParentVo.getGravatarMd5()));
// Get parent comment vo from cache
BaseCommentWithParentVO parentCommentVo = parentCommentVoMap.get(comment.getParentId());
@ -242,7 +245,8 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
// Convert to parent comment vo
parentCommentVo = new BaseCommentWithParentVO().convertFrom(parentComment);
parentCommentVo.setAvatar(buildAvatarUrl(parentComment.getGravatarMd5()));
parentCommentVo.setAvatar(
commentAssembler.buildAvatarUrl(parentComment.getGravatarMd5()));
// Cache the parent comment vo
parentCommentVoMap.put(parentComment.getId(), parentCommentVo);
@ -470,37 +474,6 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
return ids.stream().map(this::removeById).collect(Collectors.toList());
}
@Override
@NonNull
public List<BaseCommentDTO> convertTo(@NonNull List<COMMENT> comments) {
if (CollectionUtils.isEmpty(comments)) {
return Collections.emptyList();
}
return comments.stream()
.map(this::convertTo)
.collect(Collectors.toList());
}
@Override
@NonNull
public Page<BaseCommentDTO> convertTo(@NonNull Page<COMMENT> commentPage) {
Assert.notNull(commentPage, "Comment page must not be null");
return commentPage.map(this::convertTo);
}
@Override
@NonNull
public BaseCommentDTO convertTo(@NonNull COMMENT comment) {
Assert.notNull(comment, "Comment must not be null");
BaseCommentDTO baseCommentDto = new BaseCommentDTO().convertFrom(comment);
baseCommentDto.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return baseCommentDto;
}
@NonNull
protected Specification<COMMENT> buildSpecByQuery(@NonNull CommentQuery commentQuery) {
Assert.notNull(commentQuery, "Comment query must not be null");
@ -553,25 +526,6 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
};
}
@NonNull
@Override
public List<BaseCommentVO> convertToVo(@Nullable List<COMMENT> comments,
@Nullable Comparator<BaseCommentVO> comparator) {
if (CollectionUtils.isEmpty(comments)) {
return Collections.emptyList();
}
// Init the top virtual comment
BaseCommentVO topVirtualComment = new BaseCommentVO();
topVirtualComment.setId(0L);
topVirtualComment.setChildren(new LinkedList<>());
// Concrete the comment tree
concreteTree(topVirtualComment, new LinkedList<>(comments), comparator);
return topVirtualComment.getChildren();
}
@Override
@NonNull
public Page<CommentWithHasChildrenVO> pageTopCommentsBy(@NonNull Integer targetId,
@ -609,7 +563,7 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
new CommentWithHasChildrenVO().convertFrom(topComment);
comment
.setHasChildren(commentChildrenCountMap.getOrDefault(topComment.getId(), 0L) > 0);
comment.setAvatar(buildAvatarUrl(topComment.getGravatarMd5()));
comment.setAvatar(commentAssembler.buildAvatarUrl(topComment.getGravatarMd5()));
return comment;
});
}
@ -724,68 +678,4 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
// Add direct children to children result
children.addAll(topComments);
}
/**
* Concretes comment tree.
*
* @param parentComment parent comment vo must not be null
* @param comments comment list must not null
* @param commentComparator comment vo comparator
*/
protected void concreteTree(@NonNull BaseCommentVO parentComment,
@Nullable Collection<COMMENT> comments,
@Nullable Comparator<BaseCommentVO> commentComparator) {
Assert.notNull(parentComment, "Parent comment must not be null");
if (CollectionUtils.isEmpty(comments)) {
return;
}
// Get children
List<COMMENT> children = comments.stream()
.filter(comment -> Objects.equals(parentComment.getId(), comment.getParentId()))
.collect(Collectors.toList());
// Add children
children.forEach(comment -> {
// Convert to comment vo
BaseCommentVO commentVo = new BaseCommentVO().convertFrom(comment);
commentVo.setAvatar(buildAvatarUrl(commentVo.getGravatarMd5()));
if (parentComment.getChildren() == null) {
parentComment.setChildren(new LinkedList<>());
}
parentComment.getChildren().add(commentVo);
});
// Remove children
comments.removeAll(children);
if (!CollectionUtils.isEmpty(parentComment.getChildren())) {
// Recursively concrete the children
parentComment.getChildren()
.forEach(childComment -> concreteTree(childComment, comments, commentComparator));
// Sort the children
if (commentComparator != null) {
parentComment.getChildren().sort(commentComparator);
}
}
}
/**
* Build avatar url by gravatarMd5
*
* @param gravatarMd5 gravatarMd5
* @return avatar url
*/
public String buildAvatarUrl(String gravatarMd5) {
final String gravatarSource =
optionService.getByPropertyOrDefault(CommentProperties.GRAVATAR_SOURCE, String.class);
final String gravatarDefault =
optionService.getByPropertyOrDefault(CommentProperties.GRAVATAR_DEFAULT, String.class);
return gravatarSource + gravatarMd5 + "?s=256&d=" + gravatarDefault;
}
}

View File

@ -1,33 +1,22 @@
package run.halo.app.service.impl;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.JournalDTO;
import run.halo.app.model.entity.Journal;
import run.halo.app.model.entity.JournalComment;
import run.halo.app.model.vo.JournalCommentWithJournalVO;
import run.halo.app.repository.JournalCommentRepository;
import run.halo.app.repository.JournalRepository;
import run.halo.app.service.JournalCommentService;
import run.halo.app.service.OptionService;
import run.halo.app.service.UserService;
import run.halo.app.utils.ServiceUtils;
import run.halo.app.service.assembler.comment.JournalCommentAssembler;
/**
* Journal comment service implementation.
*
* @author johnniang
* @author guqing
* @date 2019-04-25
*/
@Service
@ -39,8 +28,11 @@ public class JournalCommentServiceImpl extends BaseCommentServiceImpl<JournalCom
public JournalCommentServiceImpl(JournalCommentRepository journalCommentRepository,
OptionService optionService,
UserService userService,
ApplicationEventPublisher eventPublisher, JournalRepository journalRepository) {
super(journalCommentRepository, optionService, userService, eventPublisher);
ApplicationEventPublisher eventPublisher,
JournalRepository journalRepository,
JournalCommentAssembler journalCommentAssembler) {
super(journalCommentRepository, optionService, userService, eventPublisher,
journalCommentAssembler);
this.journalRepository = journalRepository;
}
@ -50,49 +42,4 @@ public class JournalCommentServiceImpl extends BaseCommentServiceImpl<JournalCom
throw new NotFoundException("查询不到该日志信息").setErrorData(journalId);
}
}
@Override
@NonNull
public List<JournalCommentWithJournalVO> convertToWithJournalVo(
List<JournalComment> journalComments) {
if (CollectionUtils.isEmpty(journalComments)) {
return Collections.emptyList();
}
Set<Integer> journalIds =
ServiceUtils.fetchProperty(journalComments, JournalComment::getPostId);
// Get all journals
List<Journal> journals = journalRepository.findAllById(journalIds);
Map<Integer, Journal> journalMap = ServiceUtils.convertToMap(journals, Journal::getId);
return journalComments.stream()
.filter(journalComment -> journalMap.containsKey(journalComment.getPostId()))
.map(journalComment -> {
JournalCommentWithJournalVO journalCmtWithJournalVo =
new JournalCommentWithJournalVO().convertFrom(journalComment);
journalCmtWithJournalVo.setJournal(
new JournalDTO().convertFrom(journalMap.get(journalComment.getPostId())));
journalCmtWithJournalVo.setAvatar(buildAvatarUrl(journalComment.getGravatarMd5()));
return journalCmtWithJournalVo;
})
.collect(Collectors.toList());
}
@Override
@NonNull
public Page<JournalCommentWithJournalVO> convertToWithJournalVo(
@NonNull Page<JournalComment> journalCommentPage) {
Assert.notNull(journalCommentPage, "Journal comment page must not be null");
// Convert the list
List<JournalCommentWithJournalVO> journalCmtWithJournalVos =
convertToWithJournalVo(journalCommentPage.getContent());
// Build and return
return new PageImpl<>(journalCmtWithJournalVos, journalCommentPage.getPageable(),
journalCommentPage.getTotalElements());
}
}

View File

@ -1,45 +1,31 @@
package run.halo.app.service.impl;
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.ForbiddenException;
import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.post.BasePostMinimalDTO;
import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostComment;
import run.halo.app.model.enums.CommentViolationTypeEnum;
import run.halo.app.model.enums.PostPermalinkType;
import run.halo.app.model.properties.CommentProperties;
import run.halo.app.model.vo.PostCommentWithPostVO;
import run.halo.app.repository.PostCommentRepository;
import run.halo.app.repository.PostRepository;
import run.halo.app.service.CommentBlackListService;
import run.halo.app.service.OptionService;
import run.halo.app.service.PostCommentService;
import run.halo.app.service.UserService;
import run.halo.app.utils.DateUtils;
import run.halo.app.utils.ServiceUtils;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
import run.halo.app.utils.ServletUtils;
/**
* PostCommentService implementation class
* PostCommentService implementation class.
*
* @author ryanwang
* @author johnniang
* @author guqing
* @date 2019-03-14
*/
@Slf4j
@ -56,135 +42,14 @@ public class PostCommentServiceImpl extends BaseCommentServiceImpl<PostComment>
UserService userService,
OptionService optionService,
CommentBlackListService commentBlackListService,
ApplicationEventPublisher eventPublisher) {
super(postCommentRepository, optionService, userService, eventPublisher);
ApplicationEventPublisher eventPublisher,
PostCommentAssembler postCommentAssembler) {
super(postCommentRepository, optionService, userService, eventPublisher,
postCommentAssembler);
this.postRepository = postRepository;
this.commentBlackListService = commentBlackListService;
}
@Override
@NonNull
public Page<PostCommentWithPostVO> convertToWithPostVo(@NonNull Page<PostComment> commentPage) {
Assert.notNull(commentPage, "PostComment page must not be null");
return new PageImpl<>(convertToWithPostVo(commentPage.getContent()),
commentPage.getPageable(), commentPage.getTotalElements());
}
@Override
@NonNull
public PostCommentWithPostVO convertToWithPostVo(@NonNull PostComment comment) {
Assert.notNull(comment, "PostComment must not be null");
PostCommentWithPostVO postCommentWithPostVo =
new PostCommentWithPostVO().convertFrom(comment);
BasePostMinimalDTO basePostMinimalDto =
new BasePostMinimalDTO().convertFrom(postRepository.getById(comment.getPostId()));
postCommentWithPostVo.setPost(buildPostFullPath(basePostMinimalDto));
postCommentWithPostVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return postCommentWithPostVo;
}
@Override
@NonNull
public List<PostCommentWithPostVO> convertToWithPostVo(List<PostComment> postComments) {
if (CollectionUtils.isEmpty(postComments)) {
return Collections.emptyList();
}
// Fetch goods ids
Set<Integer> postIds = ServiceUtils.fetchProperty(postComments, PostComment::getPostId);
// Get all posts
Map<Integer, Post> postMap =
ServiceUtils.convertToMap(postRepository.findAllById(postIds), Post::getId);
return postComments.stream()
.filter(comment -> postMap.containsKey(comment.getPostId()))
.map(comment -> {
// Convert to vo
PostCommentWithPostVO postCommentWithPostVo =
new PostCommentWithPostVO().convertFrom(comment);
BasePostMinimalDTO basePostMinimalDto =
new BasePostMinimalDTO().convertFrom(postMap.get(comment.getPostId()));
postCommentWithPostVo.setPost(buildPostFullPath(basePostMinimalDto));
postCommentWithPostVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return postCommentWithPostVo;
}).collect(Collectors.toList());
}
private BasePostMinimalDTO buildPostFullPath(BasePostMinimalDTO post) {
PostPermalinkType permalinkType = optionService.getPostPermalinkType();
String pathSuffix = optionService.getPathSuffix();
String archivesPrefix = optionService.getArchivesPrefix();
int month = DateUtils.month(post.getCreateTime()) + 1;
String monthString = month < 10 ? "0" + month : String.valueOf(month);
int day = DateUtils.dayOfMonth(post.getCreateTime());
String dayString = day < 10 ? "0" + day : String.valueOf(day);
StringBuilder fullPath = new StringBuilder();
if (optionService.isEnabledAbsolutePath()) {
fullPath.append(optionService.getBlogBaseUrl());
}
fullPath.append(URL_SEPARATOR);
if (permalinkType.equals(PostPermalinkType.DEFAULT)) {
fullPath.append(archivesPrefix)
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.ID)) {
fullPath.append("?p=")
.append(post.getId());
} else if (permalinkType.equals(PostPermalinkType.DATE)) {
fullPath.append(DateUtils.year(post.getCreateTime()))
.append(URL_SEPARATOR)
.append(monthString)
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.DAY)) {
fullPath.append(DateUtils.year(post.getCreateTime()))
.append(URL_SEPARATOR)
.append(monthString)
.append(URL_SEPARATOR)
.append(dayString)
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.YEAR)) {
fullPath.append(DateUtils.year(post.getCreateTime()))
.append(URL_SEPARATOR)
.append(post.getSlug())
.append(pathSuffix);
} else if (permalinkType.equals(PostPermalinkType.ID_SLUG)) {
fullPath.append(archivesPrefix)
.append(URL_SEPARATOR)
.append(post.getId())
.append(pathSuffix);
}
post.setFullPath(fullPath.toString());
return post;
}
@Override
public void validateTarget(@NonNull Integer postId) {
Post post = postRepository.findById(postId)

View File

@ -1,32 +1,18 @@
package run.halo.app.service.impl;
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.post.BasePostMinimalDTO;
import run.halo.app.model.entity.Sheet;
import run.halo.app.model.entity.SheetComment;
import run.halo.app.model.enums.SheetPermalinkType;
import run.halo.app.model.vo.SheetCommentWithSheetVO;
import run.halo.app.repository.SheetCommentRepository;
import run.halo.app.repository.SheetRepository;
import run.halo.app.service.OptionService;
import run.halo.app.service.SheetCommentService;
import run.halo.app.service.UserService;
import run.halo.app.utils.ServiceUtils;
import run.halo.app.service.assembler.comment.SheetCommentAssembler;
/**
* Sheet comment service implementation.
@ -45,8 +31,10 @@ public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment
OptionService optionService,
UserService userService,
ApplicationEventPublisher eventPublisher,
SheetRepository sheetRepository) {
super(sheetCommentRepository, optionService, userService, eventPublisher);
SheetRepository sheetRepository,
SheetCommentAssembler sheetCommentAssembler) {
super(sheetCommentRepository, optionService, userService, eventPublisher,
sheetCommentAssembler);
this.sheetRepository = sheetRepository;
}
@ -59,87 +47,4 @@ public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment
throw new BadRequestException("该页面已被禁止评论").setErrorData(sheetId);
}
}
@Override
@NonNull
public SheetCommentWithSheetVO convertToWithSheetVo(@NonNull SheetComment comment) {
Assert.notNull(comment, "SheetComment must not be null");
SheetCommentWithSheetVO sheetCommentWithSheetVo =
new SheetCommentWithSheetVO().convertFrom(comment);
BasePostMinimalDTO basePostMinimalDto =
new BasePostMinimalDTO().convertFrom(sheetRepository.getOne(comment.getPostId()));
sheetCommentWithSheetVo.setSheet(buildSheetFullPath(basePostMinimalDto));
sheetCommentWithSheetVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return sheetCommentWithSheetVo;
}
@Override
@NonNull
public List<SheetCommentWithSheetVO> convertToWithSheetVo(List<SheetComment> sheetComments) {
if (CollectionUtils.isEmpty(sheetComments)) {
return Collections.emptyList();
}
Set<Integer> sheetIds = ServiceUtils.fetchProperty(sheetComments, SheetComment::getPostId);
Map<Integer, Sheet> sheetMap =
ServiceUtils.convertToMap(sheetRepository.findAllById(sheetIds), Sheet::getId);
return sheetComments.stream()
.filter(comment -> sheetMap.containsKey(comment.getPostId()))
.map(comment -> {
SheetCommentWithSheetVO sheetCmtWithPostVo =
new SheetCommentWithSheetVO().convertFrom(comment);
BasePostMinimalDTO postMinimalDto =
new BasePostMinimalDTO().convertFrom(sheetMap.get(comment.getPostId()));
sheetCmtWithPostVo.setSheet(buildSheetFullPath(postMinimalDto));
sheetCmtWithPostVo.setAvatar(buildAvatarUrl(comment.getGravatarMd5()));
return sheetCmtWithPostVo;
})
.collect(Collectors.toList());
}
@Override
@NonNull
public Page<SheetCommentWithSheetVO> convertToWithSheetVo(
@NonNull Page<SheetComment> sheetCommentPage) {
Assert.notNull(sheetCommentPage, "Sheet comment page must not be null");
return new PageImpl<>(convertToWithSheetVo(sheetCommentPage.getContent()),
sheetCommentPage.getPageable(), sheetCommentPage.getTotalElements());
}
private BasePostMinimalDTO buildSheetFullPath(BasePostMinimalDTO basePostMinimalDto) {
StringBuilder fullPath = new StringBuilder();
SheetPermalinkType permalinkType = optionService.getSheetPermalinkType();
if (optionService.isEnabledAbsolutePath()) {
fullPath.append(optionService.getBlogBaseUrl());
}
if (permalinkType.equals(SheetPermalinkType.SECONDARY)) {
fullPath.append(URL_SEPARATOR)
.append(optionService.getSheetPrefix())
.append(URL_SEPARATOR)
.append(basePostMinimalDto.getSlug())
.append(optionService.getPathSuffix());
} else if (permalinkType.equals(SheetPermalinkType.ROOT)) {
fullPath.append(URL_SEPARATOR)
.append(basePostMinimalDto.getSlug())
.append(optionService.getPathSuffix());
}
basePostMinimalDto.setFullPath(fullPath.toString());
return basePostMinimalDto;
}
}

View File

@ -20,6 +20,7 @@ import run.halo.app.repository.PostRepository;
import run.halo.app.service.CommentBlackListService;
import run.halo.app.service.OptionService;
import run.halo.app.service.UserService;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
@SpringBootTest
@ActiveProfiles("test")
@ -58,18 +59,23 @@ public class PostCommentServiceImplTest {
private PostCommentServiceImpl postCommentService;
private PostCommentAssembler postCommentAssembler;
private PostCommentParam postCommentParam;
@BeforeEach
public void setUp() {
MockitoAnnotations.openMocks(this);
postCommentAssembler = new PostCommentAssembler(mockOptionService, mockPostRepository);
postCommentService = new PostCommentServiceImpl(
mockPostCommentRepository,
mockPostRepository,
mockUserService,
mockOptionService,
mockCommentBlackListService,
mockApplicationEventPublisher
mockApplicationEventPublisher,
postCommentAssembler
);
postCommentParam = new PostCommentParam();
}
@ -118,7 +124,7 @@ public class PostCommentServiceImplTest {
String.class)).thenReturn(GRAVATAR_DEFAULT_TEST);
// Act
BaseCommentDTO result = postCommentService.convertTo(mockPostComment);
BaseCommentDTO result = postCommentAssembler.convertTo(mockPostComment);
// Assert
Assertions.assertEquals(