Author: xor
Date: 2008-10-29 22:50:08 +0000 (Wed, 29 Oct 2008)
New Revision: 23208
Modified:
trunk/plugins/FMSPlugin/FMSBoard.java
Log:
Finish the thread assembly algorithm. PLEASE REVIEW! I have not tested it and I
might have forgotten special cases.
Modified: trunk/plugins/FMSPlugin/FMSBoard.java
===================================================================
--- trunk/plugins/FMSPlugin/FMSBoard.java 2008-10-29 22:46:28 UTC (rev
23207)
+++ trunk/plugins/FMSPlugin/FMSBoard.java 2008-10-29 22:50:08 UTC (rev
23208)
@@ -4,6 +4,7 @@
package plugins.FMSPlugin;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
@@ -23,16 +24,29 @@
*
*/
public class FMSBoard extends UpdatableSortedLinkedListItemImpl implements
IndexableUpdatableSortedLinkedListItem {
+
- private final FMSBoard self = this;
+ /**
+ * Contains all messages in this board.
+ * TODO: Figure out whether we really need this or should just use the
global message hashtable of the FMSMessageManager.
+ */
+ private Hashtable<FreenetURI, FMSMessage> mAllMessages = new
Hashtable<FreenetURI, FMSMessage>();
/**
- * Contains all messages in this board, both as a Hashmap and as a
linked list which is sorted by date.
+ * Contains all threads in this board, both as a Hashmap and as a
linked list which is sorted by date.
* The hashmap is useful for checking whether a message was already
stored.
* The linked list allows fast displaying of all messages.
*/
- private final UpdatableSortedLinkedListWithForeignIndex mMessages = new
UpdatableSortedLinkedListWithForeignIndex();
+ private UpdatableSortedLinkedListWithForeignIndex mThreads = new
UpdatableSortedLinkedListWithForeignIndex();
+ /**
+ * Contains orphans for which even the parent thread did not exist.
They are currently listed in the threads list and have to be removed
+ * from it if their thread is found.
+ */
+ private LinkedList<FMSMessage> mAbsoluteOrphans = new
LinkedList<FMSMessage>();
+
+ private final FMSBoard self = this;
+
private final FMSMessageManager mMessageManager;
private final String mName;
@@ -72,32 +86,80 @@
return mName;
}
+ /**
+ * Called by the <code>FMSMessageManager</code> to add a just received
message to the board.
+ * The job for this function is to find the right place in the
thread-tree for the new message and to move around older messages
+ * if a parent message of them is received.
+ */
public void addMessage(FMSMessage newMessage) throws
UpdatableSortedLinkedListKilledException {
- if(mMessages.containsKey(newMessage)) {
+ if(mAllMessages.containsKey(newMessage)) {
/* The message was already stored */
assert(false); /* TODO: Add logging. I don't know
whether this should happen. */
return;
}
+ mAllMessages.put(newMessage.getURI(), newMessage);
- if(newMessage.getParentURI() == null) {
- mMessages.add(newMessage);
- // FIXME: link children to the thread
+ if(newMessage.isThread()) { /* The message is a thread */
+ mThreads.add(newMessage);
}
else
{
FreenetURI parentURI = newMessage.getParentURI();
- FMSMessage parentMessage =
mMessageManager.get(parentURI);
- if(parentMessage == null) {
- mMessages.add(newMessage);
- /* FIXME: The MessageManager should try to
download the parent message if it's poster has enough trust.
- * If it is programmed to do that, it will
check its Hashtable whether the parent message already exists.
- * We also do that here, therefore, when
implementing parent message downloading, please do the Hashtable checking only
once.
- */
- return;
- } else {
+ FMSMessage parentMessage =
mMessageManager.get(parentURI); /* TODO: This allows crossposting. Figure out
whether we need to handle it specially */
+ if(parentMessage != null) {
parentMessage.addChild(newMessage);
+ } else { /* The message is an orphan */
+ FMSMessage parentThread =
mMessageManager.get(newMessage.getParentThreadURI());
+ if(parentThread != null) {
+ parentThread.addChild(newMessage);
/* We found its parent thread so just stick it in there for now */
+ }
+ else { /* The message is an absolute orphan */
+ mThreads.add(newMessage); /* TODO:
Instead of hiding the message completely, we make it look like a thread.
Reconsider this. */
+ mAbsoluteOrphans.add(newMessage);
+
+ /*
+ * FIXME: The MessageManager should try
to download the parent message if it's poster has enough trust.
+ * If it is programmed to do that, it
will check its Hashtable whether the parent message already exists.
+ * We also do that here, therefore,
when implementing parent message downloading, please do the Hashtable checking
only once.
+ */
+ }
+ }
+ }
+
+ linkOrphansToNewParent(newMessage);
+ }
+
+ private void linkOrphansToNewParent(FMSMessage newMessage) throws
UpdatableSortedLinkedListKilledException {
+ if(newMessage.isThread()) {
+ for(FMSMessage o : mAbsoluteOrphans) { /* Search in
the orphans for messages which belong to this thread */
+
if(o.getParentThreadURI().equals(newMessage.getURI())) {
+ newMessage.addChild(o);
+ mAbsoluteOrphans.remove(o);
+ }
}
}
+ else {
+ FMSMessage parentThread =
(FMSMessage)mThreads.get(newMessage.getParentThreadURI());
+ if(parentThread != null) { /* Search in its parent
thread for its children */
+ Iterator<FMSMessage> iter =
parentThread.childrenIterator();
+ while(iter.hasNext()) {
+ FMSMessage parentThreadChild =
iter.next();
+
+
if(parentThreadChild.getParentURI().equals(newMessage.getURI())) { /* We found
its parent, yeah! */
+ iter.remove(); /* It's a child
of the newMessage, not of the parentThread */
+
newMessage.addChild(parentThreadChild);
+ }
+ }
+ } else { /* The new message is an absolute orphan, find
its children amongst the other absolute orphans */
+ for(FMSMessage o : mAbsoluteOrphans) {
+
if(o.getParentURI().equals(newMessage.getURI())) {
+ newMessage.addChild(o);
+ mAbsoluteOrphans.remove(o);
+ }
+ }
+ }
+ }
+
}
@@ -106,10 +168,10 @@
* @param identity The identity viewing the board.
* @return An iterator of the message which the identity will see
(based on its trust levels).
*/
- public synchronized Iterator<FMSMessage> messageIterator(final
FMSOwnIdentity identity) {
+ public synchronized Iterator<FMSMessage> threadIterator(final
FMSOwnIdentity identity) {
return new Iterator<FMSMessage>() {
private final FMSOwnIdentity mIdentity = identity;
- private Iterator<FMSMessage> iter =
self.mMessages.iterator();
+ private Iterator<FMSMessage> iter =
self.mThreads.iterator();
private FMSMessage next = iter.hasNext() ? iter.next()
: null;
public boolean hasNext() {