2 * Sone - ListNotificationFilters.java - Copyright © 2010–2013 David Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sone.notify;
20 import static com.google.common.base.Preconditions.checkNotNull;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.List;
26 import net.pterodactylus.sone.data.Post;
27 import net.pterodactylus.sone.data.PostReply;
28 import net.pterodactylus.sone.data.Reply;
29 import net.pterodactylus.sone.data.Sone;
30 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
31 import net.pterodactylus.sone.freenet.wot.Trust;
32 import net.pterodactylus.util.notify.Notification;
34 import com.google.common.base.Optional;
37 * Filter for {@link ListNotification}s.
39 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
41 public class ListNotificationFilters {
44 * Filters new-post and new-reply notifications in the given list of
45 * notifications. If {@code currentSone} is <code>null</code>, new-post and
46 * new-reply notifications are removed completely. If {@code currentSone} is
47 * not {@code null}, only posts that are posted by a friend Sone or the Sone
48 * itself, and replies that are replies to posts of friend Sones or the Sone
49 * itself will be retained in the notifications.
51 * @param notifications
52 * The notifications to filter
54 * The current Sone, or {@code null} if not logged in
55 * @return The filtered notifications
57 @SuppressWarnings("unchecked")
58 public static List<Notification> filterNotifications(Collection<? extends Notification> notifications, Sone currentSone) {
59 List<Notification> filteredNotifications = new ArrayList<Notification>();
60 for (Notification notification : notifications) {
61 if (notification.getId().equals("new-sone-notification")) {
62 if ((currentSone != null) && (!currentSone.getOptions().getBooleanOption("ShowNotification/NewSones").get())) {
65 filteredNotifications.add(notification);
66 } else if (notification.getId().equals("new-post-notification")) {
67 if ((currentSone != null) && (!currentSone.getOptions().getBooleanOption("ShowNotification/NewPosts").get())) {
70 ListNotification<Post> filteredNotification = filterNewPostNotification((ListNotification<Post>) notification, currentSone, true);
71 if (filteredNotification != null) {
72 filteredNotifications.add(filteredNotification);
74 } else if (notification.getId().equals("new-reply-notification")) {
75 if ((currentSone != null) && (!currentSone.getOptions().getBooleanOption("ShowNotification/NewReplies").get())) {
78 ListNotification<PostReply> filteredNotification = filterNewReplyNotification((ListNotification<PostReply>) notification, currentSone);
79 if (filteredNotification != null) {
80 filteredNotifications.add(filteredNotification);
82 } else if (notification.getId().equals("mention-notification")) {
83 ListNotification<Post> filteredNotification = filterNewPostNotification((ListNotification<Post>) notification, null, false);
84 if (filteredNotification != null) {
85 filteredNotifications.add(filteredNotification);
88 filteredNotifications.add(notification);
91 return filteredNotifications;
95 * Filters the new posts of the given notification. If {@code currentSone}
96 * is {@code null} and {@code soneRequired} is {@code true}, {@code null} is
97 * returned and the notification is subsequently removed. Otherwise only
98 * posts that are posted by friend Sones of the given Sone are retained; all
99 * other posts are removed.
101 * @param newPostNotification
102 * The new-post notification
104 * The current Sone, or {@code null} if not logged in
105 * @param soneRequired
106 * Whether a non-{@code null} Sone in {@code currentSone} is
108 * @return The filtered new-post notification, or {@code null} if the
109 * notification should be removed
111 public static ListNotification<Post> filterNewPostNotification(ListNotification<Post> newPostNotification, Sone currentSone, boolean soneRequired) {
112 if (soneRequired && (currentSone == null)) {
115 List<Post> newPosts = new ArrayList<Post>();
116 for (Post post : newPostNotification.getElements()) {
117 if (isPostVisible(currentSone, post)) {
121 if (newPosts.isEmpty()) {
124 if (newPosts.size() == newPostNotification.getElements().size()) {
125 return newPostNotification;
127 ListNotification<Post> filteredNotification = new ListNotification<Post>(newPostNotification);
128 filteredNotification.setElements(newPosts);
129 filteredNotification.setLastUpdateTime(newPostNotification.getLastUpdatedTime());
130 return filteredNotification;
134 * Filters the new replies of the given notification. If {@code currentSone}
135 * is {@code null}, {@code null} is returned and the notification is
136 * subsequently removed. Otherwise only replies that are replies to posts
137 * that are posted by friend Sones of the given Sone are retained; all other
138 * replies are removed.
140 * @param newReplyNotification
141 * The new-reply notification
143 * The current Sone, or {@code null} if not logged in
144 * @return The filtered new-reply notification, or {@code null} if the
145 * notification should be removed
147 public static ListNotification<PostReply> filterNewReplyNotification(ListNotification<PostReply> newReplyNotification, Sone currentSone) {
148 if (currentSone == null) {
151 List<PostReply> newReplies = new ArrayList<PostReply>();
152 for (PostReply reply : newReplyNotification.getElements()) {
153 if (isReplyVisible(currentSone, reply)) {
154 newReplies.add(reply);
157 if (newReplies.isEmpty()) {
160 if (newReplies.size() == newReplyNotification.getElements().size()) {
161 return newReplyNotification;
163 ListNotification<PostReply> filteredNotification = new ListNotification<PostReply>(newReplyNotification);
164 filteredNotification.setElements(newReplies);
165 filteredNotification.setLastUpdateTime(newReplyNotification.getLastUpdatedTime());
166 return filteredNotification;
170 * Filters the given posts, using {@link #isPostVisible(Sone, Post)} to
171 * decide whether a post should be contained in the returned list. If
172 * {@code currentSone} is not {@code null} it is used to filter out posts
173 * that are from Sones that are not followed or not trusted by the given
177 * The posts to filter
179 * The current Sone (may be {@code null})
180 * @return The filtered posts
182 public static List<Post> filterPosts(Collection<Post> posts, Sone currentSone) {
183 List<Post> filteredPosts = new ArrayList<Post>();
184 for (Post post : posts) {
185 if (isPostVisible(currentSone, post)) {
186 filteredPosts.add(post);
189 return filteredPosts;
193 * Checks whether a post is visible to the given Sone. A post is not
194 * considered visible if one of the following statements is true:
196 * <li>The post does not have a Sone.</li>
197 * <li>The post’s {@link Post#getTime() time} is in the future.</li>
200 * If {@code post} is not {@code null} more checks are performed, and the
201 * post will be invisible if:
204 * <li>The Sone of the post is not the given Sone, the given Sone does not
205 * follow the post’s Sone, and the given Sone is not the recipient of the
207 * <li>The trust relationship between the two Sones can not be retrieved.</li>
208 * <li>The given Sone has explicitely assigned negative trust to the post’s
210 * <li>The given Sone has not explicitely assigned negative trust to the
211 * post’s Sone but the implicit trust is negative.</li>
213 * If none of these statements is true the post is considered visible.
216 * The Sone that checks for a post’s visibility (may be
217 * {@code null} to skip Sone-specific checks, such as trust)
219 * The post to check for visibility
220 * @return {@code true} if the post is considered visible, {@code false}
223 public static boolean isPostVisible(Sone sone, Post post) {
224 checkNotNull(post, "post must not be null");
225 Sone postSone = post.getSone();
226 if (postSone == null) {
230 Trust trust = postSone.getIdentity().getTrust((OwnIdentity) sone.getIdentity());
232 if ((trust.getExplicit() != null) && (trust.getExplicit() < 0)) {
235 if ((trust.getExplicit() == null) && (trust.getImplicit() != null) && (trust.getImplicit() < 0)) {
240 * a null trust means that the trust updater has not yet
241 * received a trust value for this relation. if we return false,
242 * the post feed will stay empty until the trust updater has
243 * received trust values. to prevent this we simply assume that
244 * posts are visible if there is no trust.
247 if ((!postSone.equals(sone)) && !sone.hasFriend(postSone.getId()) && !sone.getId().equals(post.getRecipientId().orNull())) {
251 if (post.getTime() > System.currentTimeMillis()) {
258 * Checks whether a reply is visible to the given Sone. A reply is not
259 * considered visible if one of the following statements is true:
261 * <li>The reply does not have a post.</li>
262 * <li>The reply’s post does not have a Sone.</li>
263 * <li>The Sone of the reply’s post is not the given Sone, the given Sone
264 * does not follow the reply’s post’s Sone, and the given Sone is not the
265 * recipient of the reply’s post.</li>
266 * <li>The trust relationship between the two Sones can not be retrieved.</li>
267 * <li>The given Sone has explicitely assigned negative trust to the post’s
269 * <li>The given Sone has not explicitely assigned negative trust to the
270 * reply’s post’s Sone but the implicit trust is negative.</li>
271 * <li>The reply’s post’s {@link Post#getTime() time} is in the future.</li>
272 * <li>The reply’s {@link Reply#getTime() time} is in the future.</li>
274 * If none of these statements is true the reply is considered visible.
277 * The Sone that checks for a post’s visibility (may be
278 * {@code null} to skip Sone-specific checks, such as trust)
280 * The reply to check for visibility
281 * @return {@code true} if the reply is considered visible, {@code false}
284 public static boolean isReplyVisible(Sone sone, PostReply reply) {
285 checkNotNull(reply, "reply must not be null");
286 Optional<Post> post = reply.getPost();
287 if (!post.isPresent()) {
290 if (!isPostVisible(sone, post.get())) {
293 if (reply.getTime() > System.currentTimeMillis()) {