restructuring; broke out Query, cleaned up Mailbox
[org.ibex.mail.git] / src / org / ibex / mail / Query.java
1 package org.ibex.mail;
2 import java.util.*;
3
4 /**
5  *  [immutable] This class encapsulates a query against a mailbox.
6  *
7  *  The default implementation of Mailbox.query() simply retrieves
8  *  each message and calls Query.match() on it to filter out any
9  *  messages which do not match.
10  *
11  *  Production-quality Mailbox implementations will want to inspect
12  *  the Query object passed to Mailbox.query() to perform more
13  *  efficient queries.
14  */
15 public class Query {
16
17     public static Query not(Query q)            { return new Query(NOT, new Query[] { q },      0, 0, 0, null, null, null, null); }
18     public static Query and(Query q1, Query q2) { return new Query(AND, new Query[] { q1, q2 }, 0, 0, 0, null, null, null, null); }
19     public static Query and(Query[] q)          { return new Query(AND, q,                      0, 0, 0, null, null, null, null); }
20     public static Query or(Query q1, Query q2)  { return new Query(OR,  new Query[] { q1, q2 }, 0, 0, 0, null, null, null, null); }
21     public static Query or(Query[] q)           { return new Query(OR,  q,                      0, 0, 0, null, null, null, null); }
22     public static Query uid(int min, int max)   { return new Query(UID, null, min, max, 0, null, null, null, null); }
23     public static Query messagenum(int min, int max) { return new Query(MESSAGENUM, null, min, max, 0, null, null, null, null); }
24     public static Query sent(Date earliest, Date latest)    { return new Query(SENT, null,0,0,0,null,null, earliest, latest); }
25     public static Query arrival(Date earliest, Date latest) { return new Query(ARRIVAL, null,0,0,0,null,null, earliest, latest); }
26     public static Query header(String name, String val)     { return new Query(HEADER, null, 0, 0, 0, name, val, null, null); }
27     public static Query size(int min, int max)              { return new Query(SIZE, null, min, max, 0, null, null, null, null); }
28     public static Query body(String text)                   { return new Query(BODY, null, 0, 0, 0, null, text, null, null); }
29     public static Query flags(int flags)                    { return new Query(FLAGS, null, 0, 0, flags, null, null, null, null); }
30
31     private Query(int type, Query[] q, int min, int max, int flags, String key, String text, Date earliest, Date latest) {
32         this.type = type; this.q = q; this.min = min; this.max = max; this.flags = flags; this.key = key; this.text = text;
33         this.earliest = earliest; this.latest = latest; }
34
35     public static int ALL        = 0;
36     public static int NOT        = 1;
37     public static int AND        = 2;
38     public static int OR         = 3;
39     public static int UID        = 4;
40     public static int MESSAGENUM = 5; 
41     public static int SENT       = 6;
42     public static int ARRIVAL    = 7;
43     public static int HEADER     = 8;
44     public static int SIZE       = 9;
45     public static int FLAGS      = 10;
46     public static int BODY       = 11;
47
48     public final int type;
49     public final Query[] q;
50     public final int min;
51     public final int max;
52     public final int flags;
53     public final String key;
54     public final String text;
55     public final Date earliest;
56     public final Date latest;
57
58     public boolean match(Mailbox mbox, Message m) {
59         switch(type) {
60             case ALL:        return true;
61             case NOT:        return !q[0].match(mbox, m);
62             case OR:         for(int i=0; i<q.length; i++) if (q[i].match(mbox, m)) return true; return false;
63             case AND:        for(int i=0; i<q.length; i++) if (!q[i].match(mbox, m)) return false; return true;
64             case UID:        return mbox.uid(m)        >= min && mbox.uid <= max;
65             case MESSAGENUM: return mbox.messagenum(m) >= min && mbox.messagenum(m) <= max;
66             case SENT:       return (latest == null || m.sent.before(latest))    &&(earliest == null || m.sent.after(earliest));
67             case ARRIVAL:    return (latest == null || m.arrival.before(latest)) &&(earliest == null || m.arrival.after(earliest));
68             case SIZE:       return m.size >= min && m.size <= max;
69             case FLAGS:      return mbox.getFlags(flags);
70             case HEADER:     return m.headers.get(key) != null && ((String)m.headers.get(key)).indexOf(text) != -1;
71             case HEADER:     return m.body.indexOf(text) != -1;
72             default:         throw new Error("this should not happen");
73         }
74     }
75
76 }