+ /**
+ * Returns whether the given Sone is a local Sone.
+ *
+ * @param sone
+ * The Sone to check for its locality
+ * @return {@code true} if the given Sone is local, {@code false} otherwise
+ */
+ public boolean isLocalSone(Sone sone) {
+ synchronized (localSones) {
+ return localSones.containsKey(sone.getId());
+ }
+ }
+
+ /**
+ * Returns all local Sones.
+ *
+ * @return All local Sones
+ */
+ public Set<Sone> getLocalSones() {
+ synchronized (localSones) {
+ return new HashSet<Sone>(localSones.values());
+ }
+ }
+
+ /**
+ * Returns the local Sone with the given ID.
+ *
+ * @param id
+ * The ID of the Sone to get
+ * @return The Sone, or {@code null} if there is no Sone with the given ID
+ */
+ public Sone getLocalSone(String id) {
+ synchronized (localSones) {
+ return localSones.get(id);
+ }
+ }
+
+ /**
+ * Returns all remote Sones.
+ *
+ * @return All remote Sones
+ */
+ public Set<Sone> getRemoteSones() {
+ synchronized (remoteSones) {
+ return new HashSet<Sone>(remoteSones.values());
+ }
+ }
+
+ /**
+ * Returns the remote Sone with the given ID.
+ *
+ * @param id
+ * The ID of the remote Sone to get
+ * @return The Sone, or {@code null} if there is no such Sone
+ */
+ public Sone getRemoteSone(String id) {
+ synchronized (remoteSones) {
+ return remoteSones.get(id);
+ }
+ }
+
+ /**
+ * Returns whether the given Sone is a remote Sone.
+ *
+ * @param sone
+ * The Sone to check
+ * @return {@code true} if the given Sone is a remote Sone, {@code false}
+ * otherwise
+ */
+ public boolean isRemoteSone(Sone sone) {
+ synchronized (remoteSones) {
+ return remoteSones.containsKey(sone.getId());
+ }
+ }
+
+ /**
+ * Returns the post with the given ID.
+ *
+ * @param postId
+ * The ID of the post to get
+ * @return The post, or {@code null} if there is no such post
+ */
+ public Post getPost(String postId) {
+ synchronized (posts) {
+ return posts.get(postId);
+ }
+ }
+
+ /**
+ * Returns the reply with the given ID.
+ *
+ * @param replyId
+ * The ID of the reply to get
+ * @return The reply, or {@code null} if there is no such reply
+ */
+ public Reply getReply(String replyId) {
+ synchronized (replies) {
+ return replies.get(replyId);
+ }
+ }
+
+ /**
+ * Returns all replies for the given post, order ascending by time.
+ *
+ * @param post
+ * The post to get all replies for
+ * @return All replies for the given post
+ */
+ public List<Reply> getReplies(Post post) {
+ Set<Sone> sones = getSones();
+ List<Reply> replies = new ArrayList<Reply>();
+ for (Sone sone : sones) {
+ for (Reply reply : sone.getReplies()) {
+ if (reply.getPost().equals(post)) {
+ replies.add(reply);
+ }
+ }
+ }
+ Collections.sort(replies, Reply.TIME_COMPARATOR);
+ return replies;
+ }
+
+ /**
+ * Returns all Sones that have liked the given post.
+ *
+ * @param post
+ * The post to get the liking Sones for
+ * @return The Sones that like the given post
+ */
+ public Set<Sone> getLikes(Post post) {
+ Set<Sone> sones = new HashSet<Sone>();
+ for (Sone sone : getSones()) {
+ if (sone.getLikedPostIds().contains(post.getId())) {
+ sones.add(sone);
+ }
+ }
+ return sones;
+ }
+
+ /**
+ * Returns all Sones that have liked the given reply.
+ *
+ * @param reply
+ * The reply to get the liking Sones for
+ * @return The Sones that like the given reply
+ */
+ public Set<Sone> getLikes(Reply reply) {
+ Set<Sone> sones = new HashSet<Sone>();
+ for (Sone sone : getSones()) {
+ if (sone.getLikedPostIds().contains(reply.getId())) {
+ sones.add(sone);
+ }
+ }
+ return sones;
+ }
+