KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > mail > imap > protocol > SearchSequence


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21
22 /*
23  * @(#)SearchSequence.java 1.14 05/08/29
24  *
25  * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
26  */

27
28 package com.sun.mail.imap.protocol;
29
30 import java.util.*;
31 import java.io.IOException JavaDoc;
32
33 import javax.mail.*;
34 import javax.mail.search.*;
35 import com.sun.mail.iap.*;
36
37 /**
38  * This class traverses a search-tree and generates the
39  * corresponding IMAP search sequence.
40  *
41  * @author John Mani
42  */

43 class SearchSequence {
44
45     /**
46      * Generate the IMAP search sequence for the given search expression.
47      */

48     static Argument generateSequence(SearchTerm term, String JavaDoc charset)
49         throws SearchException, IOException JavaDoc {
50     /* Call the appropriate handler depending on the type of
51      * the search-term ...
52      */

53     if (term instanceof AndTerm) // AND
54
return and((AndTerm)term, charset);
55     else if (term instanceof OrTerm) // OR
56
return or((OrTerm)term, charset);
57     else if (term instanceof NotTerm) // NOT
58
return not((NotTerm)term, charset);
59     else if (term instanceof HeaderTerm) // HEADER
60
return header((HeaderTerm)term, charset);
61     else if (term instanceof FlagTerm) // FLAG
62
return flag((FlagTerm)term);
63     else if (term instanceof FromTerm) { // FROM
64
FromTerm fterm = (FromTerm)term;
65         return from(fterm.getAddress().toString(), charset);
66     }
67     else if (term instanceof FromStringTerm) { // FROM
68
FromStringTerm fterm = (FromStringTerm)term;
69         return from(fterm.getPattern(), charset);
70     }
71     else if (term instanceof RecipientTerm) { // RECIPIENT
72
RecipientTerm rterm = (RecipientTerm)term;
73         return recipient(rterm.getRecipientType(),
74                  rterm.getAddress().toString(),
75                  charset);
76     }
77     else if (term instanceof RecipientStringTerm) { // RECIPIENT
78
RecipientStringTerm rterm = (RecipientStringTerm)term;
79         return recipient(rterm.getRecipientType(),
80                  rterm.getPattern(),
81                  charset);
82     }
83     else if (term instanceof SubjectTerm) // SUBJECT
84
return subject((SubjectTerm)term, charset);
85     else if (term instanceof BodyTerm) // BODY
86
return body((BodyTerm)term, charset);
87     else if (term instanceof SizeTerm) // SIZE
88
return size((SizeTerm)term);
89     else if (term instanceof SentDateTerm) // SENTDATE
90
return sentdate((SentDateTerm)term);
91     else if (term instanceof ReceivedDateTerm) // INTERNALDATE
92
return receiveddate((ReceivedDateTerm)term);
93     else if (term instanceof MessageIDTerm) // MessageID
94
return messageid((MessageIDTerm)term, charset);
95     else
96         throw new SearchException("Search too complex");
97     }
98
99     /*
100      * Check if the "text" terms in the given SearchTerm contain
101      * non US-ASCII characters.
102      */

103     static boolean isAscii(SearchTerm term) {
104     if (term instanceof AndTerm || term instanceof OrTerm) {
105         SearchTerm[] terms;
106         if (term instanceof AndTerm)
107         terms = ((AndTerm)term).getTerms();
108         else
109         terms = ((OrTerm)term).getTerms();
110
111         for (int i = 0; i < terms.length; i++)
112         if (!isAscii(terms[i])) // outta here !
113
return false;
114     } else if (term instanceof NotTerm)
115         return isAscii(((NotTerm)term).getTerm());
116     else if (term instanceof StringTerm)
117         return isAscii(((StringTerm)term).getPattern());
118     else if (term instanceof AddressTerm)
119         return isAscii(((AddressTerm)term).getAddress().toString());
120     
121     // Any other term returns true.
122
return true;
123     }
124
125     private static boolean isAscii(String JavaDoc s) {
126     int l = s.length();
127
128     for (int i=0; i < l; i++) {
129         if ((int)s.charAt(i) > 0177) // non-ascii
130
return false;
131     }
132     return true;
133     }
134
135     private static Argument and(AndTerm term, String JavaDoc charset)
136             throws SearchException, IOException JavaDoc {
137     // Combine the sequences for both terms
138
SearchTerm[] terms = term.getTerms();
139     // Generate the search sequence for the first term
140
Argument result = generateSequence(terms[0], charset);
141     // Append other terms
142
for (int i = 1; i < terms.length; i++)
143         result.append(generateSequence(terms[i], charset));
144     return result;
145     }
146
147     private static Argument or(OrTerm term, String JavaDoc charset)
148             throws SearchException, IOException JavaDoc {
149     SearchTerm[] terms = term.getTerms();
150
151     /* The IMAP OR operator takes only two operands. So if
152      * we have more than 2 operands, group them into 2-operand
153      * OR Terms.
154      */

155     if (terms.length > 2) {
156         SearchTerm t = terms[0];
157
158         // Include rest of the terms
159
for (int i = 1; i < terms.length; i++)
160         t = new OrTerm(t, terms[i]);
161
162         term = (OrTerm)t; // set 'term' to the new jumbo OrTerm we
163
// just created
164
terms = term.getTerms();
165     }
166
167     // 'term' now has only two operands
168
Argument result = new Argument();
169
170     // Add the OR search-key
171
result.writeAtom("OR");
172
173     /* If this term is an AND expression, we need to enclose it
174      * within paranthesis.
175      *
176      * AND expressions are either AndTerms or FlagTerms
177      */

178     if (terms[0] instanceof AndTerm || terms[0] instanceof FlagTerm)
179         result.writeArgument(generateSequence(terms[0], charset));
180     else
181         result.append(generateSequence(terms[0], charset));
182
183     // Repeat the above for the second term
184
if (terms[1] instanceof AndTerm || terms[1] instanceof FlagTerm)
185         result.writeArgument(generateSequence(terms[1], charset));
186     else
187         result.append(generateSequence(terms[1], charset));
188
189     return result;
190     }
191
192     private static Argument not(NotTerm term, String JavaDoc charset)
193             throws SearchException, IOException JavaDoc {
194     Argument result = new Argument();
195
196     // Add the NOT search-key
197
result.writeAtom("NOT");
198
199     /* If this term is an AND expression, we need to enclose it
200      * within paranthesis.
201      *
202      * AND expressions are either AndTerms or FlagTerms
203      */

204     SearchTerm nterm = term.getTerm();
205     if (nterm instanceof AndTerm || nterm instanceof FlagTerm)
206         result.writeArgument(generateSequence(nterm, charset));
207     else
208         result.append(generateSequence(nterm, charset));
209
210     return result;
211     }
212
213     private static Argument header(HeaderTerm term, String JavaDoc charset)
214             throws SearchException, IOException JavaDoc {
215     Argument result = new Argument();
216     result.writeAtom("HEADER");
217     result.writeString(term.getHeaderName());
218     result.writeString(term.getPattern(), charset);
219     return result;
220     }
221
222     private static Argument messageid(MessageIDTerm term, String JavaDoc charset)
223             throws SearchException, IOException JavaDoc {
224     Argument result = new Argument();
225     result.writeAtom("HEADER");
226     result.writeString("Message-ID");
227     // XXX confirm that charset conversion ought to be done
228
result.writeString(term.getPattern(), charset);
229     return result;
230     }
231
232     private static Argument flag(FlagTerm term) throws SearchException {
233     boolean set = term.getTestSet();
234
235     Argument result = new Argument();
236
237     Flags flags = term.getFlags();
238     Flags.Flag[] sf = flags.getSystemFlags();
239     String JavaDoc[] uf = flags.getUserFlags();
240     if (sf.length == 0 && uf.length == 0)
241         throw new SearchException("Invalid FlagTerm");
242
243     for (int i = 0; i < sf.length; i++) {
244         if (sf[i] == Flags.Flag.DELETED)
245         result.writeAtom(set ? "DELETED": "UNDELETED");
246         else if (sf[i] == Flags.Flag.ANSWERED)
247         result.writeAtom(set ? "ANSWERED": "UNANSWERED");
248         else if (sf[i] == Flags.Flag.DRAFT)
249         result.writeAtom(set ? "DRAFT": "UNDRAFT");
250         else if (sf[i] == Flags.Flag.FLAGGED)
251         result.writeAtom(set ? "FLAGGED": "UNFLAGGED");
252         else if (sf[i] == Flags.Flag.RECENT)
253         result.writeAtom(set ? "RECENT": "OLD");
254         else if (sf[i] == Flags.Flag.SEEN)
255         result.writeAtom(set ? "SEEN": "UNSEEN");
256     }
257
258     for (int i = 0; i < uf.length; i++) {
259         result.writeAtom(set ? "KEYWORD" : "UNKEYWORD");
260         result.writeAtom(uf[i]);
261     }
262     
263     return result;
264     }
265
266     private static Argument from(String JavaDoc address, String JavaDoc charset)
267             throws SearchException, IOException JavaDoc {
268     Argument result = new Argument();
269     result.writeAtom("FROM");
270     result.writeString(address, charset);
271     return result;
272     }
273
274     private static Argument recipient(Message.RecipientType type,
275                       String JavaDoc address, String JavaDoc charset)
276             throws SearchException, IOException JavaDoc {
277     Argument result = new Argument();
278
279     if (type == Message.RecipientType.TO)
280         result.writeAtom("TO");
281     else if (type == Message.RecipientType.CC)
282         result.writeAtom("CC");
283     else if (type == Message.RecipientType.BCC)
284         result.writeAtom("BCC");
285     else
286         throw new SearchException("Illegal Recipient type");
287
288     result.writeString(address, charset);
289     return result;
290     }
291
292     private static Argument subject(SubjectTerm term, String JavaDoc charset)
293             throws SearchException, IOException JavaDoc {
294     Argument result = new Argument();
295     
296     result.writeAtom("SUBJECT");
297     result.writeString(term.getPattern(), charset);
298     return result;
299     }
300
301     private static Argument body(BodyTerm term, String JavaDoc charset)
302             throws SearchException, IOException JavaDoc {
303     Argument result = new Argument();
304
305     result.writeAtom("BODY");
306     result.writeString(term.getPattern(), charset);
307     return result;
308     }
309
310     private static Argument size(SizeTerm term)
311             throws SearchException {
312     Argument result = new Argument();
313
314     switch (term.getComparison()) {
315         case ComparisonTerm.GT:
316         result.writeAtom("LARGER");
317         break;
318         case ComparisonTerm.LT:
319         result.writeAtom("SMALLER");
320         break;
321         default:
322         // GT and LT is all we get from IMAP for size
323
throw new SearchException("Cannot handle Comparison");
324     }
325
326     result.writeNumber(term.getNumber());
327     return result;
328     }
329
330     // Date SEARCH stuff ...
331

332     /**
333      * Print an IMAP Date string, that is suitable for the Date
334      * SEARCH commands.
335      *
336      * The IMAP Date string is :
337      * date ::= date_day "-" date_month "-" date_year
338      *
339      * Note that this format does not contain the TimeZone
340      */

341     private static String JavaDoc monthTable[] = {
342       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
343       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
344     };
345
346     // A GregorianCalendar object in the current timezone
347
private static Calendar cal = new GregorianCalendar();
348
349     private static String JavaDoc toIMAPDate(Date date) {
350     StringBuffer JavaDoc s = new StringBuffer JavaDoc();
351     cal.setTime(date);
352
353     s.append(cal.get(Calendar.DATE)).append("-");
354     s.append(monthTable[cal.get(Calendar.MONTH)]).append('-');
355     s.append(cal.get(Calendar.YEAR));
356
357     return s.toString();
358     }
359
360     private static Argument sentdate(DateTerm term)
361             throws SearchException {
362     Argument result = new Argument();
363     String JavaDoc date = toIMAPDate(term.getDate());
364
365     switch (term.getComparison()) {
366         case ComparisonTerm.GT:
367         result.writeAtom("SENTSINCE " + date);
368         break;
369         case ComparisonTerm.EQ:
370         result.writeAtom("SENTON " + date);
371         break;
372         case ComparisonTerm.LT:
373         result.writeAtom("SENTBEFORE " + date);
374         break;
375         case ComparisonTerm.GE:
376         result.writeAtom("OR SENTSINCE " + date + " SENTON " + date);
377         break;
378         case ComparisonTerm.LE:
379         result.writeAtom("OR SENTBEFORE " + date + " SENTON " + date);
380         break;
381         case ComparisonTerm.NE:
382         result.writeAtom("NOT SENTON " + date);
383         break;
384         default:
385             throw new SearchException("Cannot handle Date Comparison");
386     }
387
388     return result;
389     }
390
391     private static Argument receiveddate(DateTerm term)
392             throws SearchException {
393     Argument result = new Argument();
394     String JavaDoc date = toIMAPDate(term.getDate());
395
396     switch (term.getComparison()) {
397         case ComparisonTerm.GT:
398         result.writeAtom("SINCE " + date);
399         break;
400         case ComparisonTerm.EQ:
401         result.writeAtom("ON " + date);
402         break;
403         case ComparisonTerm.LT:
404         result.writeAtom("BEFORE " + date);
405         break;
406         case ComparisonTerm.GE:
407         result.writeAtom("OR SINCE " + date + " ON " + date);
408         break;
409         case ComparisonTerm.LE:
410         result.writeAtom("OR BEFORE " + date + " ON " + date);
411         break;
412         case ComparisonTerm.NE:
413         result.writeAtom("NOT ON " + date);
414         break;
415         default:
416             throw new SearchException("Cannot handle Date Comparison");
417     }
418
419     return result;
420     }
421 }
422
Popular Tags