+ /**
+ * Returns the list of posts of this Sone, sorted by time, newest first.
+ *
+ * @return All posts of this Sone
+ */
+ public List<Post> getPosts() {
+ List<Post> sortedPosts = new ArrayList<Post>(posts);
+ Collections.sort(sortedPosts, new Comparator<Post>() {
+
+ @Override
+ public int compare(Post leftPost, Post rightPost) {
+ return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, rightPost.getTime() - leftPost.getTime()));
+ }
+
+ });
+ return sortedPosts;
+ }
+
+ /**
+ * Sets all posts of this Sone at once.
+ *
+ * @param posts
+ * The new (and only) posts of this Sone
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone setPosts(Collection<Post> posts) {
+ this.posts.clear();
+ this.posts.addAll(posts);
+ modificationCounter++;
+ return this;
+ }
+
+ /**
+ * Adds the given post to this Sone. The post will not be added if its
+ * {@link Post#getSone() Sone} is not this Sone.
+ *
+ * @param post
+ * The post to add
+ */
+ public synchronized void addPost(Post post) {
+ if (post.getSone().equals(this) && posts.add(post)) {
+ logger.log(Level.FINEST, "Adding %s to “%s”.", new Object[] { post, getName() });
+ modificationCounter++;
+ }
+ }
+
+ /**
+ * Removes the given post from this Sone.
+ *
+ * @param post
+ * The post to remove
+ */
+ public synchronized void removePost(Post post) {
+ if (post.getSone().equals(this) && posts.remove(post)) {
+ modificationCounter++;
+ }
+ }
+
+ /**
+ * Returns all replies this Sone made.
+ *
+ * @return All replies this Sone made
+ */
+ public Set<Reply> getReplies() {
+ logger.log(Level.FINEST, "Friends of %s: %s", new Object[] { this, friendSones });
+ return Collections.unmodifiableSet(replies);
+ }
+
+ /**
+ * Sets all replies of this Sone at once.
+ *
+ * @param replies
+ * The new (and only) replies of this Sone
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone setReplies(Collection<Reply> replies) {
+ this.replies.clear();
+ this.replies.addAll(replies);
+ modificationCounter++;
+ return this;
+ }
+
+ /**
+ * Adds a reply to this Sone. If the given reply was not made by this Sone,
+ * nothing is added to this Sone.
+ *
+ * @param reply
+ * The reply to add
+ */
+ public synchronized void addReply(Reply reply) {
+ if (reply.getSone().equals(this) && replies.add(reply)) {
+ modificationCounter++;
+ }
+ }
+
+ /**
+ * Removes a reply from this Sone.
+ *
+ * @param reply
+ * The reply to remove
+ */
+ public synchronized void removeReply(Reply reply) {
+ if (reply.getSone().equals(this) && replies.remove(reply)) {
+ modificationCounter++;
+ }
+ }
+
+ /**
+ * Returns the IDs of all blocked Sones. These Sones will not propagated
+ * using the “known Sones” mechanism.
+ *
+ * @return The IDs of all blocked Sones
+ */
+ public Set<String> getBlockedSoneIds() {
+ return Collections.unmodifiableSet(blockedSoneIds);
+ }
+
+ /**
+ * Returns whether the given Sone ID is blocked.
+ *
+ * @param soneId
+ * The Sone ID to check
+ * @return {@code true} if the given Sone ID is blocked, {@code false}
+ * otherwise
+ */
+ public boolean isSoneBlocked(String soneId) {
+ return blockedSoneIds.contains(soneId);
+ }
+
+ /**
+ * Adds the given ID to the list of blocked IDs.
+ *
+ * @param soneId
+ * The Sone ID to block
+ */
+ public synchronized void addBlockedSoneId(String soneId) {
+ if (blockedSoneIds.add(soneId)) {
+ modificationCounter++;
+ }
+ }
+
+ /**
+ * Removes the given ID from the list of blocked IDs.
+ *
+ * @param soneId
+ * The Sone ID to unblock
+ */
+ public synchronized void removeBlockedSoneId(String soneId) {
+ if (blockedSoneIds.remove(soneId)) {
+ modificationCounter++;
+ }
+ }
+
+ /**
+ * Returns the IDs of all liked posts.
+ *
+ * @return All liked posts’ IDs
+ */
+ public Set<String> getLikedPostIds() {
+ return Collections.unmodifiableSet(likedPostIds);
+ }
+
+ /**
+ * Sets the IDs of all liked posts.
+ *
+ * @param likedPostIds
+ * All liked posts’ IDs
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone setLikePostIds(Set<String> likedPostIds) {
+ this.likedPostIds.clear();
+ this.likedPostIds.addAll(likedPostIds);
+ modificationCounter++;
+ return this;
+ }
+
+ /**
+ * Checks whether the given post ID is liked by this Sone.
+ *
+ * @param postId
+ * The ID of the post
+ * @return {@code true} if this Sone likes the given post, {@code false}
+ * otherwise
+ */
+ public boolean isLikedPostId(String postId) {
+ return likedPostIds.contains(postId);
+ }
+
+ /**
+ * Adds the given post ID to the list of posts this Sone likes.
+ *
+ * @param postId
+ * The ID of the post
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone addLikedPostId(String postId) {
+ if (likedPostIds.add(postId)) {
+ modificationCounter++;
+ }
+ return this;
+ }
+
+ /**
+ * Removes the given post ID from the list of posts this Sone likes.
+ *
+ * @param postId
+ * The ID of the post
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone removeLikedPostId(String postId) {
+ if (likedPostIds.remove(postId)) {
+ modificationCounter++;
+ }
+ return this;
+ }
+
+ /**
+ * Returns the IDs of all liked replies.
+ *
+ * @return All liked replies’ IDs
+ */
+ public Set<String> getLikedReplyIds() {
+ return Collections.unmodifiableSet(likedReplyIds);
+ }
+
+ /**
+ * Sets the IDs of all liked replies.
+ *
+ * @param likedReplyIds
+ * All liked replies’ IDs
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone setLikeReplyIds(Set<String> likedReplyIds) {
+ this.likedReplyIds.clear();
+ this.likedReplyIds.addAll(likedReplyIds);
+ modificationCounter++;
+ return this;
+ }
+
+ /**
+ * Checks whether the given reply ID is liked by this Sone.
+ *
+ * @param replyId
+ * The ID of the reply
+ * @return {@code true} if this Sone likes the given reply, {@code false}
+ * otherwise
+ */
+ public boolean isLikedReplyId(String replyId) {
+ return likedReplyIds.contains(replyId);
+ }
+
+ /**
+ * Adds the given reply ID to the list of replies this Sone likes.
+ *
+ * @param replyId
+ * The ID of the reply
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone addLikedReplyId(String replyId) {
+ if (likedReplyIds.add(replyId)) {
+ modificationCounter++;
+ }
+ return this;
+ }
+
+ /**
+ * Removes the given post ID from the list of replies this Sone likes.
+ *
+ * @param replyId
+ * The ID of the reply
+ * @return This Sone (for method chaining)
+ */
+ public synchronized Sone removeLikedReplyId(String replyId) {
+ if (likedReplyIds.remove(replyId)) {
+ modificationCounter++;
+ }
+ return this;
+ }
+
+ /**
+ * Returns the modification counter.
+ *
+ * @return The modification counter
+ */
+ public synchronized long getModificationCounter() {
+ return modificationCounter;
+ }
+
+ /**
+ * Sets the modification counter.
+ *
+ * @param modificationCounter
+ * The new modification counter
+ */
+ public synchronized void setModificationCounter(long modificationCounter) {
+ this.modificationCounter = modificationCounter;
+ }
+
+ /**
+ * Updates the suggested edition in both the request URI and the insert URI.
+ *
+ * @param latestEdition
+ * The latest edition to update the URIs to
+ */
+ public void updateUris(long latestEdition) {
+ if ((requestUri != null) && (requestUri.getEdition() < latestEdition)) {
+ requestUri = requestUri.setSuggestedEdition(latestEdition);
+ }
+ if ((insertUri != null) && (insertUri.getEdition() < latestEdition)) {
+ insertUri = insertUri.setSuggestedEdition(latestEdition);
+ }
+ }
+
+ //
+ // PRIVATE METHODS
+ //
+
+ /**
+ * Updates the editions of the request URI and the insert URI (if latter is
+ * not {@code null}) with the greater edition of either one.
+ */
+ private void updateEditions() {
+ long requestEdition = 0;
+ if (requestUri != null) {
+ requestEdition = requestUri.getEdition();
+ }
+ long insertEdition = 0;
+ if (insertUri != null) {
+ insertEdition = insertUri.getEdition();
+ }
+ updateUris(Math.max(requestEdition, insertEdition));
+ }
+