프로젝트/PongGame

RelationController

히포파타마스 2022. 6. 3. 17:25

RelationController

사전에 정의한 API 명세에 따른 Controller를 구현한다.

 

 

 

 

1. RelationValidator

Controller로 들어오는 accountId 간에 검증을 처리한다.

Controller로 들어오는 accountId는 별개의 파라미터로 Spring에서 제공하는 Validator 기능을 사용할 수 없기에 따로 RelationValidator 클래스를 생성하고 Controller에서 해당 Validator를 적용한다.

 

 

 

■ RelationValidator

Account간 Relation의 상태에 대해 검증을 시행한다.

 

[RelationValidator]

@Component
@RequiredArgsConstructor
public class RelationValidator {

    private final RelationRepository relationRepository;
    private final AccountRepository accountRepository;

    private void isBlockRelationByAccount(Account fromAccount, Account toAccount) {
        if (relationRepository.existsByFromAccountAndToAccountAndRelationStateEquals(fromAccount, toAccount,
                RelationState.BLOCK)) {
            throw new IllegalRequestException("차단된 회원입니다.");
        }
    }

    public void isBlockRelation(Long fromAccountId, Long toAccountId) {
        Account fromAccount = accountRepository.findById(fromAccountId)
                .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));
        Account toAccount = accountRepository.findById(toAccountId)
                .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));

        isBlockRelationByAccount(fromAccount, toAccount);
    }

    public void validRequestFriend(Long fromAccountId, Long toAccountId) {
        Account fromAccount = accountRepository.findById(fromAccountId)
                .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));
        Account toAccount = accountRepository.findById(toAccountId)
                .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));

        isBlockRelationByAccount(fromAccount, toAccount);
        if (relationRepository.existsByFromAccountAndToAccountAndRelationStateEquals(fromAccount, toAccount
                , RelationState.FRIEND)) {
            throw new IllegalRequestException("이미 친구 관계입니다.");
        }
        if (fromAccount.equals(toAccount)) {
            throw new IllegalRequestException("자기자신에 대한 요청입니다.");
        }
        if (relationRepository.existsByFromAccountAndToAccountAndRelationStateEquals(fromAccount, toAccount,
                RelationState.REQUEST)) {
            throw new DuplicationRequestException("이미 존재하는 요청입니다.");
        }
    }
}

 

 

□ isBlockRelationByAccount

fromAccount -> toAccount 방향의 "차단" 상태인 Relation이 있으면 에러를 발생시킨다.

파라미터로 Id가 아닌 Account를 받는다.

 

[isBlockRelationByAccount]

public void isBlockRelationByAccount(Account fromAccount, Account toAccount) {
    if (relationRepository.existsByFromAccountAndToAccountAndRelationStateEquals(fromAccount, toAccount,
            RelationState.BLOCK)) {
        throw new IllegalRequestException("차단된 회원입니다.");
    }
}

 

 

□ isBlockRelation

fromAccount -> toAccount 방향의 "차단" 상태인 Relation이 있으면 에러를 발생시킨다.

 

[isBlockRelation]

public void isBlockRelation(Long fromAccountId, Long toAccountId) {
    Account fromAccount = accountRepository.findById(fromAccountId)
            .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));
    Account toAccount = accountRepository.findById(toAccountId)
            .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));

    isBlockRelationByAccount(fromAccount, toAccount);
}

 

 

□ validRequestFriend

"친구 요청"을 처리하는 API에서 매개변수로 받아지는 AccountId에 대해 검증을 처리하는 메서드

 

[validRequestFriend]

public void validRequestFriend(Long fromAccountId, Long toAccountId) {
    Account fromAccount = accountRepository.findById(fromAccountId)
            .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));
    Account toAccount = accountRepository.findById(toAccountId)
            .orElseThrow(() -> new NonExistResourceException("해당 Id를 갖는 Account를 찾을 수 없습니다."));

    isBlockRelationByAccount(fromAccount, toAccount);
    if (relationRepository.existsByFromAccountAndToAccountAndRelationStateEquals(fromAccount, toAccount
            , RelationState.FRIEND)) {   //[1]
        throw new IllegalRequestException("이미 친구 관계입니다.");
    }
    if (fromAccount.equals(toAccount)) {   //[2]
        throw new IllegalRequestException("자기자신에 대한 요청입니다.");
    }
    if (relationRepository.existsByFromAccountAndToAccountAndRelationStateEquals(fromAccount, toAccount,
            RelationState.REQUEST)) {   //[3]
        throw new DuplicationRequestException("이미 존재하는 요청입니다.");
    }
}

● [1] : 이미 "친구" 상태인 Relation이 있을 경우 에러 발생

● [2] : "친구 요청"을 자기 자신에게 시행할 경우 에러 발생

● [3] : 이미 "친구 요청" 상태인 Relation이 있을 경우 에러 발생

 

 

 

 

2. RelationController

■ RelationController

[RelationController]

@RestController
@RequiredArgsConstructor
public class RelationController {

    private final RelationService relationService;
    private final RelationValidator relationValidator;
    
    .
    .
    .
    
}

 

 

 

■ 생성, 변경, 삭제

Relation을 생성하거나 삭제하고, RelationState를 변경하는 API

 

[생성, 변경]

@PostMapping("/relation/request/{accountId}")
public ResultMessage requestFriend(@LoginAccountId Long loginAccountId, @PathVariable Long accountId) {
    relationValidator.validRequestFriend(loginAccountId, accountId);
    relationService.requestFriend(loginAccountId, accountId);
    return new ResultMessage("success friend request");
}

@PostMapping("/relation/request/accept/{accountId}")
public ResultMessage acceptFriend(@LoginAccountId Long loginAccountId, @PathVariable Long accountId) {
    relationValidator.isBlockRelation(loginAccountId, accountId);
    relationService.acceptFriend(accountId, loginAccountId);
    return new ResultMessage("success accept friend request");
}

@PostMapping("/relation/request/reject/{accountId}")
public ResultMessage rejectFriend(@LoginAccountId Long loginAccountId, @PathVariable Long accountId) {
    relationService.rejectRequest(accountId, loginAccountId);
    return new ResultMessage("success reject friend request");
}

@PostMapping("/relation/block/{accountId}")
public ResultMessage block(@LoginAccountId Long loginAccountId, @PathVariable Long accountId) {
    relationValidator.isBlockRelation(loginAccountId, accountId);
    relationService.block(loginAccountId, accountId);
    return new ResultMessage("success block Account");
}

@PostMapping("/relation/unBlock/{accountId}")
public ResultMessage unBlock(@LoginAccountId Long loginAccountId, @PathVariable Long accountId) {
    relationService.unBlock(loginAccountId, accountId);
    return new ResultMessage("success unBlock Account");
}

파라미터로 받아진 acoountId의 Account 간에 검증을 RelationValidator를 통해 처리한 후, RelationService에서 Business Logic을 적용한다.

 

 

 

■ 조회

Relation에 연관된 Acoount를 조회하는 API

 

[조회]

@GetMapping("relation/request/all")
public Result<List<AccountDto>> findAllRequest(@LoginAccountId Long loginAccountId) {
    List<AccountDto> accountDtoList = relationService.findAllRequest(loginAccountId).stream()
            .map(relation -> new AccountDto(relation.getToAccount()))
            .collect(Collectors.toList());
    return new Result<>(accountDtoList);
}

@GetMapping("/relation/requests")
public Page<AccountDto> findRequestsByPage(@LoginAccountId Long loginAccountId, Pageable pageable) {
    QueryResults<Relation> queryResults = relationService.findRequestsByPage(loginAccountId, pageable);
    List<AccountDto> accountDtoList = queryResults.getResults().stream()
            .map(relation -> new AccountDto(relation.getToAccount()))
            .collect(Collectors.toList());
    return new PageImpl<>(accountDtoList, pageable, queryResults.getTotal());
}

@GetMapping("/relation/requestFromOther/all")
public Result<List<AccountDto>> findAllRequestFromOther(@LoginAccountId Long loginAccountId) {
    List<AccountDto> accountDtoList = relationService.findAllRequestFromOther(loginAccountId).stream()
            .map(relation -> new AccountDto(relation.getFromAccount()))
            .collect(Collectors.toList());
    return new Result<>(accountDtoList);
}


@GetMapping("/relation/requestsFromOther")
public Page<AccountDto> findRequestsFromOtherByPage(@LoginAccountId Long loginAccountId, Pageable pageable) {
    QueryResults<Relation> queryResults = relationService.findRequestsFromOtherByPage(loginAccountId, pageable);
    List<AccountDto> accountDtoList = queryResults.getResults().stream()
            .map(relation -> new AccountDto(relation.getFromAccount()))
            .collect(Collectors.toList());
    return new PageImpl<>(accountDtoList, pageable, queryResults.getTotal());
}

@GetMapping("/relation/friend/all")
public Result<List<AccountDto>> findAllFriend(@LoginAccountId Long loginAccountId, Pageable pageable) {
    List<AccountDto> accountDtoList = relationService.findAllFriend(loginAccountId).stream()
            .map(relation -> new AccountDto(relation.getToAccount()))
            .collect(Collectors.toList());
    return new Result<>(accountDtoList);
}

@GetMapping("/relation/friends")
public Page<AccountDto> findFriends(@LoginAccountId Long loginAccountId, Pageable pageable) {
    QueryResults<Relation> queryResults = relationService.findFriendsByPage(loginAccountId, pageable);
    List<AccountDto> accountDtoList = queryResults.getResults().stream()
            .map(relation -> new AccountDto(relation.getToAccount()))
            .collect(Collectors.toList());
    return new PageImpl<>(accountDtoList, pageable, queryResults.getTotal());
}

@GetMapping("/relation/block/all")
public Result<List<AccountDto>> findAllBlock(@LoginAccountId Long loginAccountId) {
    List<AccountDto> accountDtoList = relationService.findAllBlock(loginAccountId).stream()
            .map(relation -> new AccountDto(relation.getToAccount()))
            .collect(Collectors.toList());
    return new Result<>(accountDtoList);
}

@GetMapping("/relation/blocks")
public Page<AccountDto> findBlockAccounts(@LoginAccountId Long loginAccountId, Pageable pageable) {
    QueryResults<Relation> queryResults = relationService.findBlocksByPage(loginAccountId, pageable);
    List<AccountDto> accountDtoList = queryResults.getResults().stream()
            .map(relation -> new AccountDto(relation.getToAccount()))
            .collect(Collectors.toList());
    return new PageImpl<>(accountDtoList, pageable, queryResults.getTotal());
}

RelationService에서 Relation을 찾은 후, fromAccoun와 toAccount 중 반환할 Account를 찾아 List나 Page로 반환한다.

Account는 모두 AccountDto로 옮겨져서 반환된다.