package com.oreilly.forum.domain;
import java.util.*;
/**
* Arranges a collection of MessageSummary objects into a tree.
*/
public class MessageTree {
private List topLevelMsgs = new ArrayList();
// map ids to MessageSummary objects
private Map idToMsgMap = new HashMap();
// map reply-to ids to lists of MessageSummary objects
private Map replyIDToMsgListMap = new HashMap();
/**
* Construct a new message tree from an iterator of MessageSummary
* objects.
*/
public MessageTree(Iterator messages) {
while (messages.hasNext()) {
// store each message in a map for fast retrieval by ID
MessageSummary curMsg = (MessageSummary) messages.next();
this.idToMsgMap.put(new Long(curMsg.getID()), curMsg);
// build the inverted map that maps reply-to IDs to
// lists of messages
Long curReplyID = new Long(curMsg.getInReplyTo());
List replyToList =
(List) this.replyIDToMsgListMap.get(curReplyID);
if (replyToList == null) {
replyToList = new ArrayList();
this.replyIDToMsgListMap.put(curReplyID, replyToList);
}
replyToList.add(curMsg);
}
// build the list of top-level messages. A top-level message
// fits one of the following two criteria:
// - its reply-to ID is -1
// - its reply-to ID was not found in the list of messages. This
// occurs when a message is a reply to a previous month's message
Iterator iter = this.replyIDToMsgListMap.keySet().iterator();
while (iter.hasNext()) {
Long curReplyToID = (Long) iter.next();
if (curReplyToID.longValue() == -1
|| !this.idToMsgMap.containsKey(curReplyToID)) {
List msgsToAdd =
(List) this.replyIDToMsgListMap.get(curReplyToID);
this.topLevelMsgs.addAll(msgsToAdd);
}
}
Collections.sort(this.topLevelMsgs);
}
public Iterator getTopLevelMessages() {
return Collections.unmodifiableList(this.topLevelMsgs).iterator();
}
/**
* @return an iterator of MessageSummary objects that are replies
* to the specified message.
*/
public Iterator getReplies(MessageSummary msg) {
List replies = (List) this.replyIDToMsgListMap.get(
new Long(msg.getID()));
if (replies != null) {
Collections.sort(replies);
return replies.iterator();
} else {
return Collections.EMPTY_LIST.iterator();
}
}
}
|