restructuring; broke out Query, cleaned up Mailbox
[org.ibex.mail.git] / src / org / ibex / mail / Query.java
index e39f8b4..45b5659 100644 (file)
@@ -1,29 +1,76 @@
 package org.ibex.mail;
 import java.util.*;
 
+/**
+ *  [immutable] This class encapsulates a query against a mailbox.
+ *
+ *  The default implementation of Mailbox.query() simply retrieves
+ *  each message and calls Query.match() on it to filter out any
+ *  messages which do not match.
+ *
+ *  Production-quality Mailbox implementations will want to inspect
+ *  the Query object passed to Mailbox.query() to perform more
+ *  efficient queries.
+ */
 public class Query {
 
-    public static Query not(Query q) { return null; }
-    public static Query and(Query a1, Query a2) { return null; }
-    public static Query or(Query a1, Query a2) { return null; }
-    public static Query set(int[] set) { return null; }
-    public static Query sent(Date d, boolean foo0, boolean foo) { return null; }
-    public static Query arrival(Date d, boolean foo, boolean bar) { return null; }
-    public static Query uid(int uid) { return null; }
-    public static Query uid(int[] uid) { return null; }
-    public static Query header(String name) { return null; }
-    public static Query header(String name, String val) { return null; }
-    public static Query size(int size, boolean foo) { return null; }
-    public static Query fullText(String searchFor, boolean foo, boolean bar) { return null; }
+    public static Query not(Query q)            { return new Query(NOT, new Query[] { q },      0, 0, 0, null, null, null, null); }
+    public static Query and(Query q1, Query q2) { return new Query(AND, new Query[] { q1, q2 }, 0, 0, 0, null, null, null, null); }
+    public static Query and(Query[] q)          { return new Query(AND, q,                      0, 0, 0, null, null, null, null); }
+    public static Query or(Query q1, Query q2)  { return new Query(OR,  new Query[] { q1, q2 }, 0, 0, 0, null, null, null, null); }
+    public static Query or(Query[] q)           { return new Query(OR,  q,                      0, 0, 0, null, null, null, null); }
+    public static Query uid(int min, int max)   { return new Query(UID, null, min, max, 0, null, null, null, null); }
+    public static Query messagenum(int min, int max) { return new Query(MESSAGENUM, null, min, max, 0, null, null, null, null); }
+    public static Query sent(Date earliest, Date latest)    { return new Query(SENT, null,0,0,0,null,null, earliest, latest); }
+    public static Query arrival(Date earliest, Date latest) { return new Query(ARRIVAL, null,0,0,0,null,null, earliest, latest); }
+    public static Query header(String name, String val)     { return new Query(HEADER, null, 0, 0, 0, name, val, null, null); }
+    public static Query size(int min, int max)              { return new Query(SIZE, null, min, max, 0, null, null, null, null); }
+    public static Query body(String text)                   { return new Query(BODY, null, 0, 0, 0, null, text, null, null); }
+    public static Query flags(int flags)                    { return new Query(FLAGS, null, 0, 0, flags, null, null, null, null); }
 
-    // FIXME
-    public static class Flag {
-        public static final Query ANSWERED = null;
-        public static final Query SEEN     = null;
-        public static final Query DRAFT    = null;
-        public static final Query FLAGGED  = null;
-        public static final Query RECENT   = null;
-        public static final Query DELETED  = null;
+    private Query(int type, Query[] q, int min, int max, int flags, String key, String text, Date earliest, Date latest) {
+        this.type = type; this.q = q; this.min = min; this.max = max; this.flags = flags; this.key = key; this.text = text;
+        this.earliest = earliest; this.latest = latest; }
+
+    public static int ALL        = 0;
+    public static int NOT        = 1;
+    public static int AND        = 2;
+    public static int OR         = 3;
+    public static int UID        = 4;
+    public static int MESSAGENUM = 5; 
+    public static int SENT       = 6;
+    public static int ARRIVAL    = 7;
+    public static int HEADER     = 8;
+    public static int SIZE       = 9;
+    public static int FLAGS      = 10;
+    public static int BODY       = 11;
+
+    public final int type;
+    public final Query[] q;
+    public final int min;
+    public final int max;
+    public final int flags;
+    public final String key;
+    public final String text;
+    public final Date earliest;
+    public final Date latest;
+
+    public boolean match(Mailbox mbox, Message m) {
+        switch(type) {
+            case ALL:        return true;
+            case NOT:        return !q[0].match(mbox, m);
+            case OR:         for(int i=0; i<q.length; i++) if (q[i].match(mbox, m)) return true; return false;
+            case AND:        for(int i=0; i<q.length; i++) if (!q[i].match(mbox, m)) return false; return true;
+            case UID:        return mbox.uid(m)        >= min && mbox.uid <= max;
+            case MESSAGENUM: return mbox.messagenum(m) >= min && mbox.messagenum(m) <= max;
+            case SENT:       return (latest == null || m.sent.before(latest))    &&(earliest == null || m.sent.after(earliest));
+            case ARRIVAL:    return (latest == null || m.arrival.before(latest)) &&(earliest == null || m.arrival.after(earliest));
+            case SIZE:       return m.size >= min && m.size <= max;
+            case FLAGS:      return mbox.getFlags(flags);
+            case HEADER:     return m.headers.get(key) != null && ((String)m.headers.get(key)).indexOf(text) != -1;
+            case HEADER:     return m.body.indexOf(text) != -1;
+            default:         throw new Error("this should not happen");
+        }
     }
 
 }