1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package java.util; 17 18 // BEGIN android-added 19 20 import java.io.Serializable; 21 import org.apache.harmony.kernel.vm.LangAccess; 22 23 /** 24 * An EnumSet is a specialized Set to be used with enums as keys. 25 */ 26 public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> 27 implements Cloneable, Serializable { 28 // BEGIN android-added 29 /* 30 * null-ok; package access to {@code java.lang}, set during 31 * first need. This shouldn't be used directly. Instead, use {@link 32 * SpecialAccess#LANG}, which is guaranteed to be initialized. 33 */ 34 static /*package*/ LangAccess LANG_BOOTSTRAP = null; 35 // END android-added 36 37 private static final long serialVersionUID = 1009687484059888093L; 38 39 final Class<E> elementClass; 40 EnumSet(Class<E> cls)41 EnumSet(Class<E> cls) { 42 elementClass = cls; 43 } 44 45 /** 46 * Creates an empty enum set. The permitted elements are of type 47 * Class<E>. 48 * 49 * @param elementType 50 * the class object for the elements contained. 51 * @return an empty enum set, with permitted elements of type {@code 52 * elementType}. 53 * @throws ClassCastException 54 * if the specified element type is not and enum type. 55 */ noneOf(Class<E> elementType)56 public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { 57 if (!elementType.isEnum()) { 58 throw new ClassCastException(); 59 } 60 // BEGIN android-changed 61 E[] enums = SpecialAccess.LANG.getEnumValuesInOrder(elementType); 62 if (enums.length <= 64) { 63 return new MiniEnumSet<E>(elementType, enums); 64 } 65 return new HugeEnumSet<E>(elementType, enums); 66 // END android-changed 67 } 68 69 /** 70 * Creates an enum set filled with all the enum elements of the specified 71 * {@code elementType}. 72 * 73 * @param elementType 74 * the class object for the elements contained. 75 * @return an enum set with elements solely from the specified element type. 76 * @throws ClassCastException 77 * if the specified element type is not and enum type. 78 */ allOf(Class<E> elementType)79 public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) { 80 EnumSet<E> set = noneOf(elementType); 81 set.complement(); 82 return set; 83 } 84 85 /** 86 * Creates an enum set. All the contained elements are of type 87 * Class<E>, and the contained elements are the same as those 88 * contained in {@code s}. 89 * 90 * @param s 91 * the enum set from which to copy. 92 * @return an enum set with all the elements from the specified enum set. 93 * @throws ClassCastException 94 * if the specified element type is not and enum type. 95 */ copyOf(EnumSet<E> s)96 public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) { 97 EnumSet<E> set = EnumSet.noneOf(s.elementClass); 98 set.addAll(s); 99 return set; 100 } 101 102 /** 103 * Creates an enum set. The contained elements are the same as those 104 * contained in collection {@code c}. If c is an enum set, invoking this 105 * method is the same as invoking {@link #copyOf(EnumSet)}. 106 * 107 * @param c 108 * the collection from which to copy. if it is not an enum set, 109 * it must not be empty. 110 * @return an enum set with all the elements from the specified collection. 111 * @throws IllegalArgumentException 112 * if c is not an enum set and contains no elements at all. 113 * @throws NullPointerException 114 * if {@code c} is {@code null}. 115 */ copyOf(Collection<E> c)116 public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) { 117 if (c instanceof EnumSet) { 118 return copyOf((EnumSet<E>) c); 119 } 120 if (c.isEmpty()) { 121 throw new IllegalArgumentException(); 122 } 123 Iterator<E> iterator = c.iterator(); 124 E element = iterator.next(); 125 EnumSet<E> set = EnumSet.noneOf(element.getDeclaringClass()); 126 set.add(element); 127 while (iterator.hasNext()) { 128 set.add(iterator.next()); 129 } 130 return set; 131 } 132 133 /** 134 * Creates an enum set. All the contained elements complement those from the 135 * specified enum set. 136 * 137 * @param s 138 * the specified enum set. 139 * @return an enum set with all the elements complementary to those from the 140 * specified enum set. 141 * @throws NullPointerException 142 * if {@code s} is {@code null}. 143 */ complementOf(EnumSet<E> s)144 public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) { 145 EnumSet<E> set = EnumSet.noneOf(s.elementClass); 146 set.addAll(s); 147 set.complement(); 148 return set; 149 } 150 complement()151 abstract void complement(); 152 153 /** 154 * Creates a new enum set, containing only the specified element. There are 155 * six overloadings of the method. They accept from one to five elements 156 * respectively. The sixth one receives an arbitrary number of elements, and 157 * runs slower than those that only receive a fixed number of elements. 158 * 159 * @param e 160 * the element to be initially contained. 161 * @return an enum set containing the specified element. 162 * @throws NullPointerException 163 * if {@code e} is {@code null}. 164 */ of(E e)165 public static <E extends Enum<E>> EnumSet<E> of(E e) { 166 EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass()); 167 set.add(e); 168 return set; 169 } 170 171 /** 172 * Creates a new enum set, containing only the specified elements. There are 173 * six overloadings of the method. They accept from one to five elements 174 * respectively. The sixth one receives an arbitrary number of elements, and 175 * runs slower than those that only receive a fixed number of elements. 176 * 177 * @param e1 178 * the initially contained element. 179 * @param e2 180 * another initially contained element. 181 * @return an enum set containing the specified elements. 182 * @throws NullPointerException 183 * if any of the specified elements is {@code null}. 184 */ of(E e1, E e2)185 public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) { 186 EnumSet<E> set = of(e1); 187 set.add(e2); 188 return set; 189 } 190 191 /** 192 * Creates a new enum set, containing only the specified elements. There are 193 * six overloadings of the method. They accept from one to five elements 194 * respectively. The sixth one receives an arbitrary number of elements, and 195 * runs slower than those that only receive a fixed number of elements. 196 * 197 * @param e1 198 * the initially contained element. 199 * @param e2 200 * another initially contained element. 201 * @param e3 202 * another initially contained element. 203 * @return an enum set containing the specified elements. 204 * @throws NullPointerException 205 * if any of the specified elements is {@code null}. 206 */ of(E e1, E e2, E e3)207 public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) { 208 EnumSet<E> set = of(e1, e2); 209 set.add(e3); 210 return set; 211 } 212 213 /** 214 * Creates a new enum set, containing only the specified elements. There are 215 * six overloadings of the method. They accept from one to five elements 216 * respectively. The sixth one receives an arbitrary number of elements, and 217 * runs slower than those that only receive a fixed number of elements. 218 * 219 * @param e1 220 * the initially contained element. 221 * @param e2 222 * another initially contained element. 223 * @param e3 224 * another initially contained element. 225 * @param e4 226 * another initially contained element. 227 * @return an enum set containing the specified elements. 228 * @throws NullPointerException 229 * if any of the specified elements is {@code null}. 230 */ of(E e1, E e2, E e3, E e4)231 public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) { 232 EnumSet<E> set = of(e1, e2, e3); 233 set.add(e4); 234 return set; 235 } 236 237 /** 238 * Creates a new enum set, containing only the specified elements. There are 239 * six overloadings of the method. They accept from one to five elements 240 * respectively. The sixth one receives an arbitrary number of elements, and 241 * runs slower than those that only receive a fixed number of elements. 242 * 243 * @param e1 244 * the initially contained element. 245 * @param e2 246 * another initially contained element. 247 * @param e3 248 * another initially contained element. 249 * @param e4 250 * another initially contained element. 251 * @param e5 252 * another initially contained element. 253 * @return an enum set containing the specified elements. 254 * @throws NullPointerException 255 * if any of the specified elements is {@code null}. 256 */ of(E e1, E e2, E e3, E e4, E e5)257 public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) { 258 EnumSet<E> set = of(e1, e2, e3, e4); 259 set.add(e5); 260 return set; 261 } 262 263 /** 264 * Creates a new enum set, containing only the specified elements. It can 265 * receive an arbitrary number of elements, and runs slower than those only 266 * receiving a fixed number of elements. 267 * 268 * @param start 269 * the first initially contained element. 270 * @param others 271 * the other initially contained elements. 272 * @return an enum set containing the specified elements. 273 * @throws NullPointerException 274 * if any of the specified elements is {@code null}. 275 */ of(E start, E... others)276 public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) { 277 EnumSet<E> set = of(start); 278 for (E e : others) { 279 set.add(e); 280 } 281 return set; 282 } 283 284 /** 285 * Creates an enum set containing all the elements within the range defined 286 * by {@code start} and {@code end} (inclusive). All the elements must be in 287 * order. 288 * 289 * @param start 290 * the element used to define the beginning of the range. 291 * @param end 292 * the element used to define the end of the range. 293 * @return an enum set with elements in the range from start to end. 294 * @throws NullPointerException 295 * if any one of {@code start} or {@code end} is {@code null}. 296 * @throws IllegalArgumentException 297 * if {@code start} is behind {@code end}. 298 */ range(E start, E end)299 public static <E extends Enum<E>> EnumSet<E> range(E start, E end) { 300 if (start.compareTo(end) > 0) { 301 throw new IllegalArgumentException(); 302 } 303 EnumSet<E> set = EnumSet.noneOf(start.getDeclaringClass()); 304 set.setRange(start, end); 305 return set; 306 } 307 setRange(E start, E end)308 abstract void setRange(E start, E end); 309 310 /** 311 * Creates a new enum set with the same elements as those contained in this 312 * enum set. 313 * 314 * @return a new enum set with the same elements as those contained in this 315 * enum set. 316 */ 317 @SuppressWarnings("unchecked") 318 @Override clone()319 public EnumSet<E> clone() { 320 try { 321 return (EnumSet<E>) super.clone(); 322 } catch (CloneNotSupportedException e) { 323 throw new AssertionError(e); 324 } 325 } 326 isValidType(Class<?> cls)327 boolean isValidType(Class<?> cls) { 328 return cls == elementClass || cls.getSuperclass() == elementClass; 329 } 330 331 private static class SerializationProxy<E extends Enum<E>> implements 332 Serializable { 333 334 private static final long serialVersionUID = 362491234563181265L; 335 336 private Class<E> elementType; 337 338 private E[] elements; 339 readResolve()340 private Object readResolve() { 341 EnumSet<E> set = EnumSet.noneOf(elementType); 342 for (E e : elements) { 343 set.add(e); 344 } 345 return set; 346 } 347 } 348 349 @SuppressWarnings("unchecked") writeReplace()350 Object writeReplace() { 351 SerializationProxy proxy = new SerializationProxy(); 352 proxy.elements = toArray(new Enum[0]); 353 proxy.elementType = elementClass; 354 return proxy; 355 } 356 } 357