AnnotationMemberpublic class AnnotationMember extends Object implements SerializableThis class represents member element of an annotation.
It consists of name and value, supplemented with element
definition information (such as declared type of element).
The value may be one of the following types:
- boxed primitive
- Class
- enum constant
- annotation (nested)
- one-dimensional array of the above
- Throwable
The last type is specific for this implementation; a Throwable value
means that the error occured during parsing or resolution of corresponding
class-data structures and throwing is delayed until the element
is requested for value. |
Fields Summary |
---|
protected static final char | ERRORTag description of a Throwable value type. | protected static final char | ARRAYTag description of an array value type. | protected static final char | OTHERTag description of all value types except arrays and Throwables. | protected static final Object | NO_VALUESingleton representing missing element value. | protected final String | name | protected final Object | value | protected final char | tag | protected transient Class | elementType | protected transient Method | definingMethod |
Constructors Summary |
---|
public AnnotationMember(String name, Object val)Creates a new element with specified name and value.
Definition info will be provided later when this
element becomes actual annotation member.
this.name = name;
value = val == null ? NO_VALUE : val;
if (value instanceof Throwable) {
tag = ERROR;
} else if (value.getClass().isArray()) {
tag = ARRAY;
} else {
tag = OTHER;
}
| public AnnotationMember(String name, Object val, Class type, Method m)Creates the completely defined element.
this(name, val);
definingMethod = m;
if (type == int.class) {
elementType = Integer.class;
} else if (type == boolean.class) {
elementType = Boolean.class;
} else if (type == char.class) {
elementType = Character.class;
} else if (type == float.class) {
elementType = Float.class;
} else if (type == double.class) {
elementType = Double.class;
} else if (type == long.class) {
elementType = Long.class;
} else if (type == short.class) {
elementType = Short.class;
} else if (type == byte.class) {
elementType = Byte.class;
} else {
elementType = type;
}
|
Methods Summary |
---|
public java.lang.Object | copyValue()Provides mutation-safe access to contained value. That is, caller is free
to modify the returned value, it will not affect the contained data value.
if (tag != ARRAY || Array.getLength(value) == 0) {
return value;
}
Class type = value.getClass();
if (type == int[].class) {
return ((int[])value).clone();
} else if (type == byte[].class) {
return ((byte[])value).clone();
} else if (type == short[].class) {
return ((short[])value).clone();
} else if (type == long[].class) {
return ((long[])value).clone();
} else if (type == char[].class) {
return ((char[])value).clone();
} else if (type == boolean[].class) {
return ((boolean[])value).clone();
} else if (type == float[].class) {
return ((float[])value).clone();
} else if (type == double[].class) {
return ((double[])value).clone();
}
return ((Object[])value).clone();
| public boolean | equalArrayValue(java.lang.Object otherValue)Returns true if the contained value and a passed object are equal arrays,
false otherwise. Appropriate overloaded method of Arrays.equals()
is used for equality testing.
if (value instanceof Object[] && otherValue instanceof Object[]) {
return Arrays.equals((Object[])value, (Object[])otherValue);
}
Class type = value.getClass();
if (type != otherValue.getClass()) {
return false;
}
if (type == int[].class) {
return Arrays.equals((int[])value, (int[])otherValue);
} else if (type == byte[].class) {
return Arrays.equals((byte[])value, (byte[])otherValue);
} else if (type == short[].class) {
return Arrays.equals((short[])value, (short[])otherValue);
} else if (type == long[].class) {
return Arrays.equals((long[])value, (long[])otherValue);
} else if (type == char[].class) {
return Arrays.equals((char[])value, (char[])otherValue);
} else if (type == boolean[].class) {
return Arrays.equals((boolean[])value, (boolean[])otherValue);
} else if (type == float[].class) {
return Arrays.equals((float[])value, (float[])otherValue);
} else if (type == double[].class) {
return Arrays.equals((double[])value, (double[])otherValue);
}
return false;
| public boolean | equals(java.lang.Object obj)Returns true if the specified object represents equal element
(equivalent name-value pair).
A special case is the contained Throwable value; it is considered
transcendent so no other element would be equal.
if (obj == this) {
// not a mere optimization,
// this is needed for consistency with hashCode()
return true;
}
if (obj instanceof AnnotationMember) {
AnnotationMember that = (AnnotationMember)obj;
if (name.equals(that.name) && tag == that.tag) {
if (tag == ARRAY) {
return equalArrayValue(that.value);
} else if (tag == ERROR) {
// undefined value is incomparable (transcendent)
return false;
} else {
return value.equals(that.value);
}
}
}
return false;
| public int | hashCode()Computes hash code of this element. The formula is as follows:
(name.hashCode() * 127) ^ value.hashCode()
If value is an array, one of overloaded Arrays.hashCode()
methods is used.
int hash = name.hashCode() * 127;
if (tag == ARRAY) {
Class type = value.getClass();
if (type == int[].class) {
return hash ^ Arrays.hashCode((int[])value);
} else if (type == byte[].class) {
return hash ^ Arrays.hashCode((byte[])value);
} else if (type == short[].class) {
return hash ^ Arrays.hashCode((short[])value);
} else if (type == long[].class) {
return hash ^ Arrays.hashCode((long[])value);
} else if (type == char[].class) {
return hash ^ Arrays.hashCode((char[])value);
} else if (type == boolean[].class) {
return hash ^ Arrays.hashCode((boolean[])value);
} else if (type == float[].class) {
return hash ^ Arrays.hashCode((float[])value);
} else if (type == double[].class) {
return hash ^ Arrays.hashCode((double[])value);
}
return hash ^ Arrays.hashCode((Object[])value);
} else {
return hash ^ value.hashCode();
}
| public void | rethrowError()Throws contained error (if any) with a renewed stack trace.
if (tag == ERROR) {
// need to throw cloned exception for thread safety
// besides it is better to provide actual stack trace
// rather than recorded during parsing
// first check for expected types
if (value instanceof TypeNotPresentException) {
TypeNotPresentException tnpe = (TypeNotPresentException)value;
throw new TypeNotPresentException(tnpe.typeName(), tnpe.getCause());
} else if (value instanceof EnumConstantNotPresentException) {
EnumConstantNotPresentException ecnpe = (EnumConstantNotPresentException)value;
throw new EnumConstantNotPresentException(ecnpe.enumType(), ecnpe.constantName());
} else if (value instanceof ArrayStoreException) {
ArrayStoreException ase = (ArrayStoreException)value;
throw new ArrayStoreException(ase.getMessage());
}
// got some other error, have to go with deep cloning
// via serialization mechanism
Throwable error = (Throwable)value;
StackTraceElement[] ste = error.getStackTrace();
ByteArrayOutputStream bos = new ByteArrayOutputStream(
ste == null ? 512 : (ste.length + 1) * 80);
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(error);
oos.flush();
oos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos
.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
error = (Throwable)ois.readObject();
ois.close();
throw error;
}
| protected org.apache.harmony.lang.annotation.AnnotationMember | setDefinition(org.apache.harmony.lang.annotation.AnnotationMember copy)Fills in element's definition info and returns this.
definingMethod = copy.definingMethod;
elementType = copy.elementType;
return this;
| public java.lang.String | toString()Returns readable description of this annotation value.
if (tag == ARRAY) {
StringBuilder sb = new StringBuilder(80);
sb.append(name).append("=[");
int len = Array.getLength(value);
for (int i = 0; i < len; i++) {
if (i != 0) sb.append(", ");
sb.append(Array.get(value, i));
}
return sb.append("]").toString();
} else {
return name+ "=" +value;
}
| public java.lang.Object | validateValue()Validates contained value against its member definition
and if ok returns the value.
Otherwise, if the value type mismatches definition
or the value itself describes an error,
throws appropriate exception.
Note, this method may return null if this element was constructed
with such value.
if (tag == ERROR) {
rethrowError();
}
if (value == NO_VALUE) {
return null;
}
if (elementType == value.getClass()
|| elementType.isInstance(value)) { // nested annotation value
return copyValue();
} else {
throw new AnnotationTypeMismatchException(definingMethod,
value.getClass().getName());
}
|
|