X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fmail%2FQuery.java;h=a260dee7c576dd39cba6ec5766d3a54733c13791;hb=4e71d2cd340532739288501acc515cbf16b83681;hp=45b56591449419fe1c4c39b4e39a0f47e1dbc547;hpb=034f6baad8db618ac7c3a93a5653b2071cf5f796;p=org.ibex.mail.git diff --git a/src/org/ibex/mail/Query.java b/src/org/ibex/mail/Query.java index 45b5659..a260dee 100644 --- a/src/org/ibex/mail/Query.java +++ b/src/org/ibex/mail/Query.java @@ -1,5 +1,11 @@ +// Copyright 2000-2005 the Contributors, as shown in the revision logs. +// Licensed under the Apache Public Source License 2.0 ("the License"). +// You may not use this file except in compliance with the License. + package org.ibex.mail; import java.util.*; +import org.ibex.mail.target.*; +import org.ibex.util.*; /** * [immutable] This class encapsulates a query against a mailbox. @@ -14,36 +20,54 @@ import java.util.*; */ public class Query { - 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); } + public static Query not(Query q) { return new Query(NOT, new Query[] { q },0,0,0,null,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,null); } + public static Query and(Query[] q) { return new Query(AND, q,0,0,0,null, 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, null); } + public static Query or(Query[] q) { return new Query(OR, q, 0, 0, 0, null, null, null, null, null); } + public static Query uid(int min, int max) { return new Query(UID, null, min, max, 0, null, null, null, null, null); } + public static Query imapNumber(int min,int max) { return new Query(IMAPNUM,null,min,max,0,null,null,null,null, null); } + public static Query nntpNumber(int min,int max) { return new Query(NNTPNUM,null,min,max,0,null,null,null,null, null); } + public static Query sent(Date e, Date l) { return new Query(SENT,null,0,0,0,null,null,e,l,null); } + public static Query arrival(Date e, Date l) { return new Query(ARRIVAL,null,0,0,0,null,null, e,l,null);} + public static Query header(String k, String v) { return new Query(HEADER, null, 0, 0, 0, k, v, null, null, null);} + public static Query size(int min, int max) { return new Query(SIZE, null, min, max, 0, null, null, null, null, null);} + public static Query body(String text) { return new Query(BODY, null, 0, 0, 0, null, text, null, null, null);} + public static Query full(String text) { return new Query(FULL, null, 0, 0, 0, null, text, null, null, null);} + public static Query uid(int[] set) { return new Query(UID, null, 0 ,0 ,0, null, null, null, null, set);} + public static Query imapNumber(int[] set) { return new Query(IMAPNUM, null, 0 ,0 ,0, null, null, null, null, set);} + public static Query all() { return new Query(ALL, null, 0, 0, 0, null, null, null, null, null); } + public static Query deleted() { return new Query(DELETED, null, 0, 0, 0, null, null, null, null, null); } + public static Query seen() { return new Query(SEEN, null, 0, 0, 0, null, null, null, null, null); } + public static Query flagged() { return new Query(FLAGGED, null, 0, 0, 0, null, null, null, null, null); } + public static Query draft() { return new Query(DRAFT, null, 0, 0, 0, null, null, null, null, null); } + public static Query answered() { return new Query(ANSWERED, null, 0, 0, 0, null, null, null, null, null); } + public static Query recent() { return new Query(RECENT, null, 0, 0, 0, null, null, null, null, null); } + //public static Query set(boolean uid, int[] set) { return uid ? uid(set) : imapNumber(set); } - private Query(int type, Query[] q, int min, int max, int flags, String key, String text, Date earliest, Date latest) { + private Query(int type, Query[] q,int min,int max, int flags, String key, String text, Date earliest, Date latest, int[] set) { 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; } + this.earliest = earliest; this.latest = latest; this.set = set; } - 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 static final int ALL = 0; + public static final int NOT = 1; + public static final int AND = 2; + public static final int OR = 3; + public static final int UID = 4; + public static final int SENT = 5; + public static final int ARRIVAL = 6; + public static final int HEADER = 7; + public static final int SIZE = 8; + public static final int BODY = 9; + public static final int FULL = 10; + public static final int IMAPNUM = 11; + public static final int DELETED = 12; + public static final int SEEN = 13; + public static final int FLAGGED = 14; + public static final int DRAFT = 15; + public static final int ANSWERED = 16; + public static final int RECENT = 17; + public static final int NNTPNUM = 18; public final int type; public final Query[] q; @@ -54,23 +78,99 @@ public class Query { public final String text; public final Date earliest; public final Date latest; + public final int[] set; - public boolean match(Mailbox mbox, Message m) { + public boolean match(Mailbox.Iterator it) { switch(type) { case ALL: return true; - case NOT: return !q[0].match(mbox, m); - case OR: for(int i=0; i= 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; + case NOT: return !q[0].match(it); + case OR: for(int i=0; i= it.uid()) return true; + return false; } + else return it.uid() >= min && it.uid() <= max; + case IMAPNUM: if (set != null) { + for(int i=0; i= it.imapNumber()) return true; + return false; } + else return it.imapNumber() >= min && it.imapNumber() <= max; + case NNTPNUM: if (set != null) { + for(int i=0; i= it.nntpNumber()) return true; + return false; } + else return it.imapNumber() >= min && it.imapNumber() <= max; + case SENT: return (latest==null||it.cur().date.before(latest)) && + (earliest==null||it.cur().date.after(earliest)); + case ARRIVAL: return (latest == null || it.cur().arrival.before(latest)) && + (earliest == null || it.cur().arrival.after(earliest)); + case HEADER: return it.cur().headers.get(key) != null && + ((String)it.cur().headers.get(key)).toLowerCase().indexOf(text.toLowerCase()) != -1; + case DELETED: return (it.getFlags() & Mailbox.Flag.DELETED) !=0; + case SEEN: return (it.getFlags() & Mailbox.Flag.SEEN)!=0; + case FLAGGED: return (it.getFlags() & Mailbox.Flag.FLAGGED)!=0; + case DRAFT: return (it.getFlags() & Mailbox.Flag.DRAFT)!=0; + case ANSWERED: return (it.getFlags() & Mailbox.Flag.ANSWERED)!=0; + case RECENT: return (it.getFlags() & Mailbox.Flag.RECENT)!=0; + + // FIXME: super inefficient + case BODY: throw new RuntimeException("BODY searches are not supported because they are slow"); + case FULL: throw new RuntimeException("FULL searches are not supported because they are slow"); + case SIZE: throw new RuntimeException("SIZE searches are not supported because Adam is lame"); + //return it.cur().size() >= min && it.cur().size() <= max; + default: throw new Error("this should not happen"); } } + + // FIXME: normalize multiple-range queries using AND/OR? + + private static String range(int[] set, int min, int max, String name) { + if (set != null && set.length==1) { min = set[0]; max = set[1]; set = null; } + if (set == null) { + if (min==max) return "name=="+min; + return min+"<="+name+"<="+max; + } else { + StringBuffer sb = new StringBuffer(); + for(int i=0; i0) sb.append(" || "); + sb.append(set[i]+"<="+name+"<="+set[i+1]); + } + return sb.toString(); + } + } + + private static String range(Date earliest, Date latest, String name) { + StringBuffer sb = new StringBuffer(); + if (earliest != null) sb.append(earliest + "<="); + sb.append(name); + if (latest != null) sb.append("<="+latest); + return sb.toString(); + } + + public String toString() { + switch(type) { + case ALL: return "ALL"; + case NOT: return "NOT " + q[0]; + case OR: return StringUtil.join(q, " || "); + case AND: return StringUtil.join(q, " && "); + case UID: return range(set, min, max, "uid"); + case IMAPNUM: return range(set, min, max, "imapnum"); + case NNTPNUM: return range(set, min, max, "nntpnum"); + case SENT: return range(earliest, latest, "sent"); + case ARRIVAL: return range(earliest, latest, "arrival"); + case HEADER: return "headers["+key+"]=="+text; + case DELETED: return "deleted"; + case SEEN: return "seen"; + case FLAGGED: return "flagged"; + case DRAFT: return "draft"; + case ANSWERED: return "answered"; + case RECENT: return "recent"; + // FIXME: super inefficient + case BODY: return ""; + case FULL: return ""; + case SIZE: return ""; + default: throw new Error("this should not happen"); + } + } }