1 /**
2 *
3 * Copyright 2003-2006 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package javax.mail;
19
20 import java.io.Serializable;
21 import java.util.Hashtable;
22 import java.util.Iterator;
23 import java.util.LinkedList;
24 import java.util.List;
25
26 /**
27 * Representation of flags that may be associated with a message.
28 * Flags can either be system flags, defined by the {@link Flags.Flag Flag} inner class,
29 * or user-defined flags defined by a String. The system flags represent those expected
30 * to be provided by most folder systems; user-defined flags allow for additional flags
31 * on a per-provider basis.
32 * <p/>
33 * This class is Serializable but compatibility is not guaranteed across releases.
34 *
35 * @version $Rev: 421852 $ $Date: 2006-07-14 03:02:19 -0700 (Fri, 14 Jul 2006) $
36 */
37 public class Flags implements Cloneable, Serializable {
38 public static final class Flag {
39 /**
40 * Flag that indicates that the message has been replied to; has a bit value of 1.
41 */
42 public static final Flag ANSWERED = new Flag(1);
43 /**
44 * Flag that indicates that the message has been marked for deletion and
45 * should be removed on a subsequent expunge operation; has a bit value of 2.
46 */
47 public static final Flag DELETED = new Flag(2);
48 /**
49 * Flag that indicates that the message is a draft; has a bit value of 4.
50 */
51 public static final Flag DRAFT = new Flag(4);
52 /**
53 * Flag that indicates that the message has been flagged; has a bit value of 8.
54 */
55 public static final Flag FLAGGED = new Flag(8);
56 /**
57 * Flag that indicates that the message has been delivered since the last time
58 * this folder was opened; has a bit value of 16.
59 */
60 public static final Flag RECENT = new Flag(16);
61 /**
62 * Flag that indicates that the message has been viewed; has a bit value of 32.
63 * This flag is set by the {@link Message#getInputStream()} and {@link Message#getContent()}
64 * methods.
65 */
66 public static final Flag SEEN = new Flag(32);
67 /**
68 * Flags that indicates if this folder supports user-defined flags; has a bit value of 0x80000000.
69 */
70 public static final Flag USER = new Flag(0x80000000);
71
72 private final int mask;
73
74 private Flag(int mask) {
75 this.mask = mask;
76 }
77 }
78
79
80
81 private int system_flags;
82 private final Hashtable user_flags;
83
84 /**
85 * Construct a Flags instance with no flags set.
86 */
87 public Flags() {
88 user_flags = new Hashtable();
89 }
90
91 /**
92 * Construct a Flags instance with a supplied system flag set.
93 * @param flag the system flag to set
94 */
95 public Flags(Flag flag) {
96 system_flags = flag.mask;
97 user_flags = new Hashtable();
98 }
99
100 /**
101 * Construct a Flags instance with a same flags set.
102 * @param flags the instance to copy
103 */
104 public Flags(Flags flags) {
105 system_flags = flags.system_flags;
106 user_flags = new Hashtable(flags.user_flags);
107 }
108
109 /**
110 * Construct a Flags instance with the supplied user flags set.
111 * Question: should this automatically set the USER system flag?
112 * @param name the user flag to set
113 */
114 public Flags(String name) {
115 user_flags = new Hashtable();
116 user_flags.put(name.toLowerCase(), name);
117 }
118
119 /**
120 * Set a system flag.
121 * @param flag the system flag to set
122 */
123 public void add(Flag flag) {
124 system_flags |= flag.mask;
125 }
126
127 /**
128 * Set all system and user flags from the supplied Flags.
129 * Question: do we need to check compatibility of USER flags?
130 * @param flags the Flags to add
131 */
132 public void add(Flags flags) {
133 system_flags |= flags.system_flags;
134 user_flags.putAll(flags.user_flags);
135 }
136
137 /**
138 * Set a user flag.
139 * Question: should this fail if the USER system flag is not set?
140 * @param name the user flag to set
141 */
142 public void add(String name) {
143 user_flags.put(name.toLowerCase(), name);
144 }
145
146 /**
147 * Return a copy of this instance.
148 * @return a copy of this instance
149 */
150 public Object clone() {
151 return new Flags(this);
152 }
153
154 /**
155 * See if the supplied system flags are set
156 * @param flag the system flags to check for
157 * @return true if the flags are set
158 */
159 public boolean contains(Flag flag) {
160 return (system_flags & flag.mask) != 0;
161 }
162
163 /**
164 * See if all of the supplied Flags are set
165 * @param flags the flags to check for
166 * @return true if all the supplied system and user flags are set
167 */
168 public boolean contains(Flags flags) {
169 return ((system_flags & flags.system_flags) == flags.system_flags)
170 && user_flags.keySet().containsAll(flags.user_flags.keySet());
171 }
172
173 /**
174 * See if the supplied user flag is set
175 * @param name the user flag to check for
176 * @return true if the flag is set
177 */
178 public boolean contains(String name) {
179 return user_flags.containsKey(name.toLowerCase());
180 }
181
182 /**
183 * Equality is defined as true if the other object is a instanceof Flags with the
184 * same system and user flags set (using a case-insensitive name comparison for user flags).
185 * @param other the instance to compare against
186 * @return true if the two instance are the same
187 */
188 public boolean equals(Object other) {
189 if (other == this) return true;
190 if (other instanceof Flags == false) return false;
191 final Flags flags = (Flags) other;
192 return system_flags == flags.system_flags && user_flags.keySet().equals(flags.user_flags.keySet());
193 }
194
195 /**
196 * Calculate a hashCode for this instance
197 * @return a hashCode for this instance
198 */
199 public int hashCode() {
200 return system_flags ^ user_flags.keySet().hashCode();
201 }
202
203 /**
204 * Return a list of {@link Flags.Flag Flags} containing the system flags that have been set
205 * @return the system flags that have been set
206 */
207 public Flag[] getSystemFlags() {
208
209 int size = 0;
210 if ((system_flags & Flag.ANSWERED.mask) != 0) size += 1;
211 if ((system_flags & Flag.DELETED.mask) != 0) size += 1;
212 if ((system_flags & Flag.DRAFT.mask) != 0) size += 1;
213 if ((system_flags & Flag.FLAGGED.mask) != 0) size += 1;
214 if ((system_flags & Flag.RECENT.mask) != 0) size += 1;
215 if ((system_flags & Flag.SEEN.mask) != 0) size += 1;
216 if ((system_flags & Flag.USER.mask) != 0) size += 1;
217 Flag[] result = new Flag[size];
218 if ((system_flags & Flag.USER.mask) != 0) result[--size] = Flag.USER;
219 if ((system_flags & Flag.SEEN.mask) != 0) result[--size] = Flag.SEEN;
220 if ((system_flags & Flag.RECENT.mask) != 0) result[--size] = Flag.RECENT;
221 if ((system_flags & Flag.FLAGGED.mask) != 0) result[--size] = Flag.FLAGGED;
222 if ((system_flags & Flag.DRAFT.mask) != 0) result[--size] = Flag.DRAFT;
223 if ((system_flags & Flag.DELETED.mask) != 0) result[--size] = Flag.DELETED;
224 if ((system_flags & Flag.ANSWERED.mask) != 0) result[--size] = Flag.ANSWERED;
225 return result;
226 }
227
228 /**
229 * Return a list of user flags that have been set
230 * @return a list of user flags
231 */
232 public String[] getUserFlags() {
233 return (String[]) user_flags.values().toArray(new String[user_flags.values().size()]);
234 }
235
236 /**
237 * Unset the supplied system flag.
238 * Question: what happens if we unset the USER flags and user flags are set?
239 * @param flag the flag to clear
240 */
241 public void remove(Flag flag) {
242 system_flags &= ~flag.mask;
243 }
244
245 /**
246 * Unset all flags from the supplied instance.
247 * @param flags the flags to clear
248 */
249 public void remove(Flags flags) {
250 system_flags &= ~flags.system_flags;
251 user_flags.keySet().removeAll(flags.user_flags.keySet());
252 }
253
254 /**
255 * Unset the supplied user flag.
256 * @param name the flag to clear
257 */
258 public void remove(String name) {
259 user_flags.remove(name.toLowerCase());
260 }
261 }