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