⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threadedemails.java

📁 手机邮箱撒的方式方式方式的
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package mujmail.threading;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.Vector;

import mujmail.util.Functions;
import mujmail.IStorage;
import mujmail.MessageHeader;
import mujmail.Settings;
import mujmail.ordering.Comparator;

/**
 * This class represents structure for threaded e-mail.
 * Structure contains vector of root messages and for each root message
 * it contains {@link Vector} of child messages. Child messages vectors
 * are stored in hash map, in which root message ID is the key.
 * 
 * {@link ThreadedEmails} structure is used also for other boxes too
 * (f.e. Outbox, Draft, ...). In these boxes we do not need threads, so
 * in these cases only root messages are used and, for memory saving,
 * there are not empty vectors, but nulls.
 * 
 * @author Betlista
 */
public class ThreadedEmails implements IStorage {

    /** Flag signals if we want to print debug prints */
    private static final boolean DEBUG = false;

    /* *
     * While Hashtable does not support adding nulls, we use this
     * constant to represent that there is nothing in hashtable stored under
     * some key.
     */
//    private static final Object NULL = new Object(); // why not Vector? Because Object is the simplest class.

    /** Root messages, threads (with or without children). */
    private Vector/*<MessageHeader>*/ rootMessages;

    /**
     * Child vectors mapped in map, in which parent message ID is key under
     * which child vector is stored.
     */
    private Hashtable/*< String (parentID - threadedMessageID), Vector<MessageHeader> >*/ children;

    /**
     * Mapping for getting parent for child ID.
     */
    private Hashtable/*< String (childID - threadedMessageID), MessageHeader>*/ parents;

    /**
     * Number of e-mail headers stored in structure.
     */
    int size;

    /**
     * Creates empty structure.
     */
    public ThreadedEmails() {
        children = new Hashtable();
        parents = new Hashtable();
        rootMessages = new Vector();
        size = 0;
        lastReturnedHeader = null;
        lastReturnedIndex = 0;
    }

    /**
     * <p>Returns the index at which the message is stored in vector.</p>
     * <p>
     * Invariant of this method is, that this condition have to be true:<br>
     * <code>
     *   // index is the index returned by this method<br>
     *   // messages and threadingMessageID are parameters<br>
     * threadingMessageID.equals( messages.elementAt(index).getThreadingMessageID() )
     * </code>
     * </p>
     * @param messages vector to be searched in
     * @param threadingMessageID message ID we are looking message for
     * @return index of the message in the vectors
     */
    private int indexOf(final Vector/*<MessageHeaders>*/ messages, final String threadingMessageID) {
        final int size = messages.size();
        MessageHeader header;
        for (int i = 0; i < size; ++i) {
            header = (MessageHeader)messages.elementAt( i );
            if ( threadingMessageID.equals( header.getThreadingMessageID() ) ) {
                return i;
            }
        }
        return -1;
    }
    /**
     * Adds root (new thread) to vector of root messages.
     * 
     * @param messageHeader e-mail header that represents thread parent
     *        message
     */
    public void addRoot(final MessageHeader messageHeader) {
          if (DEBUG) System.out.println("DEBUG ThreadedEmails.addRoot(MessageHeader) - message header: " + messageHeader );
          if (DEBUG) System.out.println("DEBUG ThreadedEmails.addRoot(MessageHeader) - size (start): " + size);
          // if the message is the empty root message and showing of these 
          //   messages is turned off, such message is skipped
//        if ( !Settings.rootsVisible && messageHeader.isEmpty() ) {
//        	return;
//        }
        final int index = indexOf(rootMessages, messageHeader.getThreadingMessageID() );
          if (DEBUG) System.out.println("DEBUG ThreadedEmails.addMessage(MessageHeader, MessageHeader) - index: " + index);
          // if there is not this message in root messages
        if ( index == -1 ) {
            rootMessages.addElement( messageHeader );
            //String messageID = messageHeader.getThreadingMessageID();
            //children.put(messageID, NULL); // have no children yet
            //parents.put(messageID, NULL); // have no parent too (it's root message)
            ++size;
        } else {
            MessageHeader header = (MessageHeader)rootMessages.elementAt( index );
            if ( header.isEmpty() ) {
                rootMessages.setElementAt( messageHeader, index);
            } else {
                  // this is here because we support multiple messages with same
                  //   threading message ID
                rootMessages.addElement( messageHeader );
                ++size;
            }
        }
          if (DEBUG) System.out.println("DEBUG ThreadedEmails.addRoot(MessageHeader) - size (end): " + size);
    }

    /**
     * Adds message to thread. rootMessageID could be different from
     * messageHeaders parent ID.
     * 
     * @param parentMessage e-mail header message ID of the parent message
     * @param messageHeader e-mail header to be added to the thread
     */
    public void addMessage( final MessageHeader parentMessage, final MessageHeader messageHeader ) {
          if (DEBUG) System.out.println("DEBUG ThreadedEmails.addMessage(MessageHeader, MessageHeader) - rootMessage: " + parentMessage + ", messageHeader: " + messageHeader);
          if (DEBUG) System.out.println("DEBUG ThreadedEmails.addMessage(MessageHeader, MessageHeader) - size (start): " + size);
          // when threading is not enabled - all messages are added to the root messages
        if ( ! Settings.threading ) {
        	addRoot( messageHeader );
        	return;
        }
          // roots are added yet
          // add to parents
        parents.put( messageHeader.getThreadingMessageID(), parentMessage );
          // add to children
        Object childVector = children.get( parentMessage.getThreadingMessageID() );
        if ( childVector instanceof Vector ) {
            ((Vector)childVector).addElement( messageHeader );
            ++size;
        } else {
            Vector v = new Vector();
            v.addElement( messageHeader );
            children.put( parentMessage.getThreadingMessageID(), v );
            ++size;
        }
    }

    /* ************************
     *    Interface methods   *
     **************************/

    /*
     * (non-Javadoc)
     * @see mujmail.IStorage#getEnumeration()
     */
    public Enumeration getEnumeration() {
        return new Enumerator();
    }

    /**
     * Simply returns number of e-mail headers in structure.
     * Number of messages is increased when
     * {@link #addMessage(MessageHeader, MessageHeader)} is called.
     * 
     * @return number of e-mail headers in structure.
     */
    public int getSize() {
        return size;
    }

    /**
     * Returns whether structure is empty.
     * 
     * @return true if structure is empty (size == 0), false when size > 0
     */
    public boolean isEmpty() {
        return size == 0;
    }

    private int lastReturnedIndex = 0;
    private MessageHeader lastReturnedHeader = null;

    //#ifdef MUJMAIL_TEST_GET_MESSAGE_AT
//#     public static int simpleNext = 0;
//#     public static int simplePrevious = 0;
//#     public static int nextFromZero = 0;
    //#endif

    /*
     * (non-Javadoc)
     * @see mujmail.IStorage#getMessageAt(int)
     */
    public MessageHeader getMessageAt(final int index) {
          if (DEBUG) { System.out.println("DEBUG ThreadedEmails.getMessageAt(" + index + ")" ); }
          //System.out.println("  lastReturnedIndex = " + lastReturnedIndex);
          //System.out.println("  lastReturnedHeader= " + lastReturnedHeader);

        /* TODO (Betlista): this implementation is really stupid, but
           *   this method should not be used, I want to remove usage of this
           *   method from the code
           */

          /* Betlista:
           * Previous comment is correct, but we can assume that when user uses
           * this method he wants with quite good possibility the next message
           * he wanted before - on this is based next solution:
           * 
           * I remember previously returned message and it's index and when user
           * request message with index i than:
           *   when i > lastReturnedIndex
           *     than it's called nextElement() until lastReturned == i
           *   when i < lastReturnedIndex && i > (lastReturnedIndex - i)
           *     than it's called previousElement() until lastReturned == i
           *   when i < lastReturnedIndex && i < (lastReturnedIndex - i)
           *     than it's called nextElement() for i times (from zero)
           * 
           * Note: lastReturnedIndex is shifted by one again current position
           *  lastReturnedIndex=5 means that we returned 4th position (position are conted from 0)
           */
        final Enumerator messages = new Enumerator();
        MessageHeader messageHeader = null;

        // Note: This guard has to be here because other 3 possibilities (noted above)
        //  moves index immediately
        // We want to know same position as in last call
        if (index == lastReturnedIndex - 1) { // -1 is shift between lastReturedIndex and real position
            return lastReturnedHeader;
        }
        
        if (index >= lastReturnedIndex) {
            //#ifdef MUJMAIL_TEST_GET_MESSAGE_AT
//#             ++simpleNext;
            //#endif
            messages.actual = lastReturnedHeader;
            messages.index = lastReturnedIndex;
            while ( messages.hasNextElement() ) {
                messageHeader = (MessageHeader)messages.nextElement();
                  //if (DEBUG) { System.out.println(" (" + (messages.index) + ") " + messageHeader); }
                if ( messages.index - 1 == index ) {
                    lastReturnedHeader = messages.actual;
                    lastReturnedIndex = messages.index;
                    break;
                }
            }
        } else if ( index < lastReturnedIndex ) {
            if ( index < lastReturnedIndex - index ) {
                //#ifdef MUJMAIL_TEST_GET_MESSAGE_AT
//#                 ++nextFromZero;
                //#endif
                while ( messages.hasNextElement() ) {
                    messageHeader = (MessageHeader)messages.nextElement();
                    //if (DEBUG) { System.out.println(" (" + (messages.index) + ") " + messageHeader); }
                    if ( messages.index - 1 == index ) {
                        lastReturnedHeader = messages.actual;
                        lastReturnedIndex = messages.index;
                        break;
                    }
                }
            } else {
                //#ifdef MUJMAIL_TEST_GET_MESSAGE_AT
//#                 ++simplePrevious;
                //#endif
                messages.actual = lastReturnedHeader;
                messages.index = lastReturnedIndex;
                while ( messages.hasPreviousElement() ) {
                    messageHeader = (MessageHeader)messages.previousElement();
                    //if (DEBUG) { System.out.println(" (" + (messages.index) + ") " + messageHeader); }
                    if ( messages.index - 1 == index ) {
                        lastReturnedHeader = messages.actual;
                        lastReturnedIndex = messages.index;
                        break;
                    }
                }
            }
        }
          //System.out.println("Result (" + index + ")=" + messageHeader);
          //System.out.println("  lastReturnedIndex = " + lastReturnedIndex);
          //System.out.println("  lastReturnedHeader= " + lastReturnedHeader);
          //System.out.println();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -