package com.rc.retroweaver.runtime;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
/**
* A version of the 1.5 java.lang.Enum class for the 1.4 VM.
*
* @author Toby Reyelts
*
*/
public class Enum_<E extends Enum_<E>> implements Comparable<E>, Serializable {
// Implementation notes:
//
// Due to access restrictions which are circumvented in the JDK, but can not
// be circumvented here in user-land code, we have to pre-emptively get enum
// classes to register themselves with Enum_, through a call to setEnumValues.
//
//
private int ordinal;
private String name;
private static Map<Class,Object[]> enumValues = new HashMap<Class,Object[]>();
protected Enum_( String name, int ordinal ) {
this.name = name;
this.ordinal = ordinal;
}
protected void setEnumValues( Class c, Object[] values ) {
enumValues.put( c, values );
}
/**
* Implement serialization so we can get the singleton behavior we're looking
* for in enums.
*
*/
private Object readResolve() throws ObjectStreamException {
Class c = getClass();
return valueOf( c, name );
}
// This method is present in java.lang.Class in 1.5
// but we're just duplicating it here for now
// Perhaps we'll move it into a Class_ class in the future.
//
private static <T> boolean isEnum( Class<T> class_ ) {
Class c = class_.getSuperclass();
if ( c == null ) {
return false;
}
return Enum_.class.isAssignableFrom( c );
}
// This method is present in java.lang.Class in 1.5
// but we're just duplicating it here for now
// Perhaps we'll move it into a Class_ class in the future.
//
private static <T> T[] getEnumConstants( Class<T> class_ ) {
if ( ! isEnum( class_ ) ) {
return null;
}
// Will uncomment this as soon as I add the static registration code to enum subclasses
// in the bytecode enhancement.
//
// T[] values = ( T[] ) enumValues.get( class_ );
T[] values = null;
try {
Method valuesMethod = class_.getMethod( "values" );
values = ( T[] ) valuesMethod.invoke( null );
}
catch ( java.lang.reflect.InvocationTargetException e ) {
return null;
}
catch ( NoSuchMethodException e ) {
return null;
}
catch ( IllegalAccessException e ) {
return null;
}
if ( values == null ) {
return null;
}
return ( T[] ) values.clone();
}
public static <T extends Enum_<T>> T valueOf( Class<T> enumType, String name ) {
if ( enumType == null ) {
throw new NullPointerException( "enumType is null" );
}
if ( name == null ) {
throw new NullPointerException( "name is null" );
}
T[] enums = getEnumConstants( enumType );
if ( enums != null ) {
for ( T enum_ : enums ) {
if ( enum_.name.equals( name ) ) {
return enum_;
}
}
}
throw new IllegalArgumentException( "No enum const " + enumType + "." + name );
}
public final boolean equals( Object other ) {
return other == this;
}
public final int hashCode() {
return System.identityHashCode( this );
}
public String toString() {
return name;
}
// This method shows up with a final access specifier in the current specification,
// but the current JDK 1.5 beta doesn't declare it as final. If I declare it final,
// I get verify errors, because the JDK1.5 beta generates enums that override this method.
//
public int compareTo( E e ) {
Class c1 = getDeclaringClass();
Class c2 = e.getDeclaringClass();
if ( c1 == c2 ) {
return ordinal - e.ordinal;
}
throw new ClassCastException();
}
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public final String name() {
return name;
}
public final int ordinal() {
return ordinal;
}
public final Class<E> getDeclaringClass() {
Class superClass = getClass().getSuperclass();
if ( superClass != Enum_.class ) {
return superClass;
}
else {
return ( Class ) Enum_.class;
}
}
}