From e2e5942941e53dd6f8bcb267bd23103124a5bd0c Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Mon, 4 Aug 2025 21:10:09 +0800 Subject: [PATCH] feat: add dedicated mappers --- .../controller/AdminTagController.java | 18 +-- .../controller/CategoryController.java | 21 +-- .../controller/CommentController.java | 59 +------- .../openisle/controller/DraftController.java | 21 +-- .../controller/NotificationController.java | 57 +------ .../controller/ReactionController.java | 21 +-- .../openisle/controller/SearchController.java | 29 +--- .../openisle/controller/TagController.java | 22 +-- .../openisle/controller/UserController.java | 140 +++--------------- .../com/openisle/mapper/CategoryMapper.java | 25 ++++ .../com/openisle/mapper/CommentMapper.java | 42 ++++++ .../java/com/openisle/mapper/DraftMapper.java | 24 +++ .../openisle/mapper/NotificationMapper.java | 47 ++++++ .../java/com/openisle/mapper/PostMapper.java | 101 +++---------- .../com/openisle/mapper/ReactionMapper.java | 25 ++++ .../java/com/openisle/mapper/TagMapper.java | 26 ++++ .../java/com/openisle/mapper/UserMapper.java | 104 +++++++++++++ 17 files changed, 374 insertions(+), 408 deletions(-) create mode 100644 backend/src/main/java/com/openisle/mapper/CategoryMapper.java create mode 100644 backend/src/main/java/com/openisle/mapper/CommentMapper.java create mode 100644 backend/src/main/java/com/openisle/mapper/DraftMapper.java create mode 100644 backend/src/main/java/com/openisle/mapper/NotificationMapper.java create mode 100644 backend/src/main/java/com/openisle/mapper/ReactionMapper.java create mode 100644 backend/src/main/java/com/openisle/mapper/TagMapper.java create mode 100644 backend/src/main/java/com/openisle/mapper/UserMapper.java diff --git a/backend/src/main/java/com/openisle/controller/AdminTagController.java b/backend/src/main/java/com/openisle/controller/AdminTagController.java index 6973db56a..3dba36f6c 100644 --- a/backend/src/main/java/com/openisle/controller/AdminTagController.java +++ b/backend/src/main/java/com/openisle/controller/AdminTagController.java @@ -1,6 +1,7 @@ package com.openisle.controller; import com.openisle.dto.TagDto; +import com.openisle.mapper.TagMapper; import com.openisle.model.Tag; import com.openisle.service.PostService; import com.openisle.service.TagService; @@ -16,11 +17,12 @@ import java.util.stream.Collectors; public class AdminTagController { private final TagService tagService; private final PostService postService; + private final TagMapper tagMapper; @GetMapping("/pending") public List pendingTags() { return tagService.listPendingTags().stream() - .map(t -> toDto(t, postService.countPostsByTag(t.getId()))) + .map(t -> tagMapper.toDto(t, postService.countPostsByTag(t.getId()))) .collect(Collectors.toList()); } @@ -28,18 +30,6 @@ public class AdminTagController { public TagDto approve(@PathVariable Long id) { Tag tag = tagService.approveTag(id); long count = postService.countPostsByTag(tag.getId()); - return toDto(tag, count); - } - - private TagDto toDto(Tag tag, long count) { - TagDto dto = new TagDto(); - dto.setId(tag.getId()); - dto.setName(tag.getName()); - dto.setDescription(tag.getDescription()); - dto.setIcon(tag.getIcon()); - dto.setSmallIcon(tag.getSmallIcon()); - dto.setCreatedAt(tag.getCreatedAt()); - dto.setCount(count); - return dto; + return tagMapper.toDto(tag, count); } } diff --git a/backend/src/main/java/com/openisle/controller/CategoryController.java b/backend/src/main/java/com/openisle/controller/CategoryController.java index 0908e0b3a..4df6f20af 100644 --- a/backend/src/main/java/com/openisle/controller/CategoryController.java +++ b/backend/src/main/java/com/openisle/controller/CategoryController.java @@ -3,6 +3,7 @@ package com.openisle.controller; import com.openisle.dto.CategoryDto; import com.openisle.dto.CategoryRequest; import com.openisle.dto.PostSummaryDto; +import com.openisle.mapper.CategoryMapper; import com.openisle.mapper.PostMapper; import com.openisle.model.Category; import com.openisle.service.CategoryService; @@ -20,19 +21,20 @@ public class CategoryController { private final CategoryService categoryService; private final PostService postService; private final PostMapper postMapper; + private final CategoryMapper categoryMapper; @PostMapping public CategoryDto create(@RequestBody CategoryRequest req) { Category c = categoryService.createCategory(req.getName(), req.getDescription(), req.getIcon(), req.getSmallIcon()); long count = postService.countPostsByCategory(c.getId()); - return toDto(c, count); + return categoryMapper.toDto(c, count); } @PutMapping("/{id}") public CategoryDto update(@PathVariable Long id, @RequestBody CategoryRequest req) { Category c = categoryService.updateCategory(id, req.getName(), req.getDescription(), req.getIcon(), req.getSmallIcon()); long count = postService.countPostsByCategory(c.getId()); - return toDto(c, count); + return categoryMapper.toDto(c, count); } @DeleteMapping("/{id}") @@ -43,7 +45,7 @@ public class CategoryController { @GetMapping public List list() { return categoryService.listCategories().stream() - .map(c -> toDto(c, postService.countPostsByCategory(c.getId()))) + .map(c -> categoryMapper.toDto(c, postService.countPostsByCategory(c.getId()))) .sorted((a, b) -> Long.compare(b.getCount(), a.getCount())) .collect(Collectors.toList()); } @@ -52,7 +54,7 @@ public class CategoryController { public CategoryDto get(@PathVariable Long id) { Category c = categoryService.getCategory(id); long count = postService.countPostsByCategory(c.getId()); - return toDto(c, count); + return categoryMapper.toDto(c, count); } @GetMapping("/{id}/posts") @@ -64,15 +66,4 @@ public class CategoryController { .map(postMapper::toSummaryDto) .collect(Collectors.toList()); } - - private CategoryDto toDto(Category c, long count) { - CategoryDto dto = new CategoryDto(); - dto.setId(c.getId()); - dto.setName(c.getName()); - dto.setIcon(c.getIcon()); - dto.setSmallIcon(c.getSmallIcon()); - dto.setDescription(c.getDescription()); - dto.setCount(count); - return dto; - } } diff --git a/backend/src/main/java/com/openisle/controller/CommentController.java b/backend/src/main/java/com/openisle/controller/CommentController.java index 79d4bcf17..9895970e4 100644 --- a/backend/src/main/java/com/openisle/controller/CommentController.java +++ b/backend/src/main/java/com/openisle/controller/CommentController.java @@ -1,15 +1,11 @@ package com.openisle.controller; -import com.openisle.dto.AuthorDto; import com.openisle.dto.CommentDto; import com.openisle.dto.CommentRequest; -import com.openisle.dto.ReactionDto; -import com.openisle.model.Comment; -import com.openisle.model.CommentSort; +import com.openisle.mapper.CommentMapper; import com.openisle.service.CaptchaService; import com.openisle.service.CommentService; import com.openisle.service.LevelService; -import com.openisle.service.ReactionService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -17,7 +13,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @@ -29,7 +24,7 @@ public class CommentController { private final CommentService commentService; private final LevelService levelService; private final CaptchaService captchaService; - private final ReactionService reactionService; + private final CommentMapper commentMapper; @Value("${app.captcha.enabled:false}") private boolean captchaEnabled; @@ -47,7 +42,7 @@ public class CommentController { return ResponseEntity.badRequest().build(); } Comment comment = commentService.addComment(auth.getName(), postId, req.getContent()); - CommentDto dto = toDto(comment); + CommentDto dto = commentMapper.toDto(comment); dto.setReward(levelService.awardForComment(auth.getName())); log.debug("createComment succeeded for comment {}", comment.getId()); return ResponseEntity.ok(dto); @@ -63,7 +58,7 @@ public class CommentController { return ResponseEntity.badRequest().build(); } Comment comment = commentService.addReply(auth.getName(), commentId, req.getContent()); - CommentDto dto = toDto(comment); + CommentDto dto = commentMapper.toDto(comment); dto.setReward(levelService.awardForComment(auth.getName())); log.debug("replyComment succeeded for comment {}", comment.getId()); return ResponseEntity.ok(dto); @@ -71,61 +66,19 @@ public class CommentController { @GetMapping("/posts/{postId}/comments") public List listComments(@PathVariable Long postId, - @RequestParam(value = "sort", required = false, defaultValue = "OLDEST") CommentSort sort) { + @RequestParam(value = "sort", required = false, defaultValue = "OLDEST") com.openisle.model.CommentSort sort) { log.debug("listComments called for post {} with sort {}", postId, sort); List list = commentService.getCommentsForPost(postId, sort).stream() - .map(this::toDtoWithReplies) + .map(commentMapper::toDtoWithReplies) .collect(Collectors.toList()); log.debug("listComments returning {} comments", list.size()); return list; } - private CommentDto toDtoWithReplies(Comment comment) { - CommentDto dto = toDto(comment); - List replies = commentService.getReplies(comment.getId()).stream() - .map(this::toDtoWithReplies) - .collect(Collectors.toList()); - dto.setReplies(replies); - List reactions = reactionService.getReactionsForComment(comment.getId()).stream() - .map(this::toReactionDto) - .collect(Collectors.toList()); - dto.setReactions(reactions); - return dto; - } - @DeleteMapping("/comments/{id}") public void deleteComment(@PathVariable Long id, Authentication auth) { log.debug("deleteComment called by user {} for comment {}", auth.getName(), id); commentService.deleteComment(auth.getName(), id); log.debug("deleteComment completed for comment {}", id); } - - private CommentDto toDto(Comment comment) { - CommentDto dto = new CommentDto(); - dto.setId(comment.getId()); - dto.setContent(comment.getContent()); - dto.setCreatedAt(comment.getCreatedAt()); - AuthorDto author = new AuthorDto(); - author.setId(comment.getAuthor().getId()); - author.setUsername(comment.getAuthor().getUsername()); - author.setAvatar(comment.getAuthor().getAvatar()); - dto.setAuthor(author); - dto.setReward(0); - return dto; - } - - private ReactionDto toReactionDto(com.openisle.model.Reaction reaction) { - ReactionDto dto = new ReactionDto(); - dto.setId(reaction.getId()); - dto.setType(reaction.getType()); - dto.setUser(reaction.getUser().getUsername()); - if (reaction.getPost() != null) { - dto.setPostId(reaction.getPost().getId()); - } - if (reaction.getComment() != null) { - dto.setCommentId(reaction.getComment().getId()); - } - dto.setReward(0); - return dto; - } } diff --git a/backend/src/main/java/com/openisle/controller/DraftController.java b/backend/src/main/java/com/openisle/controller/DraftController.java index 06a076062..4f9ecd408 100644 --- a/backend/src/main/java/com/openisle/controller/DraftController.java +++ b/backend/src/main/java/com/openisle/controller/DraftController.java @@ -2,6 +2,7 @@ package com.openisle.controller; import com.openisle.dto.DraftDto; import com.openisle.dto.DraftRequest; +import com.openisle.mapper.DraftMapper; import com.openisle.model.Draft; import com.openisle.service.DraftService; import lombok.RequiredArgsConstructor; @@ -9,24 +10,23 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; -import java.util.stream.Collectors; - @RestController @RequestMapping("/api/drafts") @RequiredArgsConstructor public class DraftController { private final DraftService draftService; + private final DraftMapper draftMapper; @PostMapping public ResponseEntity saveDraft(@RequestBody DraftRequest req, Authentication auth) { Draft draft = draftService.saveDraft(auth.getName(), req.getCategoryId(), req.getTitle(), req.getContent(), req.getTagIds()); - return ResponseEntity.ok(toDto(draft)); + return ResponseEntity.ok(draftMapper.toDto(draft)); } @GetMapping("/me") public ResponseEntity getMyDraft(Authentication auth) { return draftService.getDraft(auth.getName()) - .map(d -> ResponseEntity.ok(toDto(d))) + .map(d -> ResponseEntity.ok(draftMapper.toDto(d))) .orElseGet(() -> ResponseEntity.noContent().build()); } @@ -35,17 +35,4 @@ public class DraftController { draftService.deleteDraft(auth.getName()); return ResponseEntity.ok().build(); } - - private DraftDto toDto(Draft draft) { - DraftDto dto = new DraftDto(); - dto.setId(draft.getId()); - dto.setTitle(draft.getTitle()); - dto.setContent(draft.getContent()); - if (draft.getCategory() != null) { - dto.setCategoryId(draft.getCategory().getId()); - } - dto.setTagIds(draft.getTags().stream().map(com.openisle.model.Tag::getId).collect(Collectors.toList())); - return dto; - } - } diff --git a/backend/src/main/java/com/openisle/controller/NotificationController.java b/backend/src/main/java/com/openisle/controller/NotificationController.java index 2da1b1a85..5462b94fc 100644 --- a/backend/src/main/java/com/openisle/controller/NotificationController.java +++ b/backend/src/main/java/com/openisle/controller/NotificationController.java @@ -1,19 +1,14 @@ package com.openisle.controller; -import com.openisle.dto.AuthorDto; -import com.openisle.dto.CommentDto; import com.openisle.dto.NotificationDto; import com.openisle.dto.NotificationMarkReadRequest; import com.openisle.dto.NotificationUnreadCountDto; -import com.openisle.dto.PostSummaryDto; -import com.openisle.model.Comment; -import com.openisle.model.Notification; +import com.openisle.mapper.NotificationMapper; import com.openisle.service.NotificationService; import lombok.RequiredArgsConstructor; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @@ -23,12 +18,13 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class NotificationController { private final NotificationService notificationService; + private final NotificationMapper notificationMapper; @GetMapping public List list(@RequestParam(value = "read", required = false) Boolean read, Authentication auth) { return notificationService.listNotifications(auth.getName(), read).stream() - .map(this::toDto) + .map(notificationMapper::toDto) .collect(Collectors.toList()); } @@ -44,51 +40,4 @@ public class NotificationController { public void markRead(@RequestBody NotificationMarkReadRequest req, Authentication auth) { notificationService.markRead(auth.getName(), req.getIds()); } - - private NotificationDto toDto(Notification n) { - NotificationDto dto = new NotificationDto(); - dto.setId(n.getId()); - dto.setType(n.getType()); - if (n.getPost() != null) { - PostSummaryDto postDto = new PostSummaryDto(); - postDto.setId(n.getPost().getId()); - postDto.setTitle(n.getPost().getTitle()); - dto.setPost(postDto); - } - if (n.getComment() != null) { - dto.setComment(toCommentDto(n.getComment())); - Comment parent = n.getComment().getParent(); - if (parent != null) { - dto.setParentComment(toCommentDto(parent)); - } - } - if (n.getFromUser() != null) { - AuthorDto author = new AuthorDto(); - author.setId(n.getFromUser().getId()); - author.setUsername(n.getFromUser().getUsername()); - author.setAvatar(n.getFromUser().getAvatar()); - dto.setFromUser(author); - } - if (n.getReactionType() != null) { - dto.setReactionType(n.getReactionType()); - } - dto.setApproved(n.getApproved()); - dto.setContent(n.getContent()); - dto.setRead(n.isRead()); - dto.setCreatedAt(n.getCreatedAt()); - return dto; - } - - private CommentDto toCommentDto(Comment comment) { - CommentDto dto = new CommentDto(); - dto.setId(comment.getId()); - dto.setContent(comment.getContent()); - dto.setCreatedAt(comment.getCreatedAt()); - AuthorDto author = new AuthorDto(); - author.setId(comment.getAuthor().getId()); - author.setUsername(comment.getAuthor().getUsername()); - author.setAvatar(comment.getAuthor().getAvatar()); - dto.setAuthor(author); - return dto; - } } diff --git a/backend/src/main/java/com/openisle/controller/ReactionController.java b/backend/src/main/java/com/openisle/controller/ReactionController.java index d03da47ad..e5466f7b6 100644 --- a/backend/src/main/java/com/openisle/controller/ReactionController.java +++ b/backend/src/main/java/com/openisle/controller/ReactionController.java @@ -2,6 +2,7 @@ package com.openisle.controller; import com.openisle.dto.ReactionDto; import com.openisle.dto.ReactionRequest; +import com.openisle.mapper.ReactionMapper; import com.openisle.model.Reaction; import com.openisle.model.ReactionType; import com.openisle.service.LevelService; @@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.*; public class ReactionController { private final ReactionService reactionService; private final LevelService levelService; + private final ReactionMapper reactionMapper; /** * Get all available reaction types. @@ -35,7 +37,7 @@ public class ReactionController { if (reaction == null) { return ResponseEntity.noContent().build(); } - ReactionDto dto = toDto(reaction); + ReactionDto dto = reactionMapper.toDto(reaction); dto.setReward(levelService.awardForReaction(auth.getName())); return ResponseEntity.ok(dto); } @@ -48,23 +50,8 @@ public class ReactionController { if (reaction == null) { return ResponseEntity.noContent().build(); } - ReactionDto dto = toDto(reaction); + ReactionDto dto = reactionMapper.toDto(reaction); dto.setReward(levelService.awardForReaction(auth.getName())); return ResponseEntity.ok(dto); } - - private ReactionDto toDto(Reaction reaction) { - ReactionDto dto = new ReactionDto(); - dto.setId(reaction.getId()); - dto.setType(reaction.getType()); - dto.setUser(reaction.getUser().getUsername()); - if (reaction.getPost() != null) { - dto.setPostId(reaction.getPost().getId()); - } - if (reaction.getComment() != null) { - dto.setCommentId(reaction.getComment().getId()); - } - dto.setReward(0); - return dto; - } } diff --git a/backend/src/main/java/com/openisle/controller/SearchController.java b/backend/src/main/java/com/openisle/controller/SearchController.java index 38f586f31..0380ee41b 100644 --- a/backend/src/main/java/com/openisle/controller/SearchController.java +++ b/backend/src/main/java/com/openisle/controller/SearchController.java @@ -3,8 +3,8 @@ package com.openisle.controller; import com.openisle.dto.PostSummaryDto; import com.openisle.dto.SearchResultDto; import com.openisle.dto.UserDto; -import com.openisle.model.Post; -import com.openisle.model.User; +import com.openisle.mapper.PostMapper; +import com.openisle.mapper.UserMapper; import com.openisle.service.SearchService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; @@ -20,32 +20,34 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class SearchController { private final SearchService searchService; + private final UserMapper userMapper; + private final PostMapper postMapper; @GetMapping("/users") public List searchUsers(@RequestParam String keyword) { return searchService.searchUsers(keyword).stream() - .map(this::toUserDto) + .map(userMapper::toDto) .collect(Collectors.toList()); } @GetMapping("/posts") public List searchPosts(@RequestParam String keyword) { return searchService.searchPosts(keyword).stream() - .map(this::toPostDto) + .map(postMapper::toSummaryDto) .collect(Collectors.toList()); } @GetMapping("/posts/content") public List searchPostsByContent(@RequestParam String keyword) { return searchService.searchPostsByContent(keyword).stream() - .map(this::toPostDto) + .map(postMapper::toSummaryDto) .collect(Collectors.toList()); } @GetMapping("/posts/title") public List searchPostsByTitle(@RequestParam String keyword) { return searchService.searchPostsByTitle(keyword).stream() - .map(this::toPostDto) + .map(postMapper::toSummaryDto) .collect(Collectors.toList()); } @@ -64,19 +66,4 @@ public class SearchController { }) .collect(Collectors.toList()); } - - private UserDto toUserDto(User user) { - UserDto dto = new UserDto(); - dto.setId(user.getId()); - dto.setUsername(user.getUsername()); - dto.setAvatar(user.getAvatar()); - return dto; - } - - private PostSummaryDto toPostDto(Post post) { - PostSummaryDto dto = new PostSummaryDto(); - dto.setId(post.getId()); - dto.setTitle(post.getTitle()); - return dto; - } } diff --git a/backend/src/main/java/com/openisle/controller/TagController.java b/backend/src/main/java/com/openisle/controller/TagController.java index 9e8d83dea..72db5eda5 100644 --- a/backend/src/main/java/com/openisle/controller/TagController.java +++ b/backend/src/main/java/com/openisle/controller/TagController.java @@ -4,6 +4,7 @@ import com.openisle.dto.PostSummaryDto; import com.openisle.dto.TagDto; import com.openisle.dto.TagRequest; import com.openisle.mapper.PostMapper; +import com.openisle.mapper.TagMapper; import com.openisle.model.PublishMode; import com.openisle.model.Role; import com.openisle.model.Tag; @@ -24,6 +25,7 @@ public class TagController { private final PostService postService; private final UserRepository userRepository; private final PostMapper postMapper; + private final TagMapper tagMapper; @PostMapping public TagDto create(@RequestBody TagRequest req, org.springframework.security.core.Authentication auth) { @@ -42,14 +44,14 @@ public class TagController { approved, auth != null ? auth.getName() : null); long count = postService.countPostsByTag(tag.getId()); - return toDto(tag, count); + return tagMapper.toDto(tag, count); } @PutMapping("/{id}") public TagDto update(@PathVariable Long id, @RequestBody TagRequest req) { Tag tag = tagService.updateTag(id, req.getName(), req.getDescription(), req.getIcon(), req.getSmallIcon()); long count = postService.countPostsByTag(tag.getId()); - return toDto(tag, count); + return tagMapper.toDto(tag, count); } @DeleteMapping("/{id}") @@ -61,7 +63,7 @@ public class TagController { public List list(@RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "limit", required = false) Integer limit) { List dtos = tagService.searchTags(keyword).stream() - .map(t -> toDto(t, postService.countPostsByTag(t.getId()))) + .map(t -> tagMapper.toDto(t, postService.countPostsByTag(t.getId()))) .sorted((a, b) -> Long.compare(b.getCount(), a.getCount())) .collect(Collectors.toList()); if (limit != null && limit > 0 && dtos.size() > limit) { @@ -74,7 +76,7 @@ public class TagController { public TagDto get(@PathVariable Long id) { Tag tag = tagService.getTag(id); long count = postService.countPostsByTag(tag.getId()); - return toDto(tag, count); + return tagMapper.toDto(tag, count); } @GetMapping("/{id}/posts") @@ -86,16 +88,4 @@ public class TagController { .map(postMapper::toSummaryDto) .collect(Collectors.toList()); } - - private TagDto toDto(Tag tag, long count) { - TagDto dto = new TagDto(); - dto.setId(tag.getId()); - dto.setName(tag.getName()); - dto.setIcon(tag.getIcon()); - dto.setSmallIcon(tag.getSmallIcon()); - dto.setDescription(tag.getDescription()); - dto.setCreatedAt(tag.getCreatedAt()); - dto.setCount(count); - return dto; - } } diff --git a/backend/src/main/java/com/openisle/controller/UserController.java b/backend/src/main/java/com/openisle/controller/UserController.java index 06ae159c9..01afbabb6 100644 --- a/backend/src/main/java/com/openisle/controller/UserController.java +++ b/backend/src/main/java/com/openisle/controller/UserController.java @@ -1,17 +1,13 @@ package com.openisle.controller; -import com.openisle.dto.CommentInfoDto; -import com.openisle.dto.ParentCommentDto; -import com.openisle.dto.PostMetaDto; -import com.openisle.dto.TagDto; -import com.openisle.dto.UpdateProfileDto; -import com.openisle.dto.UserAggregateDto; -import com.openisle.dto.UserDto; +import com.openisle.dto.*; import com.openisle.exception.NotFoundException; +import com.openisle.mapper.TagMapper; +import com.openisle.mapper.UserMapper; import com.openisle.model.User; import com.openisle.service.*; -import org.springframework.beans.factory.annotation.Value; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @@ -31,10 +27,10 @@ public class UserController { private final ReactionService reactionService; private final TagService tagService; private final SubscriptionService subscriptionService; - private final PostReadService postReadService; - private final UserVisitService userVisitService; private final LevelService levelService; private final JwtService jwtService; + private final UserMapper userMapper; + private final TagMapper tagMapper; @Value("${app.upload.check-type:true}") private boolean checkImageType; @@ -51,13 +47,10 @@ public class UserController { @Value("${app.user.tags-limit:50}") private int defaultTagsLimit; - @Value("${app.snippet-length:50}") - private int snippetLength; - @GetMapping("/me") public ResponseEntity me(Authentication auth) { User user = userService.findByUsername(auth.getName()).orElseThrow(); - return ResponseEntity.ok(toDto(user, auth)); + return ResponseEntity.ok(userMapper.toDto(user, auth)); } @PostMapping("/me/avatar") @@ -85,7 +78,7 @@ public class UserController { User user = userService.updateProfile(auth.getName(), dto.getUsername(), dto.getIntroduction()); return ResponseEntity.ok(Map.of( "token", jwtService.generateToken(user.getUsername()), - "user", toDto(user, auth) + "user", userMapper.toDto(user, auth) )); } @@ -99,7 +92,7 @@ public class UserController { public ResponseEntity getUser(@PathVariable("identifier") String identifier, Authentication auth) { User user = userService.findByIdentifier(identifier).orElseThrow(() -> new NotFoundException("User not found")); - return ResponseEntity.ok(toDto(user, auth)); + return ResponseEntity.ok(userMapper.toDto(user, auth)); } @GetMapping("/{identifier}/posts") @@ -108,7 +101,7 @@ public class UserController { int l = limit != null ? limit : defaultPostsLimit; User user = userService.findByIdentifier(identifier).orElseThrow(); return postService.getRecentPostsByUser(user.getUsername(), l).stream() - .map(this::toMetaDto) + .map(userMapper::toMetaDto) .collect(java.util.stream.Collectors.toList()); } @@ -118,7 +111,7 @@ public class UserController { int l = limit != null ? limit : defaultRepliesLimit; User user = userService.findByIdentifier(identifier).orElseThrow(); return commentService.getRecentCommentsByUser(user.getUsername(), l).stream() - .map(this::toCommentInfoDto) + .map(userMapper::toCommentInfoDto) .collect(java.util.stream.Collectors.toList()); } @@ -129,7 +122,7 @@ public class UserController { User user = userService.findByIdentifier(identifier).orElseThrow(); java.util.List ids = reactionService.topPostIds(user.getUsername(), l); return postService.getPostsByIds(ids).stream() - .map(this::toMetaDto) + .map(userMapper::toMetaDto) .collect(java.util.stream.Collectors.toList()); } @@ -140,7 +133,7 @@ public class UserController { User user = userService.findByIdentifier(identifier).orElseThrow(); java.util.List ids = reactionService.topCommentIds(user.getUsername(), l); return commentService.getCommentsByIds(ids).stream() - .map(this::toCommentInfoDto) + .map(userMapper::toCommentInfoDto) .collect(java.util.stream.Collectors.toList()); } @@ -150,17 +143,7 @@ public class UserController { int l = limit != null ? limit : 10; User user = userService.findByIdentifier(identifier).orElseThrow(); return tagService.getTagsByUser(user.getUsername()).stream() - .map(t -> { - TagDto dto = new TagDto(); - dto.setId(t.getId()); - dto.setName(t.getName()); - dto.setDescription(t.getDescription()); - dto.setIcon(t.getIcon()); - dto.setSmallIcon(t.getSmallIcon()); - dto.setCreatedAt(t.getCreatedAt()); - dto.setCount(postService.countPostsByTag(t.getId())); - return dto; - }) + .map(t -> tagMapper.toDto(t, postService.countPostsByTag(t.getId()))) .sorted((a, b) -> Long.compare(b.getCount(), a.getCount())) .limit(l) .collect(java.util.stream.Collectors.toList()); @@ -172,17 +155,7 @@ public class UserController { int l = limit != null ? limit : defaultTagsLimit; User user = userService.findByIdentifier(identifier).orElseThrow(); return tagService.getRecentTagsByUser(user.getUsername(), l).stream() - .map(t -> { - TagDto dto = new TagDto(); - dto.setId(t.getId()); - dto.setName(t.getName()); - dto.setDescription(t.getDescription()); - dto.setIcon(t.getIcon()); - dto.setSmallIcon(t.getSmallIcon()); - dto.setCreatedAt(t.getCreatedAt()); - dto.setCount(postService.countPostsByTag(t.getId())); - return dto; - }) + .map(t -> tagMapper.toDto(t, postService.countPostsByTag(t.getId()))) .collect(java.util.stream.Collectors.toList()); } @@ -190,7 +163,7 @@ public class UserController { public java.util.List following(@PathVariable("identifier") String identifier) { User user = userService.findByIdentifier(identifier).orElseThrow(); return subscriptionService.getSubscribedUsers(user.getUsername()).stream() - .map(this::toDto) + .map(userMapper::toDto) .collect(java.util.stream.Collectors.toList()); } @@ -198,17 +171,14 @@ public class UserController { public java.util.List followers(@PathVariable("identifier") String identifier) { User user = userService.findByIdentifier(identifier).orElseThrow(); return subscriptionService.getSubscribers(user.getUsername()).stream() - .map(this::toDto) + .map(userMapper::toDto) .collect(java.util.stream.Collectors.toList()); } - /** - * List all administrator users. - */ @GetMapping("/admins") public java.util.List admins() { return userService.getAdmins().stream() - .map(this::toDto) + .map(userMapper::toDto) .collect(java.util.stream.Collectors.toList()); } @@ -221,83 +191,15 @@ public class UserController { int pLimit = postsLimit != null ? postsLimit : defaultPostsLimit; int rLimit = repliesLimit != null ? repliesLimit : defaultRepliesLimit; java.util.List posts = postService.getRecentPostsByUser(user.getUsername(), pLimit).stream() - .map(this::toMetaDto) + .map(userMapper::toMetaDto) .collect(java.util.stream.Collectors.toList()); java.util.List replies = commentService.getRecentCommentsByUser(user.getUsername(), rLimit).stream() - .map(this::toCommentInfoDto) + .map(userMapper::toCommentInfoDto) .collect(java.util.stream.Collectors.toList()); UserAggregateDto dto = new UserAggregateDto(); - dto.setUser(toDto(user, auth)); + dto.setUser(userMapper.toDto(user, auth)); dto.setPosts(posts); dto.setReplies(replies); return ResponseEntity.ok(dto); } - - private UserDto toDto(User user, Authentication viewer) { - UserDto dto = new UserDto(); - dto.setId(user.getId()); - dto.setUsername(user.getUsername()); - dto.setEmail(user.getEmail()); - dto.setAvatar(user.getAvatar()); - dto.setRole(user.getRole().name()); - dto.setIntroduction(user.getIntroduction()); - dto.setFollowers(subscriptionService.countSubscribers(user.getUsername())); - dto.setFollowing(subscriptionService.countSubscribed(user.getUsername())); - dto.setCreatedAt(user.getCreatedAt()); - dto.setLastPostTime(postService.getLastPostTime(user.getUsername())); - dto.setLastCommentTime(commentService.getLastCommentTimeOfUserByUserId(user.getId())); - dto.setTotalViews(postService.getTotalViews(user.getUsername())); - dto.setVisitedDays(userVisitService.countVisits(user.getUsername())); - dto.setReadPosts(postReadService.countReads(user.getUsername())); - dto.setLikesSent(reactionService.countLikesSent(user.getUsername())); - dto.setLikesReceived(reactionService.countLikesReceived(user.getUsername())); - dto.setExperience(user.getExperience()); - dto.setCurrentLevel(levelService.getLevel(user.getExperience())); - dto.setNextLevelExp(levelService.nextLevelExp(user.getExperience())); - if (viewer != null) { - dto.setSubscribed(subscriptionService.isSubscribed(viewer.getName(), user.getUsername())); - } else { - dto.setSubscribed(false); - } - return dto; - } - - private UserDto toDto(User user) { - return toDto(user, null); - } - - private PostMetaDto toMetaDto(com.openisle.model.Post post) { - PostMetaDto dto = new PostMetaDto(); - dto.setId(post.getId()); - dto.setTitle(post.getTitle()); - String content = post.getContent(); - if (content == null) { - content = ""; - } - if (snippetLength >= 0) { - dto.setSnippet(content.length() > snippetLength ? content.substring(0, snippetLength) : content); - } else { - dto.setSnippet(content); - } - dto.setCreatedAt(post.getCreatedAt()); - dto.setCategory(post.getCategory().getName()); - dto.setViews(post.getViews()); - return dto; - } - - private CommentInfoDto toCommentInfoDto(com.openisle.model.Comment comment) { - CommentInfoDto dto = new CommentInfoDto(); - dto.setId(comment.getId()); - dto.setContent(comment.getContent()); - dto.setCreatedAt(comment.getCreatedAt()); - dto.setPost(toMetaDto(comment.getPost())); - if (comment.getParent() != null) { - ParentCommentDto pc = new ParentCommentDto(); - pc.setId(comment.getParent().getId()); - pc.setAuthor(comment.getParent().getAuthor().getUsername()); - pc.setContent(comment.getParent().getContent()); - dto.setParentComment(pc); - } - return dto; - } } diff --git a/backend/src/main/java/com/openisle/mapper/CategoryMapper.java b/backend/src/main/java/com/openisle/mapper/CategoryMapper.java new file mode 100644 index 000000000..cd078b677 --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/CategoryMapper.java @@ -0,0 +1,25 @@ +package com.openisle.mapper; + +import com.openisle.dto.CategoryDto; +import com.openisle.model.Category; +import org.springframework.stereotype.Component; + +/** Mapper for category entities. */ +@Component +public class CategoryMapper { + + public CategoryDto toDto(Category c) { + return toDto(c, null); + } + + public CategoryDto toDto(Category c, Long count) { + CategoryDto dto = new CategoryDto(); + dto.setId(c.getId()); + dto.setName(c.getName()); + dto.setDescription(c.getDescription()); + dto.setIcon(c.getIcon()); + dto.setSmallIcon(c.getSmallIcon()); + dto.setCount(count); + return dto; + } +} diff --git a/backend/src/main/java/com/openisle/mapper/CommentMapper.java b/backend/src/main/java/com/openisle/mapper/CommentMapper.java new file mode 100644 index 000000000..d9b065b45 --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/CommentMapper.java @@ -0,0 +1,42 @@ +package com.openisle.mapper; + +import com.openisle.dto.CommentDto; +import com.openisle.model.Comment; +import com.openisle.service.CommentService; +import com.openisle.service.ReactionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.stream.Collectors; + +/** Mapper for comments including replies and reactions. */ +@Component +@RequiredArgsConstructor +public class CommentMapper { + + private final CommentService commentService; + private final ReactionService reactionService; + private final ReactionMapper reactionMapper; + private final UserMapper userMapper; + + public CommentDto toDto(Comment comment) { + CommentDto dto = new CommentDto(); + dto.setId(comment.getId()); + dto.setContent(comment.getContent()); + dto.setCreatedAt(comment.getCreatedAt()); + dto.setAuthor(userMapper.toAuthorDto(comment.getAuthor())); + dto.setReward(0); + return dto; + } + + public CommentDto toDtoWithReplies(Comment comment) { + CommentDto dto = toDto(comment); + dto.setReplies(commentService.getReplies(comment.getId()).stream() + .map(this::toDtoWithReplies) + .collect(Collectors.toList())); + dto.setReactions(reactionService.getReactionsForComment(comment.getId()).stream() + .map(reactionMapper::toDto) + .collect(Collectors.toList())); + return dto; + } +} diff --git a/backend/src/main/java/com/openisle/mapper/DraftMapper.java b/backend/src/main/java/com/openisle/mapper/DraftMapper.java new file mode 100644 index 000000000..5e93fb05d --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/DraftMapper.java @@ -0,0 +1,24 @@ +package com.openisle.mapper; + +import com.openisle.dto.DraftDto; +import com.openisle.model.Draft; +import org.springframework.stereotype.Component; + +import java.util.stream.Collectors; + +/** Mapper for draft entities. */ +@Component +public class DraftMapper { + + public DraftDto toDto(Draft draft) { + DraftDto dto = new DraftDto(); + dto.setId(draft.getId()); + dto.setTitle(draft.getTitle()); + dto.setContent(draft.getContent()); + if (draft.getCategory() != null) { + dto.setCategoryId(draft.getCategory().getId()); + } + dto.setTagIds(draft.getTags().stream().map(tag -> tag.getId()).collect(Collectors.toList())); + return dto; + } +} diff --git a/backend/src/main/java/com/openisle/mapper/NotificationMapper.java b/backend/src/main/java/com/openisle/mapper/NotificationMapper.java new file mode 100644 index 000000000..26bc751b3 --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/NotificationMapper.java @@ -0,0 +1,47 @@ +package com.openisle.mapper; + +import com.openisle.dto.NotificationDto; +import com.openisle.dto.PostSummaryDto; +import com.openisle.model.Comment; +import com.openisle.model.Notification; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** Mapper for notifications. */ +@Component +@RequiredArgsConstructor +public class NotificationMapper { + + private final CommentMapper commentMapper; + private final UserMapper userMapper; + + public NotificationDto toDto(Notification n) { + NotificationDto dto = new NotificationDto(); + dto.setId(n.getId()); + dto.setType(n.getType()); + if (n.getPost() != null) { + PostSummaryDto postDto = new PostSummaryDto(); + postDto.setId(n.getPost().getId()); + postDto.setTitle(n.getPost().getTitle()); + dto.setPost(postDto); + } + if (n.getComment() != null) { + dto.setComment(commentMapper.toDto(n.getComment())); + Comment parent = n.getComment().getParent(); + if (parent != null) { + dto.setParentComment(commentMapper.toDto(parent)); + } + } + if (n.getFromUser() != null) { + dto.setFromUser(userMapper.toAuthorDto(n.getFromUser())); + } + if (n.getReactionType() != null) { + dto.setReactionType(n.getReactionType()); + } + dto.setApproved(n.getApproved()); + dto.setContent(n.getContent()); + dto.setRead(n.isRead()); + dto.setCreatedAt(n.getCreatedAt()); + return dto; + } +} diff --git a/backend/src/main/java/com/openisle/mapper/PostMapper.java b/backend/src/main/java/com/openisle/mapper/PostMapper.java index 58693d306..8b5d36e0c 100644 --- a/backend/src/main/java/com/openisle/mapper/PostMapper.java +++ b/backend/src/main/java/com/openisle/mapper/PostMapper.java @@ -1,7 +1,12 @@ package com.openisle.mapper; -import com.openisle.dto.*; -import com.openisle.model.*; +import com.openisle.dto.CommentDto; +import com.openisle.dto.PostDetailDto; +import com.openisle.dto.PostSummaryDto; +import com.openisle.dto.ReactionDto; +import com.openisle.model.CommentSort; +import com.openisle.model.Post; +import com.openisle.model.User; import com.openisle.service.CommentService; import com.openisle.service.ReactionService; import com.openisle.service.SubscriptionService; @@ -12,9 +17,7 @@ import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; -/** - * Mapper responsible for converting domain models into DTOs. - */ +/** Mapper responsible for converting posts into DTOs. */ @Component @RequiredArgsConstructor public class PostMapper { @@ -22,6 +25,11 @@ public class PostMapper { private final CommentService commentService; private final ReactionService reactionService; private final SubscriptionService subscriptionService; + private final CommentMapper commentMapper; + private final ReactionMapper reactionMapper; + private final UserMapper userMapper; + private final TagMapper tagMapper; + private final CategoryMapper categoryMapper; public PostSummaryDto toSummaryDto(Post post) { PostSummaryDto dto = new PostSummaryDto(); @@ -34,7 +42,7 @@ public class PostMapper { applyCommon(post, dto); List comments = commentService.getCommentsForPost(post.getId(), CommentSort.OLDEST) .stream() - .map(this::toCommentDtoWithReplies) + .map(commentMapper::toDtoWithReplies) .collect(Collectors.toList()); dto.setComments(comments); dto.setSubscribed(viewer != null && subscriptionService.isPostSubscribed(viewer, post.getId())); @@ -46,96 +54,25 @@ public class PostMapper { dto.setTitle(post.getTitle()); dto.setContent(post.getContent()); dto.setCreatedAt(post.getCreatedAt()); - dto.setAuthor(toAuthorDto(post.getAuthor())); - dto.setCategory(toCategoryDto(post.getCategory())); - dto.setTags(post.getTags().stream().map(this::toTagDto).collect(Collectors.toList())); + dto.setAuthor(userMapper.toAuthorDto(post.getAuthor())); + dto.setCategory(categoryMapper.toDto(post.getCategory())); + dto.setTags(post.getTags().stream().map(tagMapper::toDto).collect(Collectors.toList())); dto.setViews(post.getViews()); dto.setStatus(post.getStatus()); dto.setPinnedAt(post.getPinnedAt()); List reactions = reactionService.getReactionsForPost(post.getId()) .stream() - .map(this::toReactionDto) + .map(reactionMapper::toDto) .collect(Collectors.toList()); dto.setReactions(reactions); List participants = commentService.getParticipants(post.getId(), 5); - dto.setParticipants(participants.stream().map(this::toAuthorDto).collect(Collectors.toList())); + dto.setParticipants(participants.stream().map(userMapper::toAuthorDto).collect(Collectors.toList())); LocalDateTime last = commentService.getLastCommentTime(post.getId()); dto.setLastReplyAt(last != null ? last : post.getCreatedAt()); dto.setReward(0); dto.setSubscribed(false); } - - private CommentDto toCommentDtoWithReplies(Comment comment) { - CommentDto dto = toCommentDto(comment); - List replies = commentService.getReplies(comment.getId()).stream() - .map(this::toCommentDtoWithReplies) - .collect(Collectors.toList()); - dto.setReplies(replies); - - List reactions = reactionService.getReactionsForComment(comment.getId()) - .stream() - .map(this::toReactionDto) - .collect(Collectors.toList()); - dto.setReactions(reactions); - - return dto; - } - - private CommentDto toCommentDto(Comment comment) { - CommentDto dto = new CommentDto(); - dto.setId(comment.getId()); - dto.setContent(comment.getContent()); - dto.setCreatedAt(comment.getCreatedAt()); - dto.setAuthor(toAuthorDto(comment.getAuthor())); - dto.setReward(0); - return dto; - } - - private ReactionDto toReactionDto(Reaction reaction) { - ReactionDto dto = new ReactionDto(); - dto.setId(reaction.getId()); - dto.setType(reaction.getType()); - dto.setUser(reaction.getUser().getUsername()); - if (reaction.getPost() != null) { - dto.setPostId(reaction.getPost().getId()); - } - if (reaction.getComment() != null) { - dto.setCommentId(reaction.getComment().getId()); - } - dto.setReward(0); - return dto; - } - - private CategoryDto toCategoryDto(Category category) { - CategoryDto dto = new CategoryDto(); - dto.setId(category.getId()); - dto.setName(category.getName()); - dto.setDescription(category.getDescription()); - dto.setIcon(category.getIcon()); - dto.setSmallIcon(category.getSmallIcon()); - return dto; - } - - private TagDto toTagDto(Tag tag) { - TagDto dto = new TagDto(); - dto.setId(tag.getId()); - dto.setName(tag.getName()); - dto.setDescription(tag.getDescription()); - dto.setIcon(tag.getIcon()); - dto.setSmallIcon(tag.getSmallIcon()); - dto.setCreatedAt(tag.getCreatedAt()); - return dto; - } - - private AuthorDto toAuthorDto(User user) { - AuthorDto dto = new AuthorDto(); - dto.setId(user.getId()); - dto.setUsername(user.getUsername()); - dto.setAvatar(user.getAvatar()); - return dto; - } } - diff --git a/backend/src/main/java/com/openisle/mapper/ReactionMapper.java b/backend/src/main/java/com/openisle/mapper/ReactionMapper.java new file mode 100644 index 000000000..d5cca8c90 --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/ReactionMapper.java @@ -0,0 +1,25 @@ +package com.openisle.mapper; + +import com.openisle.dto.ReactionDto; +import com.openisle.model.Reaction; +import org.springframework.stereotype.Component; + +/** Mapper for reactions. */ +@Component +public class ReactionMapper { + + public ReactionDto toDto(Reaction reaction) { + ReactionDto dto = new ReactionDto(); + dto.setId(reaction.getId()); + dto.setType(reaction.getType()); + dto.setUser(reaction.getUser().getUsername()); + if (reaction.getPost() != null) { + dto.setPostId(reaction.getPost().getId()); + } + if (reaction.getComment() != null) { + dto.setCommentId(reaction.getComment().getId()); + } + dto.setReward(0); + return dto; + } +} diff --git a/backend/src/main/java/com/openisle/mapper/TagMapper.java b/backend/src/main/java/com/openisle/mapper/TagMapper.java new file mode 100644 index 000000000..b19fbfffa --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/TagMapper.java @@ -0,0 +1,26 @@ +package com.openisle.mapper; + +import com.openisle.dto.TagDto; +import com.openisle.model.Tag; +import org.springframework.stereotype.Component; + +/** Mapper for tag entities. */ +@Component +public class TagMapper { + + public TagDto toDto(Tag tag) { + return toDto(tag, null); + } + + public TagDto toDto(Tag tag, Long count) { + TagDto dto = new TagDto(); + dto.setId(tag.getId()); + dto.setName(tag.getName()); + dto.setDescription(tag.getDescription()); + dto.setIcon(tag.getIcon()); + dto.setSmallIcon(tag.getSmallIcon()); + dto.setCreatedAt(tag.getCreatedAt()); + dto.setCount(count); + return dto; + } +} diff --git a/backend/src/main/java/com/openisle/mapper/UserMapper.java b/backend/src/main/java/com/openisle/mapper/UserMapper.java new file mode 100644 index 000000000..3edca1a49 --- /dev/null +++ b/backend/src/main/java/com/openisle/mapper/UserMapper.java @@ -0,0 +1,104 @@ +package com.openisle.mapper; + +import com.openisle.dto.*; +import com.openisle.model.Comment; +import com.openisle.model.Post; +import com.openisle.model.User; +import com.openisle.service.*; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +/** Mapper for user related DTOs. */ +@Component +@RequiredArgsConstructor +public class UserMapper { + + private final SubscriptionService subscriptionService; + private final PostService postService; + private final CommentService commentService; + private final ReactionService reactionService; + private final UserVisitService userVisitService; + private final PostReadService postReadService; + private final LevelService levelService; + + @Value("${app.snippet-length:50}") + private int snippetLength; + + public AuthorDto toAuthorDto(User user) { + AuthorDto dto = new AuthorDto(); + dto.setId(user.getId()); + dto.setUsername(user.getUsername()); + dto.setAvatar(user.getAvatar()); + return dto; + } + + public UserDto toDto(User user, Authentication viewer) { + UserDto dto = new UserDto(); + dto.setId(user.getId()); + dto.setUsername(user.getUsername()); + dto.setEmail(user.getEmail()); + dto.setAvatar(user.getAvatar()); + dto.setRole(user.getRole().name()); + dto.setIntroduction(user.getIntroduction()); + dto.setFollowers(subscriptionService.countSubscribers(user.getUsername())); + dto.setFollowing(subscriptionService.countSubscribed(user.getUsername())); + dto.setCreatedAt(user.getCreatedAt()); + dto.setLastPostTime(postService.getLastPostTime(user.getUsername())); + dto.setLastCommentTime(commentService.getLastCommentTimeOfUserByUserId(user.getId())); + dto.setTotalViews(postService.getTotalViews(user.getUsername())); + dto.setVisitedDays(userVisitService.countVisits(user.getUsername())); + dto.setReadPosts(postReadService.countReads(user.getUsername())); + dto.setLikesSent(reactionService.countLikesSent(user.getUsername())); + dto.setLikesReceived(reactionService.countLikesReceived(user.getUsername())); + dto.setExperience(user.getExperience()); + dto.setCurrentLevel(levelService.getLevel(user.getExperience())); + dto.setNextLevelExp(levelService.nextLevelExp(user.getExperience())); + if (viewer != null) { + dto.setSubscribed(subscriptionService.isSubscribed(viewer.getName(), user.getUsername())); + } else { + dto.setSubscribed(false); + } + return dto; + } + + public UserDto toDto(User user) { + return toDto(user, null); + } + + public PostMetaDto toMetaDto(Post post) { + PostMetaDto dto = new PostMetaDto(); + dto.setId(post.getId()); + dto.setTitle(post.getTitle()); + String content = post.getContent(); + if (content == null) { + content = ""; + } + if (snippetLength >= 0) { + dto.setSnippet(content.length() > snippetLength ? content.substring(0, snippetLength) : content); + } else { + dto.setSnippet(content); + } + dto.setCreatedAt(post.getCreatedAt()); + dto.setCategory(post.getCategory().getName()); + dto.setViews(post.getViews()); + return dto; + } + + public CommentInfoDto toCommentInfoDto(Comment comment) { + CommentInfoDto dto = new CommentInfoDto(); + dto.setId(comment.getId()); + dto.setContent(comment.getContent()); + dto.setCreatedAt(comment.getCreatedAt()); + dto.setPost(toMetaDto(comment.getPost())); + if (comment.getParent() != null) { + ParentCommentDto pc = new ParentCommentDto(); + pc.setId(comment.getParent().getId()); + pc.setAuthor(comment.getParent().getAuthor().getUsername()); + pc.setContent(comment.getParent().getContent()); + dto.setParentComment(pc); + } + return dto; + } +}