+ for (Part part : soneTextParser.parse(null, new StringReader(text))) {
+ if (part instanceof SonePart) {
+ mentionedSones.add(((SonePart) part).getSone());
+ }
+ }
+ } catch (IOException ioe1) {
+ logger.log(Level.WARNING, String.format("Could not parse post text: %s", text), ioe1);
+ }
+ return Collections2.filter(mentionedSones, Sone.LOCAL_SONE_FILTER);
+ }
+
+ /**
+ * Returns the Sone insert notification for the given Sone. If no
+ * notification for the given Sone exists, a new notification is created and
+ * cached.
+ *
+ * @param sone
+ * The Sone to get the insert notification for
+ * @return The Sone insert notification
+ */
+ private TemplateNotification getSoneInsertNotification(Sone sone) {
+ synchronized (soneInsertNotifications) {
+ TemplateNotification templateNotification = soneInsertNotifications.get(sone);
+ if (templateNotification == null) {
+ templateNotification = new TemplateNotification(parseTemplate("/templates/notify/soneInsertNotification.html"));
+ templateNotification.set("insertSone", sone);
+ soneInsertNotifications.put(sone, templateNotification);
+ }
+ return templateNotification;
+ }
+ }
+
+ private boolean localSoneMentionedInNewPostOrReply(Post post) {
+ if (!post.getSone().isLocal()) {
+ if (!getMentionedSones(post.getText()).isEmpty() && !post.isKnown()) {
+ return true;
+ }
+ }
+ for (PostReply postReply : getCore().getReplies(post.getId())) {
+ if (postReply.getSone().isLocal()) {
+ continue;
+ }
+ if (!getMentionedSones(postReply.getText()).isEmpty() && !postReply.isKnown()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //
+ // EVENT HANDLERS
+ //
+
+ /**
+ * Notifies the web interface that a new {@link Sone} was found.
+ *
+ * @param newSoneFoundEvent
+ * The event
+ */
+ @Subscribe
+ public void newSoneFound(NewSoneFoundEvent newSoneFoundEvent) {
+ newSoneNotification.add(newSoneFoundEvent.sone());
+ if (!hasFirstStartNotification()) {
+ notificationManager.addNotification(newSoneNotification);
+ }
+ }
+
+ /**
+ * Notifies the web interface that a new {@link Post} was found.
+ *
+ * @param newPostFoundEvent
+ * The event
+ */
+ @Subscribe
+ public void newPostFound(NewPostFoundEvent newPostFoundEvent) {
+ Post post = newPostFoundEvent.post();
+ boolean isLocal = post.getSone().isLocal();
+ if (isLocal) {
+ localPostNotification.add(post);
+ } else {
+ newPostNotification.add(post);
+ }
+ if (!hasFirstStartNotification()) {
+ notificationManager.addNotification(isLocal ? localPostNotification : newPostNotification);
+ if (!getMentionedSones(post.getText()).isEmpty() && !isLocal) {
+ mentionNotification.add(post);
+ notificationManager.addNotification(mentionNotification);
+ }
+ } else {
+ getCore().markPostKnown(post);
+ }
+ }
+
+ /**
+ * Notifies the web interface that a new {@link PostReply} was found.
+ *
+ * @param newPostReplyFoundEvent
+ * The event
+ */
+ @Subscribe
+ public void newReplyFound(NewPostReplyFoundEvent newPostReplyFoundEvent) {
+ PostReply reply = newPostReplyFoundEvent.postReply();
+ boolean isLocal = reply.getSone().isLocal();
+ if (isLocal) {
+ localReplyNotification.add(reply);
+ } else {
+ newReplyNotification.add(reply);
+ }
+ if (!hasFirstStartNotification()) {
+ notificationManager.addNotification(isLocal ? localReplyNotification : newReplyNotification);
+ if (reply.getPost().isPresent() && localSoneMentionedInNewPostOrReply(reply.getPost().get())) {
+ mentionNotification.add(reply.getPost().get());
+ notificationManager.addNotification(mentionNotification);
+ }
+ } else {
+ getCore().markReplyKnown(reply);
+ }
+ }
+
+ /**
+ * Notifies the web interface that a {@link Sone} was marked as known.
+ *
+ * @param markSoneKnownEvent
+ * The event
+ */
+ @Subscribe
+ public void markSoneKnown(MarkSoneKnownEvent markSoneKnownEvent) {
+ newSoneNotification.remove(markSoneKnownEvent.sone());
+ }
+
+ /**
+ * Notifies the web interface that a {@link Post} was marked as known.
+ *
+ * @param markPostKnownEvent
+ * The event
+ */
+ @Subscribe
+ public void markPostKnown(MarkPostKnownEvent markPostKnownEvent) {
+ newPostNotification.remove(markPostKnownEvent.post());
+ localPostNotification.remove(markPostKnownEvent.post());
+ if (!localSoneMentionedInNewPostOrReply(markPostKnownEvent.post())) {
+ mentionNotification.remove(markPostKnownEvent.post());
+ }
+ }
+
+ /**
+ * Notifies the web interface that a {@link PostReply} was marked as known.
+ *
+ * @param markPostReplyKnownEvent
+ * The event
+ */
+ @Subscribe
+ public void markReplyKnown(MarkPostReplyKnownEvent markPostReplyKnownEvent) {
+ PostReply postReply = markPostReplyKnownEvent.postReply();
+ newReplyNotification.remove(postReply);
+ localReplyNotification.remove(postReply);
+ if (postReply.getPost().isPresent() && !localSoneMentionedInNewPostOrReply(postReply.getPost().get())) {
+ mentionNotification.remove(postReply.getPost().get());
+ }
+ }
+
+ /**
+ * Notifies the web interface that a {@link Sone} was removed.
+ *
+ * @param soneRemovedEvent
+ * The event
+ */
+ @Subscribe
+ public void soneRemoved(SoneRemovedEvent soneRemovedEvent) {
+ newSoneNotification.remove(soneRemovedEvent.sone());
+ }
+
+ /**
+ * Notifies the web interface that a {@link Post} was removed.
+ *
+ * @param postRemovedEvent
+ * The event
+ */
+ @Subscribe
+ public void postRemoved(PostRemovedEvent postRemovedEvent) {
+ newPostNotification.remove(postRemovedEvent.post());
+ localPostNotification.remove(postRemovedEvent.post());
+ if (!localSoneMentionedInNewPostOrReply(postRemovedEvent.post())) {
+ mentionNotification.remove(postRemovedEvent.post());
+ }
+ }
+
+ /**
+ * Notifies the web interface that a {@link PostReply} was removed.
+ *
+ * @param postReplyRemovedEvent
+ * The event
+ */
+ @Subscribe
+ public void replyRemoved(PostReplyRemovedEvent postReplyRemovedEvent) {
+ PostReply reply = postReplyRemovedEvent.postReply();
+ newReplyNotification.remove(reply);
+ localReplyNotification.remove(reply);
+ if (reply.getPost().isPresent() && !localSoneMentionedInNewPostOrReply(reply.getPost().get())) {
+ mentionNotification.remove(reply.getPost().get());
+ }
+ }
+
+ /**
+ * Notifies the web interface that a Sone was locked.
+ *
+ * @param soneLockedEvent
+ * The event
+ */
+ @Subscribe
+ public void soneLocked(SoneLockedEvent soneLockedEvent) {
+ final Sone sone = soneLockedEvent.sone();
+ ScheduledFuture<?> tickerObject = ticker.schedule(new Runnable() {
+
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void run() {
+ lockedSonesNotification.add(sone);
+ notificationManager.addNotification(lockedSonesNotification);
+ }
+ }, 5, TimeUnit.MINUTES);
+ lockedSonesTickerObjects.put(sone, tickerObject);
+ }
+
+ /**
+ * Notifies the web interface that a Sone was unlocked.
+ *
+ * @param soneUnlockedEvent
+ * The event
+ */
+ @Subscribe
+ public void soneUnlocked(SoneUnlockedEvent soneUnlockedEvent) {
+ lockedSonesNotification.remove(soneUnlockedEvent.sone());
+ lockedSonesTickerObjects.remove(soneUnlockedEvent.sone()).cancel(false);
+ }
+
+ /**
+ * Notifies the web interface that a {@link Sone} is being inserted.
+ *
+ * @param soneInsertingEvent
+ * The event
+ */
+ @Subscribe
+ public void soneInserting(SoneInsertingEvent soneInsertingEvent) {
+ TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertingEvent.sone());
+ soneInsertNotification.set("soneStatus", "inserting");
+ if (soneInsertingEvent.sone().getOptions().getBooleanOption("EnableSoneInsertNotifications").get()) {
+ notificationManager.addNotification(soneInsertNotification);