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 | } |