package java.lang;
import java.lang.annotation.Annotation;
import lejos.nxt.VM;
/**
* Not fully functional.
*/
public class Class<T>
{
// Note the following fields are mapped on to read only flash entries
// held within the VM. They should not be changed. New fields should not
// be added to this class unless changes are also made to the VM.
// The CIA fields are really a C union (with different contents for
// (C)lasses (I)nterfaces and (A)rrays), but it is not obvious how to
// implement a union in Java so instead we use shared fields.
private short CIAData1;
private short CIAData2;
private byte CIACnt1;
private byte CIACnt2;
private byte parentClass;
private byte flags;
@SuppressWarnings("unchecked")
public <U> Class<? extends U> asSubclass(Class<U> cls)
{
if (!cls.isAssignableFrom(this))
throw new ClassCastException();
return (Class<? extends U>)this;
}
@SuppressWarnings("unchecked")
public T cast(Object o)
{
if (!this.isInstance(o))
throw new ClassCastException();
return (T)o;
}
/**
* Always return false.
* @return True if asserts are enabled false if they are disabled.
*/
public boolean desiredAssertionStatus()
{
return (VM.getVMOptions() & VM.VM_ASSERT) != 0;
}
/**
* @exception ClassNotFoundException Thrown always in TinyVM.
*/
@SuppressWarnings("unused")
public static Class<?> forName (String aName)
throws ClassNotFoundException
{
throw new ClassNotFoundException();
}
public Class<?> getComponentType()
{
if (!this.isArray())
return null;
return VM.getClass(this.CIAData2 & 0xFF);
}
public Class<?>[] getInterfaces()
{
// Note this is not a correct implementation. We will return all
// of the interfaces that are implemented by this class and any super
// classes, we will also return any super interfaces that are also
// implemented. We could possible fix up some of this, but I'm not
// sure it is worth the effort. Andy
int interfaceCnt = 0;
int i = 0;
// First work out the max number of interfaces
for(;;)
{
Class<?> cls = VM.getClass(i++);
if (cls == null) break;
if (cls.isInterface() && VM.isAssignable(this, cls))
interfaceCnt++;
}
Class<?>[] interfaces = new Class<?>[interfaceCnt];
// now get them
i = 0;
interfaceCnt = 0;
for(;;)
{
Class<?> cls = VM.getClass(i++);
if (cls == null) break;
if (cls.isInterface() && VM.isAssignable(this, cls))
interfaces[interfaceCnt++] = cls;
}
return interfaces;
}
@SuppressWarnings("unchecked")
public Class<? super T> getSuperclass()
{
if (0 != (flags & (VM.VMClass.C_INTERFACE | VM.VMClass.C_PRIMITIVE)) || this == Object.class)
return null;
return (Class<? super T>)VM.getClass(this.parentClass & 0xFF);
}
public boolean isAnnotation()
{
return this.isInterface() && Annotation.class != this && Annotation.class.isAssignableFrom(this);
}
public boolean isArray()
{
return 0 != (flags & VM.VMClass.C_ARRAY);
}
public boolean isAssignableFrom(Class<?> cls)
{
return VM.isAssignable(cls, this);
}
public boolean isEnum()
{
return this.getSuperclass() == Enum.class;
}
public boolean isInstance(Object obj)
{
if (obj == null)
return false;
return this.isAssignableFrom(obj.getClass());
}
public boolean isInterface()
{
return 0 != (flags & VM.VMClass.C_INTERFACE);
}
public boolean isPrimitive()
{
return 0 != (flags & VM.VMClass.C_PRIMITIVE);
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
if (this.isInterface())
sb.append("interface ");
else
sb.append("class ");
sb.append(VM.getClassNumber(this));
return sb.toString();
}
}