Use database to return friends of a Sone.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / SoneChangeDetector.java
1 package net.pterodactylus.sone.core;
2
3 import static com.google.common.base.Optional.absent;
4 import static com.google.common.base.Optional.fromNullable;
5 import static com.google.common.collect.FluentIterable.from;
6
7 import java.util.Collection;
8
9 import net.pterodactylus.sone.data.Post;
10 import net.pterodactylus.sone.data.PostReply;
11 import net.pterodactylus.sone.data.Sone;
12
13 import com.google.common.base.Optional;
14 import com.google.common.base.Predicate;
15 import com.google.common.collect.FluentIterable;
16
17 /**
18  * Compares the contents of two {@link Sone}s and fires events for new and
19  * removed elements.
20  *
21  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
22  */
23 public class SoneChangeDetector {
24
25         private final Sone oldSone;
26         private Optional<PostProcessor> newPostProcessor = absent();
27         private Optional<PostProcessor> removedPostProcessor = absent();
28         private Optional<PostReplyProcessor> newPostReplyProcessor = absent();
29         private Optional<PostReplyProcessor> removedPostReplyProcessor = absent();
30
31         public SoneChangeDetector(Sone oldSone) {
32                 this.oldSone = oldSone;
33         }
34
35         public void onNewPosts(PostProcessor newPostProcessor) {
36                 this.newPostProcessor = fromNullable(newPostProcessor);
37         }
38
39         public void onRemovedPosts(PostProcessor removedPostProcessor) {
40                 this.removedPostProcessor = fromNullable(removedPostProcessor);
41         }
42
43         public void onNewPostReplies(PostReplyProcessor newPostReplyProcessor) {
44                 this.newPostReplyProcessor = fromNullable(newPostReplyProcessor);
45         }
46
47         public void onRemovedPostReplies(
48                         PostReplyProcessor removedPostReplyProcessor) {
49                 this.removedPostReplyProcessor = fromNullable(removedPostReplyProcessor);
50         }
51
52         public void detectChanges(Sone newSone) {
53                 processPosts(from(newSone.getPosts()).filter(
54                                 notContainedIn(oldSone.getPosts())), newPostProcessor);
55                 processPosts(from(oldSone.getPosts()).filter(
56                                 notContainedIn(newSone.getPosts())), removedPostProcessor);
57                 processPostReplies(from(newSone.getReplies()).filter(
58                                 notContainedIn(oldSone.getReplies())), newPostReplyProcessor);
59                 processPostReplies(from(oldSone.getReplies()).filter(
60                                 notContainedIn(newSone.getReplies())), removedPostReplyProcessor);
61         }
62
63         private void processPostReplies(FluentIterable<PostReply> postReplies,
64                         Optional<PostReplyProcessor> postReplyProcessor) {
65                 for (PostReply postReply : postReplies) {
66                         notifyPostReplyProcessor(postReplyProcessor, postReply);
67                 }
68         }
69
70         private void notifyPostReplyProcessor(
71                         Optional<PostReplyProcessor> postReplyProcessor,
72                         PostReply postReply) {
73                 if (postReplyProcessor.isPresent()) {
74                         postReplyProcessor.get()
75                                         .processPostReply(postReply);
76                 }
77         }
78
79         private void processPosts(FluentIterable<Post> posts,
80                         Optional<PostProcessor> newPostProcessor) {
81                 for (Post post : posts) {
82                         notifyPostProcessor(newPostProcessor, post);
83                 }
84         }
85
86         private void notifyPostProcessor(Optional<PostProcessor> postProcessor,
87                         Post newPost) {
88                 if (postProcessor.isPresent()) {
89                         postProcessor.get().processPost(newPost);
90                 }
91         }
92
93         private <T> Predicate<T> notContainedIn(final Collection<T> posts) {
94                 return new Predicate<T>() {
95                         @Override
96                         public boolean apply(T element) {
97                                 return !posts.contains(element);
98                         }
99                 };
100         }
101
102         public interface PostProcessor {
103
104                 void processPost(Post post);
105
106         }
107
108         public interface PostReplyProcessor {
109
110                 void processPostReply(PostReply postReply);
111
112         }
113
114 }