package net.pterodactylus.sone.core;
+import static com.google.common.base.Optional.absent;
import static com.google.common.base.Optional.of;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import net.pterodactylus.sone.database.PostBuilder.PostCreated;
import net.pterodactylus.sone.database.PostReplyBuilder;
import net.pterodactylus.sone.database.PostReplyBuilder.PostReplyCreated;
+import net.pterodactylus.sone.database.SoneBuilder.SoneCreated;
import net.pterodactylus.sone.database.SoneProvider;
import net.pterodactylus.sone.fcp.FcpInterface;
import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
synchronized (sones) {
final Sone sone;
try {
- sone = database.newSoneBuilder().by(ownIdentity).local().build().setInsertUri(new FreenetURI(ownIdentity.getInsertUri())).setRequestUri(new FreenetURI(ownIdentity.getRequestUri()));
+ sone = database.newSoneBuilder().by(ownIdentity.getId()).local().build(Optional.<SoneCreated>absent()).setInsertUri(new FreenetURI(ownIdentity.getInsertUri())).setRequestUri(new FreenetURI(ownIdentity.getRequestUri()));
} catch (MalformedURLException mue1) {
logger.log(Level.SEVERE, String.format("Could not convert the Identity’s URIs to Freenet URIs: %s, %s", ownIdentity.getInsertUri(), ownIdentity.getRequestUri()), mue1);
return null;
return null;
}
synchronized (sones) {
- final Sone sone = database.newSoneBuilder().by(identity).build();
+ final Sone sone = database.newSoneBuilder().by(identity.getId()).build(Optional.<SoneCreated>absent());
if (sone.isLocal()) {
return sone;
}
- sone.setIdentity(identity);
boolean newSone = sone.getRequestUri() == null;
sone.setRequestUri(SoneUri.create(identity.getRequestUri()));
sone.setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), (long) 0));
@SuppressWarnings("synthetic-access")
public void run() {
Optional<Sone> sone = getRemoteSone(identity.getId());
- sone.get().setIdentity(identity);
sone.get().setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), sone.get().getLatestEdition()));
soneDownloader.addSone(sone.get());
soneDownloader.fetchSone(sone.get());
return null;
}
- Sone sone = new DefaultSone(new MemoryDatabase(null), originalSone.getId(), originalSone.isLocal()).setIdentity(originalSone.getIdentity());
+ Sone sone = new DefaultSone(new MemoryDatabase(null), originalSone.getId(), originalSone.isLocal());
SimpleXML soneXml;
try {
Identity getIdentity();
/**
- * Sets the identity of this Sone. The {@link Identity#getId() ID} of the
- * identity has to match this Sone’s {@link #getId()}.
- *
- * @param identity
- * The identity of this Sone
- * @return This Sone (for method chaining)
- * @throws IllegalArgumentException
- * if the ID of the identity does not match this Sone’s ID
- */
- Sone setIdentity(Identity identity) throws IllegalArgumentException;
-
- /**
* Returns the name of this Sone.
*
* @return The name of this Sone
--- /dev/null
+package net.pterodactylus.sone.data.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import net.pterodactylus.sone.database.SoneBuilder;
+import net.pterodactylus.sone.freenet.wot.Identity;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.internal.util.$Preconditions;
+
+/**
+ * Abstract {@link SoneBuilder} implementation.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public abstract class AbstractSoneBuilder implements SoneBuilder {
+
+ protected String id;
+ protected boolean local;
+
+ @Override
+ public SoneBuilder by(String id) {
+ this.id = id;
+ return this;
+ }
+
+ @Override
+ public SoneBuilder local() {
+ local = true;
+ return this;
+ }
+
+ protected void validate() throws IllegalStateException {
+ checkState(id != null, "id must not be null");
+ }
+
+}
/** Whether the Sone is local. */
private final boolean local;
- /** The identity of this Sone. */
- private Identity identity;
-
/** The URI under which the Sone is stored in Freenet. */
private volatile FreenetURI requestUri;
}
public Identity getIdentity() {
- return identity;
- }
-
- public DefaultSone setIdentity(Identity identity) throws IllegalArgumentException {
- if (!identity.getId().equals(id)) {
- throw new IllegalArgumentException("Identity’s ID does not match Sone’s ID!");
- }
- this.identity = identity;
- return this;
+ return database.getIdentity(id).get();
}
public String getName() {
- return (identity != null) ? identity.getNickname() : null;
+ return getIdentity().getNickname();
}
public boolean isLocal() {
@Override
public String toString() {
- return getClass().getName() + "[identity=" + identity + ",requestUri=" + requestUri + ",insertUri(" + String.valueOf(insertUri).length() + "),friends(" + friendSones.size() + "),posts(" + posts.size() + "),replies(" + replies.size() + "),albums(" + getRootAlbum().getAlbums().size() + ")]";
+ return getClass().getName() + "[id=" + id + ",requestUri=" + requestUri + ",insertUri(" + String.valueOf(insertUri).length() + "),friends(" + friendSones.size() + "),posts(" + posts.size() + "),replies(" + replies.size() + "),albums(" + getRootAlbum().getAlbums().size() + ")]";
}
}
--- /dev/null
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.database.Database;
+import net.pterodactylus.sone.database.SoneBuilder;
+
+import com.google.common.base.Optional;
+
+/**
+ * {@link SoneBuilder} implementation that can create {@link DefaultSone}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class DefaultSoneBuilder extends AbstractSoneBuilder {
+
+ private final Database database;
+
+ public DefaultSoneBuilder(Database database) {
+ this.database = database;
+ }
+
+ @Override
+ public Sone build(Optional<SoneCreated> soneCreated) throws IllegalStateException {
+ validate();
+ Sone sone = new DefaultSone(database, id, local);
+ if (soneCreated.isPresent()) {
+ soneCreated.get().soneCreated(sone);
+ }
+ return sone;
+ }
+
+}
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
-public interface Database extends Service, SoneDatabase, PostDatabase, PostReplyDatabase, AlbumDatabase, ImageDatabase {
+public interface Database extends Service, IdentityDatabase, SoneDatabase, PostDatabase, PostReplyDatabase, AlbumDatabase, ImageDatabase {
/**
* Saves the database.
--- /dev/null
+package net.pterodactylus.sone.database;
+
+import net.pterodactylus.sone.freenet.wot.Identity;
+
+import com.google.common.base.Optional;
+
+/**
+ * Database for handling {@link Identity}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ’Bombe‘ Roden</a>
+ */
+public interface IdentityDatabase {
+
+ Optional<Identity> getIdentity(String identityId);
+
+}
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.freenet.wot.Identity;
+import com.google.common.base.Optional;
+
/**
* Builder for {@link Sone} objects.
*
*/
public interface SoneBuilder {
- SoneBuilder by(Identity identity);
+ SoneBuilder by(String id);
SoneBuilder local();
- Sone build() throws IllegalStateException;
+ Sone build(Optional<SoneCreated> soneCreated) throws IllegalStateException;
+
+ interface SoneCreated {
+
+ void soneCreated(Sone createdSone);
+
+ }
}
import net.pterodactylus.sone.database.DatabaseException;
import net.pterodactylus.sone.database.PostDatabase;
import net.pterodactylus.sone.database.SoneBuilder;
+import net.pterodactylus.sone.freenet.wot.Identity;
import net.pterodactylus.util.config.Configuration;
import net.pterodactylus.util.config.ConfigurationException;
import com.google.common.base.Optional;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Maps;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import com.google.common.util.concurrent.AbstractService;
/** The configuration. */
private final Configuration configuration;
+ private final Map<String, Identity> identities = Maps.newHashMap();
private final Map<String, Sone> sones = new HashMap<String, Sone>();
/** All posts by their ID. */
}
@Override
+ public Optional<Identity> getIdentity(String identityId) {
+ lock.readLock().lock();
+ try {
+ return fromNullable(identities.get(identityId));
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ @Override
public Optional<Sone> getSone(String soneId) {
lock.readLock().lock();
try {