package org.ntlab.tampoposerver.services; import org.ntlab.tampoposerver.models.FriendPair; import org.ntlab.tampoposerver.models.FriendRequest; import org.ntlab.tampoposerver.models.User; import org.ntlab.tampoposerver.repositories.FriendRepository; import org.ntlab.tampoposerver.repositories.FriendRequestRepository; import org.ntlab.tampoposerver.repositories.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collection; import java.util.Optional; // MEMO: ユーザーのトークンを認証するところはUserRepositoryに任せる // MEMO: フレンド系の操作で認証が必要な場合はここで対応する @Service public class FriendService { private final UserRepository userRepository; private final FriendRepository friendRepository; private final FriendRequestRepository friendRequestRepository; @Autowired public FriendService(UserRepository userRepository, FriendRepository friendRepository, FriendRequestRepository friendRequestRepository) { this.userRepository = userRepository; this.friendRepository = friendRepository; this.friendRequestRepository = friendRequestRepository; } /** * 新しいフレンドリクエストを作成する * * @param token APIリクエストをしてきたユーザーの認証用トークン * @param senderId フレンドリクエストを送ったユーザーのユーザーID * @param receiverId フレンドリクエストを受け取ったユーザーのユーザーID * @return 作成されたフレンドリクエストのインスタンス(tokenに対応したユーザーがsenderIdでもreceiverIdにも関係しない場合は{@code Optional.empty()}) * @apiNote {@code token} が有効かどうか、{@code senderId}と{@code receiverId}に対応したユーザーがそれぞれ存在するかどうかは別に判定が必要 */ public Optional<FriendRequest> createFriendRequest(String token, String senderId, String receiverId) { User sender = userRepository.getUser(senderId); User receiver = userRepository.getUser(receiverId); if (!sender.getToken().equals(token) && !receiver.getToken().equals(token)) { return Optional.empty(); } FriendRequest newRequest = friendRequestRepository.create(new FriendRequest(senderId, receiverId)); return Optional.of(newRequest); } /** * ユーザー自身に関連するフレンドリクエストをすべて返す * * @param token ユーザー認証用のトークン * @return ユーザー自身に関連するすべてのフレンドリクエストのインスタンス(リクエストがなければ空のリスト) * @apiNote {@code token} が有効かどうかは別に判定が必要 */ public ArrayList<FriendRequest> getFriendRequests(String token) { ArrayList<FriendRequest> results = new ArrayList<>(); Collection<FriendRequest> allRequests = friendRequestRepository.findAll(); for (FriendRequest request : allRequests) { User sender = userRepository.getUser(request.getSenderId()); User receiver = userRepository.getUser(request.getReceiverId()); if (sender.getToken().equals(token) || receiver.getToken().equals(token)) { results.add(request); } } return results; } /** * 指定したフレンドリクエストを削除する * * @param token APIリクエストをしてきたユーザーの認証用トークン * @param friendRequestId 削除する対象のフレンドリクエストのID * @return 削除に成功したらtrue, それ以外はfalse * @apiNote {@code token} が有効かどうかは別に判定が必要 */ public boolean removeFriendRequest(String token, int friendRequestId) { FriendRequest targetRequest = friendRequestRepository.find(friendRequestId); if (targetRequest == null) { return false; } User sender = userRepository.getUser(targetRequest.getSenderId()); User receiver = userRepository.getUser(targetRequest.getReceiverId()); if (!sender.getToken().equals(token) && !receiver.getToken().equals(token)) { return false; } return friendRequestRepository.delete(friendRequestId); } /** * 新しくフレンドペアを作成する * * @param user0Id 片方のユーザーのユーザーID * @param user1Id もう一方のユーザーのユーザーID * @return 追加されたフレンドペアのインスタンス(エラーがあった場合は{@code Optional.empty()}) * @apiNote {@code token} が有効かどうかは別に判定が必要 */ public Optional<FriendPair> createFriendPair(String user0Id, String user1Id) { // フレンドリクエストを検索して削除する FriendRequest acceptedRequest = friendRequestRepository.findAll().stream().filter((req) -> { return (req.getSenderId().equals(user0Id) && req.getReceiverId().equals(user1Id)) || (req.getSenderId().equals(user1Id) && req.getReceiverId().equals(user0Id)); }).findFirst().orElse(null); if (acceptedRequest == null) { return Optional.empty(); } friendRequestRepository.delete(acceptedRequest.getId()); // フレンドを追加する FriendPair createdPair = friendRepository.add(new FriendPair(user0Id, user1Id)); userRepository.addFriendPair(user0Id, createdPair); userRepository.addFriendPair(user1Id, createdPair); return Optional.of(createdPair); } /** * 指定したフレンドのペアを取得する * * @param token APIリクエストをしてきたユーザーの認証用トークン * @param friendPairId 取得する対象のフレンドペアのID * @return 渡したフレンドペアのIDに対応したフレンドペア * @apiNote {@code token} が有効かどうかは別に判定が必要 */ public Optional<FriendPair> getFriendPair(String token, int friendPairId) { FriendPair foundPair = friendRepository.find(friendPairId); if (foundPair == null) { return Optional.empty(); } User user0 = userRepository.getUser(foundPair.getUser0Id()); User user1 = userRepository.getUser(foundPair.getUser1Id()); if (!user0.getToken().equals(token) && !user1.getToken().equals(token)) { return Optional.empty(); } return Optional.of(foundPair); } /** * 指定したフレンドのペアを削除する * * @param token APIリクエストをしてきたユーザーの認証用トークン * @param friendPairId 削除する対象のフレンドペアのID * @return 削除に成功したらtrue, それ以外はfalse */ public boolean removeFriendPair(String token, int friendPairId) { FriendPair foundPair = friendRepository.find(friendPairId); if (foundPair == null) { return false; } User user0 = userRepository.getUser(foundPair.getUser0Id()); User user1 = userRepository.getUser(foundPair.getUser1Id()); if (!user0.getToken().equals(token) && !user1.getToken().equals(token)) { return false; } // フレンドペアを削除する return friendRepository.delete(friendPairId) && userRepository.deleteFriendPair(user0.getUserId(), foundPair) && userRepository.deleteFriendPair(user1.getUserId(), foundPair); } /** * ユーザーIDが{@code userId}のユーザーとフレンドになっているユーザーのIDをすべて返す * * @param token APIリクエストをしてきたユーザーの認証用トークン * @param userId APIリクエストをしてきたユーザーのID * @return ユーザーIDが {@code userId} のユーザーとフレンドになっているユーザーすべてのID * @apiNote ペアがない場合は空の配列、トークンとユーザーIDで認証できなければnullを返す */ public ArrayList<String> getFriendIds(String token, String userId) { User user = userRepository.getUser(userId); if (user == null || !user.getToken().equals(token)) { return null; } ArrayList<String> friendIds = new ArrayList<>(); for (FriendPair friendPair : user.getFriendPairs()) { if (friendPair.getUser0Id().equals(user.getUserId())) { friendIds.add(friendPair.getUser1Id()); } else { friendIds.add(friendPair.getUser0Id()); } } return friendIds; } }