X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=b838216860d0593ac5a8d6badf959cb63d067a33;hb=358a9a2ab0ead0cc4dd86e3b97fa387ec958ec01;hp=3c3a659872c6d980607cbf43840f7e9f5c92aadd;hpb=adf590c0b33f1cc3f136d8d3a714f7051407535f;p=Sone.git diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index 3c3a659..b838216 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -18,9 +18,13 @@ package net.pterodactylus.sone.core; import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -29,18 +33,14 @@ import java.util.logging.Logger; import net.pterodactylus.sone.core.SoneException.Type; import net.pterodactylus.sone.data.Post; -import net.pterodactylus.sone.data.PostShell; import net.pterodactylus.sone.data.Profile; import net.pterodactylus.sone.data.Reply; -import net.pterodactylus.sone.data.ReplyShell; -import net.pterodactylus.sone.data.Shell; -import net.pterodactylus.sone.data.ShellCache; import net.pterodactylus.sone.data.Sone; -import net.pterodactylus.sone.data.SoneShell; import net.pterodactylus.util.config.Configuration; import net.pterodactylus.util.config.ConfigurationException; import net.pterodactylus.util.logging.Logging; import net.pterodactylus.util.service.AbstractService; +import freenet.client.FetchResult; import freenet.keys.FreenetURI; /** @@ -71,13 +71,13 @@ public class Core extends AbstractService { /* various caches follow here. */ /** Cache for all known Sones. */ - private final ShellCache soneCache = new ShellCache(SoneShell.creator); + private final Map soneCache = new HashMap(); /** Cache for all known posts. */ - private final ShellCache postCache = new ShellCache(PostShell.creator); + private final Map postCache = new HashMap(); /** Cache for all known replies. */ - private final ShellCache replyCache = new ShellCache(ReplyShell.creator); + private final Map replyCache = new HashMap(); /** * Creates a new core. @@ -111,7 +111,8 @@ public class Core extends AbstractService { */ public Core freenetInterface(FreenetInterface freenetInterface) { this.freenetInterface = freenetInterface; - soneDownloader = new SoneDownloader(freenetInterface); + soneDownloader = new SoneDownloader(this, freenetInterface); + soneDownloader.start(); return this; } @@ -125,18 +126,92 @@ public class Core extends AbstractService { } /** - * Returns a Sone or a {@link Shell} around one for the given ID. + * Returns the Sone with the given ID, or an empty Sone that has been + * initialized with the given ID. * * @param soneId * The ID of the Sone - * @return The Sone, or a {@link Shell} around one + * @return The Sone */ public Sone getSone(String soneId) { - Sone sone = soneCache.get(soneId); - if (sone instanceof SoneShell) { - soneCache.put(soneId, sone = ((SoneShell) sone).getShelled()); + if (!soneCache.containsKey(soneId)) { + Sone sone = new Sone(soneId); + soneCache.put(soneId, sone); } - return sone; + return soneCache.get(soneId); + } + + /** + * Returns all known sones. + * + * @return All known sones + */ + public Collection getKnownSones() { + return soneCache.values(); + } + + /** + * Creates a new post. + * + * @param sone + * The sone that creates the post + * @param text + * The text of the post + * @return The created post + */ + public Post createPost(Sone sone, String text) { + return createPost(sone, System.currentTimeMillis(), text); + } + + /** + * Creates a new post. + * + * @param sone + * The Sone that creates the post + * @param time + * The time of the post + * @param text + * The text of the post + * @return The created post + */ + public Post createPost(Sone sone, long time, String text) { + Post post = getPost(UUID.randomUUID().toString()).setSone(sone).setTime(time).setText(text); + sone.addPost(post); + return post; + } + + /** + * Creates a reply. + * + * @param sone + * The Sone that posts the reply + * @param post + * The post the reply refers to + * @param text + * The text of the reply + * @return The created reply + */ + public Reply createReply(Sone sone, Post post, String text) { + return createReply(sone, post, System.currentTimeMillis(), text); + } + + /** + * Creates a reply. + * + * @param sone + * The Sone that posts the reply + * @param post + * The post the reply refers to + * @param time + * The time of the post + * @param text + * The text of the reply + * @return The created reply + */ + public Reply createReply(Sone sone, Post post, long time, String text) { + Reply reply = getReply(UUID.randomUUID().toString()).setSone(sone).setPost(post).setTime(time).setText(text); + sone.addReply(reply); + return reply; } // @@ -144,17 +219,27 @@ public class Core extends AbstractService { // /** + * Adds a Sone to watch for updates. The Sone needs to be completely + * initialized. + * + * @param sone + * The Sone to watch for updates + */ + public void addSone(Sone sone) { + soneCache.put(sone.getId(), sone); + soneDownloader.addSone(sone); + } + + /** * Adds the given Sone. * * @param sone * The Sone to add */ - public void addSone(Sone sone) { + public void addLocalSone(Sone sone) { if (localSones.add(sone)) { - soneCache.put(sone.getId(), sone); SoneInserter soneInserter = new SoneInserter(freenetInterface, sone); soneInserter.start(); - soneDownloader.addSone(sone); soneInserters.put(sone, soneInserter); } } @@ -206,11 +291,11 @@ public class Core extends AbstractService { Sone sone; try { logger.log(Level.FINEST, "Creating new Sone “%s” at %s (%s)…", new Object[] { name, finalRequestUri, finalInsertUri }); - sone = new Sone(UUID.randomUUID(), name, new FreenetURI(finalRequestUri).setKeyType("USK").setDocName("Sone-" + name), new FreenetURI(finalInsertUri).setKeyType("USK").setDocName("Sone-" + name)); + sone = getSone(UUID.randomUUID().toString()).setName(name).setRequestUri(new FreenetURI(finalRequestUri).setKeyType("USK").setDocName("Sone-" + name)).setInsertUri(new FreenetURI(finalInsertUri).setKeyType("USK").setDocName("Sone-" + name)); sone.setProfile(new Profile()); /* set modification counter to 1 so it is inserted immediately. */ sone.setModificationCounter(1); - addSone(sone); + addLocalSone(sone); } catch (MalformedURLException mue1) { throw new SoneException(Type.INVALID_URI); } @@ -218,6 +303,22 @@ public class Core extends AbstractService { } /** + * Loads the Sone from the given request URI. + * + * @param requestUri + * The request URI to load the Sone from + */ + public void loadSone(String requestUri) { + try { + FreenetURI realRequestUri = new FreenetURI(requestUri).setMetaString(new String[] { "sone.xml" }); + FetchResult fetchResult = freenetInterface.fetchUri(realRequestUri); + soneDownloader.parseSone(null, fetchResult, realRequestUri); + } catch (MalformedURLException mue1) { + logger.log(Level.INFO, "Could not create URI from “" + requestUri + "”.", mue1); + } + } + + /** * Deletes the given Sone from this plugin instance. * * @param sone @@ -229,6 +330,63 @@ public class Core extends AbstractService { localSones.remove(sone); } + /** + * Returns the post with the given ID. If no post exists yet with the given + * ID, a new post is returned. + * + * @param postId + * The ID of the post + * @return The post + */ + public Post getPost(String postId) { + if (!postCache.containsKey(postId)) { + postCache.put(postId, new Post(postId)); + } + return postCache.get(postId); + } + + /** + * Returns the reply with the given ID. If no reply exists yet with the + * given ID, a new reply is returned. + * + * @param replyId + * The ID of the reply + * @return The reply + */ + public Reply getReply(String replyId) { + if (!replyCache.containsKey(replyId)) { + replyCache.put(replyId, new Reply(replyId)); + } + return replyCache.get(replyId); + } + + /** + * Gets all replies to the given post, sorted by date, oldest first. + * + * @param post + * The post the replies refer to + * @return The sorted list of replies for the post + */ + public List getReplies(Post post) { + List replies = new ArrayList(); + for (Reply reply : replyCache.values()) { + if (reply.getPost().equals(post)) { + replies.add(reply); + } + } + Collections.sort(replies, new Comparator() { + + /** + * {@inheritDoc} + */ + @Override + public int compare(Reply leftReply, Reply rightReply) { + return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, leftReply.getTime() - rightReply.getTime())); + } + }); + return replies; + } + // // SERVICE METHODS // @@ -285,8 +443,7 @@ public class Core extends AbstractService { profile.setFirstName(firstName); profile.setMiddleName(middleName); profile.setLastName(lastName); - Sone sone = new Sone(UUID.fromString(id), name, new FreenetURI(requestUri), new FreenetURI(insertUri)); - soneCache.put(id, sone); + Sone sone = getSone(id).setName(name).setRequestUri(new FreenetURI(requestUri)).setInsertUri(new FreenetURI(insertUri)); sone.setProfile(profile); int postId = 0; do { @@ -297,8 +454,7 @@ public class Core extends AbstractService { } long time = configuration.getLongValue(postPrefix + "/Time").getValue(null); String text = configuration.getStringValue(postPrefix + "/Text").getValue(null); - Post post = new Post(UUID.fromString(id), sone, time, text); - postCache.put(id, post); + Post post = getPost(id).setSone(sone).setTime(time).setText(text); sone.addPost(post); } while (true); int replyCounter = 0; @@ -308,20 +464,31 @@ public class Core extends AbstractService { if (replyId == null) { break; } - Sone replySone = soneCache.get(configuration.getStringValue(replyPrefix + "/Sone/ID").getValue(null)); - String replySoneKey = configuration.getStringValue(replyPrefix + "/Sone/Key").getValue(null); - String replySoneName = configuration.getStringValue(replyPrefix + "/Sone/Name").getValue(null); - if (replySone instanceof SoneShell) { - ((SoneShell) replySone).setRequestUri(new FreenetURI(replySoneKey)).setName(replySoneName); - } - Post replyPost = postCache.get(configuration.getStringValue(replyPrefix + "/Post").getValue(null)); + Post replyPost = getPost(configuration.getStringValue(replyPrefix + "/Post").getValue(null)); long replyTime = configuration.getLongValue(replyPrefix + "/Time").getValue(null); String replyText = configuration.getStringValue(replyPrefix + "/Text").getValue(null); - Reply reply = new ReplyShell().setSone(replySone).setPost(replyPost).setTime(replyTime).setText(replyText).getShelled(); - replyCache.put(replyId, reply); + Reply reply = getReply(replyId).setSone(sone).setPost(replyPost).setTime(replyTime).setText(replyText); + sone.addReply(reply); } while (true); + + /* load friends. */ + int friendCounter = 0; + while (true) { + String friendPrefix = sonePrefix + "/Friend." + friendCounter++; + String friendId = configuration.getStringValue(friendPrefix + "/ID").getValue(null); + if (friendId == null) { + break; + } + Sone friendSone = getSone(friendId); + String friendKey = configuration.getStringValue(friendPrefix + "/Key").getValue(null); + String friendName = configuration.getStringValue(friendPrefix + "/Name").getValue(null); + friendSone.setRequestUri(new FreenetURI(friendKey)).setName(friendName); + soneDownloader.addSone(friendSone); + sone.addFriend(friendSone); + } + sone.setModificationCounter(modificationCounter); - addSone(sone); + addLocalSone(sone); } catch (MalformedURLException mue1) { logger.log(Level.WARNING, "Could not create Sone from requestUri (“" + requestUri + "”) and insertUri (“" + insertUri + "”)!", mue1); } @@ -365,15 +532,23 @@ public class Core extends AbstractService { for (Reply reply : sone.getReplies()) { String replyPrefix = sonePrefix + "/Reply." + replyId++; configuration.getStringValue(replyPrefix + "/ID").setValue(reply.getId()); - configuration.getStringValue(replyPrefix + "/Sone/ID").setValue(reply.getSone().getId()); - configuration.getStringValue(replyPrefix + "/Sone/Key").setValue(reply.getSone().getRequestUri().toString()); - configuration.getStringValue(replyPrefix + "/Sone/Name").setValue(reply.getSone().getName()); configuration.getStringValue(replyPrefix + "/Post").setValue(reply.getPost().getId()); configuration.getLongValue(replyPrefix + "/Time").setValue(reply.getTime()); configuration.getStringValue(replyPrefix + "/Text").setValue(reply.getText()); } /* write null ID as terminator. */ configuration.getStringValue(sonePrefix + "/Reply." + replyId + "/ID").setValue(null); + + int friendId = 0; + for (Sone friend : sone.getFriends()) { + String friendPrefix = sonePrefix + "/Friend." + friendId++; + configuration.getStringValue(friendPrefix + "/ID").setValue(friend.getId()); + configuration.getStringValue(friendPrefix + "/Key").setValue(friend.getRequestUri().toString()); + configuration.getStringValue(friendPrefix + "/Name").setValue(friend.getName()); + } + /* write null ID as terminator. */ + configuration.getStringValue(sonePrefix + "/Friend." + friendId + "/ID").setValue(null); + } /* write null ID as terminator. */ configuration.getStringValue("Sone/Sone." + soneId + "/ID").setValue(null);