001 package net.sourceforge.retroweaver.runtime.java.lang;
002
003 import java.io.InvalidObjectException;
004 import java.io.ObjectStreamException;
005 import java.io.Serializable;
006 import java.util.HashMap;
007 import java.util.Map;
008
009 /**
010 * A version of the 1.5 java.lang.Enum class for the 1.4 VM.
011 */
012 public class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
013
014 private static final long serialVersionUID = -1689726118486609581L;
015
016 private final transient int ordinal_;
017
018 private final String name_;
019
020 private static final Map<Class, Object[]> enumValues = new HashMap<Class, Object[]>();
021
022 protected Enum(final String name, final int ordinal) {
023 this.name_ = name;
024 this.ordinal_ = ordinal;
025 }
026
027 protected static final void setEnumValues(final Object[] values, final Class c) {
028 synchronized(enumValues) {
029 enumValues.put(c, values);
030 }
031 }
032
033 protected static final <T> T[] getEnumValues(final Class<T> class_) {
034 synchronized(enumValues) {
035 final T[] values = (T[]) enumValues.get(class_);
036 if (values != null) {
037 return values;
038 }
039 }
040
041 if (!class_.isEnum()) {
042 return null;
043 }
044
045 // force initialization of class_ as
046 // class loader may not have called static initializers yet
047 try {
048 Class.forName(class_.getName(), true, class_.getClassLoader());
049 } catch (ClassNotFoundException e) {
050 // can not happen: class_ has already been resolved.
051 }
052
053 synchronized(enumValues) {
054 return (T[]) enumValues.get(class_);
055 }
056 }
057
058 /**
059 * Implement serialization so we can get the singleton behavior we're
060 * looking for in enums.
061 */
062 protected Object readResolve() throws ObjectStreamException {
063 /*
064 * The implementation is based on "Java Object Serialization Specification",
065 * revision 1.5.0:
066 *
067 * only the name_ is saved, serialVersionUID is 0L for all enum types
068 * InvalidObjectException is raised if valueOf() raises IllegalArgumentException.
069 *
070 */
071
072 final Class<E> clazz = getDeclaringClass();
073 /*
074 * Note: getClass() would not work for enum inner classes
075 * such as CMYK.Cyan in the test suite.
076 */
077 try {
078 return valueOf(clazz, name_);
079 } catch (IllegalArgumentException iae) {
080 final InvalidObjectException ioe = new InvalidObjectException(name_ + " is not a valid enum for " + clazz.getName());
081 try {
082 ioe.initCause(iae);
083 } catch (NoSuchMethodError nsm) {
084 // cause should be set according to the spec but it's only available in 1.4
085 }
086
087 throw ioe;
088 }
089 }
090
091 public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) {
092
093 if (enumType == null) {
094 throw new NullPointerException("enumType is null"); // NOPMD by xlv
095 }
096
097 if (name == null) {
098 throw new NullPointerException("name_ is null"); // NOPMD by xlv
099 }
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 }