Home | History | Annotate | Download | only in lang
      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 
     17 package java.lang;
     18 
     19 import java.io.Serializable;
     20 import java.lang.reflect.Method;
     21 import java.security.AccessController;
     22 import java.security.PrivilegedExceptionAction;
     23 
     24 import org.apache.harmony.luni.util.Msg;
     25 
     26 /**
     27  * The superclass of all enumerated types. Actual enumeration types inherit from
     28  * this class, but extending this class does not make a class an enumeration
     29  * type, since the compiler needs to generate special information for it.
     30  */
     31 public abstract class Enum<E extends Enum<E>> implements Serializable,
     32         Comparable<E> {
     33 
     34     private static final long serialVersionUID = -4300926546619394005L;
     35 
     36     private final String name;
     37 
     38     private final int ordinal;
     39 
     40     /**
     41      * Constructor for constants of enum subtypes.
     42      *
     43      * @param name
     44      *            the enum constant's declared name.
     45      * @param ordinal
     46      *            the enum constant's ordinal, which corresponds to its position
     47      *            in the enum declaration, starting at zero.
     48      */
     49     protected Enum(String name, int ordinal) {
     50         this.name = name;
     51         this.ordinal = ordinal;
     52     }
     53 
     54     /**
     55      * Returns the name of this enum constant. The name is the field as it
     56      * appears in the {@code enum} declaration.
     57      *
     58      * @return the name of this enum constant.
     59      * @see #toString()
     60      */
     61     public final String name() {
     62         return name;
     63     }
     64 
     65     /**
     66      * Returns the position of the enum constant in the declaration. The first
     67      * constant has an ordinal value of zero.
     68      *
     69      * @return the ordinal value of this enum constant.
     70      */
     71     public final int ordinal() {
     72         return ordinal;
     73     }
     74 
     75     /**
     76      * Returns a string containing a concise, human-readable description of this
     77      * object. In this case, the enum constant's name is returned.
     78      *
     79      * @return a printable representation of this object.
     80      */
     81     @Override
     82     public String toString() {
     83         return name;
     84     }
     85 
     86     /**
     87      * Compares this object with the specified object and indicates if they are
     88      * equal. In order to be equal, {@code object} must be identical to this
     89      * enum constant.
     90      *
     91      * @param other
     92      *            the object to compare this enum constant with.
     93      * @return {@code true} if the specified object is equal to this
     94      *         {@code Enum}; {@code false} otherwise.
     95      */
     96     @Override
     97     public final boolean equals(Object other) {
     98         return this == other;
     99     }
    100 
    101     @Override
    102     public final int hashCode() {
    103         return ordinal + (name == null ? 0 : name.hashCode());
    104     }
    105 
    106     /**
    107      * {@code Enum} objects are singletons, they may not be cloned. This method
    108      * always throws a {@code CloneNotSupportedException}.
    109      *
    110      * @return does not return.
    111      * @throws CloneNotSupportedException
    112      *             is always thrown.
    113      */
    114     @Override
    115     protected final Object clone() throws CloneNotSupportedException {
    116         // KA004=Enums may not be cloned
    117         throw new CloneNotSupportedException(Msg.getString("KA004")); //$NON-NLS-1$
    118     }
    119 
    120     /**
    121      * Compares this object to the specified enum object to determine their
    122      * relative order. This method compares the object's ordinal values, that
    123      * is, their position in the enum declaration.
    124      *
    125      * @param o
    126      *            the enum object to compare this object to.
    127      * @return a negative value if the ordinal value of this enum constant is
    128      *         less than the ordinal value of {@code o}; 0 if the ordinal
    129      *         values of this enum constant and {@code o} are equal; a positive
    130      *         value if the ordinal value of this enum constant is greater than
    131      *         the ordinal value of {@code o}.
    132      * @see java.lang.Comparable
    133      */
    134     public final int compareTo(E o) {
    135         return ordinal - o.ordinal;
    136     }
    137 
    138     /**
    139      * Returns the enum constant's declaring class.
    140      *
    141      * @return the class object representing the constant's enum type.
    142      */
    143     @SuppressWarnings("unchecked")
    144     public final Class<E> getDeclaringClass() {
    145         Class<?> myClass = getClass();
    146         Class<?> mySuperClass = myClass.getSuperclass();
    147         if (Enum.class == mySuperClass) {
    148             return (Class<E>)myClass;
    149         }
    150         return (Class<E>)mySuperClass;
    151     }
    152 
    153     /**
    154      * Returns the constant with the specified name of the specified enum type.
    155      *
    156      * @param enumType
    157      *            the class of the enumerated type to search for the constant
    158      *            value.
    159      * @param name
    160      *            the name of the constant value to find.
    161      * @return the enum constant.
    162      * @throws NullPointerException
    163      *             if either {@code enumType} or {@code name} are {@code null}.
    164      * @throws IllegalArgumentException
    165      *             if {@code enumType} is not an enumerated type or does not
    166      *             have a constant value called {@code name}.
    167      */
    168     public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
    169         if ((enumType == null) || (name == null)) {
    170             // KA001=Argument must not be null
    171             throw new NullPointerException(Msg.getString("KA001")); //$NON-NLS-1$
    172         }
    173 
    174         // BEGIN android-changed
    175         enumType.checkPublicMemberAccess();
    176 
    177         T result = enumType.getClassCache().getEnumValue(name);
    178 
    179         if (result == null) {
    180             if (!enumType.isEnum()) {
    181                 // KA005={0} is not an enum type
    182                 throw new IllegalArgumentException(Msg.getString("KA005", enumType)); //$NON-NLS-1$
    183             } else {
    184                 // KA006={0} is not a constant in the enum type {1}
    185                 throw new IllegalArgumentException(Msg.getString("KA006", name, //$NON-NLS-1$
    186                                 enumType));
    187             }
    188         }
    189 
    190         return result;
    191         // END android-changed
    192     }
    193 
    194     /*
    195      * Helper to invoke the values() static method on T and answer the result.
    196      * Returns null if there is a problem.
    197      */
    198     @SuppressWarnings("unchecked")
    199     static <T extends Enum<T>> T[] getValues(final Class<T> enumType) {
    200         try {
    201             Method values = AccessController
    202                     .doPrivileged(new PrivilegedExceptionAction<Method>() {
    203                         public Method run() throws Exception {
    204                             Method valsMethod = enumType.getMethod("values", //$NON-NLS-1$
    205                                     (Class[]) null);
    206                             valsMethod.setAccessible(true);
    207                             return valsMethod;
    208                         }
    209                     });
    210             return (T[]) values.invoke(enumType, (Object[])null);
    211         } catch (Exception e) {
    212             return null;
    213         }
    214     }
    215 }
    216