📄 algorithm.java
字号:
package mujmail.threading;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import mujmail.MessageHeader;
import mujmail.Settings;
/**
* Class represents algorithm for creating mail threads.
*
* Algorithm is based on description written by Jamie Zawinski at
* <a href="http://www.jwz.org/doc/threading.html">
* http://www.jwz.org/doc/threading.html
* </a>
*
* @author Betlista
*/
public class Algorithm {
/** Subject for empty root messages. */
private static final String EMPTY_MESSAGE_SUBJECT = "root";
/** Flag signals if we want to print debug prints. */
public static final boolean DEBUG = false; // used in MailDB too
/** Instance of the singleton class. */
private static final Algorithm algorithm = new Algorithm();
/** Method to enable accessing the {@link #Algorithm()} instance. */
public static Algorithm getAlgorithm() {
return algorithm;
}
/**
* Algorithm that group messages to so called threads - group of messages
* that belongs together, this messages create discussion.
*
* Algorithm assumes that all MessageHeaders have set parent IDs.
*
* This method just call {@link #processMessage(Hashtable, MessageHeader)}
* for each message in messageHeaders.
*
* @param messageHeaders to be sorted
* @see #processMessage(Hashtable, MessageHeader)
*/
public ThreadedEmails invoke(final Vector/*<MessageHeaders>*/ messageHeaders) {
if (DEBUG) System.out.println("DEBUG Algorithm.invoke(" + messageHeaders.toString() + ")");
if ( !Settings.threading ) {
final ThreadedEmails threadedEmails = new ThreadedEmails();
final int size = messageHeaders.size();
for ( int i = 0; i < size; ++i) {
threadedEmails.addRoot( (MessageHeader)messageHeaders.elementAt(i) );
}
return threadedEmails;
}
try {
//checkContent( messageHeaders );
// idTable represents mapping, it maps message (represented by
// message ID) to Container
final Hashtable idTable2 = new Hashtable( messageHeaders.size() ); // Hashtable<String /*messageID*/, Vector<MessageHeader> >
// for each message
MessageHeader message;
final int size = messageHeaders.size();
for ( int i = 0; i < size; ++i) {
message = (MessageHeader)messageHeaders.elementAt( i );
processMessage( idTable2, message );
}
if (DEBUG) System.out.println("=== Creating threads ===");
// when all messages are processed, we have parent message for each one
ThreadedEmails structure = createThreads( idTable2 );
if (DEBUG) {
System.out.println("DEBUG Algorithm.invoke(Vector) - end" );
//#ifdef MUJMAIL_DEVELOPMENT
//# structure.printToConsole();
//#endif
}
return structure;
} catch (Throwable t) {
System.err.println("ERROR Algorithm.invoke(Vector) - unexpected exception");
t.printStackTrace();
if (DEBUG) System.out.println("DEBUG Algorithm.invoke(Vector) - end, returning null");
return null;
}
}
/**
* Checks if message ID is already in idTable.
* <ul>
* <li>if it's not we put the message header into ID table</li>
* <li>when it is in idTable we check if the message header is empty (it
* was processed as reference in previous steps of algorithm) we
* simply mark it as not empty</li>
* <ul>
* <li>when the message is not empty that means we are processing same
* message again and that is error - exception is thrown</li>
* </ul>
* </ul>
* @param idTable
* @param messageHeader
* @exception IllegalStateException when message already processed wants to
* be processed again (or object in ID table is not instance
* of {@link MessageHeader message header})
*/
private void processMessage(final Hashtable/*<String, MessageHeader>*/ idTable, final MessageHeader messageHeader) throws IllegalStateException {
if (DEBUG) {
System.out.println("DEBUG Algorithm.processMessage(..., " + messageHeader.toString() + ")");
//#ifdef MUJMAIL_DEVELOPMENT
//# dumpIDTable(idTable);
//#endif
}
final String messageID = messageHeader.getThreadingMessageID();
// 1. A.)
Object o = idTable.get( messageID );
Vector messageHeaders;
if ( o == null ) {
// message is not in idTable yet
messageHeaders = new Vector();
messageHeaders.addElement( messageHeader );
idTable.put( messageID, messageHeaders );
} else {
messageHeaders = (Vector)o;
MessageHeader storedMessageHeader = (MessageHeader)messageHeaders.elementAt( 0 ); // get first element
if ( storedMessageHeader.isEmpty() ) {
// container does not reference to any message
// this could happen when we processed message references
// and there was no container created for reference, so
// we created empty container
//storedMessageHeader.setEmpty( false );
messageHeaders = new Vector();
messageHeaders.addElement( messageHeader );
idTable.put( messageID, messageHeaders );
} else {
messageHeaders.addElement( messageHeader );
// idTable3.put( messageID, messageHeader ); // not needed
}
}
processMessageParentIDs(idTable, messageHeader);
}
/**
* For each message loops over the list of message parents and adds the
* parent (grandparent, ...) to ID table.
*
* @param idTable
* @param messageHeader
* @throws IllegalStateException
*/
private void processMessageParentIDs(final Hashtable idTable, final MessageHeader messageHeader) throws IllegalStateException {
if (DEBUG) {
System.out.println("DEBUG Algorithm.processMessageParentIDs(..., " + messageHeader.toString() + ")");
//#ifdef MUJMAIL_DEVELOPMENT
//# dumpIDTable(idTable);
//#endif
}
//final Vector messageHeaders = (Vector)idTable.get( messageHeader.getThreadingMessageID() );
final Vector parentIDs = messageHeader.getParentIDs(); // Vector<String>
final int size = parentIDs.size();
if (DEBUG) {
System.out.println( "DEBUG Algorithm.processMessageParentIDs(..., ...) - size: " + size );
System.out.println( "DEBUG Algorithm.processMessageParentIDs(..., ...) - parentIDs: " + parentIDs );
}
if (size == 0) return; // if there are no parent IDs we have nothing to do
String previousParentID = null;
String parentID = null;
Vector parentIDVector;
MessageHeader parentHeader = null;
for ( int i = 0; i < size; ++i) {
// parentID = message ID of parent message
parentID = (String)parentIDs.elementAt( i );
parentIDVector = (Vector)idTable.get( parentID );
if ( parentIDVector == null ) {
parentHeader = null;
} else {
parentHeader = (MessageHeader)parentIDVector.elementAt( 0 );
}
if ( parentHeader == null ) {
// if such message is not in idTable add it as a empty box
parentHeader = new MessageHeader( messageHeader.getBox() );
parentHeader.setThreadingMessageID( parentID );
parentHeader.setSubject( EMPTY_MESSAGE_SUBJECT );
parentHeader.setParentID( previousParentID );
parentHeader.setEmpty( true );
Vector vector = new Vector();
vector.addElement( parentHeader );
idTable.put(parentID, vector );
}
// parentHeader = messageHeader;
previousParentID = parentID;
//#ifdef MUJMAIL_DEVELOPMENT
//# if (DEBUG) dumpIDTable(idTable);
//#endif
}
// final int parentIDVectorSize = messageHeaders.size();
// for all messages in parent ID vector set parentID
// for ( int j = 0; j < parentIDVectorSize; ++j ) {
// ((MessageHeader)messageHeaders.elementAt( j )).setParentID( parentID );
// }
// break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -