2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common Development
8
* and Distribution License("CDDL") (collectively, the "License"). You
9
* may not use this file except in compliance with the License. You can obtain
10
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
11
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
12
* language governing permissions and limitations under the License.
14
* When distributing the software, include this License Header Notice in each
15
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
16
* Sun designates this particular file as subject to the "Classpath" exception
17
* as provided by Sun in the GPL Version 2 section of the License file that
18
* accompanied this code. If applicable, add the following below the License
19
* Header, with the fields enclosed by brackets [] replaced by your own
20
* identifying information: "Portions Copyrighted [year]
21
* [name of copyright owner]"
25
* If you wish your version of this file to be governed by only the CDDL or
26
* only the GPL Version 2, indicate your decision by adding "[Contributor]
27
* elects to include this software in this distribution under the [CDDL or GPL
28
* Version 2] license." If you don't indicate a single choice of license, a
29
* recipient has the option to distribute your version of this file under
30
* either the CDDL, the GPL Version 2 or to extend the choice of license to
31
* its licensees as provided above. However, if you add GPL Version 2 code
32
* and therefore, elected the GPL Version 2 license, then the option applies
33
* only if the new code is made subject to such option by the copyright
39
import java.io.Serializable;
43
* The Flags class represents the set of flags on a Message. Flags
44
* are composed of predefined system flags, and user defined flags. <p>
46
* A System flag is represented by the <code>Flags.Flag</code>
47
* inner class. A User defined flag is represented as a String.
48
* User flags are case-independent. <p>
50
* A set of standard system flags are predefined. Most folder
51
* implementations are expected to support these flags. Some
52
* implementations may also support arbitrary user-defined flags. The
53
* <code>getPermanentFlags</code> method on a Folder returns a Flags
54
* object that holds all the flags that are supported by that folder
57
* A Flags object is serializable so that (for example) the
58
* use of Flags objects in search terms can be serialized
59
* along with the search terms. <p>
61
* <strong>Warning:</strong>
62
* Serialized objects of this class may not be compatible with future
63
* JavaMail API releases. The current serialization support is
64
* appropriate for short term storage. <p>
66
* The below code sample illustrates how to set, examine and get the
67
* flags for a message. <p>
70
* Message m = folder.getMessage(1);
71
* m.setFlag(Flags.Flag.DELETED, true); // set the DELETED flag
73
* // Check if DELETED flag is set of this message
74
* if (m.isSet(Flags.Flag.DELETED))
75
* System.out.println("DELETED message");
77
* // Examine ALL system flags for this message
78
* Flags flags = m.getFlags();
79
* Flags.Flag[] sf = flags.getSystemFlags();
80
* for (int i = 0; i < sf.length; i++) {
81
* if (sf[i] == Flags.Flag.DELETED)
82
* System.out.println("DELETED message");
83
* else if (sf[i] == Flags.Flag.SEEN)
84
* System.out.println("SEEN message");
91
* @see Folder#getPermanentFlags
93
* @author Bill Shannon
96
public class Flags implements Cloneable, Serializable {
98
private int system_flags = 0;
99
private Hashtable user_flags = null;
101
private final static int ANSWERED_BIT = 0x01;
102
private final static int DELETED_BIT = 0x02;
103
private final static int DRAFT_BIT = 0x04;
104
private final static int FLAGGED_BIT = 0x08;
105
private final static int RECENT_BIT = 0x10;
106
private final static int SEEN_BIT = 0x20;
107
private final static int USER_BIT = 0x80000000;
109
private static final long serialVersionUID = 6243590407214169028L;
112
* This inner class represents an individual system flag. A set
113
* of standard system flag objects are predefined here.
115
public static final class Flag {
117
* This message has been answered. This flag is set by clients
118
* to indicate that this message has been answered to.
120
public static final Flag ANSWERED = new Flag(ANSWERED_BIT);
123
* This message is marked deleted. Clients set this flag to
124
* mark a message as deleted. The expunge operation on a folder
125
* removes all messages in that folder that are marked for deletion.
127
public static final Flag DELETED = new Flag(DELETED_BIT);
130
* This message is a draft. This flag is set by clients
131
* to indicate that the message is a draft message.
133
public static final Flag DRAFT = new Flag(DRAFT_BIT);
136
* This message is flagged. No semantic is defined for this flag.
137
* Clients alter this flag.
139
public static final Flag FLAGGED = new Flag(FLAGGED_BIT);
142
* This message is recent. Folder implementations set this flag
143
* to indicate that this message is new to this folder, that is,
144
* it has arrived since the last time this folder was opened. <p>
146
* Clients cannot alter this flag.
148
public static final Flag RECENT = new Flag(RECENT_BIT);
151
* This message is seen. This flag is implicitly set by the
152
* implementation when the this Message's content is returned
153
* to the client in some form. The <code>getInputStream</code>
154
* and <code>getContent</code> methods on Message cause this
155
* flag to be set. <p>
157
* Clients can alter this flag.
159
public static final Flag SEEN = new Flag(SEEN_BIT);
162
* A special flag that indicates that this folder supports
163
* user defined flags. <p>
165
* The implementation sets this flag. Clients cannot alter
166
* this flag but can use it to determine if a folder supports
167
* user defined flags by using
168
* <code>folder.getPermanentFlags().contains(Flags.Flag.USER)</code>.
170
public static final Flag USER = new Flag(USER_BIT);
172
// flags are stored as bits for efficiency
174
private Flag(int bit) {
181
* Construct an empty Flags object.
186
* Construct a Flags object initialized with the given flags.
188
* @param flags the flags for initialization
190
public Flags(Flags flags) {
191
this.system_flags = flags.system_flags;
192
if (flags.user_flags != null)
193
this.user_flags = (Hashtable)flags.user_flags.clone();
197
* Construct a Flags object initialized with the given system flag.
199
* @param flag the flag for initialization
201
public Flags(Flag flag) {
202
this.system_flags |= flag.bit;
206
* Construct a Flags object initialized with the given user flag.
208
* @param flag the flag for initialization
210
public Flags(String flag) {
211
user_flags = new Hashtable(1);
212
user_flags.put(flag.toLowerCase(Locale.ENGLISH), flag);
216
* Add the specified system flag to this Flags object.
218
* @param flag the flag to add
220
public void add(Flag flag) {
221
system_flags |= flag.bit;
225
* Add the specified user flag to this Flags object.
227
* @param flag the flag to add
229
public void add(String flag) {
230
if (user_flags == null)
231
user_flags = new Hashtable(1);
232
user_flags.put(flag.toLowerCase(Locale.ENGLISH), flag);
236
* Add all the flags in the given Flags object to this
239
* @param f Flags object
241
public void add(Flags f) {
242
system_flags |= f.system_flags; // add system flags
244
if (f.user_flags != null) { // add user-defined flags
245
if (user_flags == null)
246
user_flags = new Hashtable(1);
248
Enumeration e = f.user_flags.keys();
250
while (e.hasMoreElements()) {
251
String s = (String)e.nextElement();
252
user_flags.put(s, f.user_flags.get(s));
258
* Remove the specified system flag from this Flags object.
260
* @param flag the flag to be removed
262
public void remove(Flag flag) {
263
system_flags &= ~flag.bit;
267
* Remove the specified user flag from this Flags object.
269
* @param flag the flag to be removed
271
public void remove(String flag) {
272
if (user_flags != null)
273
user_flags.remove(flag.toLowerCase(Locale.ENGLISH));
277
* Remove all flags in the given Flags object from this
280
* @param f the flag to be removed
282
public void remove(Flags f) {
283
system_flags &= ~f.system_flags; // remove system flags
285
if (f.user_flags != null) {
286
if (user_flags == null)
289
Enumeration e = f.user_flags.keys();
290
while (e.hasMoreElements())
291
user_flags.remove(e.nextElement());
296
* Check whether the specified system flag is present in this Flags object.
298
* @return true of the given flag is present, otherwise false.
300
public boolean contains(Flag flag) {
301
return (system_flags & flag.bit) != 0;
305
* Check whether the specified user flag is present in this Flags object.
307
* @return true of the given flag is present, otherwise false.
309
public boolean contains(String flag) {
310
if (user_flags == null)
313
return user_flags.containsKey(flag.toLowerCase(Locale.ENGLISH));
317
* Check whether all the flags in the specified Flags object are
318
* present in this Flags object.
320
* @return true if all flags in the given Flags object are present,
323
public boolean contains(Flags f) {
324
// Check system flags
325
if ((f.system_flags & system_flags) != f.system_flags)
329
if (f.user_flags != null) {
330
if (user_flags == null)
332
Enumeration e = f.user_flags.keys();
334
while (e.hasMoreElements()) {
335
if (!user_flags.containsKey(e.nextElement()))
340
// If we've made it till here, return true
345
* Check whether the two Flags objects are equal.
347
* @return true if they're equal
349
public boolean equals(Object obj) {
350
if (!(obj instanceof Flags))
353
Flags f = (Flags)obj;
355
// Check system flags
356
if (f.system_flags != this.system_flags)
360
if (f.user_flags == null && this.user_flags == null)
362
if (f.user_flags != null && this.user_flags != null &&
363
f.user_flags.size() == this.user_flags.size()) {
364
Enumeration e = f.user_flags.keys();
366
while (e.hasMoreElements()) {
367
if (!this.user_flags.containsKey(e.nextElement()))
377
* Compute a hash code for this Flags object.
379
* @return the hash code
381
public int hashCode() {
382
int hash = system_flags;
383
if (user_flags != null) {
384
Enumeration e = user_flags.keys();
385
while (e.hasMoreElements())
386
hash += ((String)e.nextElement()).hashCode();
392
* Return all the system flags in this Flags object. Returns
393
* an array of size zero if no flags are set.
395
* @return array of Flags.Flag objects representing system flags
397
public Flag[] getSystemFlags() {
398
Vector v = new Vector();
399
if ((system_flags & ANSWERED_BIT) != 0)
400
v.addElement(Flag.ANSWERED);
401
if ((system_flags & DELETED_BIT) != 0)
402
v.addElement(Flag.DELETED);
403
if ((system_flags & DRAFT_BIT) != 0)
404
v.addElement(Flag.DRAFT);
405
if ((system_flags & FLAGGED_BIT) != 0)
406
v.addElement(Flag.FLAGGED);
407
if ((system_flags & RECENT_BIT) != 0)
408
v.addElement(Flag.RECENT);
409
if ((system_flags & SEEN_BIT) != 0)
410
v.addElement(Flag.SEEN);
411
if ((system_flags & USER_BIT) != 0)
412
v.addElement(Flag.USER);
414
Flag[] f = new Flag[v.size()];
420
* Return all the user flags in this Flags object. Returns
421
* an array of size zero if no flags are set.
423
* @return array of Strings, each String represents a flag.
425
public String[] getUserFlags() {
426
Vector v = new Vector();
427
if (user_flags != null) {
428
Enumeration e = user_flags.elements();
430
while (e.hasMoreElements())
431
v.addElement(e.nextElement());
434
String[] f = new String[v.size()];
440
* Returns a clone of this Flags object.
442
public Object clone() {
445
f = (Flags)super.clone();
446
} catch (CloneNotSupportedException cex) {
447
// ignore, can't happen
449
if (this.user_flags != null && f != null)
450
f.user_flags = (Hashtable)this.user_flags.clone();
455
public static void main(String argv[]) throws Exception {
456
// a new flags object
457
Flags f1 = new Flags();
458
f1.add(Flags.Flag.DELETED);
459
f1.add(Flags.Flag.SEEN);
460
f1.add(Flags.Flag.RECENT);
461
f1.add(Flags.Flag.ANSWERED);
463
// check copy constructor with only system flags
464
Flags fc = new Flags(f1);
465
if (f1.equals(fc) && fc.equals(f1))
466
System.out.println("success");
468
System.out.println("fail");
470
// check clone with only system flags
471
fc = (Flags)f1.clone();
472
if (f1.equals(fc) && fc.equals(f1))
473
System.out.println("success");
475
System.out.println("fail");
477
// add a user flag and make sure it still works right
480
// shouldn't be equal here
481
if (!f1.equals(fc) && !fc.equals(f1))
482
System.out.println("success");
484
System.out.println("fail");
487
fc = (Flags)f1.clone();
488
if (f1.equals(fc) && fc.equals(f1))
489
System.out.println("success");
491
System.out.println("fail");
493
// make sure user flag hash tables are separate
494
fc.add("AnotherFlag");
495
if (!f1.equals(fc) && !fc.equals(f1))
496
System.out.println("success");
498
System.out.println("fail");
500
// check copy constructor
502
if (f1.equals(fc) && fc.equals(f1))
503
System.out.println("success");
505
System.out.println("fail");
507
// another new flags object
508
Flags f2 = new Flags(Flags.Flag.ANSWERED);
511
if (f1.contains(Flags.Flag.DELETED))
512
System.out.println("success");
514
System.out.println("fail");
516
if (f1.contains(Flags.Flag.SEEN))
517
System.out.println("success");
519
System.out.println("fail");
521
if (f1.contains(Flags.Flag.RECENT))
522
System.out.println("success");
524
System.out.println("fail");
526
if (f1.contains("MyFlag"))
527
System.out.println("success");
529
System.out.println("fail");
531
if (f2.contains(Flags.Flag.ANSWERED))
532
System.out.println("success");
534
System.out.println("fail");
537
System.out.println("----------------");
539
String[] s = f1.getUserFlags();
540
for (int i = 0; i < s.length; i++)
541
System.out.println(s[i]);
542
System.out.println("----------------");
543
s = f2.getUserFlags();
544
for (int i = 0; i < s.length; i++)
545
System.out.println(s[i]);
547
System.out.println("----------------");
549
if (f1.contains(f2)) // this should be true
550
System.out.println("success");
552
System.out.println("fail");
554
if (!f2.contains(f1)) // this should be false
555
System.out.println("success");
557
System.out.println("fail");
559
Flags f3 = new Flags();
560
f3.add(Flags.Flag.DELETED);
561
f3.add(Flags.Flag.SEEN);
562
f3.add(Flags.Flag.RECENT);
563
f3.add(Flags.Flag.ANSWERED);
564
f3.add("ANOTHERFLAG");
567
f1.add("AnotherFlag");
570
System.out.println("equals success");
572
System.out.println("fail");
574
System.out.println("equals success");
576
System.out.println("fail");
577
System.out.println("f1 hash code " + f1.hashCode());
578
System.out.println("f3 hash code " + f3.hashCode());
579
if (f1.hashCode() == f3.hashCode())
580
System.out.println("success");
582
System.out.println("fail");