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    }