🔀 Merge branch 'release/v82'
[Sone.git] / src / main / java / net / pterodactylus / sone / database / memory / MemoryFriendDatabase.java
1 package net.pterodactylus.sone.database.memory;
2
3 import java.util.Collection;
4 import java.util.concurrent.locks.ReadWriteLock;
5 import java.util.concurrent.locks.ReentrantReadWriteLock;
6
7 import javax.annotation.Nonnull;
8 import javax.annotation.Nullable;
9
10 import com.google.common.collect.HashMultimap;
11 import com.google.common.collect.Multimap;
12
13 /**
14  * In-memory implementation of friend-related functionality.
15  */
16 class MemoryFriendDatabase {
17
18         private final ReadWriteLock lock = new ReentrantReadWriteLock();
19         private final ConfigurationLoader configurationLoader;
20         private final Multimap<String, String> soneFriends = HashMultimap.create();
21
22         MemoryFriendDatabase(ConfigurationLoader configurationLoader) {
23                 this.configurationLoader = configurationLoader;
24         }
25
26         Collection<String> getFriends(String localSoneId) {
27                 loadFriends(localSoneId);
28                 lock.readLock().lock();
29                 try {
30                         return soneFriends.get(localSoneId);
31                 } finally {
32                         lock.readLock().unlock();
33                 }
34         }
35
36         boolean isFriend(String localSoneId, String friendSoneId) {
37                 loadFriends(localSoneId);
38                 lock.readLock().lock();
39                 try {
40                         return soneFriends.containsEntry(localSoneId, friendSoneId);
41                 } finally {
42                         lock.readLock().unlock();
43                 }
44         }
45
46         void addFriend(String localSoneId, String friendSoneId) {
47                 loadFriends(localSoneId);
48                 lock.writeLock().lock();
49                 try {
50                         if (soneFriends.put(localSoneId, friendSoneId)) {
51                                 configurationLoader.saveFriends(localSoneId, soneFriends.get(localSoneId));
52                                 if (configurationLoader.getSoneFollowingTime(friendSoneId) == null) {
53                                         configurationLoader.setSoneFollowingTime(friendSoneId, System.currentTimeMillis());
54                                 }
55                         }
56                 } finally {
57                         lock.writeLock().unlock();
58                 }
59         }
60
61         void removeFriend(String localSoneId, String friendSoneId) {
62                 loadFriends(localSoneId);
63                 lock.writeLock().lock();
64                 try {
65                         if (soneFriends.remove(localSoneId, friendSoneId)) {
66                                 configurationLoader.saveFriends(localSoneId, soneFriends.get(localSoneId));
67                                 boolean unfollowedSoneStillFollowed = false;
68                                 for (String soneId : soneFriends.keys()) {
69                                         unfollowedSoneStillFollowed |= getFriends(soneId).contains(friendSoneId);
70                                 }
71                                 if (!unfollowedSoneStillFollowed) {
72                                         configurationLoader.removeSoneFollowingTime(friendSoneId);
73                                 }
74                         }
75                 } finally {
76                         lock.writeLock().unlock();
77                 }
78         }
79
80         @Nullable
81         Long getFollowingTime(@Nonnull String soneId) {
82                 return configurationLoader.getSoneFollowingTime(soneId);
83         }
84
85         private void loadFriends(String localSoneId) {
86                 lock.writeLock().lock();
87                 try {
88                         if (soneFriends.containsKey(localSoneId)) {
89                                 return;
90                         }
91                         soneFriends.putAll(localSoneId, configurationLoader.loadFriends(localSoneId));
92                 } finally {
93                         lock.writeLock().unlock();
94                 }
95         }
96
97 }