1 21 22 package org.armedbear.j.mail; 23 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.Comparator ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 import javax.swing.tree.DefaultMutableTreeNode ; 32 import org.armedbear.j.Debug; 33 import org.armedbear.j.Log; 34 35 public final class SortByThread 36 { 37 private final List entries; 38 39 private final Node root = new Node (); 40 private final Map idMap = new HashMap (); 41 42 public SortByThread(List entries) 43 { 44 this.entries = Collections.unmodifiableList(entries); 45 } 46 47 public void run() 48 { 49 final int count = entries.size(); 50 ArrayList nodes = new ArrayList (count); 52 for (int i = 0; i < count; i++) { 53 final MailboxEntry entry = (MailboxEntry) entries.get(i); 54 Node node = new Node (entry); 55 nodes.add(node); 56 String messageId = entry.getMessageId(); 57 if (messageId != null && messageId.length() > 0) 58 idMap.put(messageId, node); 59 else 60 Debug.bug(); 61 } 62 63 for (int i = 0; i < count; i++) { 64 final MailboxEntry entry = (MailboxEntry) entries.get(i); 65 String [] references = entry.getReferences(); 67 if (references != null) { 68 for (int j = 0; j < references.length; j++) { 69 String reference = references[j]; 70 if (reference == null || reference.length() == 0) 71 continue; 72 Node node = (Node ) idMap.get(reference); 73 if (node == null) { 74 node = new Node (reference, entry.getBaseSubject()); 75 idMap.put(reference, node); 76 nodes.add(node); 77 } 78 } 79 } 80 String inReplyTo = entry.getInReplyTo(); 82 if (inReplyTo != null && inReplyTo.length() > 0) { 83 Node node = (Node ) idMap.get(inReplyTo); 84 if (node == null) { 85 node = new Node (inReplyTo, entry.getBaseSubject()); 86 idMap.put(inReplyTo, node); 87 nodes.add(node); 88 } 89 } 90 } 91 92 Iterator iter = nodes.iterator(); 93 while (iter.hasNext()) { 94 Node node = (Node ) iter.next(); 95 if (node.getParent() == null) { 96 Node parent = findParentForNode(node); 97 if (parent != null) 98 parent.add(node); 99 else 100 root.add(node); 101 } 102 } 103 104 removeEmptyContainers(root); 105 106 groupMessagesBySubject(); 107 108 sort(root); 110 } 111 112 private void removeEmptyContainers(final Node parent) 113 { 114 for (int i = 0; i < parent.getChildCount(); i++) { 115 Node node = (Node ) parent.getChildAt(i); 116 if (node.getMailboxEntry() == null && node.getChildCount() == 0) { 117 parent.remove(i); 119 --i; 120 continue; 121 } 122 if (node.getMailboxEntry() == null && node.getChildCount() > 0) { 123 Debug.assertTrue(node.getParent() == parent); 124 if (parent != root || node.getChildCount() == 1) { 125 for (int j = node.getChildCount(); j-- > 0;) { 126 Node child = (Node ) node.getChildAt(j); 127 Debug.assertTrue(child.getParent() == node); 128 node.remove(j); 129 Debug.assertTrue(child.getParent() == null); 130 parent.add(child); 131 Debug.assertTrue(child.getParent() == parent); 132 } 133 Debug.assertTrue(node.getChildCount() == 0); 134 parent.remove(i); 135 --i; 136 continue; 137 } 138 } 139 if (node.getMailboxEntry() != null) { 140 removeEmptyContainers(node); 141 } 142 } 143 } 144 145 private void groupMessagesBySubject() 146 { 147 HashMap subjectMap = createSubjectMap(); 148 149 for (int i = root.getChildCount(); i-- > 0; ) { 151 final Node node = (Node ) root.getChildAt(i); 152 MailboxEntry entry = node.getMailboxEntry(); 153 if (entry == null) { 154 if (node.getChildCount() > 0) 155 entry = ((Node )node.getChildAt(0)).getMailboxEntry(); 156 if (entry == null) 157 continue; 158 } 159 final String baseSubject = entry.getBaseSubject(); 160 if (baseSubject == null || baseSubject.length() == 0) 161 continue; 162 Node oldNode = (Node ) subjectMap.get(baseSubject); 163 if (oldNode == node) 164 continue; 165 166 if (oldNode.isDummy() && node.isDummy()) { 167 for (int j = node.getChildCount(); j-- > 0;) { 169 Node child = (Node ) node.getChildAt(j); 170 node.remove(j); 171 oldNode.add(child); 172 } 173 root.remove(i); 175 continue; 176 } 177 178 if (oldNode.isDummy()) { 179 Debug.assertTrue(!node.isDummy()); 180 root.remove(i); 182 oldNode.add(node); 183 continue; 184 } 185 186 Debug.assertTrue(!oldNode.isDummy()); 187 final MailboxEntry oldEntry = oldNode.getMailboxEntry(); 188 Debug.assertTrue(oldEntry != null); 189 if (!node.isDummy()) { 190 if (entry.subjectIsReply() && !oldEntry.subjectIsReply()) { 191 root.remove(i); 193 oldNode.add(node); 194 continue; 195 } 196 } 197 198 if (!entry.subjectIsReply() && !oldEntry.subjectIsReply()) 200 continue; 201 202 Node c = new Node (oldEntry); 205 for (int j = oldNode.getChildCount(); j-- > 0;) { 206 Node child = (Node ) oldNode.getChildAt(j); 207 oldNode.remove(j); 208 c.add(child); 209 } 210 oldNode.setUserObject(null); 212 oldNode.setBaseSubject(baseSubject); 213 oldNode.add(c); 215 oldNode.add(node); 216 } 217 218 subjectMap.clear(); 219 subjectMap = null; 220 } 221 222 private HashMap createSubjectMap() 223 { 224 HashMap subjectMap = new HashMap (); 225 for (int i = 0, limit = root.getChildCount(); i < limit; i++) { 226 final Node node = (Node ) root.getChildAt(i); 227 MailboxEntry entry = node.getMailboxEntry(); 228 if (entry == null) { 229 if (node.getChildCount() > 0) 231 entry = ((Node )node.getChildAt(0)).getMailboxEntry(); 232 else { 233 Log.debug("dummy node child count is zero"); 234 continue; 235 } 236 } 237 if (entry != null) { 238 String baseSubject = entry.getBaseSubject(); 239 if (baseSubject != null && baseSubject.length() > 0) { 240 Node oldNode = (Node ) subjectMap.get(baseSubject); 241 if (oldNode == null) { 242 subjectMap.put(baseSubject, node); 243 } else { 244 MailboxEntry oldEntry = oldNode.getMailboxEntry(); 245 if (oldEntry != null && oldEntry.subjectIsReply() && 246 !entry.subjectIsReply()) { 247 subjectMap.put(baseSubject, node); 248 } else if (node.getMailboxEntry() == null && oldEntry != null) { 249 subjectMap.put(baseSubject, node); 250 } 251 } 252 } 253 } 254 } 255 return subjectMap; 256 } 257 258 private void sort(Node node) 259 { 260 for (int i = 0, limit = node.getChildCount(); i < limit; i++) 262 sort((Node )node.getChildAt(i)); 263 if (node.getChildCount() > 1) 264 node.sortChildren(); 265 } 266 267 private Node findParentForNode(Node node) 268 { 269 final MailboxEntry entry = node.getMailboxEntry(); 270 if (entry == null) 271 return null; 272 final String inReplyTo = entry.getInReplyTo(); 273 if (inReplyTo != null) { 274 Node parent = (Node ) idMap.get(inReplyTo); 275 if (parent != null) 276 if (!parent.isNodeAncestor(node)) 277 return parent; 278 } 279 final String [] references = entry.getReferences(); 280 if (references != null) { 281 for (int i = references.length; i-- > 0;) { 282 Node parent = (Node ) idMap.get(references[i]); 283 if (parent != null) 284 if (!parent.isNodeAncestor(node)) 285 return parent; 286 } 287 } 288 return null; 289 } 290 291 private int sequenceNumber; 292 293 public void addEntries(Mailbox mb, MailboxFilter filter) 294 { 295 sequenceNumber = 1; 296 addEntriesForNode(root, mb, filter, 0); 297 } 298 299 private void addEntriesForNode(Node node, Mailbox mb, MailboxFilter filter, 300 int depth) 301 { 302 if (node != root) { 303 MailboxEntry entry = node.getMailboxEntry(); 304 if (entry != null) { 305 entry.setSequenceNumber(sequenceNumber++); 306 if (filter == null || filter.accept(entry)) 307 mb.appendLine(entry, depth); 308 } else { 309 if (node.getChildCount() > 0) { 310 Node child = (Node ) node.getChildAt(0); 311 MailboxEntry childEntry = child.getMailboxEntry(); 312 if (childEntry != null) 313 childEntry.setOrphan(true); 314 } 315 } 316 } 317 for (int i = 0, limit = node.getChildCount(); i < limit; i++) 318 addEntriesForNode((Node )node.getChildAt(i), mb, filter, depth + 1); 319 } 320 } 321 322 class Node extends DefaultMutableTreeNode 323 { 324 private String messageId; 325 private String baseSubject; 326 327 Node() 328 { 329 super(); 330 } 331 332 Node(MailboxEntry entry) 333 { 334 super(entry); 335 } 336 337 Node(String messageId, String baseSubject) 338 { 339 this.messageId = messageId; 340 this.baseSubject = baseSubject; 341 } 342 343 MailboxEntry getMailboxEntry() 344 { 345 return (MailboxEntry) getUserObject(); 346 } 347 348 String getBaseSubject() 349 { 350 return baseSubject; 351 } 352 353 void setBaseSubject(String s) 354 { 355 baseSubject = s; 356 } 357 358 String getMessageId() 359 { 360 return messageId; 361 } 362 363 RFC822Date getDate() 364 { 365 MailboxEntry entry = getMailboxEntry(); 366 if (entry != null) 367 return entry.getDate(); 368 if (getChildCount() > 0) { 369 Node child = (Node ) getChildAt(0); 370 entry = child.getMailboxEntry(); 371 if (entry != null) 372 return entry.getDate(); 373 } 374 Log.debug("getDate no date"); 375 return null; 376 } 377 378 boolean isDummy() 379 { 380 return getUserObject() == null; 381 } 382 383 void sortChildren() 384 { 385 if (children != null) 386 sortEntriesByDate(children); 387 } 388 389 private static final Comparator comparator = new Comparator () { 390 public int compare(Object o1, Object o2) 391 { 392 return RFC822Date.compare(((Node )o1).getDate(), 393 ((Node )o2).getDate()); 394 } 395 }; 396 397 private static final void sortEntriesByDate(List list) 398 { 399 Collections.sort(list, comparator); 400 } 401 } 402 | Popular Tags |