Skip to content

Commit

Permalink
refactor: Author DTO is integrated into ProfileDTO
Browse files Browse the repository at this point in the history
  • Loading branch information
zoooo-hs committed Dec 3, 2022
1 parent eeb928e commit ee5017d
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.zoooohs.realworld.domain.article.dto;

import io.zoooohs.realworld.domain.profile.dto.ProfileDto;
import lombok.*;

import javax.validation.constraints.NotNull;
Expand All @@ -25,19 +26,7 @@ public class ArticleDto {
private LocalDateTime updatedAt;
private Boolean favorited;
private Long favoritesCount;
private Author author;

// TODO: ProfileDTO 통합 필요
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Author {
private String username;
private String bio;
private String image;
private Boolean following;
}
private ProfileDto author;

@Getter
@Builder
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.zoooohs.realworld.domain.article.dto;

import io.zoooohs.realworld.domain.profile.dto.ProfileDto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -19,7 +20,7 @@ public class CommentDto {
private LocalDateTime updatedAt;
@NotNull
private String body;
private ArticleDto.Author author;
private ProfileDto author;

@Getter
@Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.zoooohs.realworld.domain.article.repository.ArticleRepository;
import io.zoooohs.realworld.domain.article.repository.FavoriteRepository;
import io.zoooohs.realworld.domain.common.entity.BaseEntity;
import io.zoooohs.realworld.domain.profile.dto.ProfileDto;
import io.zoooohs.realworld.domain.profile.entity.FollowEntity;
import io.zoooohs.realworld.domain.profile.repository.FollowRepository;
import io.zoooohs.realworld.domain.profile.service.ProfileService;
Expand Down Expand Up @@ -58,32 +59,26 @@ public ArticleDto createArticle(ArticleDto article, AuthUserDetails authUserDeta
articleEntity.setTagList(tagList);

articleEntity = articleRepository.save(articleEntity);
return convertEntityToDto(articleEntity, false, 0L, false);
return convertEntityToDto(articleEntity, false, 0L, authUserDetails);
}

@Override
public ArticleDto getArticle(String slug, AuthUserDetails authUserDetails) {
ArticleEntity found = articleRepository.findBySlug(slug).orElseThrow(() -> new AppException(Error.ARTICLE_NOT_FOUND));
Boolean following = profileService.getProfile(found.getAuthor().getUsername(), authUserDetails).getFollowing();
List<FavoriteEntity> favorites = found.getFavoriteList();
Boolean favorited = favorites.stream().anyMatch(favoriteEntity -> favoriteEntity.getUser().getId().equals(authUserDetails.getId()));
int favoriteCount = favorites.size();
return convertEntityToDto(found, favorited, (long) favoriteCount, following);
return convertEntityToDto(found, favorited, (long) favoriteCount, authUserDetails);
}

private ArticleDto convertEntityToDto(ArticleEntity entity, Boolean favorited, Long favoritesCount, Boolean following) {
// TODO: author, following -> profile service에서 get profile로 끝내기
private ArticleDto convertEntityToDto(ArticleEntity entity, Boolean favorited, Long favoritesCount, AuthUserDetails authUserDetails) {
ProfileDto author = profileService.getProfileByUserId(entity.getAuthor().getId(), authUserDetails);
return ArticleDto.builder()
.slug(entity.getSlug())
.title(entity.getTitle())
.description(entity.getDescription())
.body(entity.getBody())
.author(ArticleDto.Author.builder()
.username(entity.getAuthor().getUsername())
.bio(entity.getAuthor().getBio())
.image(entity.getAuthor().getImage())
.following(following)
.build())
.author(author)
.createdAt(entity.getCreatedAt())
.updatedAt(entity.getUpdatedAt())
.favorited(favorited)
Expand Down Expand Up @@ -130,7 +125,7 @@ public List<ArticleDto> feedArticles(AuthUserDetails authUserDetails, FeedParams
List<FavoriteEntity> favorites = entity.getFavoriteList();
Boolean favorited = favorites.stream().anyMatch(favoriteEntity -> favoriteEntity.getUser().getId().equals(authUserDetails.getId()));
int favoriteCount = favorites.size();
return convertEntityToDto(entity, favorited, (long) favoriteCount, true);
return convertEntityToDto(entity, favorited, (long) favoriteCount, authUserDetails);
}).collect(Collectors.toList());
}

Expand Down Expand Up @@ -186,15 +181,11 @@ public List<ArticleDto> listArticle(ArticleQueryParam articleQueryParam, AuthUse
}

private List<ArticleDto> convertToArticleList(List<ArticleEntity> articleEntities, AuthUserDetails authUserDetails) {
List<Long> authorIds = articleEntities.stream().map(ArticleEntity::getAuthor).map(BaseEntity::getId).collect(Collectors.toList());
List<Long> followeeIds = followRepository.findByFollowerIdAndFolloweeIdIn(authUserDetails.getId(), authorIds).stream().map(FollowEntity::getFollowee).map(BaseEntity::getId).collect(Collectors.toList());

return articleEntities.stream().map(entity -> {
List<FavoriteEntity> favorites = entity.getFavoriteList();
Boolean favorited = favorites.stream().anyMatch(favoriteEntity -> favoriteEntity.getUser().getId().equals(authUserDetails.getId()));
int favoriteCount = favorites.size();
Boolean following = followeeIds.stream().anyMatch(followeeId -> followeeId.equals(entity.getAuthor().getId()));
return convertEntityToDto(entity, favorited, (long) favoriteCount, following);
return convertEntityToDto(entity, favorited, (long) favoriteCount, authUserDetails);
}).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package io.zoooohs.realworld.domain.article.servie;

import io.zoooohs.realworld.domain.article.dto.ArticleDto;
import io.zoooohs.realworld.domain.article.dto.CommentDto;
import io.zoooohs.realworld.domain.article.entity.ArticleEntity;
import io.zoooohs.realworld.domain.article.entity.CommentEntity;
import io.zoooohs.realworld.domain.article.repository.ArticleRepository;
import io.zoooohs.realworld.domain.article.repository.CommentRepository;
import io.zoooohs.realworld.domain.common.entity.BaseEntity;
import io.zoooohs.realworld.domain.profile.dto.ProfileDto;
import io.zoooohs.realworld.domain.profile.service.ProfileService;
import io.zoooohs.realworld.domain.user.entity.UserEntity;
import io.zoooohs.realworld.exception.AppException;
Expand Down Expand Up @@ -40,18 +40,7 @@ public CommentDto addCommentsToAnArticle(String slug, CommentDto comment, AuthUs
.build();
commentRepository.save(commentEntity);

return CommentDto.builder()
.id(commentEntity.getId())
.createdAt(commentEntity.getCreatedAt())
.updatedAt(commentEntity.getUpdatedAt())
.body(commentEntity.getBody())
.author(ArticleDto.Author.builder()
.username(commentEntity.getAuthor().getUsername())
.bio(commentEntity.getAuthor().getBio())
.image(commentEntity.getArticle().getAuthor().getImage())
.following(false)
.build())
.build();
return convertToDTO(authUserDetails, commentEntity);
}

@Transactional
Expand All @@ -71,20 +60,17 @@ public List<CommentDto> getCommentsBySlug(String slug, AuthUserDetails authUserD
Long articleId = articleRepository.findBySlug(slug).map(BaseEntity::getId).orElseThrow(() -> new AppException(Error.ARTICLE_NOT_FOUND));

List<CommentEntity> commentEntities = commentRepository.findByArticleId(articleId);
return commentEntities.stream().map(commentEntity -> {
Boolean following = profileService.getProfile(commentEntity.getAuthor().getUsername(), authUserDetails).getFollowing();
return CommentDto.builder()
.id(commentEntity.getId())
.createdAt(commentEntity.getCreatedAt())
.updatedAt(commentEntity.getUpdatedAt())
.body(commentEntity.getBody())
.author(ArticleDto.Author.builder()
.username(commentEntity.getAuthor().getUsername())
.bio(commentEntity.getAuthor().getBio())
.image(commentEntity.getArticle().getAuthor().getImage())
.following(following)
.build())
.build();
}).collect(Collectors.toList());
return commentEntities.stream().map(commentEntity -> convertToDTO(authUserDetails, commentEntity)).collect(Collectors.toList());
}

private CommentDto convertToDTO(AuthUserDetails authUserDetails, CommentEntity commentEntity) {
ProfileDto author = profileService.getProfileByUserId(commentEntity.getAuthor().getId(), authUserDetails);
return CommentDto.builder()
.id(commentEntity.getId())
.createdAt(commentEntity.getCreatedAt())
.updatedAt(commentEntity.getUpdatedAt())
.body(commentEntity.getBody())
.author(author)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ public class ProfilesController {
private final ProfileService profileService;

@GetMapping("/{username}")
public ProfileDto getProfile(@PathVariable("username") String name, @AuthenticationPrincipal AuthUserDetails authUserDetails) {
return profileService.getProfile(name, authUserDetails);
public ProfileDto.Single getProfile(@PathVariable("username") String name, @AuthenticationPrincipal AuthUserDetails authUserDetails) {
return new ProfileDto.Single(profileService.getProfile(name, authUserDetails));
}

@PostMapping("/{username}/follow")
public ProfileDto followUser(@PathVariable("username") String name, @AuthenticationPrincipal AuthUserDetails authUserDetails) {
return profileService.followUser(name, authUserDetails);
public ProfileDto.Single followUser(@PathVariable("username") String name, @AuthenticationPrincipal AuthUserDetails authUserDetails) {
return new ProfileDto.Single(profileService.followUser(name, authUserDetails));
}

@DeleteMapping("/{username}/follow")
public ProfileDto unfollowUser(@PathVariable("username") String name, @AuthenticationPrincipal AuthUserDetails authUserDetails) {
return profileService.unfollowUser(name, authUserDetails);
public ProfileDto.Single unfollowUser(@PathVariable("username") String name, @AuthenticationPrincipal AuthUserDetails authUserDetails) {
return new ProfileDto.Single(profileService.unfollowUser(name, authUserDetails));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.zoooohs.realworld.domain.profile.dto;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -11,11 +9,17 @@
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonTypeName("profile")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class ProfileDto {
private String username;
private String bio;
private String image;
private Boolean following;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public static class Single {
private ProfileDto profile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public interface ProfileService {
ProfileDto followUser(final String name, final AuthUserDetails authUserDetails);

ProfileDto unfollowUser(final String name, final AuthUserDetails authUserDetails);

ProfileDto getProfileByUserId(Long userId, AuthUserDetails authUserDetails);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ public ProfileDto unfollowUser(String name, AuthUserDetails authUserDetails) {
return convertToProfile(followee, false);
}

@Override
public ProfileDto getProfileByUserId(Long userId, AuthUserDetails authUserDetails) {
UserEntity user = userRepository.findById(userId).orElseThrow(() -> new AppException(Error.USER_NOT_FOUND));
Boolean following = followRepository.findByFolloweeIdAndFollowerId(user.getId(), authUserDetails.getId()).isPresent();

return convertToProfile(user, following);
}

private ProfileDto convertToProfile(UserEntity user, Boolean following) {
return ProfileDto.builder()
.username(user.getUsername())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.zoooohs.realworld.domain.article.dto.CommentDto;
import io.zoooohs.realworld.domain.article.servie.ArticleService;
import io.zoooohs.realworld.domain.article.servie.CommentService;
import io.zoooohs.realworld.domain.profile.dto.ProfileDto;
import io.zoooohs.realworld.security.AuthUserDetails;
import io.zoooohs.realworld.security.JWTAuthFilter;
import org.hamcrest.Matchers;
Expand Down Expand Up @@ -55,15 +56,15 @@ public class ArticlesControllerTest {
@MockBean
CommentService commentService;

private ArticleDto.Author author;
private ProfileDto author;
private ArticleDto article;
private ArticleDto.SingleArticle singleArticle;
private String slug;


@BeforeEach
void setUp() {
author = ArticleDto.Author.builder().username("username").build();
author = ProfileDto.builder().username("username").build();
article = ArticleDto.builder()
.title("article title")
.description("description")
Expand Down Expand Up @@ -137,7 +138,7 @@ void whenValidUserFeed_thenReturnMultipleArticle() throws Exception {
.description("description")
.body("hi there")
.tagList(List.of("tag1", "tag2"))
.author(ArticleDto.Author.builder().following(true).build())
.author(ProfileDto.builder().following(true).build())
.build();

when(articleService.feedArticles(any(AuthUserDetails.class), any())).thenReturn(List.of(article));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class ArticleServiceImplTest {
private UserEntity author;
private ArticleEntity expectedArticle;
private LocalDateTime beforeWrite;
private ProfileDto authorProfile;

@BeforeEach
void setUp() {
Expand All @@ -82,6 +83,10 @@ void setUp() {
.image("photo-path")
.build();

authorProfile = ProfileDto.builder()
.username(author.getUsername())
.following(true).build();

expectedArticle = ArticleEntity.builder()
.id(1L)
.slug(expectedSlug)
Expand Down Expand Up @@ -120,7 +125,7 @@ void whenThereIsArticleWithSlug_thenReturnSingleArticle() {
String slug = "article-title";

when(articleRepository.findBySlug(eq(slug))).thenReturn(Optional.ofNullable(expectedArticle));
when(profileService.getProfile(eq(author.getUsername()), any(AuthUserDetails.class))).thenReturn(ProfileDto.builder().following(false).build());
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);

ArticleDto actual = articleService.getArticle(slug, authUserDetails);

Expand All @@ -134,7 +139,7 @@ void whenUpdateArticleWithNewTitle_thenReturnUpdatedSingleArticleWithUpdatedTitl
ArticleDto.Update updateArticle = ArticleDto.Update.builder().title("new title").build();

when(articleRepository.findBySlug(eq(slug))).thenReturn(Optional.ofNullable(expectedArticle));
when(profileService.getProfile(eq(author.getUsername()), any(AuthUserDetails.class))).thenReturn(ProfileDto.builder().following(false).build());
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);

ArticleDto actual = articleService.updateArticle(slug, updateArticle, authUserDetails);

Expand All @@ -156,6 +161,7 @@ void whenDeleteValidSlug_thenReturnVoid() {
void whenValidUserFeed_thenReturnMultipleArticle() {
when(followRepository.findByFollowerId(eq(authUserDetails.getId()))).thenReturn(List.of(FollowEntity.builder().followee(author).build()));
when(articleRepository.findByAuthorIdInOrderByCreatedAtDesc(anyList(), any())).thenReturn(List.of(expectedArticle));
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);

FeedParams feedParams = FeedParams.builder().offset(0).limit(1).build();

Expand All @@ -182,7 +188,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
}
}
});
when(profileService.getProfile(eq(author.getUsername()), any(AuthUserDetails.class))).thenReturn(ProfileDto.builder().following(false).build());
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);


ArticleDto actual = articleService.favoriteArticle(expectedArticle.getSlug(), authUserDetails);
Expand Down Expand Up @@ -210,7 +216,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
return Optional.ofNullable(expectedArticle);
}
});
when(profileService.getProfile(eq(author.getUsername()), any(AuthUserDetails.class))).thenReturn(ProfileDto.builder().following(false).build());
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);

ArticleDto actual = articleService.unfavoriteArticle(expectedArticle.getSlug(), authUserDetails);

Expand All @@ -236,6 +242,7 @@ void whenQueryArticlesByAuthorName_thenReturnArticles() {
query.setAuthor("testUser");

when(articleRepository.findByAuthorName(eq("testUser"), any())).thenReturn(List.of(expectedArticle));
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);

List<ArticleDto> actual = articleService.listArticle(query, authUserDetails);

Expand All @@ -250,6 +257,7 @@ void whenQueryArticlesByFavorited_thenReturnArticles() {
expectedArticle.setFavoriteList(List.of(FavoriteEntity.builder().user(UserEntity.builder().id(1L).username("username").build()).build()));

when(articleRepository.findByFavoritedUsername(eq("username"), any())).thenReturn(List.of(expectedArticle));
when(profileService.getProfileByUserId(eq(author.getId()), any(AuthUserDetails.class))).thenReturn(authorProfile);

List<ArticleDto> actual = articleService.listArticle(query, authUserDetails);

Expand Down
Loading

0 comments on commit ee5017d

Please sign in to comment.