Skip to content

Commit

Permalink
Merge pull request #170 from kakao-tech-campus-2nd-step3/feature/ISSU…
Browse files Browse the repository at this point in the history
…E-167

이미지 validator, linker, deletelinker 수정
  • Loading branch information
jjt4515 authored Nov 13, 2024
2 parents e8a47c6 + 76ece87 commit 6a2eb54
Show file tree
Hide file tree
Showing 20 changed files with 233 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@
import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.ImageType;

import java.util.HashMap;
import java.util.Map;
import java.util.List;

@Component
public class ImageDeleteFactory {

private final Map<ImageType, ImageDeleteLinker> handlerMap;
private final List<ImageDeleteLinker> deleteLinkers;

public ImageDeleteFactory(
ProductDeleteLinker productDeleteLinker,
MemberProfileDeleteLinker memberProfileDeleteLinker) {
this.handlerMap = new HashMap<>();
handlerMap.put(ImageType.PRODUCT, productDeleteLinker);
handlerMap.put(ImageType.MEMBER_PROFILE, memberProfileDeleteLinker);
public ImageDeleteFactory(List<ImageDeleteLinker> deleteLinkers) {
this.deleteLinkers = deleteLinkers;
}

public ImageDeleteLinker getDeleteLinker(ImageType type) {
return handlerMap.get(type);
return deleteLinkers.stream()
.filter(linker -> linker.supports(type))
.findFirst()
.orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package poomasi.domain.image.deleteLinker;

import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;

public interface ImageDeleteLinker {
boolean supports(ImageType type);
void handleImageDeletion(Image image);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.member._profile.entity.MemberProfile;
import poomasi.domain.member._profile.service.MemberProfileService;

Expand All @@ -14,6 +15,11 @@ public MemberProfileDeleteLinker(MemberProfileService memberProfileService) {
this.memberProfileService = memberProfileService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.MEMBER_PROFILE;
}

@Override
public void handleImageDeletion(Image image) {
MemberProfile memberProfile = memberProfileService.getMemberProfileById(image.getReferenceId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product.entity.Product;
import poomasi.domain.product.service.ProductService;

Expand All @@ -14,6 +15,11 @@ public ProductDeleteLinker(ProductService productService) {
this.productService = productService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT;
}

@Override
public void handleImageDeletion(Image image) {
Product product = productService.findProductById(image.getReferenceId());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package poomasi.domain.image.deleteLinker;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product._intro.entity.ProductIntro;
import poomasi.domain.product._intro.service.ProductIntroService;

import java.util.Arrays;
import java.util.List;

@Component
public class ProductIntroDeleteLinker implements ImageDeleteLinker {

private final ProductIntroService productIntroService;

public ProductIntroDeleteLinker(ProductIntroService productIntroService) {
this.productIntroService = productIntroService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT_INTRO;
}

@Transactional
@Override
public void handleImageDeletion(Image image) {
ProductIntro productIntro = productIntroService.getIntroByIntroId(image.getReferenceId());

List<Image> images = Arrays.asList(productIntro.getMainImage(), productIntro.getSubImage1(), productIntro.getSubImage2(), productIntro.getSubImage3());
for (int i = 0; i < images.size(); i++) {
if (images.get(i) == image) {
switch (i) {
case 0 -> productIntro.setMainImage(null);
case 1 -> productIntro.setSubImage1(null);
case 2 -> productIntro.setSubImage2(null);
case 3 -> productIntro.setSubImage3(null);
}
}
}
productIntroService.saveExistedProductIntro(productIntro);
}
}
4 changes: 1 addition & 3 deletions src/main/java/poomasi/domain/image/entity/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import java.time.LocalDateTime;

@Entity
@Table(name = "image")/*, )uniqueConstraints = {
@UniqueConstraint(columnNames = {"type", "reference_id"})
})*/
@Table(name = "image")
@Getter
@Setter
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package poomasi.domain.image.linker;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product._intro.entity.ProductIntro;
import poomasi.domain.product._intro.service.ProductIntroService;
import poomasi.global.error.BusinessException;

import java.util.Arrays;
import java.util.List;

import static poomasi.global.error.BusinessError.IMAGE_LIMIT_EXCEED;

@Service
public class ProductIntroImageLinker implements ImageLinker {

private final ProductIntroService productIntroService;

public ProductIntroImageLinker(ProductIntroService productIntroService) {
this.productIntroService = productIntroService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT_INTRO;
}

@Transactional
@Override
public void link(Long referenceId, Image savedImage) {
ProductIntro productIntro = productIntroService.getIntroByIntroId(referenceId);
addImageToProductIntro(productIntro, savedImage);
productIntroService.saveExistedProductIntro(productIntro);
}

private void addImageToProductIntro(ProductIntro productIntro, Image savedImage) {
List<Image> images = Arrays.asList(
productIntro.getMainImage(),
productIntro.getSubImage1(),
productIntro.getSubImage2(),
productIntro.getSubImage3()
);

for (int i = 0; i < images.size(); i++) {
if (images.get(i) == null) {
setImageByIndex(productIntro, i, savedImage);
return;
}
}

throw new BusinessException(IMAGE_LIMIT_EXCEED);
}

private void setImageByIndex(ProductIntro productIntro, int index, Image image) {
switch (index) {
case 0 -> productIntro.setMainImage(image);
case 1 -> productIntro.setSubImage1(image);
case 2 -> productIntro.setSubImage2(image);
case 3 -> productIntro.setSubImage3(image);
}
}
}
18 changes: 13 additions & 5 deletions src/main/java/poomasi/domain/image/service/ImageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
public class ImageService {

private static final int DEFAULT_IMAGE_LIMIT = 5;
private static final int IMAGE_ONE_LIMIT = 1;
private static final int MEMBER_PROFILE_IMAGE_LIMIT = 1;
private static final int PRODUCT_INTRO_IMAGE_LIMIT = 4;

private final ImageRepository imageRepository;
private final MemberService memberService;
Expand Down Expand Up @@ -88,16 +89,23 @@ private Image recoverImageOrThrow(Image existingImage, ImageRequest imageRequest
}

private void validateImageLimit(ImageRequest imageRequest) {
int imageLimit = DEFAULT_IMAGE_LIMIT;
if (imageRequest.type() == ImageType.MEMBER_PROFILE || imageRequest.type() == ImageType.PRODUCT) {
imageLimit = IMAGE_ONE_LIMIT; // 멤버 프로필, 상품 이미지는 한 장으로 제한
}
int imageLimit = determineImageLimit(imageRequest.type());

if (imageRepository.countByTypeAndReferenceIdAndDeletedAtIsNull(imageRequest.type(), imageRequest.referenceId()) >= imageLimit) {
throw new BusinessException(IMAGE_LIMIT_EXCEED);
}
}

private int determineImageLimit(ImageType imageType) {
if (imageType == ImageType.MEMBER_PROFILE) {
return MEMBER_PROFILE_IMAGE_LIMIT;
}
if (imageType == ImageType.PRODUCT_INTRO) {
return PRODUCT_INTRO_IMAGE_LIMIT;
}
return DEFAULT_IMAGE_LIMIT;
}

// 여러 이미지 저장
@Transactional
public List<Image> saveMultipleImages(Long memberId, List<ImageRequest> imageRequests) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import poomasi.domain.farm.repository.FarmRepository;

import poomasi.domain.image.entity.ImageType;

@Component
@RequiredArgsConstructor
public class FarmOwnerValidator implements ImageOwnerValidator {
private final FarmRepository farmRepository;

@Override
public boolean supports(ImageType type) {
return type == ImageType.FARM;
}

@Override
public boolean validateOwner(Long memberId, Long referenceId) {
return farmRepository.findById(referenceId)
return farmRepository.findByIdAndDeletedAtIsNull(referenceId)
.filter(farm -> farm.getOwnerId().equals(memberId))
.isPresent();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package poomasi.domain.image.validator;

import poomasi.domain.image.entity.ImageType;

public interface ImageOwnerValidator {
boolean validateOwner(Long memberId, Long referenceId);
boolean supports(ImageType type);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,21 @@
import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.ImageType;

import java.util.EnumMap;
import java.util.Map;
import java.util.List;

@Component
public class ImageOwnerValidatorFactory {
private final Map<ImageType, ImageOwnerValidator> validators = new EnumMap<>(ImageType.class);

public ImageOwnerValidatorFactory(FarmOwnerValidator farmOwnerValidator,
ProductOwnerValidator productOwnerValidator,
ReviewOwnerValidator reviewOwnerValidator,
MemberProfileOwnerValidator memberProfileOwnerValidator) {
validators.put(ImageType.FARM, farmOwnerValidator);
validators.put(ImageType.PRODUCT, productOwnerValidator);
validators.put(ImageType.FARM_REVIEW, reviewOwnerValidator);
validators.put(ImageType.PRODUCT_REVIEW, reviewOwnerValidator);
validators.put(ImageType.MEMBER_PROFILE, memberProfileOwnerValidator);
private final List<ImageOwnerValidator> validators;

public ImageOwnerValidatorFactory(List<ImageOwnerValidator> validators) {
this.validators = validators;
}

public ImageOwnerValidator getValidator(ImageType type) {
return validators.get(type);
return validators.stream()
.filter(validator -> validator.supports(type))
.findFirst()
.orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.member.repository.MemberRepository;

@Component
@RequiredArgsConstructor
public class MemberProfileOwnerValidator implements ImageOwnerValidator{
private final MemberRepository memberRepository;

@Override
public boolean supports(ImageType type) {
return type == ImageType.MEMBER_PROFILE;
}

@Override
public boolean validateOwner(Long memberId, Long referenceId) {
return memberRepository.findById(memberId)
return memberRepository.findByIdAndDeletedAtIsNull(memberId)
.filter(member -> member.getMemberProfile().getId().equals(referenceId))
.isPresent();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package poomasi.domain.image.validator;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product._intro.repository.ProductIntroRepository;

@Component
@RequiredArgsConstructor
public class ProductIntroOwnerValidator implements ImageOwnerValidator{
private final ProductIntroRepository productIntroRepository;

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT_INTRO;
}

@Override
public boolean validateOwner(Long memberId, Long referenceId) {
return productIntroRepository.findById(referenceId)
.filter(productIntro -> productIntro.getFarmerId().equals(memberId))
.isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product.repository.ProductRepository;

@Component
@RequiredArgsConstructor
public class ProductOwnerValidator implements ImageOwnerValidator{
private final ProductRepository productRepository;

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT;
}

@Override
public boolean validateOwner(Long memberId, Long referenceId) {
return productRepository.findById(referenceId)
Expand Down
Loading

0 comments on commit 6a2eb54

Please sign in to comment.