<artifactId>guava</artifactId>
<version>14.0-rc1</version>
</dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
</dependencies>
<repositories>
<repository>
import net.pterodactylus.sone.data.Client;
import net.pterodactylus.sone.data.Image;
import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostBuilder;
+import net.pterodactylus.sone.data.PostBuilderFactory;
import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.PostReplyBuilder;
+import net.pterodactylus.sone.data.PostReplyBuilderFactory;
import net.pterodactylus.sone.data.Profile;
import net.pterodactylus.sone.data.Profile.Field;
import net.pterodactylus.sone.data.Reply;
import net.pterodactylus.sone.data.Sone.ShowCustomAvatars;
import net.pterodactylus.sone.data.Sone.SoneStatus;
import net.pterodactylus.sone.data.TemporaryImage;
-import net.pterodactylus.sone.data.impl.PostImpl;
-import net.pterodactylus.sone.data.impl.PostReplyImpl;
import net.pterodactylus.sone.fcp.FcpInterface;
import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
import net.pterodactylus.sone.freenet.wot.Identity;
import net.pterodactylus.util.service.AbstractService;
import net.pterodactylus.util.thread.NamedThreadFactory;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Ordering;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Inject;
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
-public class Core extends AbstractService implements SoneProvider, PostProvider {
+public class Core extends AbstractService implements SoneProvider, PostProvider, PostReplyProvider {
/** The logger. */
private static final Logger logger = Logging.getLogger(Core.class);
/** All known Sones. */
private final Set<String> knownSones = new HashSet<String>();
+ /** The post builder. */
+ private final PostBuilderFactory postBuilderFactory;
+
/** All posts. */
private final Map<String, Post> posts = new HashMap<String, Post>();
/** All known posts. */
private final Set<String> knownPosts = new HashSet<String>();
+ /** The post reply builder factory. */
+ private final PostReplyBuilderFactory postReplyBuilderFactory;
+
/** All replies. */
private final Map<String, PostReply> replies = new HashMap<String, PostReply>();
* The WebOfTrust updater
* @param eventBus
* The event bus
+ * @param postBuilderFactory
+ * The post builder
+ * @param postReplyBuilderFactory
+ * The post reply builder factory
*/
@Inject
- public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus) {
+ public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, PostBuilderFactory postBuilderFactory, PostReplyBuilderFactory postReplyBuilderFactory) {
super("Sone Core");
this.configuration = configuration;
this.freenetInterface = freenetInterface;
this.updateChecker = new UpdateChecker(eventBus, freenetInterface);
this.webOfTrustUpdater = webOfTrustUpdater;
this.eventBus = eventBus;
+ this.postBuilderFactory = postBuilderFactory;
+ this.postReplyBuilderFactory = postReplyBuilderFactory;
}
//
}
/**
- * Returns the post with the given ID.
+ * Returns a post builder.
*
- * @param postId
- * The ID of the post to get
- * @return The post with the given ID, or a new post with the given ID
+ * @return A new post builder
*/
- public Post getPost(String postId) {
- return getPost(postId, true);
+ public PostBuilder postBuilder() {
+ return postBuilderFactory.newPostBuilder();
}
/**
- * Returns the post with the given ID, optionally creating a new post.
- *
- * @param postId
- * The ID of the post to get
- * @param create
- * {@code true} it create a new post if no post with the given ID
- * exists, {@code false} to return {@code null}
- * @return The post, or {@code null} if there is no such post
+ * {@inheritDoc}
*/
@Override
- public Post getPost(String postId, boolean create) {
+ public Optional<Post> getPost(String postId) {
synchronized (posts) {
- Post post = posts.get(postId);
- if ((post == null) && create) {
- post = new PostImpl(postId);
- posts.put(postId, post);
- }
- return post;
+ return Optional.fromNullable(posts.get(postId));
}
}
}
/**
- * Returns the reply with the given ID. If there is no reply with the given
- * ID yet, a new one is created, unless {@code create} is false in which
- * case {@code null} is returned.
+ * Returns a post reply builder.
*
- * @param replyId
- * The ID of the reply to get
- * @param create
- * {@code true} to always return a {@link Reply}, {@code false}
- * to return {@code null} if no reply can be found
- * @return The reply, or {@code null} if there is no such reply
+ * @return A new post reply builder
*/
- public PostReply getPostReply(String replyId, boolean create) {
+ public PostReplyBuilder postReplyBuilder() {
+ return postReplyBuilderFactory.newPostReplyBuilder();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Optional<PostReply> getPostReply(String replyId) {
synchronized (replies) {
- PostReply reply = replies.get(replyId);
- if (create && (reply == null)) {
- reply = new PostReplyImpl(replyId);
- replies.put(replyId, reply);
- }
- return reply;
+ return Optional.fromNullable(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
+ * {@inheritDoc}
*/
- public List<PostReply> getReplies(Post post) {
- Set<Sone> sones = getSones();
- List<PostReply> replies = new ArrayList<PostReply>();
- for (Sone sone : sones) {
- for (PostReply reply : sone.getReplies()) {
- if (reply.getPost().equals(post)) {
- replies.add(reply);
- }
+ @Override
+ public List<PostReply> getReplies(final Post post) {
+ return Ordering.from(Reply.TIME_COMPARATOR).sortedCopy(FluentIterable.from(getSones()).transformAndConcat(new Function<Sone, Iterable<PostReply>>() {
+
+ @Override
+ public Iterable<PostReply> apply(Sone sone) {
+ return sone.getReplies();
}
- }
- Collections.sort(replies, Reply.TIME_COMPARATOR);
- return replies;
+ }).filter(new Predicate<PostReply>() {
+
+ @Override
+ public boolean apply(PostReply reply) {
+ return post.equals(reply.getPost());
+ }
+ }));
}
/**
Set<Post> posts = new HashSet<Post>();
synchronized (bookmarkedPosts) {
for (String bookmarkedPostId : bookmarkedPosts) {
- Post post = getPost(bookmarkedPostId, false);
- if (post != null) {
- posts.add(post);
+ Optional<Post> post = getPost(bookmarkedPostId);
+ if (!post.isPresent()) {
+ posts.add(post.get());
}
}
}
synchronized (sones) {
final Sone sone = getRemoteSone(identity.getId(), true).setIdentity(identity);
boolean newSone = sone.getRequestUri() == null;
- sone.setRequestUri(getSoneUri(identity.getRequestUri()));
+ sone.setRequestUri(SoneUri.create(identity.getRequestUri()));
sone.setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), (long) 0));
if (newSone) {
synchronized (knownSones) {
List<Post> storedPosts = storedSone.getPosts();
synchronized (knownPosts) {
for (Post post : sone.getPosts()) {
- post.setSone(storedSone).setKnown(knownPosts.contains(post.getId()));
- if (!storedPosts.contains(post)) {
- if (post.getTime() < getSoneFollowingTime(sone)) {
- knownPosts.add(post.getId());
- post.setKnown(true);
- } else if (!knownPosts.contains(post.getId())) {
- eventBus.post(new NewPostFoundEvent(post));
+ PostBuilder postBuilder = postBuilderFactory.newPostBuilder();
+ postBuilder.copyPost(post).from(storedSone);
+ Post newPost = postBuilder.build().setKnown(knownPosts.contains(post.getId()));
+ if (!storedPosts.contains(newPost)) {
+ if (newPost.getTime() < getSoneFollowingTime(sone)) {
+ knownPosts.add(newPost.getId());
+ newPost.setKnown(true);
+ } else if (!knownPosts.contains(newPost.getId())) {
+ eventBus.post(new NewPostFoundEvent(newPost));
}
}
- posts.put(post.getId(), post);
+ posts.put(newPost.getId(), newPost);
}
}
}
logger.log(Level.WARNING, "Invalid post found, aborting load!");
return;
}
- Post post = getPost(postId).setSone(sone).setTime(postTime).setText(postText);
+ PostBuilder postBuilder = postBuilder().withId(postId).from(sone).withTime(postTime).withText(postText);
if ((postRecipientId != null) && (postRecipientId.length() == 43)) {
- post.setRecipient(getSone(postRecipientId));
+ postBuilder.to(getSone(postRecipientId));
}
- posts.add(post);
+ posts.add(postBuilder.build());
}
/* load replies. */
logger.log(Level.WARNING, "Invalid reply found, aborting load!");
return;
}
- replies.add(getPostReply(replyId, true).setSone(sone).setPost(getPost(postId)).setTime(replyTime).setText(replyText));
+ PostReplyBuilder postReplyBuilder = postReplyBuilderFactory.newPostReplyBuilder();
+ postReplyBuilder.withId(replyId).from(sone).to(postId).withTime(replyTime).withText(replyText);
+ replies.add(postReplyBuilder.build());
}
/* load post likes. */
logger.log(Level.FINE, String.format("Tried to create post for non-local Sone: %s", sone));
return null;
}
- final Post post = new PostImpl(sone, time, text.trim());
+ PostBuilder postBuilder = postBuilderFactory.newPostBuilder();
+ postBuilder.from(sone).randomId().withTime(time).withText(text.trim());
if (recipient != null) {
- post.setRecipient(recipient);
+ postBuilder.to(recipient);
}
+ final Post post = postBuilder.build();
synchronized (posts) {
posts.put(post.getId(), post);
}
* @return The created reply
*/
public PostReply createReply(Sone sone, Post post, String text) {
- return createReply(sone, post, System.currentTimeMillis(), text);
- }
-
- /**
- * Creates a new reply.
- *
- * @param sone
- * The Sone that creates the reply
- * @param post
- * The post that this reply refers to
- * @param time
- * The time of the reply
- * @param text
- * The text of the reply
- * @return The created reply
- */
- public PostReply createReply(Sone sone, Post post, long time, String text) {
checkNotNull(text, "text must not be null");
checkArgument(text.trim().length() > 0, "text must not be empty");
if (!sone.isLocal()) {
logger.log(Level.FINE, String.format("Tried to create reply for non-local Sone: %s", sone));
return null;
}
- final PostReply reply = new PostReplyImpl(sone, post, System.currentTimeMillis(), text.trim());
+ PostReplyBuilder postReplyBuilder = postReplyBuilderFactory.newPostReplyBuilder();
+ postReplyBuilder.randomId().from(sone).to(post.getId()).currentTime().withText(text.trim());
+ final PostReply reply = postReplyBuilder.build();
synchronized (replies) {
replies.put(reply.getId(), reply);
}
for (PostReply reply : sone.getReplies()) {
String replyPrefix = sonePrefix + "/Replies/" + replyCounter++;
configuration.getStringValue(replyPrefix + "/ID").setValue(reply.getId());
- configuration.getStringValue(replyPrefix + "/Post/ID").setValue(reply.getPost().getId());
+ configuration.getStringValue(replyPrefix + "/Post/ID").setValue(reply.getPostId());
configuration.getLongValue(replyPrefix + "/Time").setValue(reply.getTime());
configuration.getStringValue(replyPrefix + "/Text").setValue(reply.getText());
}
}
/**
- * Generate a Sone URI from the given URI and latest edition.
- *
- * @param uriString
- * The URI to derive the Sone URI from
- * @return The derived URI
- */
- private static FreenetURI getSoneUri(String uriString) {
- try {
- FreenetURI uri = new FreenetURI(uriString).setDocName("Sone").setMetaString(new String[0]);
- return uri;
- } catch (MalformedURLException mue1) {
- logger.log(Level.WARNING, String.format("Could not create Sone URI from URI: %s", uriString), mue1);
- return null;
- }
- }
-
- /**
* Notifies the core that a new {@link OwnIdentity} was added.
*
* @param ownIdentityAddedEvent
import net.pterodactylus.sone.data.Post;
+import com.google.common.base.Optional;
+
/**
* Interface for objects that can provide {@link Post}s by their ID.
*
public interface PostProvider {
/**
- * Returns the post with the given ID, if it exists. If it does not exist
- * and {@code create} is {@code false}, {@code null} is returned; otherwise,
- * a new post with the given ID is created and returned.
+ * Returns the post with the given ID.
*
* @param postId
* The ID of the post to return
- * @param create
- * {@code true} to create a new post if no post with the given ID
- * exists, {@code false} to return {@code null} instead
* @return The post with the given ID, or {@code null}
*/
- public Post getPost(String postId, boolean create);
+ public Optional<Post> getPost(String postId);
}
--- /dev/null
+/*
+ * Sone - PostReplyProvider.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.core;
+
+import java.util.List;
+
+import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
+
+import com.google.common.base.Optional;
+
+/**
+ * Interface for objects that can provide {@link PostReply}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostReplyProvider {
+
+ /**
+ * Returns the reply with the given ID.
+ *
+ * @param id
+ * The ID of the reply to get
+ * @return The reply, or {@code null} if there is no such reply
+ */
+ public Optional<PostReply> getPostReply(String id);
+
+ /**
+ * 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<PostReply> getReplies(Post post);
+
+}
import net.pterodactylus.sone.data.Client;
import net.pterodactylus.sone.data.Image;
import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostBuilder;
import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.PostReplyBuilder;
import net.pterodactylus.sone.data.Profile;
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.data.Sone.SoneStatus;
return null;
}
try {
- Post post = core.getPost(postId).setSone(sone).setTime(Long.parseLong(postTime)).setText(postText);
+ PostBuilder postBuilder = core.postBuilder();
+ /* TODO - parse time correctly. */
+ postBuilder.withId(postId).from(sone).withTime(Long.parseLong(postTime)).withText(postText);
if ((postRecipientId != null) && (postRecipientId.length() == 43)) {
- post.setRecipient(core.getSone(postRecipientId));
+ postBuilder.to(core.getSone(postRecipientId));
}
- posts.add(post);
+ posts.add(postBuilder.build());
} catch (NumberFormatException nfe1) {
/* TODO - mark Sone as bad. */
logger.log(Level.WARNING, String.format("Downloaded post for Sone %s with invalid time: %s", sone, postTime));
return null;
}
try {
- replies.add(core.getPostReply(replyId, true).setSone(sone).setPost(core.getPost(replyPostId)).setTime(Long.parseLong(replyTime)).setText(replyText));
+ PostReplyBuilder postReplyBuilder = core.postReplyBuilder();
+ /* TODO - parse time correctly. */
+ postReplyBuilder.withId(replyId).from(sone).to(replyPostId).withTime(Long.parseLong(replyTime)).withText(replyText);
+ replies.add(postReplyBuilder.build());
} catch (NumberFormatException nfe1) {
/* TODO - mark Sone as bad. */
logger.log(Level.WARNING, String.format("Downloaded reply for Sone %s with invalid time: %s", sone, replyTime));
--- /dev/null
+/*
+ * Sone - SoneUri.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.core;
+
+import java.net.MalformedURLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.pterodactylus.util.logging.Logging;
+import freenet.keys.FreenetURI;
+
+/**
+ * Helper class that creates {@link FreenetURI}s for Sone to insert to and
+ * request from.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class SoneUri {
+
+ /** The logger. */
+ private static final Logger logger = Logging.getLogger(SoneUri.class);
+
+ /**
+ * Generate a Sone URI from the given URI.
+ *
+ * @param uri
+ * The URI to derive the Sone URI from
+ * @return The derived URI
+ */
+ public static FreenetURI create(String uri) {
+ try {
+ return new FreenetURI(uri).setDocName("Sone").setMetaString(new String[0]);
+ } catch (MalformedURLException mue1) {
+ /* this should never happen. */
+ logger.log(Level.WARNING, String.format("Could not create Sone URI from URI: %s", uri), mue1);
+ return null;
+ }
+ }
+
+}
public Sone getSone();
/**
- * Sets the Sone of this post.
- *
- * @param sone
- * The Sone of this post
- * @return This post (for method chaining)
- */
- public Post setSone(Sone sone);
-
- /**
* Returns the recipient of this post, if any.
*
* @return The recipient of this post, or {@code null}
public Sone getRecipient();
/**
- * Sets the recipient of this post.
- *
- * @param recipient
- * The recipient of this post, or {@code null}
- * @return This post (for method chaining)
- */
- public Post setRecipient(Sone recipient);
-
- /**
* Returns the time of the post.
*
* @return The time of the post (in milliseconds since Jan 1, 1970 UTC)
public long getTime();
/**
- * Sets the time of this post.
- *
- * @param time
- * The time of this post (in milliseconds since Jan 1, 1970 UTC)
- * @return This post (for method chaining)
- */
- public Post setTime(long time);
-
- /**
* Returns the text of the post.
*
* @return The text of the post
public String getText();
/**
- * Sets the text of this post.
- *
- * @param text
- * The text of this post
- * @return This post (for method chaining)
- */
- public Post setText(String text);
-
- /**
* Returns whether this post is known.
*
* @return {@code true} if this post is known, {@code false} otherwise
--- /dev/null
+/*
+ * Sone - PostBuilder.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Builder for {@link Post} objects.
+ * <p>
+ * A {@link Post} consists of the following elements:
+ * <ul>
+ * <li>an ID,</li>
+ * <li>a {@link Sone sender},</li>
+ * <li>an optional {@link Sone recipient},</li>
+ * <li>a time,</li>
+ * <li>and a text.</li>
+ * </ul>
+ * Except for the recipient, all this elements have to be configured on this
+ * builder. For the ID you have the possibility to configure either a random ID
+ * (which should be used for new posts) or a custom ID you specify (for creating
+ * an existing post). For the time you can use the current time (again, for
+ * creating new posts) or the given time (for loading posts). It is an error to
+ * specify both ways for either the ID or the time.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostBuilder {
+
+ /**
+ * Copies all attributes of the given post to this post builder.
+ *
+ * @param post
+ * The post whose attributes to copy into this builder
+ * @return This builder
+ * @throws NullPointerException
+ * if {@code post} is {@code null}
+ */
+ public PostBuilder copyPost(Post post) throws NullPointerException;
+
+ /**
+ * Configures this builder to use the given Sone as sender of the new post.
+ *
+ * @param sender
+ * The sender of the post
+ * @return This post builder
+ */
+ public PostBuilder from(Sone sender);
+
+ /**
+ * Configures this builder to use a random ID for the new post. If this
+ * method is used, {@link #withId(String)} must not be used.
+ *
+ * @return This post builder
+ */
+ public PostBuilder randomId();
+
+ /**
+ * Configures this builder to use the given ID as ID for the new post. If
+ * this method is used, {@link #randomId()} must not be used.
+ *
+ * @param id
+ * The ID to use for the post
+ * @return This post builder
+ */
+ public PostBuilder withId(String id);
+
+ /**
+ * Configures this builder to use the current time when creating the post.
+ * If this method is used, {@link #withTime(long)} must not be used.
+ *
+ * @return This post builder
+ */
+ public PostBuilder currentTime();
+
+ /**
+ * Configures the builder to use the given time as time for the new post. If
+ * this method is used, {@link #currentTime()} must not be used.
+ *
+ * @param time
+ * The time to use for the post
+ * @return This post builder
+ */
+ public PostBuilder withTime(long time);
+
+ /**
+ * Configures the builder to use the given text for the new post.
+ *
+ * @param text
+ * The text to use for the post
+ * @return This post builder
+ */
+ public PostBuilder withText(String text);
+
+ /**
+ * Configures the builder to use the given {@link Sone} as recipient for the
+ * post.
+ *
+ * @param recipient
+ * The recipient of the post
+ * @return This post builder
+ */
+ public PostBuilder to(Sone recipient);
+
+ /**
+ * Verifies this builder’s configuration and creates a new post.
+ * <p>
+ * The following conditions must be met in order for this builder to be
+ * configured correctly:
+ * <ul>
+ * <li>Exactly one of {@link #randomId()} or {@link #withId(String)} must
+ * have been called.</li>
+ * <li>The {@link #from(Sone) sender} must not be {@code null}.</li>
+ * <li>Exactly one of {@link #currentTime()} or {@link #withTime(long)} must
+ * have been called.</li>
+ * <li>The {@link #withText(String) text} must not be {@code null} and must
+ * contain something other than whitespace.</li>
+ * <li>The {@link #to(Sone) recipient} must either not have been set, or it
+ * must have been set to a {@link Sone} other than {@link #from(Sone) the
+ * sender}.</li>
+ * </ul>
+ *
+ * @return A new post
+ * @throws IllegalStateException
+ * if this builder’s configuration is not valid
+ */
+ public Post build() throws IllegalStateException;
+
+}
--- /dev/null
+/*
+ * Sone - PostBuilderFactory.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Factory for {@link PostBuilder}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostBuilderFactory {
+
+ /**
+ * Creates a new post builder.
+ *
+ * @return A new post builder
+ */
+ public PostBuilder newPostBuilder();
+
+}
package net.pterodactylus.sone.data;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+
/**
* A reply is like a {@link Post} but can never be posted on its own, it always
* refers to another {@link Post}.
public interface PostReply extends Reply<PostReply> {
/**
+ * Filter that selects {@link PostReply}s that have a
+ * {@link Optional#isPresent() present} {@link #getPost() post}.
+ */
+ public static final Predicate<PostReply> HAS_POST_FILTER = new Predicate<PostReply>() {
+
+ @Override
+ public boolean apply(PostReply postReply) {
+ return postReply.getPost().isPresent();
+ }
+ };
+
+ /**
+ * Returns the ID of the post this reply refers to.
+ *
+ * @return The ID of the post this reply refers to
+ */
+ public String getPostId();
+
+ /**
* Returns the post this reply refers to.
*
* @return The post this reply refers to
*/
- public Post getPost();
+ public Optional<Post> getPost();
/**
* Sets the post this reply refers to.
*
- * @param post
- * The post this reply refers to
+ * @param postId
+ * The ID of the post to reply to
* @return This reply
*/
- public PostReply setPost(Post post);
+ public PostReply setPost(String postId);
}
--- /dev/null
+/*
+ * Sone - PostReplyBuilder.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Builder for a {@link PostReply} object.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostReplyBuilder extends ReplyBuilder<PostReplyBuilder> {
+
+ /**
+ * Configures this builder to set the given post as post the created reply
+ * refers to.
+ *
+ * @param postId
+ * The ID of the post the reply refers to
+ * @return This builder
+ */
+ public PostReplyBuilder to(String postId);
+
+ /**
+ * Verifies the configuration of this builder and creates a new post reply.
+ * <p>
+ * The following conditions must be met in order for the configuration to be
+ * considered valid:
+ * <ul>
+ * <li>Exactly one of {@link #randomId()} or {@link #withId(String)} must
+ * have been called.</li>
+ * <li>The {@link #from(Sone) sender} must not be {@code null}.</li>
+ * <li>Exactly one of {@link #currentTime()} or {@link #withTime(long)} must
+ * have been called.</li>
+ * <li>The {@link #withText(String) text} must not be {@code null} and must
+ * contain something other than whitespace.</li>
+ * <li>The {@link #to(String) post} have been set.</li>
+ * </ul>
+ *
+ * @return The created post reply
+ * @throws IllegalStateException
+ * if this builder’s configuration is not valid
+ */
+ public PostReply build() throws IllegalStateException;
+
+}
--- /dev/null
+/*
+ * Sone - PostReplyBuilderFactory.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Factory for {@link PostReplyBuilder}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostReplyBuilderFactory {
+
+ /**
+ * Creates a new post reply builder.
+ *
+ * @return A new post reply builder
+ */
+ public PostReplyBuilder newPostReplyBuilder();
+
+}
--- /dev/null
+/*
+ * Sone - ReplyBuilder.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Methods that all reply builders need to implement in order to be able to
+ * create any kind of {@link Reply}.
+ *
+ * @param <B>
+ * The type of the builder
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface ReplyBuilder<B extends ReplyBuilder<B>> {
+
+ /**
+ * Configures this builder to use a random ID when creating the reply. If
+ * this method is used, {@link #withId(String)} must not be used.
+ *
+ * @return This builder
+ */
+ public B randomId();
+
+ /**
+ * Configures this builder to use the given ID when creating the reply. If
+ * this method is used, {@link #randomId()} must not be used.
+ *
+ * @param id
+ * The ID of the reply
+ * @return This builder
+ */
+ public B withId(String id);
+
+ /**
+ * Configures this builder to use the given {@link Sone} as sender of the
+ * reply.
+ *
+ * @param sender
+ * The sender of the reply
+ * @return This builder
+ */
+ public B from(Sone sender);
+
+ /**
+ * Configures this builder to use the current time when creating the reply.
+ * If this method is used, {@link #withTime(long)} must not be used.
+ *
+ * @return This builder
+ */
+ public B currentTime();
+
+ /**
+ * Configures this builder to use the given time when creating the reply. If
+ * this method is used, {@link #currentTime()} must not be used.
+ *
+ * @param time
+ * The time of the reply
+ * @return This builder
+ */
+ public B withTime(long time);
+
+ /**
+ * Configures this builder to use the given text when creating the reply.
+ *
+ * @param text
+ * The text of the reply
+ * @return This builder
+ */
+ public B withText(String text);
+
+}
--- /dev/null
+/*
+ * Sone - ReplyBuilder.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.data.ReplyBuilder;
+import net.pterodactylus.sone.data.Sone;
+
+/**
+ * Abstract implementation of a {@link ReplyBuilder}.
+ *
+ * @param <B>
+ * The interface implemented and exposed by the builder
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class AbstractReplyBuilder<B extends ReplyBuilder<B>> implements ReplyBuilder<B> {
+
+ /** Whether to use a random ID for the reply. */
+ protected boolean randomId;
+
+ /** The ID of the reply. */
+ protected String id;
+
+ /** The sender of the reply. */
+ protected Sone sender;
+
+ /** Whether to use the current time when creating the reply. */
+ protected boolean currentTime;
+
+ /** The time of the reply. */
+ protected long time;
+
+ /** The text of the reply. */
+ protected String text;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public B randomId() {
+ this.randomId = true;
+ return (B) this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public B withId(String id) {
+ this.id = id;
+ return (B) this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public B from(Sone sender) {
+ this.sender = sender;
+ return (B) this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public B currentTime() {
+ this.currentTime = true;
+ return (B) this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public B withTime(long time) {
+ this.time = time;
+ return (B) this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public B withText(String text) {
+ this.text = text;
+ return (B) this;
+ }
+
+}
--- /dev/null
+/*
+ * Sone - DefaultPostBuilderFactory.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.data.PostBuilder;
+import net.pterodactylus.sone.data.PostBuilderFactory;
+
+/**
+ * {@link PostBuilderFactory} implementation that creates
+ * {@link PostBuilderImpl}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class DefaultPostBuilderFactory implements PostBuilderFactory {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder newPostBuilder() {
+ return new PostBuilderImpl();
+ }
+
+}
--- /dev/null
+/*
+ * Sone - DefaultPostReplyBuilderFactory.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.core.PostProvider;
+import net.pterodactylus.sone.data.PostReplyBuilder;
+import net.pterodactylus.sone.data.PostReplyBuilderFactory;
+
+import com.google.inject.Inject;
+
+/**
+ * {@link PostReplyBuilderFactory} that creates {@link PostReplyBuilderImpl}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class DefaultPostReplyBuilderFactory implements PostReplyBuilderFactory {
+
+ /** The post provider. */
+ private final PostProvider postProvider;
+
+ /**
+ * Creates a new default post reply builder factory.
+ *
+ * @param postProvider
+ * The post provider
+ */
+ @Inject
+ public DefaultPostReplyBuilderFactory(PostProvider postProvider) {
+ this.postProvider = postProvider;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostReplyBuilder newPostReplyBuilder() {
+ return new PostReplyBuilderImpl(postProvider);
+ }
+
+}
--- /dev/null
+/*
+ * Sone - PostBuilderImpl.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.UUID;
+
+import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostBuilder;
+import net.pterodactylus.sone.data.Sone;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * {@link PostBuilder} implementation that creates {@link PostImpl} objects.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PostBuilderImpl implements PostBuilder {
+
+ /** Wether to create a post with a random ID. */
+ private boolean randomId;
+
+ /** The ID of the post. */
+ private String id;
+
+ /** The sender of the post. */
+ private Sone sender;
+
+ /** Whether to use the current time when creating the post. */
+ private boolean currentTime;
+
+ /** The time of the post. */
+ private long time;
+
+ /** The text of the post. */
+ private String text;
+
+ /** The (optional) recipient of the post. */
+ private Sone recipient;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder copyPost(Post post) {
+ this.randomId = false;
+ this.id = post.getId();
+ this.sender = post.getSone();
+ this.currentTime = false;
+ this.time = post.getTime();
+ this.text = post.getText();
+ this.recipient = post.getRecipient();
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder randomId() {
+ randomId = true;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder withId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder from(Sone sender) {
+ this.sender = sender;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder currentTime() {
+ currentTime = true;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder withTime(long time) {
+ this.time = time;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder withText(String text) {
+ this.text = text;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostBuilder to(Sone recipient) {
+ this.recipient = recipient;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Post build() {
+ checkState((randomId && (id == null)) || (!randomId && (id != null)), "exactly one of random ID or custom ID must be set");
+ checkState(sender != null, "sender must not be null");
+ checkState((currentTime && (time == 0)) || (!currentTime && (time > 0)), "one of current time or custom time must be set");
+ checkState(!StringUtils.isBlank(text), "text must not be empty");
+ checkState((recipient == null) || !recipient.equals(sender), "sender and recipient must not be the same");
+ return new PostImpl(randomId ? UUID.randomUUID().toString() : id, sender, currentTime ? System.currentTimeMillis() : time, text).setRecipient(recipient);
+ }
+
+}
}
/**
- * {@inheritDoc}
+ * Sets the Sone of this post.
+ *
+ * @param sone
+ * The Sone of this post
+ * @return This post (for method chaining)
*/
- @Override
public PostImpl setSone(Sone sone) {
this.sone = sone;
return this;
}
/**
- * {@inheritDoc}
+ * Sets the recipient of this post.
+ *
+ * @param recipient
+ * The recipient of this post, or {@code null}
+ * @return This post (for method chaining)
*/
- @Override
public PostImpl setRecipient(Sone recipient) {
if (!sone.equals(recipient)) {
this.recipient = recipient;
}
/**
- * {@inheritDoc}
+ * Sets the time of this post.
+ *
+ * @param time
+ * The time of this post (in milliseconds since Jan 1, 1970 UTC)
+ * @return This post (for method chaining)
*/
- @Override
public PostImpl setTime(long time) {
this.time = time;
return this;
}
/**
- * {@inheritDoc}
+ * Sets the text of this post.
+ *
+ * @param text
+ * The text of this post
+ * @return This post (for method chaining)
*/
- @Override
public PostImpl setText(String text) {
this.text = text;
return this;
--- /dev/null
+/*
+ * Sone - PostReplyBuilderImpl.java - Copyright © 2013 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.UUID;
+
+import net.pterodactylus.sone.core.PostProvider;
+import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.PostReplyBuilder;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * {@link PostReplyBuilder} implementation that creates {@link PostReplyImpl}
+ * objects.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PostReplyBuilderImpl extends AbstractReplyBuilder<PostReplyBuilder> implements PostReplyBuilder {
+
+ /** The post builder. */
+ private final PostProvider postProvider;
+
+ /** The ID of the post the created reply refers to. */
+ private String postId;
+
+ /**
+ * Creates a new post reply builder.
+ *
+ * @param postProvider
+ * The post provider
+ */
+ public PostReplyBuilderImpl(PostProvider postProvider) {
+ this.postProvider = postProvider;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostReplyBuilder to(String postId) {
+ this.postId = postId;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PostReply build() {
+ checkState((randomId && (id == null)) || (!randomId && (id != null)), "either random ID nor custom ID must be set");
+ checkState(sender != null, "sender must not be null");
+ checkState((currentTime && (time == 0)) || (!currentTime && (time >= 0)), "either current time or custom time must be set");
+ checkState(!StringUtils.isBlank(text), "text must not be empty");
+ checkState(postId != null, "post must not be null");
+
+ /* create new post reply. */
+ PostReplyImpl postReplyImpl = new PostReplyImpl(postProvider, randomId ? UUID.randomUUID().toString() : id);
+ postReplyImpl.setSone(sender);
+ postReplyImpl.setPost(postId);
+ postReplyImpl.setTime(currentTime ? System.currentTimeMillis() : time);
+ postReplyImpl.setText(text);
+ return postReplyImpl;
+ }
+}
package net.pterodactylus.sone.data.impl;
-import java.util.UUID;
-
+import net.pterodactylus.sone.core.PostProvider;
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.Sone;
+
+import com.google.common.base.Optional;
/**
* Simple {@link PostReply} implementation.
*/
public class PostReplyImpl extends ReplyImpl<PostReply> implements PostReply {
+ /** The post provider. */
+ private final PostProvider postProvider;
+
/** The Post this reply refers to. */
- private volatile Post post;
+ private volatile String postId;
/**
* Creates a new reply.
*
+ * @param postProvider
+ * The post provider
* @param id
* The ID of the reply
*/
- public PostReplyImpl(String id) {
- this(id, null, null, 0, null);
- }
-
- /**
- * Creates a new reply.
- *
- * @param sone
- * The sone that posted the reply
- * @param post
- * The post to reply to
- * @param text
- * The text of the reply
- */
- public PostReplyImpl(Sone sone, Post post, String text) {
- this(sone, post, System.currentTimeMillis(), text);
+ public PostReplyImpl(PostProvider postProvider, String id) {
+ super(id);
+ this.postProvider = postProvider;
+ this.postId = postId;
}
- /**
- * Creates a new reply-
- *
- * @param sone
- * The sone that posted the reply
- * @param post
- * The post to reply to
- * @param time
- * The time of the reply
- * @param text
- * The text of the reply
- */
- public PostReplyImpl(Sone sone, Post post, long time, String text) {
- this(UUID.randomUUID().toString(), sone, post, time, text);
- }
+ //
+ // ACCESSORS
+ //
/**
- * Creates a new reply-
- *
- * @param sone
- * The sone that posted the reply
- * @param id
- * The ID of the reply
- * @param post
- * The post to reply to
- * @param time
- * The time of the reply
- * @param text
- * The text of the reply
+ * {@inheritDocs}
*/
- public PostReplyImpl(String id, Sone sone, Post post, long time, String text) {
- super(id, sone, time, text);
- this.post = post;
+ @Override
+ public String getPostId() {
+ return postId;
}
- //
- // ACCESSORS
- //
-
/**
* {@inheritDoc}
*/
@Override
- public Post getPost() {
- return post;
+ public Optional<Post> getPost() {
+ return postProvider.getPost(postId);
}
/**
* Sets the post this reply refers to.
*
- * @param post
- * The post this reply refers to
+ * @param postId
+ * The ID of the post to reply to
* @return This reply (for method chaining)
*/
@Override
- public PostReply setPost(Post post) {
- this.post = post;
+ public PostReply setPost(String postId) {
+ this.postId = postId;
return this;
}
import net.pterodactylus.sone.freenet.fcp.FcpException;
import net.pterodactylus.sone.template.SoneAccessor;
+import com.google.common.base.Optional;
import com.google.common.collect.Collections2;
import freenet.node.FSParseException;
protected Post getPost(SimpleFieldSet simpleFieldSet, String parameterName) throws FcpException {
try {
String postId = simpleFieldSet.getString(parameterName);
- Post post = core.getPost(postId, false);
- if (post == null) {
+ Optional<Post> post = core.getPost(postId);
+ if (!post.isPresent()) {
throw new FcpException("Could not load post from “" + postId + "”.");
}
- return post;
+ return post.get();
} catch (FSParseException fspe1) {
throw new FcpException("Could not post ID from “" + parameterName + "”.", fspe1);
}
protected PostReply getReply(SimpleFieldSet simpleFieldSet, String parameterName) throws FcpException {
try {
String replyId = simpleFieldSet.getString(parameterName);
- PostReply reply = core.getPostReply(replyId, false);
- if (reply == null) {
+ Optional<PostReply> reply = core.getPostReply(replyId);
+ if (!reply.isPresent()) {
throw new FcpException("Could not load reply from “" + replyId + "”.");
}
- return reply;
+ return reply.get();
} catch (FSParseException fspe1) {
throw new FcpException("Could not reply ID from “" + parameterName + "”.", fspe1);
}
import net.pterodactylus.sone.core.Core;
import net.pterodactylus.sone.core.FreenetInterface;
+import net.pterodactylus.sone.core.PostProvider;
import net.pterodactylus.sone.core.WebOfTrustUpdater;
+import net.pterodactylus.sone.data.PostBuilderFactory;
+import net.pterodactylus.sone.data.PostReplyBuilderFactory;
+import net.pterodactylus.sone.data.impl.DefaultPostBuilderFactory;
+import net.pterodactylus.sone.data.impl.DefaultPostReplyBuilderFactory;
import net.pterodactylus.sone.fcp.FcpInterface;
import net.pterodactylus.sone.freenet.PluginStoreConfigurationBackend;
import net.pterodactylus.sone.freenet.plugin.PluginConnector;
bind(String.class).annotatedWith(Names.named("WebOfTrustContext")).toInstance("Sone");
bind(SonePlugin.class).toInstance(SonePlugin.this);
bind(FcpInterface.class).in(Singleton.class);
+ bind(PostBuilderFactory.class).to(DefaultPostBuilderFactory.class).in(Singleton.class);
+ bind(PostReplyBuilderFactory.class).to(DefaultPostReplyBuilderFactory.class).in(Singleton.class);
+ bind(PostProvider.class).to(Core.class).in(Singleton.class);
bindListener(Matchers.any(), new TypeListener() {
@Override
import net.pterodactylus.sone.freenet.wot.Trust;
import net.pterodactylus.util.notify.Notification;
+import com.google.common.base.Optional;
+
/**
* Filter for {@link ListNotification}s.
*
*/
public static boolean isReplyVisible(Sone sone, PostReply reply) {
checkNotNull(reply, "reply must not be null");
- Post post = reply.getPost();
- if (post == null) {
+ Optional<Post> post = reply.getPost();
+ if (!post.isPresent()) {
return false;
}
- if (!isPostVisible(sone, post)) {
+ if (!isPostVisible(sone, post.get())) {
return false;
}
if (reply.getTime() > System.currentTimeMillis()) {
import net.pterodactylus.util.template.Filter;
import net.pterodactylus.util.template.TemplateContext;
+import com.google.common.base.Optional;
+
/**
* {@link Filter} implementation that groups replies by the post the are in
* reply to, returning a map with the post as key and the list of replies as
Map<Post, Set<Sone>> postSones = new HashMap<Post, Set<Sone>>();
Map<Post, Set<PostReply>> postReplies = new HashMap<Post, Set<PostReply>>();
for (PostReply reply : allReplies) {
- Post post = reply.getPost();
- Set<Sone> sones = postSones.get(post);
+ /*
+ * All replies from a new-reply notification have posts,
+ * ListNotificationFilters takes care of that.
+ */
+ Optional<Post> post = reply.getPost();
+ Set<Sone> sones = postSones.get(post.get());
if (sones == null) {
sones = new HashSet<Sone>();
- postSones.put(post, sones);
+ postSones.put(post.get(), sones);
}
sones.add(reply.getSone());
- Set<PostReply> replies = postReplies.get(post);
+ Set<PostReply> replies = postReplies.get(post.get());
if (replies == null) {
replies = new HashSet<PostReply>();
- postReplies.put(post, replies);
+ postReplies.put(post.get(), replies);
}
replies.add(reply);
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.core.PostProvider;
import net.pterodactylus.sone.core.SoneProvider;
import net.pterodactylus.sone.data.Post;
if (linkType == LinkType.POST) {
if (line.length() >= (7 + 36)) {
String postId = line.substring(7, 43);
- Post post = postProvider.getPost(postId, false);
- if ((post != null) && (post.getSone() != null)) {
- parts.add(new PostPart(post));
+ Optional<Post> post = postProvider.getPost(postId);
+ if (post.isPresent()) {
+ parts.add(new PostPart(post.get()));
} else {
parts.add(new PlainTextPart(line.substring(0, 43)));
}
package net.pterodactylus.sone.web;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.text.TextFilter;
String text = request.getHttpRequest().getPartAsStringFailsafe("text", 65536).trim();
String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256);
if (request.getMethod() == Method.POST) {
- Post post = webInterface.getCore().getPost(postId);
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ if (!post.isPresent()) {
+ throw new RedirectException("noPermission.html");
+ }
if (text.length() > 0) {
String senderId = request.getHttpRequest().getPartAsStringFailsafe("sender", 43);
Sone sender = webInterface.getCore().getLocalSone(senderId, false);
sender = getCurrentSone(request.getToadletContext());
}
text = TextFilter.filter(request.getHttpRequest().getHeader("host"), text);
- webInterface.getCore().createReply(sender, post, text);
+ webInterface.getCore().createReply(sender, post.get(), text);
throw new RedirectException(returnPage);
}
templateContext.set("errorTextEmpty", true);
package net.pterodactylus.sone.web;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.web.page.FreenetRequest;
import net.pterodactylus.util.template.Template;
if (request.getMethod() == Method.GET) {
String postId = request.getHttpRequest().getParam("post");
String returnPage = request.getHttpRequest().getParam("returnPage");
- Post post = webInterface.getCore().getPost(postId);
- templateContext.set("post", post);
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ if (!post.isPresent()) {
+ throw new RedirectException("noPermission.html");
+ }
+ templateContext.set("post", post.get());
templateContext.set("returnPage", returnPage);
return;
} else if (request.getMethod() == Method.POST) {
String postId = request.getHttpRequest().getPartAsStringFailsafe("post", 36);
String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256);
- Post post = webInterface.getCore().getPost(postId);
- if (!post.getSone().isLocal()) {
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ if (!post.isPresent() || !post.get().getSone().isLocal()) {
throw new RedirectException("noPermission.html");
}
if (request.getHttpRequest().isPartSet("confirmDelete")) {
- webInterface.getCore().deletePost(post);
+ webInterface.getCore().deletePost(post.get());
throw new RedirectException(returnPage);
} else if (request.getHttpRequest().isPartSet("abortDelete")) {
throw new RedirectException(returnPage);
import net.pterodactylus.util.template.TemplateContext;
import net.pterodactylus.util.web.Method;
+import com.google.common.base.Optional;
+
/**
* This page lets the user delete a reply.
*
protected void processTemplate(FreenetRequest request, TemplateContext templateContext) throws RedirectException {
super.processTemplate(request, templateContext);
String replyId = request.getHttpRequest().getPartAsStringFailsafe("reply", 36);
- PostReply reply = webInterface.getCore().getPostReply(replyId, false);
+ Optional<PostReply> reply = webInterface.getCore().getPostReply(replyId);
String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256);
if (request.getMethod() == Method.POST) {
- if (!reply.getSone().isLocal()) {
+ if (!reply.get().getSone().isLocal()) {
throw new RedirectException("noPermission.html");
}
if (request.getHttpRequest().isPartSet("confirmDelete")) {
- webInterface.getCore().deleteReply(reply);
+ webInterface.getCore().deleteReply(reply.get());
throw new RedirectException(returnPage);
} else if (request.getHttpRequest().isPartSet("abortDelete")) {
throw new RedirectException(returnPage);
import net.pterodactylus.util.template.Template;
import net.pterodactylus.util.template.TemplateContext;
+import com.google.common.base.Optional;
+
/**
* Page that lets the user mark a number of {@link Sone}s, {@link Post}s, or
* {@link Reply Replie}s as known.
for (StringTokenizer idTokenizer = new StringTokenizer(ids); idTokenizer.hasMoreTokens();) {
String id = idTokenizer.nextToken();
if (type.equals("post")) {
- Post post = webInterface.getCore().getPost(id, false);
- if (post == null) {
+ Optional<Post> post = webInterface.getCore().getPost(id);
+ if (!post.isPresent()) {
continue;
}
- webInterface.getCore().markPostKnown(post);
+ webInterface.getCore().markPostKnown(post.get());
} else if (type.equals("reply")) {
- PostReply reply = webInterface.getCore().getPostReply(id, false);
- if (reply == null) {
+ Optional<PostReply> reply = webInterface.getCore().getPostReply(id);
+ if (!reply.isPresent()) {
continue;
}
- webInterface.getCore().markReplyKnown(reply);
+ webInterface.getCore().markReplyKnown(reply.get());
} else if (type.equals("sone")) {
Sone sone = webInterface.getCore().getSone(id, false);
if (sone == null) {
/* collect new elements from notifications. */
Set<Post> posts = new HashSet<Post>(webInterface.getNewPosts());
for (PostReply reply : webInterface.getNewReplies()) {
- posts.add(reply.getPost());
+ posts.add(reply.getPost().get());
}
/* filter and sort them. */
import net.pterodactylus.util.text.TextException;
import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
*/
private String getPostId(String phrase) {
String postId = phrase.startsWith("post://") ? phrase.substring(7) : phrase;
- return (webInterface.getCore().getPost(postId, false) != null) ? postId : null;
+ return (webInterface.getCore().getPost(postId) != null) ? postId : null;
}
/**
*/
private String getReplyPostId(String phrase) {
String replyId = phrase.startsWith("reply://") ? phrase.substring(8) : phrase;
- return (webInterface.getCore().getPostReply(replyId, false) != null) ? webInterface.getCore().getPostReply(replyId, false).getPost().getId() : null;
+ Optional<PostReply> postReply = webInterface.getCore().getPostReply(replyId);
+ if (!postReply.isPresent()) {
+ return null;
+ }
+ return postReply.get().getPostId();
}
/**
import java.net.URI;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.template.SoneAccessor;
import net.pterodactylus.sone.web.page.FreenetRequest;
@Override
protected String getPageTitle(FreenetRequest request) {
String postId = request.getHttpRequest().getParam("post");
- Post post = webInterface.getCore().getPost(postId, false);
+ Optional<Post> post = webInterface.getCore().getPost(postId);
String title = "";
- if ((post != null) && (post.getSone() != null)) {
- title = post.getText().substring(0, Math.min(20, post.getText().length())) + "…";
- title += " - " + SoneAccessor.getNiceName(post.getSone()) + " - ";
+ if (post.isPresent()) {
+ title = post.get().getText().substring(0, Math.min(20, post.get().getText().length())) + "…";
+ title += " - " + SoneAccessor.getNiceName(post.get().getSone()) + " - ";
}
title += webInterface.getL10n().getString("Page.ViewPost.Title");
return title;
super.processTemplate(request, templateContext);
String postId = request.getHttpRequest().getParam("post");
boolean raw = request.getHttpRequest().getParam("raw").equals("true");
- Post post = webInterface.getCore().getPost(postId);
- templateContext.set("post", post);
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ templateContext.set("post", post.get());
templateContext.set("raw", raw);
}
import net.pterodactylus.util.template.Template;
import net.pterodactylus.util.template.TemplateContext;
+import com.google.common.base.Optional;
+
/**
* Lets the user browser another Sone.
*
Set<PostReply> replies = sone.getReplies();
final Map<Post, List<PostReply>> repliedPosts = new HashMap<Post, List<PostReply>>();
for (PostReply reply : replies) {
- Post post = reply.getPost();
- if (repliedPosts.containsKey(post) || sone.equals(post.getSone()) || (sone.equals(post.getRecipient()))) {
+ Optional<Post> post = reply.getPost();
+ if (!post.isPresent() || repliedPosts.containsKey(post.get()) || sone.equals(post.get().getSone()) || (sone.equals(post.get().getRecipient()))) {
continue;
}
- repliedPosts.put(post, webInterface.getCore().getReplies(post));
+ repliedPosts.put(post.get(), webInterface.getCore().getReplies(post.get()));
}
List<Post> posts = new ArrayList<Post>(repliedPosts.keySet());
Collections.sort(posts, new Comparator<Post>() {
}
if (!hasFirstStartNotification()) {
notificationManager.addNotification(isLocal ? localReplyNotification : newReplyNotification);
- if (!getMentionedSones(reply.getText()).isEmpty() && !isLocal && (reply.getPost().getSone() != null) && (reply.getTime() <= System.currentTimeMillis())) {
- mentionNotification.add(reply.getPost());
+ if (!getMentionedSones(reply.getText()).isEmpty() && !isLocal && reply.getPost().isPresent() && (reply.getTime() <= System.currentTimeMillis())) {
+ mentionNotification.add(reply.getPost().get());
notificationManager.addNotification(mentionNotification);
}
} else {
public void markReplyKnown(MarkPostReplyKnownEvent markPostReplyKnownEvent) {
newReplyNotification.remove(markPostReplyKnownEvent.postReply());
localReplyNotification.remove(markPostReplyKnownEvent.postReply());
- mentionNotification.remove(markPostReplyKnownEvent.postReply().getPost());
+ mentionNotification.remove(markPostReplyKnownEvent.postReply().getPost().get());
}
/**
localReplyNotification.remove(reply);
if (!getMentionedSones(reply.getText()).isEmpty()) {
boolean isMentioned = false;
- for (PostReply existingReply : getCore().getReplies(reply.getPost())) {
+ for (PostReply existingReply : getCore().getReplies(reply.getPost().get())) {
isMentioned |= !reply.isKnown() && !getMentionedSones(existingReply.getText()).isEmpty();
}
if (!isMentioned) {
- mentionNotification.remove(reply.getPost());
+ mentionNotification.remove(reply.getPost().get());
}
}
}
package net.pterodactylus.sone.web.ajax;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.PostReply;
import net.pterodactylus.sone.data.Sone;
if (sender == null) {
sender = getCurrentSone(request.getToadletContext());
}
- Post post = webInterface.getCore().getPost(postId);
- if ((post == null) || (post.getSone() == null)) {
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ if (!post.isPresent()) {
return createErrorJsonObject("invalid-post-id");
}
text = TextFilter.filter(request.getHttpRequest().getHeader("host"), text);
- PostReply reply = webInterface.getCore().createReply(sender, post, text);
+ PostReply reply = webInterface.getCore().createReply(sender, post.get(), text);
return createSuccessJsonObject().put("reply", reply.getId()).put("sone", sender.getId());
}
package net.pterodactylus.sone.web.ajax;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.web.WebInterface;
import net.pterodactylus.sone.web.page.FreenetRequest;
@Override
protected JsonObject createJsonObject(FreenetRequest request) {
String postId = request.getHttpRequest().getParam("post");
- Post post = webInterface.getCore().getPost(postId, false);
- if ((post == null) || (post.getSone() == null)) {
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ if (!post.isPresent()) {
return createErrorJsonObject("invalid-post-id");
}
- if (!post.getSone().isLocal()) {
+ if (!post.get().getSone().isLocal()) {
return createErrorJsonObject("not-authorized");
}
- webInterface.getCore().deletePost(post);
+ webInterface.getCore().deletePost(post.get());
return createSuccessJsonObject();
}
package net.pterodactylus.sone.web.ajax;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.PostReply;
import net.pterodactylus.sone.web.WebInterface;
import net.pterodactylus.sone.web.page.FreenetRequest;
@Override
protected JsonObject createJsonObject(FreenetRequest request) {
String replyId = request.getHttpRequest().getParam("reply");
- PostReply reply = webInterface.getCore().getPostReply(replyId, false);
- if (reply == null) {
+ Optional<PostReply> reply = webInterface.getCore().getPostReply(replyId);
+ if (!reply.isPresent()) {
return createErrorJsonObject("invalid-reply-id");
}
- if (!reply.getSone().isLocal()) {
+ if (!reply.get().getSone().isLocal()) {
return createErrorJsonObject("not-authorized");
}
- webInterface.getCore().deleteReply(reply);
+ webInterface.getCore().deleteReply(reply.get());
return createSuccessJsonObject();
}
import net.pterodactylus.util.json.JsonArray;
import net.pterodactylus.util.json.JsonObject;
+import com.google.common.base.Optional;
+
/**
* AJAX page that retrieves the number of “likes” a {@link Post} has.
*
return createErrorJsonObject("invalid-" + type + "-id");
}
if ("post".equals(type)) {
- Post post = webInterface.getCore().getPost(id);
- Set<Sone> sones = webInterface.getCore().getLikes(post);
+ Optional<Post> post = webInterface.getCore().getPost(id);
+ if (!post.isPresent()) {
+ return createErrorJsonObject("invalid-post-id");
+ }
+ Set<Sone> sones = webInterface.getCore().getLikes(post.get());
return createSuccessJsonObject().put("likes", sones.size()).put("sones", getSones(sones));
} else if ("reply".equals(type)) {
- PostReply reply = webInterface.getCore().getPostReply(id, false);
- Set<Sone> sones = webInterface.getCore().getLikes(reply);
+ Optional<PostReply> reply = webInterface.getCore().getPostReply(id);
+ if (!reply.isPresent()) {
+ return createErrorJsonObject("invalid-reply-id");
+ }
+ Set<Sone> sones = webInterface.getCore().getLikes(reply.get());
return createSuccessJsonObject().put("likes", sones.size()).put("sones", getSones(sones));
}
return createErrorJsonObject("invalid-type");
import java.io.StringWriter;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.web.WebInterface;
@Override
protected JsonObject createJsonObject(FreenetRequest request) {
String postId = request.getHttpRequest().getParam("post");
- Post post = webInterface.getCore().getPost(postId, false);
- if (post == null) {
+ Optional<Post> post = webInterface.getCore().getPost(postId);
+ if (!post.isPresent()) {
return createErrorJsonObject("invalid-post-id");
}
- return createSuccessJsonObject().put("post", createJsonPost(request, post, getCurrentSone(request.getToadletContext())));
+ return createSuccessJsonObject().put("post", createJsonPost(request, post.get(), getCurrentSone(request.getToadletContext())));
}
/**
import java.io.StringWriter;
+import com.google.common.base.Optional;
+
import net.pterodactylus.sone.data.PostReply;
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.web.WebInterface;
@Override
protected JsonObject createJsonObject(FreenetRequest request) {
String replyId = request.getHttpRequest().getParam("reply");
- PostReply reply = webInterface.getCore().getPostReply(replyId, false);
- if ((reply == null) || (reply.getSone() == null)) {
+ Optional<PostReply> reply = webInterface.getCore().getPostReply(replyId);
+ if (!reply.isPresent()) {
return createErrorJsonObject("invalid-reply-id");
}
- return createSuccessJsonObject().put("reply", createJsonReply(request, reply, getCurrentSone(request.getToadletContext())));
+ return createSuccessJsonObject().put("reply", createJsonReply(request, reply.get(), getCurrentSone(request.getToadletContext())));
}
/**
private JsonObject createJsonReply(FreenetRequest request, PostReply reply, Sone currentSone) {
JsonObject jsonReply = new JsonObject();
jsonReply.put("id", reply.getId());
- jsonReply.put("postId", reply.getPost().getId());
+ jsonReply.put("postId", reply.getPostId());
jsonReply.put("soneId", reply.getSone().getId());
jsonReply.put("time", reply.getTime());
StringWriter stringWriter = new StringWriter();
});
}
/* remove replies to unknown posts. */
- newReplies = Collections2.filter(newReplies, new Predicate<PostReply>() {
-
- @Override
- public boolean apply(PostReply reply) {
- return (reply.getPost() != null) && (reply.getPost().getSone() != null);
- }
- });
+ newReplies = Collections2.filter(newReplies, PostReply.HAS_POST_FILTER);
JsonArray jsonReplies = new JsonArray();
for (PostReply reply : newReplies) {
JsonObject jsonReply = new JsonObject();
jsonReply.put("id", reply.getId());
jsonReply.put("sone", reply.getSone().getId());
- jsonReply.put("post", reply.getPost().getId());
- jsonReply.put("postSone", reply.getPost().getSone().getId());
+ jsonReply.put("post", reply.getPostId());
+ jsonReply.put("postSone", reply.getPost().get().getSone().getId());
jsonReplies.add(jsonReply);
}
return createSuccessJsonObject().put("loggedIn", currentSone != null).put("options", createJsonOptions(currentSone)).put("sones", jsonSones).put("notificationHash", notifications.hashCode()).put("newPosts", jsonPosts).put("newReplies", jsonReplies);
import net.pterodactylus.sone.web.page.FreenetRequest;
import net.pterodactylus.util.json.JsonObject;
+import com.google.common.base.Optional;
+
/**
* Ajax page that returns a formatted, relative timestamp for replies or posts.
*
if (allIds.length() > 0) {
String[] ids = allIds.split(",");
for (String id : ids) {
- Post post = webInterface.getCore().getPost(id, false);
- if (post == null) {
+ Optional<Post> post = webInterface.getCore().getPost(id);
+ if (!post.isPresent()) {
continue;
}
JsonObject postTime = new JsonObject();
- Time time = getTime(post.getTime());
+ Time time = getTime(post.get().getTime());
postTime.put("timeText", time.getText());
postTime.put("refreshTime", TimeUnit.MILLISECONDS.toSeconds(time.getRefresh()));
synchronized (dateFormat) {
- postTime.put("tooltip", dateFormat.format(new Date(post.getTime())));
+ postTime.put("tooltip", dateFormat.format(new Date(post.get().getTime())));
}
postTimes.put(id, postTime);
}
if (allIds.length() > 0) {
String[] ids = allIds.split(",");
for (String id : ids) {
- PostReply reply = webInterface.getCore().getPostReply(id, false);
- if (reply == null) {
+ Optional<PostReply> reply = webInterface.getCore().getPostReply(id);
+ if (!reply.isPresent()) {
continue;
}
JsonObject replyTime = new JsonObject();
- Time time = getTime(reply.getTime());
+ Time time = getTime(reply.get().getTime());
replyTime.put("timeText", time.getText());
replyTime.put("refreshTime", TimeUnit.MILLISECONDS.toSeconds(time.getRefresh()));
synchronized (dateFormat) {
- replyTime.put("tooltip", dateFormat.format(new Date(reply.getTime())));
+ replyTime.put("tooltip", dateFormat.format(new Date(reply.get().getTime())));
}
replyTimes.put(id, replyTime);
}
import net.pterodactylus.sone.web.page.FreenetRequest;
import net.pterodactylus.util.json.JsonObject;
+import com.google.common.base.Optional;
+
/**
* AJAX page that lets the user mark a number of {@link Sone}s, {@link Post}s,
* or {@link Reply}s as known.
Core core = webInterface.getCore();
for (String id : ids) {
if (type.equals("post")) {
- Post post = core.getPost(id, false);
- if (post == null) {
+ Optional<Post> post = core.getPost(id);
+ if (!post.isPresent()) {
continue;
}
- core.markPostKnown(post);
+ core.markPostKnown(post.get());
} else if (type.equals("reply")) {
- PostReply reply = core.getPostReply(id, false);
- if (reply == null) {
+ Optional<PostReply> reply = core.getPostReply(id);
+ if (!reply.isPresent()) {
continue;
}
- core.markReplyKnown(reply);
+ core.markReplyKnown(reply.get());
} else if (type.equals("sone")) {
Sone sone = core.getSone(id, false);
if (sone == null) {