| 1 | package net.sourceforge.retroweaver.runtime.java.lang; |
| 2 | |
| 3 | import java.io.InvalidObjectException; |
| 4 | import java.io.ObjectStreamException; |
| 5 | import java.io.Serializable; |
| 6 | import java.util.HashMap; |
| 7 | import java.util.Map; |
| 8 | |
| 9 | /** |
| 10 | * A version of the 1.5 java.lang.Enum class for the 1.4 VM. |
| 11 | */ |
| 12 | public class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { |
| 13 | |
| 14 | private static final long serialVersionUID = -1689726118486609581L; |
| 15 | |
| 16 | private final transient int ordinal_; |
| 17 | |
| 18 | private final String name_; |
| 19 | |
| 20 | private static final Map<Class, Object[]> enumValues = new HashMap<Class, Object[]>(); |
| 21 | |
| 22 | protected Enum(final String name, final int ordinal) { |
| 23 | this.name_ = name; |
| 24 | this.ordinal_ = ordinal; |
| 25 | } |
| 26 | |
| 27 | protected static final void setEnumValues(final Object[] values, final Class c) { |
| 28 | synchronized(enumValues) { |
| 29 | enumValues.put(c, values); |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | protected static final <T> T[] getEnumValues(final Class<T> class_) { |
| 34 | synchronized(enumValues) { |
| 35 | final T[] values = (T[]) enumValues.get(class_); |
| 36 | if (values != null) { |
| 37 | return values; |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | if (!class_.isEnum()) { |
| 42 | return null; |
| 43 | } |
| 44 | |
| 45 | // force initialization of class_ as |
| 46 | // class loader may not have called static initializers yet |
| 47 | try { |
| 48 | Class.forName(class_.getName(), true, class_.getClassLoader()); |
| 49 | } catch (ClassNotFoundException e) { |
| 50 | // can not happen: class_ has already been resolved. |
| 51 | } |
| 52 | |
| 53 | synchronized(enumValues) { |
| 54 | return (T[]) enumValues.get(class_); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | /** |
| 59 | * Implement serialization so we can get the singleton behavior we're |
| 60 | * looking for in enums. |
| 61 | */ |
| 62 | protected Object readResolve() throws ObjectStreamException { |
| 63 | /* |
| 64 | * The implementation is based on "Java Object Serialization Specification", |
| 65 | * revision 1.5.0: |
| 66 | * |
| 67 | * only the name_ is saved, serialVersionUID is 0L for all enum types |
| 68 | * InvalidObjectException is raised if valueOf() raises IllegalArgumentException. |
| 69 | * |
| 70 | */ |
| 71 | |
| 72 | final Class<E> clazz = getDeclaringClass(); |
| 73 | /* |
| 74 | * Note: getClass() would not work for enum inner classes |
| 75 | * such as CMYK.Cyan in the test suite. |
| 76 | */ |
| 77 | try { |
| 78 | return valueOf(clazz, name_); |
| 79 | } catch (IllegalArgumentException iae) { |
| 80 | final InvalidObjectException ioe = new InvalidObjectException(name_ + " is not a valid enum for " + clazz.getName()); |
| 81 | try { |
| 82 | ioe.initCause(iae); |
| 83 | } catch (NoSuchMethodError nsm) { |
| 84 | // cause should be set according to the spec but it's only available in 1.4 |
| 85 | } |
| 86 | |
| 87 | throw ioe; |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) { |
| 92 | |
| 93 | if (enumType == null) { |
| 94 | throw new NullPointerException("enumType is null"); // NOPMD by xlv |
| 95 | } |
| 96 | |
| 97 | if (name == null) { |
| 98 | throw new NullPointerException("name_ is null"); // NOPMD by xlv |
| 99 | } |
| 100 | |
| 101 | final T[] enums = getEnumValues(enumType); |
| 102 | |
| 103 | if (enums != null) { |
| 104 | for (T enum_ : enums) { |
| 105 | if (enum_.name_.equals(name)) { |
| 106 | return enum_; |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | throw new IllegalArgumentException("No enum const " + enumType + "." |
| 112 | + name); |
| 113 | } |
| 114 | |
| 115 | public final boolean equals(final Object other) { |
| 116 | return other == this; |
| 117 | } |
| 118 | |
| 119 | public final int hashCode() { |
| 120 | return System.identityHashCode(this); |
| 121 | } |
| 122 | |
| 123 | public String toString() { |
| 124 | return name_; |
| 125 | } |
| 126 | |
| 127 | public final int compareTo(final E e) { |
| 128 | final Class c1 = getDeclaringClass(); |
| 129 | final Class c2 = e.getDeclaringClass(); |
| 130 | |
| 131 | if (c1 == c2) { // NOPMD by xlv |
| 132 | return ordinal_ - e.ordinal_; |
| 133 | } |
| 134 | |
| 135 | throw new ClassCastException(); |
| 136 | } |
| 137 | |
| 138 | protected final Object clone() throws CloneNotSupportedException { |
| 139 | throw new CloneNotSupportedException(); |
| 140 | } |
| 141 | |
| 142 | public final String name() { |
| 143 | return name_; |
| 144 | } |
| 145 | |
| 146 | public final int ordinal() { |
| 147 | return ordinal_; |
| 148 | } |
| 149 | |
| 150 | public final Class<E> getDeclaringClass() { |
| 151 | final Class clazz = getClass(); |
| 152 | final Class superClass = clazz.getSuperclass(); |
| 153 | if (superClass == Enum.class) { |
| 154 | return clazz; |
| 155 | } else { |
| 156 | return superClass; |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | } |