Source for java.util.EnumSet

   1: /* EnumSet.java - Set of enum objects
   2:    Copyright (C) 2004, 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.util;
  40: 
  41: import java.io.Serializable;
  42: 
  43: /**
  44:  * @author Tom Tromey (tromey@redhat.com)
  45:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  46:  * @since 1.5 
  47:  */
  48: 
  49: // FIXME: serialization is special.
  50: public class EnumSet<T extends Enum<T>>
  51:   extends AbstractSet<T>
  52:   implements Cloneable, Serializable
  53: {
  54:   private static final long serialVersionUID = 4782406773684236311L;
  55: 
  56:   BitSet store;
  57:   int cardinality;
  58:   Class<T> enumClass;
  59: 
  60:   EnumSet()
  61:   {
  62:   }
  63: 
  64:   public EnumSet<T> clone()
  65:   {
  66:     EnumSet<T> r;
  67: 
  68:     try
  69:       {
  70:     r = (EnumSet<T>) super.clone();
  71:       }
  72:     catch (CloneNotSupportedException _)
  73:       {
  74:     /* Can't happen */
  75:     return null;
  76:       }
  77:     r.store = (BitSet) store.clone();
  78:     return r;
  79:   }
  80: 
  81:   public int size()
  82:   {
  83:     return cardinality;
  84:   }
  85: 
  86:   public Iterator<T> iterator()
  87:   {
  88:     return new Iterator<T>()
  89:     {
  90:       int next = -1;
  91:       int count = 0;
  92: 
  93:       public boolean hasNext()
  94:       {
  95:     return count < cardinality;
  96:       }
  97: 
  98:       public T next()
  99:       {
 100:     next = store.nextSetBit(next + 1);
 101:     ++count;
 102:     return enumClass.getEnumConstants()[next];
 103:       }
 104: 
 105:       public void remove()
 106:       {
 107:     if (! store.get(next))
 108:       {
 109:         store.clear(next);
 110:         --cardinality;
 111:       }
 112:       }
 113:     };
 114:   }
 115: 
 116:   public boolean add(T val)
 117:   {
 118:     if (store.get(val.ordinal()))
 119:       return false;
 120:     store.set(val.ordinal());
 121:     ++cardinality;
 122:     return true;
 123:   }
 124: 
 125:   public boolean addAll(Collection<? extends T> c)
 126:   {
 127:     boolean result = false;
 128:     if (c instanceof EnumSet)
 129:       {
 130:     EnumSet<T> other = (EnumSet<T>) c;
 131:     if (enumClass == other.enumClass)
 132:       {
 133:         store.or(other.store);
 134:         int save = cardinality;
 135:         cardinality = store.cardinality();
 136:         result = save != cardinality;
 137:       }
 138:       }
 139:     else
 140:       {
 141:     for (T val : c)
 142:       {
 143:         if (add (val))
 144:           result = true;
 145:       }
 146:       }
 147:     return result;
 148:   }
 149: 
 150:   public void clear()
 151:   {
 152:     store.clear();
 153:     cardinality = 0;
 154:   }
 155: 
 156:   public boolean contains(Object o)
 157:   {
 158:     if (! (o instanceof Enum))
 159:       return false;
 160:     Enum<T> e = (Enum<T>) o;
 161:     if (e.getDeclaringClass() != enumClass)
 162:       return false;
 163:     return store.get(e.ordinal());
 164:   }
 165: 
 166:   public boolean containsAll(Collection<?> c)
 167:   {
 168:     if (c instanceof EnumSet)
 169:       {
 170:     EnumSet<T> other = (EnumSet<T>) c;
 171:     if (enumClass == other.enumClass)
 172:       return store.containsAll(other.store);
 173:     return false;
 174:       }
 175:     return super.containsAll(c);
 176:   }
 177: 
 178:   public boolean remove(Object o)
 179:   {
 180:     if (! (o instanceof Enum))
 181:       return false;
 182:     Enum<T> e = (Enum<T>) o;
 183:     if (e.getDeclaringClass() != enumClass)
 184:       return false;
 185:     store.clear(e.ordinal());
 186:     --cardinality;
 187:     return true;
 188:   }
 189: 
 190:   public boolean removeAll(Collection<?> c)
 191:   {
 192:     if (c instanceof EnumSet)
 193:       {
 194:     EnumSet<T> other = (EnumSet<T>) c;
 195:     if (enumClass != other.enumClass)
 196:       return false;
 197:     store.andNot(other.store);
 198:     int save = cardinality;
 199:     cardinality = store.cardinality();
 200:     return save != cardinality;
 201:       }
 202:     return super.removeAll(c);
 203:   }
 204: 
 205:   public boolean retainAll(Collection<?> c)
 206:   {
 207:     if (c instanceof EnumSet)
 208:       {
 209:     EnumSet<T> other = (EnumSet<T>) c;
 210:     if (enumClass != other.enumClass)
 211:       return false;
 212:     store.and(other.store);
 213:     int save = cardinality;
 214:     cardinality = store.cardinality();
 215:     return save != cardinality;
 216:       }
 217:     return super.retainAll(c);
 218:   }
 219: 
 220:   public static <T extends Enum<T>> EnumSet<T> allOf(Class<T> eltType)
 221:   {
 222:     EnumSet<T> r = new EnumSet<T>();
 223:     r.store = new BitSet(eltType.getEnumConstants().length);
 224:     r.store.set(0, r.store.size());
 225:     r.cardinality = r.store.size();
 226:     r.enumClass = eltType;
 227:     return r;
 228:   }
 229: 
 230:   public static <T extends Enum<T>> EnumSet<T> noneOf(Class<T> eltType)
 231:   {
 232:     EnumSet<T> r = new EnumSet<T>();
 233:     r.store = new BitSet(eltType.getEnumConstants().length);
 234:     r.enumClass = eltType;
 235:     return r;
 236:   }
 237: 
 238:   public static <T extends Enum<T>> EnumSet<T> copyOf(EnumSet<T> other)
 239:   {
 240:     // We can't just use `other.clone' since we don't want to make a
 241:     // subclass.
 242:     EnumSet<T> r = new EnumSet<T>();
 243:     r.store = (BitSet) other.store.clone();
 244:     r.cardinality = other.cardinality;
 245:     r.enumClass = other.enumClass;
 246:     return r;
 247:   }
 248: 
 249:   public static <T extends Enum<T>> EnumSet<T> copyOf(Collection<T> other)
 250:   {
 251:     if (other instanceof EnumSet)
 252:       return copyOf((EnumSet<T>) other);
 253:     EnumSet<T> r = new EnumSet<T>();
 254:     for (T val : other)
 255:       {
 256:     if (r.store == null)
 257:       {
 258:         r.enumClass = val.getDeclaringClass();
 259:         r.store = new BitSet(r.enumClass.getEnumConstants().length);
 260:       }
 261:     r.store.set(val.ordinal());
 262:       }
 263:     // The collection must contain at least one element.
 264:     if (r.store == null)
 265:       throw new IllegalArgumentException();
 266:     r.cardinality = r.store.cardinality();
 267:     return r;
 268:   }
 269: 
 270:   public static <T extends Enum<T>> EnumSet<T> complementOf(EnumSet<T> other)
 271:   {
 272:     EnumSet<T> r = new EnumSet<T>();
 273:     r.store = (BitSet) other.store.clone();
 274:     r.store.flip(0, r.store.size());
 275:     r.cardinality = r.store.size() - other.cardinality;
 276:     r.enumClass = other.enumClass;
 277:     return r;
 278:   }
 279: 
 280:   public static <T extends Enum<T>> EnumSet<T> of(T first)
 281:   {
 282:     EnumSet<T> r = new EnumSet<T>();
 283:     r.enumClass = first.getDeclaringClass();
 284:     r.store = new BitSet(r.enumClass.getEnumConstants().length);
 285:     r.store.set(first.ordinal());
 286:     r.cardinality = 1;
 287:     return r;
 288:   }
 289: 
 290:   public static <T extends Enum<T>> EnumSet<T> of(T first, T second)
 291:   {
 292:     EnumSet<T> r = new EnumSet<T>();
 293:     r.enumClass = first.getDeclaringClass();
 294:     r.store = new BitSet(r.enumClass.getEnumConstants().length);
 295:     r.store.set(first.ordinal());
 296:     r.store.set(second.ordinal());
 297:     r.cardinality = r.store.cardinality();
 298:     return r;
 299:   }
 300: 
 301:   public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third)
 302:   {
 303:     EnumSet<T> r = new EnumSet<T>();
 304:     r.enumClass = first.getDeclaringClass();
 305:     r.store = new BitSet(r.enumClass.getEnumConstants().length);
 306:     r.store.set(first.ordinal());
 307:     r.store.set(second.ordinal());
 308:     r.store.set(third.ordinal());
 309:     r.cardinality = r.store.cardinality();
 310:     return r;
 311:   }
 312: 
 313:   public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third,
 314:                           T fourth)
 315:   {
 316:     EnumSet<T> r = new EnumSet<T>();
 317:     r.enumClass = first.getDeclaringClass();
 318:     r.store = new BitSet(r.enumClass.getEnumConstants().length);
 319:     r.store.set(first.ordinal());
 320:     r.store.set(second.ordinal());
 321:     r.store.set(third.ordinal());
 322:     r.store.set(fourth.ordinal());
 323:     r.cardinality = r.store.cardinality();
 324:     return r;
 325:   }
 326: 
 327:   public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third,
 328:                           T fourth, T fifth)
 329:   {
 330:     EnumSet<T> r = new EnumSet<T>();
 331:     r.enumClass = first.getDeclaringClass();
 332:     r.store = new BitSet(r.enumClass.getEnumConstants().length);
 333:     r.store.set(first.ordinal());
 334:     r.store.set(second.ordinal());
 335:     r.store.set(third.ordinal());
 336:     r.store.set(fourth.ordinal());
 337:     r.store.set(fifth.ordinal());
 338:     r.cardinality = r.store.cardinality();
 339:     return r;
 340:   }
 341: 
 342:   public static <T extends Enum<T>> EnumSet<T> of(T first, T... rest)
 343:   {
 344:     EnumSet<T> r = new EnumSet<T>();
 345:     r.enumClass = first.getDeclaringClass();
 346:     r.store = new BitSet(r.enumClass.getEnumConstants().length);
 347:     r.store.set(first.ordinal());
 348:     for (T val : rest)
 349:       r.store.set(val.ordinal());
 350:     r.cardinality = r.store.cardinality();
 351:     return r;
 352:   }
 353: 
 354:   public static <T extends Enum<T>> EnumSet<T> range(T from, T to)
 355:   {
 356:     if (from.compareTo(to) > 0)
 357:       throw new IllegalArgumentException();
 358:     EnumSet<T> r = new EnumSet<T>();
 359:     r.store = new BitSet(from.getDeclaringClass().getEnumConstants().length);
 360:     r.store.set(from.ordinal(), to.ordinal() + 1);
 361:     r.enumClass = from.getDeclaringClass();
 362:     r.cardinality = to.ordinal() - from.ordinal() + 1;
 363:     return r;
 364:   }
 365: }