1 package net.pterodactylus.sone.core;
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;
7 import java.util.Collection;
9 import net.pterodactylus.sone.data.Post;
10 import net.pterodactylus.sone.data.PostReply;
11 import net.pterodactylus.sone.data.Sone;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Predicate;
15 import com.google.common.collect.FluentIterable;
18 * Compares the contents of two {@link Sone}s and fires events for new and
21 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
23 public class SoneChangeDetector {
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();
31 public SoneChangeDetector(Sone oldSone) {
32 this.oldSone = oldSone;
35 public void onNewPosts(PostProcessor newPostProcessor) {
36 this.newPostProcessor = fromNullable(newPostProcessor);
39 public void onRemovedPosts(PostProcessor removedPostProcessor) {
40 this.removedPostProcessor = fromNullable(removedPostProcessor);
43 public void onNewPostReplies(PostReplyProcessor newPostReplyProcessor) {
44 this.newPostReplyProcessor = fromNullable(newPostReplyProcessor);
47 public void onRemovedPostReplies(
48 PostReplyProcessor removedPostReplyProcessor) {
49 this.removedPostReplyProcessor = fromNullable(removedPostReplyProcessor);
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);
63 private void processPostReplies(FluentIterable<PostReply> postReplies,
64 Optional<PostReplyProcessor> postReplyProcessor) {
65 for (PostReply postReply : postReplies) {
66 notifyPostReplyProcessor(postReplyProcessor, postReply);
70 private void notifyPostReplyProcessor(
71 Optional<PostReplyProcessor> postReplyProcessor,
72 PostReply postReply) {
73 if (postReplyProcessor.isPresent()) {
74 postReplyProcessor.get()
75 .processPostReply(postReply);
79 private void processPosts(FluentIterable<Post> posts,
80 Optional<PostProcessor> newPostProcessor) {
81 for (Post post : posts) {
82 notifyPostProcessor(newPostProcessor, post);
86 private void notifyPostProcessor(Optional<PostProcessor> postProcessor,
88 if (postProcessor.isPresent()) {
89 postProcessor.get().processPost(newPost);
93 private <T> Predicate<T> notContainedIn(final Collection<T> posts) {
94 return new Predicate<T>() {
96 public boolean apply(T element) {
97 return !posts.contains(element);
102 public interface PostProcessor {
104 void processPost(Post post);
108 public interface PostReplyProcessor {
110 void processPostReply(PostReply postReply);