Skip to content

Commit

Permalink
feat: LinkEntity 에 linkBundleId 필드 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
hseong3243 committed Jan 31, 2024
1 parent 6ff72c4 commit 8d71746
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 24 deletions.
5 changes: 5 additions & 0 deletions src/main/java/com/seong/shoutlink/domain/link/Link.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ public class Link {


public Link(String url, String description) {
this(null, url, description);
}

public Link(Long linkId, String url, String description) {
this.linkId = linkId;
this.url = url;
this.description = description;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.seong.shoutlink.domain.link;

import com.seong.shoutlink.domain.linkbundle.LinkBundle;
import lombok.Getter;

@Getter
public class LinkWithLinkBundle {

private final Link link;
private final LinkBundle linkBundle;

public LinkWithLinkBundle(Link link, LinkBundle linkBundle) {
this.link = link;
this.linkBundle = linkBundle;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public ResponseEntity<CreateLinkResponse> createLink(
@Valid @RequestBody CreateLinkRequest request) {
CreateLinkResponse response = linkService.createLink(new CreateLinkCommand(
memberId,
request.linkBundleId(),
request.url(),
request.description()));
return ResponseEntity.status(HttpStatus.CREATED).body(response);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.seong.shoutlink.domain.link.controller.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

public record CreateLinkRequest(
@NotNull(message = "링크 묶음 ID는 필수값입니다.")
Long linkBundleId,
@NotBlank(message = "링크 url은 필수값입니다.")
String url,
String description) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.seong.shoutlink.domain.link.repository;

import com.seong.shoutlink.domain.link.Link;
import com.seong.shoutlink.domain.link.LinkWithLinkBundle;
import com.seong.shoutlink.domain.linkbundle.LinkBundle;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
Expand All @@ -20,13 +22,20 @@ public class LinkEntity {

private String url;
private String description;
private Long linkBundleId;

private LinkEntity(String url, String description) {
private LinkEntity(String url, String description, Long linkBundleId) {
this.url = url;
this.description = description;
this.linkBundleId = linkBundleId;
}

public static LinkEntity create(Link link) {
return new LinkEntity(link.getUrl(), link.getDescription());
public static LinkEntity create(LinkWithLinkBundle linkWithLinkBundle) {
Link link = linkWithLinkBundle.getLink();
LinkBundle linkBundle = linkWithLinkBundle.getLinkBundle();
return new LinkEntity(
link.getUrl(),
link.getDescription(),
linkBundle.getLinkBundleId());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.seong.shoutlink.domain.link.repository;

import com.seong.shoutlink.domain.link.Link;
import com.seong.shoutlink.domain.link.LinkWithLinkBundle;
import com.seong.shoutlink.domain.link.service.LinkRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
Expand All @@ -12,8 +12,8 @@ public class LinkRepositoryImpl implements LinkRepository {
private final LinkJpaRepository linkJpaRepository;

@Override
public Long save(Link link) {
LinkEntity linkEntity = linkJpaRepository.save(LinkEntity.create(link));
public Long save(LinkWithLinkBundle linkWithLinkBundle) {
LinkEntity linkEntity = linkJpaRepository.save(LinkEntity.create(linkWithLinkBundle));
return linkEntity.getLinkId();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.seong.shoutlink.domain.link.service;

import com.seong.shoutlink.domain.link.Link;
import com.seong.shoutlink.domain.link.LinkWithLinkBundle;

public interface LinkRepository {

Long save(Link link);
Long save(LinkWithLinkBundle linkWithLinkBundle);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.seong.shoutlink.domain.link.service;

import com.seong.shoutlink.domain.common.EventPublisher;
import com.seong.shoutlink.domain.exception.ErrorCode;
import com.seong.shoutlink.domain.exception.ShoutLinkException;
import com.seong.shoutlink.domain.link.Link;
import com.seong.shoutlink.domain.link.LinkWithLinkBundle;
import com.seong.shoutlink.domain.link.service.event.CreateLinkEvent;
import com.seong.shoutlink.domain.link.service.request.CreateLinkCommand;
import com.seong.shoutlink.domain.link.service.response.CreateLinkResponse;
import com.seong.shoutlink.domain.linkbundle.LinkBundle;
import com.seong.shoutlink.domain.linkbundle.service.LinkBundleRepository;
import com.seong.shoutlink.domain.member.service.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -16,15 +21,21 @@ public class LinkService {

private final MemberRepository memberRepository;
private final LinkRepository linkRepository;
private final LinkBundleRepository linkBundleRepository;
private final EventPublisher eventPublisher;

@Transactional
public CreateLinkResponse createLink(CreateLinkCommand command) {
// Member member = memberRepository.findById(command.memberId())
// .orElseThrow(() -> new ShoutLinkException("존재하지 않는 사용자입니다.", ErrorCode.NOT_FOUND));
LinkBundle linkBundle = getLinkBundle(command.linkBundleId());
Link link = new Link(command.url(), command.description());
Long linkId = linkRepository.save(link);
LinkWithLinkBundle linkWithLinkBundle = new LinkWithLinkBundle(link, linkBundle);
Long linkId = linkRepository.save(linkWithLinkBundle);
eventPublisher.publishEvent(new CreateLinkEvent(command.url()));
return new CreateLinkResponse(linkId);
}

private LinkBundle getLinkBundle(Long linkBundleId) {
return linkBundleRepository.findById(linkBundleId)
.orElseThrow(() -> new ShoutLinkException("존재하지 않는 링크 번들입니다.", ErrorCode.NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.seong.shoutlink.domain.link.service.request;

public record CreateLinkCommand(Long memberId, String url, String description) {
public record CreateLinkCommand(Long memberId, Long linkBundleId, String url, String description) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ public class LinkBundle {
private Long linkBundleId;
private String description;
private boolean isDefault;
private Member member;
private Long memberId;

public LinkBundle(String description, boolean isDefault, Member member) {
this(null, description, isDefault, member.getMemberId());
}

public LinkBundle(Long linkBundleId, String description, boolean isDefault, Long memberId) {
this.linkBundleId = linkBundleId;
this.description = description;
this.isDefault = isDefault;
this.member = member;
this.memberId = memberId;
}

public void initId(Long linkBundleId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ public static LinkBundleEntity create(LinkBundle linkBundle) {
linkBundle.getLinkBundleId(),
linkBundle.getDescription(),
linkBundle.isDefault(),
linkBundle.getMember().getMemberId());
linkBundle.getMemberId());
}

public LinkBundle toDomain() {
return new LinkBundle(
linkBundleId,
description,
isDefault,
memberId
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.seong.shoutlink.domain.linkbundle.LinkBundle;
import com.seong.shoutlink.domain.linkbundle.service.LinkBundleRepository;
import com.seong.shoutlink.domain.member.Member;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

Expand All @@ -24,4 +25,10 @@ public Long save(LinkBundle linkBundle) {
public void updateDefaultBundleFalse(Member member) {
linkBundleJpaRepository.updateDefaultBundleFalse(member.getMemberId());
}

@Override
public Optional<LinkBundle> findById(Long linkBundleId) {
return linkBundleJpaRepository.findById(linkBundleId)
.map(LinkBundleEntity::toDomain);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import com.seong.shoutlink.domain.linkbundle.LinkBundle;
import com.seong.shoutlink.domain.member.Member;
import java.util.Optional;

public interface LinkBundleRepository {

Long save(LinkBundle linkBundle);

void updateDefaultBundleFalse(Member member);

Optional<LinkBundle> findById(Long linkBundleId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class LinkControllerTest extends BaseControllerTest {
@DisplayName("성공: 링크 생성 API 호출 시")
void createLink() throws Exception {
//given
CreateLinkRequest request = new CreateLinkRequest("https://hseong.tistory.com/", "내 블로그");
CreateLinkRequest request = new CreateLinkRequest(1L, "https://hseong.tistory.com/", "내 블로그");
CreateLinkResponse response = new CreateLinkResponse(1L);
given(linkService.createLink(any())).willReturn(response);

Expand All @@ -42,6 +42,7 @@ void createLink() throws Exception {
headerWithName(AUTHORIZATION).description("사용자 액세스 토큰")
),
requestFields(
fieldWithPath("linkBundleId").type(JsonFieldType.NUMBER).description("링크 번들 ID"),
fieldWithPath("url").type(JsonFieldType.STRING).description("링크 url"),
fieldWithPath("description").type(JsonFieldType.STRING).description("링크 설명")
.optional()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.seong.shoutlink.domain.link.repository;

import com.seong.shoutlink.domain.link.Link;
import com.seong.shoutlink.domain.link.LinkWithLinkBundle;
import com.seong.shoutlink.domain.link.service.LinkRepository;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -10,9 +11,14 @@ public class FakeLinkRepository implements LinkRepository {
private final Map<Long, Link> memory = new HashMap<>();

@Override
public Long save(Link link) {
public Long save(LinkWithLinkBundle linkWithLinkBundle) {
long nextId = getNextId();
memory.put(nextId, linkWithLinkBundle.getLink());
return nextId;
}

private long getNextId() {
long nextId = memory.keySet().size() + 1;
memory.put(nextId, link);
return nextId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import com.seong.shoutlink.domain.link.repository.FakeLinkRepository;
import com.seong.shoutlink.domain.link.service.request.CreateLinkCommand;
import com.seong.shoutlink.domain.link.service.response.CreateLinkResponse;
import com.seong.shoutlink.domain.linkbundle.repository.FakeLinkBundleRepository;
import com.seong.shoutlink.domain.member.Member;
import com.seong.shoutlink.domain.member.repository.StubMemberRepository;
import com.seong.shoutlink.fixture.LinkBundleFixture;
import com.seong.shoutlink.fixture.MemberFixture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -22,22 +25,26 @@ class CreateLinkTest {
private LinkService linkService;
private StubMemberRepository memberRepository;
private FakeLinkRepository linkRepository;
private FakeLinkBundleRepository linkBundleRepository;
private StubEventPublisher eventPublisher;

@BeforeEach
void setUp() {
memberRepository = new StubMemberRepository(MemberFixture.member());
Member member = MemberFixture.member();
memberRepository = new StubMemberRepository(member);
linkRepository = new FakeLinkRepository();
linkBundleRepository = new FakeLinkBundleRepository(LinkBundleFixture.linkBundle(member));
eventPublisher = new StubEventPublisher();
linkService = new LinkService(memberRepository, linkRepository, eventPublisher);
linkService = new LinkService(memberRepository, linkRepository, linkBundleRepository,
eventPublisher);
}

@Test
@DisplayName("성공: 링크 저장됨")
void createLink() {
//given
CreateLinkCommand command = new CreateLinkCommand(1L,
"https://hseong.tistory.com/", "내 블로그");
1L, "https://hseong.tistory.com/", "내 블로그");

//when
CreateLinkResponse response = linkService.createLink(command);
Expand All @@ -51,7 +58,7 @@ void createLink() {
void createLink_ThenPublishCreateLinkEvent() {
//given
CreateLinkCommand command = new CreateLinkCommand(1L,
"https://hseong.tistory.com/", "내 블로그");
1L, "https://hseong.tistory.com/", "내 블로그");

//when
CreateLinkResponse response = linkService.createLink(command);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class FakeLinkBundleRepository implements LinkBundleRepository {

private final Map<Long, LinkBundle> memory = new HashMap<>();

public FakeLinkBundleRepository(LinkBundle... linkBundles) {
for (LinkBundle linkBundle : linkBundles) {
memory.put(getNextId(), linkBundle);
}
}

@Override
public Long save(LinkBundle linkBundle) {
long nextId = getNextId();
Expand All @@ -22,16 +29,21 @@ public Long save(LinkBundle linkBundle) {
@Override
public void updateDefaultBundleFalse(Member member) {
List<LinkBundle> defaultLinkBundle = memory.values().stream()
.filter(linkBundle -> linkBundle.isDefault() && linkBundle.getMember().equals(member))
.filter(linkBundle -> linkBundle.isDefault() && linkBundle.getMemberId().equals(member.getMemberId()))
.toList();
defaultLinkBundle.forEach(lb -> {
memory.remove(lb.getLinkBundleId());
memory.put(lb.getLinkBundleId(),
new LinkBundle(lb.getDescription(), false, lb.getMember()));
new LinkBundle(lb.getDescription(), false, member));
});
}

private long getNextId() {
return memory.keySet().size() + 1;
}

@Override
public Optional<LinkBundle> findById(Long linkBundleId) {
return memory.values().stream().findFirst();
}
}
16 changes: 16 additions & 0 deletions src/test/java/com/seong/shoutlink/fixture/LinkBundleFixture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.seong.shoutlink.fixture;

import com.seong.shoutlink.domain.linkbundle.LinkBundle;
import com.seong.shoutlink.domain.member.Member;

public final class LinkBundleFixture {

public static final long LINK_BUNDLE_ID = 1L;
public static final String DESCRIPTION = "기본 분류";
public static final boolean IS_DEFAULT = true;
public static final long MEMBER_ID = 1L;

public static LinkBundle linkBundle(Member member) {
return new LinkBundle(LINK_BUNDLE_ID, DESCRIPTION, IS_DEFAULT, MEMBER_ID);
}
}
2 changes: 2 additions & 0 deletions src/test/java/com/seong/shoutlink/fixture/LinkFixture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
package com.seong.shoutlink.fixture;public class LinkFixture {
}

0 comments on commit 8d71746

Please sign in to comment.