X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fdata%2Fimpl%2FSoneImpl.java;h=f2f2ea620ba161af8a45e924ea1b0539a2cd9c1f;hp=b8953044e402a22900acf4dfacd8d1ab548305e9;hb=64740709990291688170ebd1f192af5eb9090618;hpb=0180e9f4ebbafc2846dec7727faf571e221a0b92 diff --git a/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java b/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java index b895304..f2f2ea6 100644 --- a/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java +++ b/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java @@ -1,5 +1,5 @@ /* - * Sone - SoneImpl.java - Copyright © 2010–2013 David Roden + * Sone - SoneImpl.java - Copyright © 2010–2020 David Roden * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,11 @@ package net.pterodactylus.sone.data.impl; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.logging.Logger.getLogger; +import static net.pterodactylus.sone.data.PostKt.newestPostFirst; +import static net.pterodactylus.sone.data.ReplyKt.newestReplyFirst; +import static net.pterodactylus.sone.data.SoneKt.*; import java.net.MalformedURLException; import java.util.ArrayList; @@ -31,17 +35,20 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import net.pterodactylus.sone.data.Album; +import net.pterodactylus.sone.data.AlbumKt; import net.pterodactylus.sone.data.Client; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.PostReply; import net.pterodactylus.sone.data.Profile; -import net.pterodactylus.sone.data.Reply; import net.pterodactylus.sone.data.Sone; import net.pterodactylus.sone.data.SoneOptions; import net.pterodactylus.sone.data.SoneOptions.DefaultSoneOptions; +import net.pterodactylus.sone.database.Database; import net.pterodactylus.sone.freenet.wot.Identity; -import net.pterodactylus.sone.freenet.wot.OwnIdentity; import freenet.keys.FreenetURI; @@ -52,13 +59,14 @@ import com.google.common.hash.Hashing; * {@link Sone} implementation. *

* Operations that modify the Sone need to synchronize on the Sone in question. - * - * @author David ‘Bombe’ Roden */ public class SoneImpl implements Sone { /** The logger. */ - private static final Logger logger = getLogger("Sone.Data"); + private static final Logger logger = getLogger(SoneImpl.class.getName()); + + /** The database. */ + private final Database database; /** The ID of this Sone. */ private final String id; @@ -87,20 +95,17 @@ public class SoneImpl implements Sone { /** Whether this Sone is known. */ private volatile boolean known; - /** All friend Sones. */ - private final Set friendSones = new CopyOnWriteArraySet(); - /** All posts. */ - private final Set posts = new CopyOnWriteArraySet(); + private final Set posts = new CopyOnWriteArraySet<>(); /** All replies. */ - private final Set replies = new CopyOnWriteArraySet(); + private final Set replies = new CopyOnWriteArraySet<>(); /** The IDs of all liked posts. */ - private final Set likedPostIds = new CopyOnWriteArraySet(); + private final Set likedPostIds = new CopyOnWriteArraySet<>(); /** The IDs of all liked replies. */ - private final Set likedReplyIds = new CopyOnWriteArraySet(); + private final Set likedReplyIds = new CopyOnWriteArraySet<>(); /** The root album containing all albums. */ private final Album rootAlbum = new AlbumImpl(this); @@ -111,12 +116,14 @@ public class SoneImpl implements Sone { /** * Creates a new Sone. * + * @param database The database * @param identity * The identity of the Sone * @param local * {@code true} if the Sone is a local Sone, {@code false} otherwise */ - public SoneImpl(Identity identity, boolean local) { + public SoneImpl(Database database, Identity identity, boolean local) { + this.database = database; this.id = identity.getId(); this.identity = identity; this.local = local; @@ -131,6 +138,7 @@ public class SoneImpl implements Sone { * * @return The identity of this Sone */ + @Nonnull public String getId() { return id; } @@ -140,6 +148,7 @@ public class SoneImpl implements Sone { * * @return The identity of this Sone */ + @Nonnull public Identity getIdentity() { return identity; } @@ -149,6 +158,7 @@ public class SoneImpl implements Sone { * * @return The name of this Sone */ + @Nonnull public String getName() { return (identity != null) ? identity.getNickname() : null; } @@ -167,6 +177,7 @@ public class SoneImpl implements Sone { * * @return The request URI of this Sone */ + @Nonnull public FreenetURI getRequestUri() { try { return new FreenetURI(getIdentity().getRequestUri()) @@ -182,25 +193,6 @@ public class SoneImpl implements Sone { } /** - * Returns the insert URI of this Sone. - * - * @return The insert URI of this Sone - */ - public FreenetURI getInsertUri() { - if (!isLocal()) { - return null; - } - try { - return new FreenetURI(((OwnIdentity) getIdentity()).getInsertUri()) - .setDocName("Sone") - .setMetaString(new String[0]) - .setSuggestedEdition(latestEdition); - } catch (MalformedURLException e) { - throw new IllegalStateException(format("Own identity %s's insert URI is incorrect.", getIdentity()), e); - } - } - - /** * Returns the latest edition of this Sone. * * @return The latest edition of this Sone @@ -241,6 +233,7 @@ public class SoneImpl implements Sone { * The time of the update (in milliseconds since Jan 1, 1970 UTC) * @return This Sone (for method chaining) */ + @Nonnull public Sone setTime(long time) { this.time = time; return this; @@ -251,6 +244,7 @@ public class SoneImpl implements Sone { * * @return The status of this Sone */ + @Nonnull public SoneStatus getStatus() { return status; } @@ -264,7 +258,8 @@ public class SoneImpl implements Sone { * @throws IllegalArgumentException * if {@code status} is {@code null} */ - public Sone setStatus(SoneStatus status) { + @Nonnull + public Sone setStatus(@Nonnull SoneStatus status) { this.status = checkNotNull(status, "status must not be null"); return this; } @@ -276,6 +271,7 @@ public class SoneImpl implements Sone { * * @return A copy of the profile */ + @Nonnull public Profile getProfile() { return new Profile(profile); } @@ -288,7 +284,7 @@ public class SoneImpl implements Sone { * @param profile * The profile to set */ - public void setProfile(Profile profile) { + public void setProfile(@Nonnull Profile profile) { this.profile = new Profile(profile); } @@ -297,6 +293,7 @@ public class SoneImpl implements Sone { * * @return The client used by this Sone, or {@code null} */ + @Nullable public Client getClient() { return client; } @@ -308,7 +305,8 @@ public class SoneImpl implements Sone { * The client used by this Sone, or {@code null} * @return This Sone (for method chaining) */ - public Sone setClient(Client client) { + @Nonnull + public Sone setClient(@Nullable Client client) { this.client = client; return this; } @@ -329,6 +327,7 @@ public class SoneImpl implements Sone { * {@code true} if this Sone is known, {@code false} otherwise * @return This Sone */ + @Nonnull public Sone setKnown(boolean known) { this.known = known; return this; @@ -339,8 +338,9 @@ public class SoneImpl implements Sone { * * @return The friend Sones of this Sone */ - public List getFriends() { - return new ArrayList(friendSones); + @Nonnull + public Collection getFriends() { + return database.getFriends(this); } /** @@ -351,34 +351,8 @@ public class SoneImpl implements Sone { * @return {@code true} if this Sone has the given Sone as a friend, {@code * false} otherwise */ - public boolean hasFriend(String friendSoneId) { - return friendSones.contains(friendSoneId); - } - - /** - * Adds the given Sone as a friend Sone. - * - * @param friendSone - * The friend Sone to add - * @return This Sone (for method chaining) - */ - public Sone addFriend(String friendSone) { - if (!friendSone.equals(id)) { - friendSones.add(friendSone); - } - return this; - } - - /** - * Removes the given Sone as a friend Sone. - * - * @param friendSoneId - * The ID of the friend Sone to remove - * @return This Sone (for method chaining) - */ - public Sone removeFriend(String friendSoneId) { - friendSones.remove(friendSoneId); - return this; + public boolean hasFriend(@Nonnull String friendSoneId) { + return database.isFriend(this, friendSoneId); } /** @@ -386,12 +360,13 @@ public class SoneImpl implements Sone { * * @return All posts of this Sone */ + @Nonnull public List getPosts() { List sortedPosts; synchronized (this) { - sortedPosts = new ArrayList(posts); + sortedPosts = new ArrayList<>(posts); } - Collections.sort(sortedPosts, Post.TIME_COMPARATOR); + sortedPosts.sort(newestPostFirst()); return sortedPosts; } @@ -402,7 +377,8 @@ public class SoneImpl implements Sone { * The new (and only) posts of this Sone * @return This Sone (for method chaining) */ - public Sone setPosts(Collection posts) { + @Nonnull + public Sone setPosts(@Nonnull Collection posts) { synchronized (this) { this.posts.clear(); this.posts.addAll(posts); @@ -417,7 +393,7 @@ public class SoneImpl implements Sone { * @param post * The post to add */ - public void addPost(Post post) { + public void addPost(@Nonnull Post post) { if (post.getSone().equals(this) && posts.add(post)) { logger.log(Level.FINEST, String.format("Adding %s to “%s”.", post, getName())); } @@ -429,7 +405,7 @@ public class SoneImpl implements Sone { * @param post * The post to remove */ - public void removePost(Post post) { + public void removePost(@Nonnull Post post) { if (post.getSone().equals(this)) { posts.remove(post); } @@ -440,6 +416,7 @@ public class SoneImpl implements Sone { * * @return All replies this Sone made */ + @Nonnull public Set getReplies() { return Collections.unmodifiableSet(replies); } @@ -451,7 +428,8 @@ public class SoneImpl implements Sone { * The new (and only) replies of this Sone * @return This Sone (for method chaining) */ - public Sone setReplies(Collection replies) { + @Nonnull + public Sone setReplies(@Nonnull Collection replies) { this.replies.clear(); this.replies.addAll(replies); return this; @@ -464,7 +442,7 @@ public class SoneImpl implements Sone { * @param reply * The reply to add */ - public void addReply(PostReply reply) { + public void addReply(@Nonnull PostReply reply) { if (reply.getSone().equals(this)) { replies.add(reply); } @@ -476,7 +454,7 @@ public class SoneImpl implements Sone { * @param reply * The reply to remove */ - public void removeReply(PostReply reply) { + public void removeReply(@Nonnull PostReply reply) { if (reply.getSone().equals(this)) { replies.remove(reply); } @@ -487,6 +465,7 @@ public class SoneImpl implements Sone { * * @return All liked posts’ IDs */ + @Nonnull public Set getLikedPostIds() { return Collections.unmodifiableSet(likedPostIds); } @@ -498,7 +477,8 @@ public class SoneImpl implements Sone { * All liked posts’ IDs * @return This Sone (for method chaining) */ - public Sone setLikePostIds(Set likedPostIds) { + @Nonnull + public Sone setLikePostIds(@Nonnull Set likedPostIds) { this.likedPostIds.clear(); this.likedPostIds.addAll(likedPostIds); return this; @@ -512,7 +492,7 @@ public class SoneImpl implements Sone { * @return {@code true} if this Sone likes the given post, {@code false} * otherwise */ - public boolean isLikedPostId(String postId) { + public boolean isLikedPostId(@Nonnull String postId) { return likedPostIds.contains(postId); } @@ -523,7 +503,8 @@ public class SoneImpl implements Sone { * The ID of the post * @return This Sone (for method chaining) */ - public Sone addLikedPostId(String postId) { + @Nonnull + public Sone addLikedPostId(@Nonnull String postId) { likedPostIds.add(postId); return this; } @@ -533,11 +514,9 @@ public class SoneImpl implements Sone { * * @param postId * The ID of the post - * @return This Sone (for method chaining) */ - public Sone removeLikedPostId(String postId) { + public void removeLikedPostId(@Nonnull String postId) { likedPostIds.remove(postId); - return this; } /** @@ -545,6 +524,7 @@ public class SoneImpl implements Sone { * * @return All liked replies’ IDs */ + @Nonnull public Set getLikedReplyIds() { return Collections.unmodifiableSet(likedReplyIds); } @@ -556,7 +536,8 @@ public class SoneImpl implements Sone { * All liked replies’ IDs * @return This Sone (for method chaining) */ - public Sone setLikeReplyIds(Set likedReplyIds) { + @Nonnull + public Sone setLikeReplyIds(@Nonnull Set likedReplyIds) { this.likedReplyIds.clear(); this.likedReplyIds.addAll(likedReplyIds); return this; @@ -570,7 +551,7 @@ public class SoneImpl implements Sone { * @return {@code true} if this Sone likes the given reply, {@code false} * otherwise */ - public boolean isLikedReplyId(String replyId) { + public boolean isLikedReplyId(@Nonnull String replyId) { return likedReplyIds.contains(replyId); } @@ -581,7 +562,8 @@ public class SoneImpl implements Sone { * The ID of the reply * @return This Sone (for method chaining) */ - public Sone addLikedReplyId(String replyId) { + @Nonnull + public Sone addLikedReplyId(@Nonnull String replyId) { likedReplyIds.add(replyId); return this; } @@ -591,11 +573,9 @@ public class SoneImpl implements Sone { * * @param replyId * The ID of the reply - * @return This Sone (for method chaining) */ - public Sone removeLikedReplyId(String replyId) { + public void removeLikedReplyId(@Nonnull String replyId) { likedReplyIds.remove(replyId); - return this; } /** @@ -603,6 +583,7 @@ public class SoneImpl implements Sone { * * @return The root album of this Sone */ + @Nonnull public Album getRootAlbum() { return rootAlbum; } @@ -612,6 +593,7 @@ public class SoneImpl implements Sone { * * @return The options of this Sone */ + @Nonnull public SoneOptions getOptions() { return options; } @@ -623,7 +605,7 @@ public class SoneImpl implements Sone { * The options of this Sone */ /* TODO - remove this method again, maybe add an option provider */ - public void setOptions(SoneOptions options) { + public void setOptions(@Nonnull SoneOptions options) { this.options = options; } @@ -635,46 +617,46 @@ public class SoneImpl implements Sone { @Override public synchronized String getFingerprint() { Hasher hash = Hashing.sha256().newHasher(); - hash.putString(profile.getFingerprint()); + hash.putString(profile.getFingerprint(), UTF_8); - hash.putString("Posts("); + hash.putString("Posts(", UTF_8); for (Post post : getPosts()) { - hash.putString("Post(").putString(post.getId()).putString(")"); + hash.putString("Post(", UTF_8).putString(post.getId(), UTF_8).putString(")", UTF_8); } - hash.putString(")"); + hash.putString(")", UTF_8); - List replies = new ArrayList(getReplies()); - Collections.sort(replies, Reply.TIME_COMPARATOR); - hash.putString("Replies("); + List replies = new ArrayList<>(getReplies()); + replies.sort(newestReplyFirst().reversed()); + hash.putString("Replies(", UTF_8); for (PostReply reply : replies) { - hash.putString("Reply(").putString(reply.getId()).putString(")"); + hash.putString("Reply(", UTF_8).putString(reply.getId(), UTF_8).putString(")", UTF_8); } - hash.putString(")"); + hash.putString(")", UTF_8); - List likedPostIds = new ArrayList(getLikedPostIds()); + List likedPostIds = new ArrayList<>(getLikedPostIds()); Collections.sort(likedPostIds); - hash.putString("LikedPosts("); + hash.putString("LikedPosts(", UTF_8); for (String likedPostId : likedPostIds) { - hash.putString("Post(").putString(likedPostId).putString(")"); + hash.putString("Post(", UTF_8).putString(likedPostId, UTF_8).putString(")", UTF_8); } - hash.putString(")"); + hash.putString(")", UTF_8); - List likedReplyIds = new ArrayList(getLikedReplyIds()); + List likedReplyIds = new ArrayList<>(getLikedReplyIds()); Collections.sort(likedReplyIds); - hash.putString("LikedReplies("); + hash.putString("LikedReplies(", UTF_8); for (String likedReplyId : likedReplyIds) { - hash.putString("Reply(").putString(likedReplyId).putString(")"); + hash.putString("Reply(", UTF_8).putString(likedReplyId, UTF_8).putString(")", UTF_8); } - hash.putString(")"); + hash.putString(")", UTF_8); - hash.putString("Albums("); + hash.putString("Albums(", UTF_8); for (Album album : rootAlbum.getAlbums()) { - if (!Album.NOT_EMPTY.apply(album)) { + if (!AlbumKt.notEmpty().invoke(album)) { continue; } - hash.putString(album.getFingerprint()); + hash.putString(album.getFingerprint(), UTF_8); } - hash.putString(")"); + hash.putString(")", UTF_8); return hash.hash().toString(); } @@ -686,7 +668,7 @@ public class SoneImpl implements Sone { /** {@inheritDoc} */ @Override public int compareTo(Sone sone) { - return NICE_NAME_COMPARATOR.compare(this, sone); + return niceNameComparator().compare(this, sone); } // @@ -711,7 +693,7 @@ public class SoneImpl implements Sone { /** {@inheritDoc} */ @Override public String toString() { - return getClass().getName() + "[identity=" + identity + ",friends(" + friendSones.size() + "),posts(" + posts.size() + "),replies(" + replies.size() + "),albums(" + getRootAlbum().getAlbums().size() + ")]"; + return getClass().getName() + "[identity=" + identity + ",posts(" + posts.size() + "),replies(" + replies.size() + "),albums(" + getRootAlbum().getAlbums().size() + ")]"; } }