001: /*
002: * MailboxFilter.java
003: *
004: * Copyright (C) 2002 Peter Graves
005: * $Id: MailboxFilter.java,v 1.1.1.1 2002/09/24 16:10:01 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j.mail;
023:
024: import java.util.Stack;
025: import org.armedbear.j.Debug;
026: import org.armedbear.j.FastStringReader;
027: import org.armedbear.j.Log;
028:
029: public abstract class MailboxFilter {
030: public static MailboxFilter getMailboxFilter(String input) {
031: input = input.trim();
032: if (input.indexOf('~') < 0)
033: return new GenericMailboxFilter(input);
034: FastStringReader reader = new FastStringReader(input);
035: try {
036: return parse(reader);
037: } catch (Exception e) {
038: Log.error(e);
039: return null;
040: }
041: }
042:
043: private static MailboxFilter parse(FastStringReader reader)
044: throws Exception {
045: Stack stack = new Stack();
046: while (parseNextTerm(reader, stack))
047: ;
048: Debug.assertTrue(stack.size() == 1);
049: return (MailboxFilter) stack.pop();
050: }
051:
052: // Returns false if end of input is reached, true otherwise.
053: private static boolean parseNextTerm(FastStringReader reader,
054: Stack stack) throws Exception {
055: reader.skipWhitespace();
056: char c = reader.readChar();
057: switch (c) {
058: case '~': {
059: MailboxFilter filter = parseTilde(reader);
060: if (filter != null) {
061: if (stack.size() > 0) {
062: MailboxFilter existing = (MailboxFilter) stack
063: .pop();
064: if (existing instanceof AndTerm) {
065: ((AndTerm) existing).add(filter);
066: stack.push(existing);
067: } else
068: stack.push(new AndTerm(existing, filter));
069: } else
070: stack.push(filter);
071: }
072: break;
073: }
074: case '!': {
075: MailboxFilter filter = parseNot(reader);
076: if (filter != null) {
077: if (stack.size() > 0) {
078: MailboxFilter existing = (MailboxFilter) stack
079: .pop();
080: if (existing instanceof AndTerm) {
081: ((AndTerm) existing).add(filter);
082: stack.push(existing);
083: } else
084: stack.push(new AndTerm(existing, filter));
085: } else
086: stack.push(filter);
087: }
088: break;
089: }
090: case '(': {
091: MailboxFilter filter = parse(reader);
092: break;
093: }
094: case ')':
095: return false;
096: case '|': {
097: MailboxFilter filter = parseOr(reader);
098: if (filter != null) {
099: if (stack.size() > 0) {
100: MailboxFilter existing = (MailboxFilter) stack
101: .pop();
102: if (existing instanceof OrTerm) {
103: ((OrTerm) existing).add(filter);
104: stack.push(existing);
105: } else
106: stack.push(new OrTerm(existing, filter));
107: } else
108: stack.push(filter);
109: }
110: break;
111: }
112: case '\0':
113: return false; // End of input.
114: default:
115: throw new Exception();
116: }
117: return true;
118: }
119:
120: // We've just seen '|'.
121: private static MailboxFilter parseOr(FastStringReader reader)
122: throws Exception {
123: reader.skipWhitespace();
124: MailboxFilter filter = null;
125: char c = reader.readChar();
126: switch (c) {
127: case '~':
128: filter = parseTilde(reader);
129: break;
130: case '!':
131: filter = parseNot(reader);
132: break;
133: case '(':
134: filter = parse(reader);
135: break;
136: default:
137: Log.error("char = " + c);
138: throw new Exception();
139: }
140: Debug.assertTrue(filter != null);
141: return filter;
142: }
143:
144: private static NotTerm parseNot(FastStringReader reader)
145: throws Exception {
146: reader.skipWhitespace();
147: MailboxFilter filter = null;
148: char c = reader.readChar();
149: switch (c) {
150: case '~':
151: filter = parseTilde(reader);
152: break;
153: case '(':
154: filter = parse(reader);
155: break;
156: default:
157: throw new Exception();
158: }
159: Debug.assertTrue(filter != null);
160: return new NotTerm(filter);
161: }
162:
163: private static MailboxFilter parseTilde(FastStringReader reader)
164: throws Exception {
165: MailboxFilter filter = null;
166: char c = reader.readChar();
167: switch (c) {
168: case 'C':
169: filter = new ToOrCcMailboxFilter(reader);
170: break;
171: case 'D':
172: filter = new DeletedMailboxFilter();
173: break;
174: case 'F':
175: filter = new FlaggedMailboxFilter();
176: break;
177: case 'N':
178: filter = new NewMailboxFilter();
179: break;
180: case 'R':
181: filter = new ReadMailboxFilter();
182: break;
183: case 'U':
184: filter = new UnreadMailboxFilter();
185: break;
186: case 'T':
187: filter = new TaggedMailboxFilter();
188: break;
189: case 'f':
190: filter = new FromMailboxFilter(reader);
191: break;
192: case 't':
193: filter = new ToMailboxFilter(reader);
194: break;
195: case 'd':
196: filter = DateSentMailboxFilter.getMailboxFilter(reader);
197: break;
198: default:
199: Log.error("parseTilde() returning null, remainder = |"
200: + reader.remainder() + "|");
201: throw new Exception();
202: }
203: return filter;
204: }
205:
206: public abstract boolean accept(MailboxEntry entry);
207: }
|