692d7c42ddbac6f2325a79f01f2e5190dee1346c
[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  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
17  */
18 class MemoryFriendDatabase {
19
20         private final ReadWriteLock lock = new ReentrantReadWriteLock();
21         private final ConfigurationLoader configurationLoader;
22         private final Multimap<String, String> soneFriends = HashMultimap.create();
23
24         MemoryFriendDatabase(ConfigurationLoader configurationLoader) {
25                 this.configurationLoader = configurationLoader;
26         }
27
28         Collection<String> getFriends(String localSoneId) {
29                 loadFriends(localSoneId);
30                 lock.readLock().lock();
31                 try {
32                         return soneFriends.get(localSoneId);
33                 } finally {
34                         lock.readLock().unlock();
35                 }
36         }
37
38         boolean isFriend(String localSoneId, String friendSoneId) {
39                 loadFriends(localSoneId);
40                 lock.readLock().lock();
41                 try {
42                         return soneFriends.containsEntry(localSoneId, friendSoneId);
43                 } finally {
44                         lock.readLock().unlock();
45                 }
46         }
47
48         void addFriend(String localSoneId, String friendSoneId) {
49                 loadFriends(localSoneId);
50                 lock.writeLock().lock();
51                 try {
52                         if (soneFriends.put(localSoneId, friendSoneId)) {
53                                 configurationLoader.saveFriends(localSoneId, soneFriends.get(localSoneId));
54                                 if (configurationLoader.getSoneFollowingTime(friendSoneId) == null) {
55                                         configurationLoader.setSoneFollowingTime(friendSoneId, System.currentTimeMillis());
56                                 }
57                         }
58                 } finally {
59                         lock.writeLock().unlock();
60                 }
61         }
62
63         void removeFriend(String localSoneId, String friendSoneId) {
64                 loadFriends(localSoneId);
65                 lock.writeLock().lock();
66                 try {
67                         if (soneFriends.remove(localSoneId, friendSoneId)) {
68                                 configurationLoader.saveFriends(localSoneId, soneFriends.get(localSoneId));
69                                 boolean unfollowedSoneStillFollowed = false;
70                                 for (String soneId : soneFriends.keys()) {
71                                         unfollowedSoneStillFollowed |= getFriends(soneId).contains(friendSoneId);
72                                 }
73                                 if (!unfollowedSoneStillFollowed) {
74                                         configurationLoader.removeSoneFollowingTime(friendSoneId);
75                                 }
76                         }
77                 } finally {
78                         lock.writeLock().unlock();
79                 }
80         }
81
82         @Nullable
83         Long getFollowingTime(@Nonnull String soneId) {
84                 return configurationLoader.getSoneFollowingTime(soneId);
85         }
86
87         private void loadFriends(String localSoneId) {
88                 lock.writeLock().lock();
89                 try {
90                         if (soneFriends.containsKey(localSoneId)) {
91                                 return;
92                         }
93                         soneFriends.putAll(localSoneId, configurationLoader.loadFriends(localSoneId));
94                 } finally {
95                         lock.writeLock().unlock();
96                 }
97         }
98
99 }