1 package net.pterodactylus.sone.database.memory;
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.HashSet;
8 import java.util.concurrent.locks.ReadWriteLock;
9 import java.util.concurrent.locks.ReentrantReadWriteLock;
11 import net.pterodactylus.sone.data.Post;
12 import net.pterodactylus.sone.database.DatabaseException;
13 import net.pterodactylus.sone.utils.Optionals;
15 import com.google.common.base.Function;
16 import com.google.common.base.Optional;
17 import com.google.common.collect.FluentIterable;
18 import com.google.common.collect.HashMultimap;
19 import com.google.common.collect.Multimap;
22 * Groups {@link Post}-related database functions.
24 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
26 class MemoryPostDatabase {
28 private final ReadWriteLock lock = new ReentrantReadWriteLock();
29 private final MemoryDatabase database;
30 private final ConfigurationLoader configurationLoader;
31 private final Multimap<String, String> sonePosts = HashMultimap.create();
32 private final Map<String, String> postSones = new HashMap<String, String>();
33 private final Map<String, Long> postTimes = new HashMap<String, Long>();
34 private final Map<String, String> postRecipients = new HashMap<String, String>();
35 private final Multimap<String, String> recipientPosts = HashMultimap.create();
36 private final Map<String, String> postTexts = new HashMap<String, String>();
37 private final Set<String> knownPosts = new HashSet<String>();
39 MemoryPostDatabase(MemoryDatabase database, ConfigurationLoader configurationLoader) {
40 this.database = database;
41 this.configurationLoader = configurationLoader;
52 Optional<Post> getPost(String postId) {
53 lock.readLock().lock();
55 if (!postSones.containsKey(postId)) {
56 return Optional.absent();
58 String sender = postSones.get(postId);
59 String recipientId = postRecipients.get(postId);
60 long time = postTimes.get(postId);
61 String text = postTexts.get(postId);
62 return Optional.<Post>of(
63 new MemoryPost(database, database, postId, sender, recipientId, time, text));
65 lock.readLock().unlock();
69 Collection<Post> getPostsFrom(String soneId) {
70 lock.readLock().lock();
72 return FluentIterable.from(sonePosts.get(soneId))
73 .transform(postLoader)
74 .transform(Optionals.<Post>get())
77 lock.readLock().unlock();
81 Collection<Post> getDirectedPosts(String recipientId) {
82 lock.readLock().lock();
84 return FluentIterable.from(recipientPosts.get(recipientId))
85 .transform(postLoader)
86 .transform(Optionals.<Post>get())
89 lock.readLock().unlock();
93 void storePosts(String soneId, Collection<Post> posts) {
94 lock.writeLock().lock();
96 removePostsFor(soneId);
97 for (Post post : posts) {
101 lock.writeLock().unlock();
105 void storePost(Post post) {
106 String soneId = post.getSone().getId();
107 final String postId = post.getId();
108 sonePosts.put(soneId, postId);
109 postSones.put(postId, soneId);
110 postRecipients.put(postId, post.getRecipientId().orNull());
111 if (post.getRecipientId().isPresent()) {
112 recipientPosts.put(post.getRecipientId().get(), postId);
114 postTimes.put(postId, post.getTime());
115 postTexts.put(postId, post.getText());
118 void removePostsFor(String soneId) {
119 lock.writeLock().lock();
121 for (String postId : sonePosts.removeAll(soneId)) {
125 lock.writeLock().unlock();
129 void removePost(String postId) {
130 lock.writeLock().lock();
132 postSones.remove(postId);
133 String recipient = postRecipients.remove(postId);
134 if (recipient != null) {
135 recipientPosts.remove(recipient, postId);
137 postTimes.remove(postId);
138 postTexts.remove(postId);
140 lock.writeLock().unlock();
144 boolean isPostKnown(String postId) {
145 lock.readLock().lock();
147 return knownPosts.contains(postId);
149 lock.readLock().unlock();
153 void setPostKnown(String postId, boolean known) {
154 lock.writeLock().lock();
157 knownPosts.add(postId);
159 knownPosts.remove(postId);
163 lock.writeLock().unlock();
167 private void loadKnownPosts() {
168 Set<String> knownPosts = configurationLoader.loadKnownPosts();
169 lock.writeLock().lock();
171 this.knownPosts.clear();
172 this.knownPosts.addAll(knownPosts);
174 lock.writeLock().unlock();
178 private void saveKnownPosts() {
179 lock.readLock().lock();
181 configurationLoader.saveKnownPosts(knownPosts);
183 lock.readLock().unlock();
187 private Function<String, Optional<Post>> postLoader = new Function<String, Optional<Post>>() {
189 public Optional<Post> apply(String input) {
190 return getPost(input);