1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18d736c6d053f63e4cd8dfb16c57093c67be3e18cdElliott Hughespackage libcore.reflect; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ByteArrayInputStream; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ByteArrayOutputStream; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.annotation.AnnotationTypeMismatchException; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Array; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Method; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 31f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * This class represents member element of an annotation. 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It consists of name and value, supplemented with element 33f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * definition information (such as declared type of element). 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <br>The value may be one of the following types: 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul> 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li> boxed primitive 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li> Class 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li> enum constant 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li> annotation (nested) 40f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * <li> one-dimensional array of the above 41f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * <li> Throwable 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul> 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The last type is specific for this implementation; a Throwable value 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * means that the error occured during parsing or resolution of corresponding 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * class-data structures and throwing is delayed until the element 46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * is requested for value. 47f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 48d736c6d053f63e4cd8dfb16c57093c67be3e18cdElliott Hughes * @see AnnotationFactory 49f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Alexey V. Varlamov, Serguei S. Zapreyev 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @version $Revision$ 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project@SuppressWarnings({"serial"}) 54d736c6d053f63e4cd8dfb16c57093c67be3e18cdElliott Hughespublic final class AnnotationMember implements Serializable { 55f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Tag description of a Throwable value type. 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected static final char ERROR = '!'; 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Tag description of an array value type. 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected static final char ARRAY = '['; 65f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Tag description of all value types except arrays and Throwables. 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected static final char OTHER = '*'; 70f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char INT = 'I'; 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char CHAR = 'C'; 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char DOUBLE = 'D'; 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char FLOAT = 'F'; 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char BYTE = 'B'; 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char LONG = 'J'; 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char SHORT = 'S'; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char BOOL = 'Z'; 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char CLASS = 'c'; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char ENUM = 'e'; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// public static final char ANTN = '@'; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private enum DefaultValues {NO_VALUE} 84f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Singleton representing missing element value. 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected static final Object NO_VALUE = DefaultValues.NO_VALUE; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected final String name; 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected final Object value; // a primitive value is wrapped to the corresponding wrapper class 92f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes protected final char tag; 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // no sense to serialize definition info as it can be changed arbitrarily 94f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes protected transient Class<?> elementType; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected transient Method definingMethod; 96f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 97f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new element with specified name and value. 100f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Definition info will be provided later when this 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * element becomes actual annotation member. 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name element name, must not be null 103f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @param val element value, should be of addmissible type, 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as specified in the description of this class 105f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #setDefinition(AnnotationMember) 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public AnnotationMember(String name, Object val) { 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.name = name; 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project value = val == null ? NO_VALUE : val; 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (value instanceof Throwable) { 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tag = ERROR; 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (value.getClass().isArray()) { 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tag = ARRAY; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project tag = OTHER; 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 119f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates the completely defined element. 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name element name, must not be null 123f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @param value element value, should be of addmissible type, 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as specified in the description of this class 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param m element-defining method, reflected on the annotation type 126f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @param type declared type of this element 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (return type of the defining method) 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public AnnotationMember(String name, Object val, Class type, Method m) { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this(name, val); 131f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project definingMethod = m; 133f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type == int.class) { 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Integer.class; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == boolean.class) { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Boolean.class; 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == char.class) { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Character.class; 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == float.class) { 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Float.class; 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == double.class) { 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Double.class; 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == long.class) { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Long.class; 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == short.class) { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Short.class; 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == byte.class) { 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = Byte.class; 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = type; 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Fills in element's definition info and returns this. 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected AnnotationMember setDefinition(AnnotationMember copy) { 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project definingMethod = copy.definingMethod; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementType = copy.elementType; 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 163f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 165f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Returns readable description of this annotation value. 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toString() { 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ARRAY) { 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project StringBuilder sb = new StringBuilder(80); 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sb.append(name).append("=["); 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int len = Array.getLength(value); 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < len; i++) { 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (i != 0) sb.append(", "); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sb.append(Array.get(value, i)); 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sb.append("]").toString(); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return name+ "=" +value; 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 181f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the specified object represents equal element 184f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * (equivalent name-value pair). 185f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * <br> A special case is the contained Throwable value; it is considered 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * transcendent so no other element would be equal. 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if passed object is equivalent element representation, 188f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * false otherwise 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #equalArrayValue(Object) 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.annotation.Annotation#equals(Object) 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equals(Object obj) { 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (obj == this) { 194f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // not a mere optimization, 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // this is needed for consistency with hashCode() 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (obj instanceof AnnotationMember) { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember that = (AnnotationMember)obj; 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (name.equals(that.name) && tag == that.tag) { 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ARRAY) { 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return equalArrayValue(that.value); 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (tag == ERROR) { 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // undefined value is incomparable (transcendent) 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return value.equals(that.value); 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 213f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the contained value and a passed object are equal arrays, 216f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * false otherwise. Appropriate overloaded method of Arrays.equals() 217f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * is used for equality testing. 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.util.Arrays#equals(java.lang.Object[], java.lang.Object[]) 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the value is array and is equal to specified object, 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * false otherwise 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equalArrayValue(Object otherValue) { 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (value instanceof Object[] && otherValue instanceof Object[]) { 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((Object[])value, (Object[])otherValue); 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class type = value.getClass(); 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type != otherValue.getClass()) { 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type == int[].class) { 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((int[])value, (int[])otherValue); 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == byte[].class) { 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((byte[])value, (byte[])otherValue); 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == short[].class) { 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((short[])value, (short[])otherValue); 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == long[].class) { 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((long[])value, (long[])otherValue); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == char[].class) { 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((char[])value, (char[])otherValue); 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == boolean[].class) { 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((boolean[])value, (boolean[])otherValue); 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == float[].class) { 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((float[])value, (float[])otherValue); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == double[].class) { 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Arrays.equals((double[])value, (double[])otherValue); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 249f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Computes hash code of this element. The formula is as follows: 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code> (name.hashCode() * 127) ^ value.hashCode() </code> 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <br>If value is an array, one of overloaded Arrays.hashCode() 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * methods is used. 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the hash code 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.util.Arrays#hashCode(java.lang.Object[]) 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.annotation.Annotation#hashCode() 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int hashCode() { 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int hash = name.hashCode() * 127; 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ARRAY) { 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class type = value.getClass(); 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type == int[].class) { 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((int[])value); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == byte[].class) { 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((byte[])value); 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == short[].class) { 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((short[])value); 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == long[].class) { 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((long[])value); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == char[].class) { 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((char[])value); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == boolean[].class) { 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((boolean[])value); 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == float[].class) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((float[])value); 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == double[].class) { 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((double[])value); 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ Arrays.hashCode((Object[])value); 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash ^ value.hashCode(); 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Throws contained error (if any) with a renewed stack trace. 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void rethrowError() throws Throwable { 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ERROR) { 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // need to throw cloned exception for thread safety 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // besides it is better to provide actual stack trace 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // rather than recorded during parsing 294f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 295f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // first check for expected types 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (value instanceof TypeNotPresentException) { 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project TypeNotPresentException tnpe = (TypeNotPresentException)value; 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new TypeNotPresentException(tnpe.typeName(), tnpe.getCause()); 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (value instanceof EnumConstantNotPresentException) { 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project EnumConstantNotPresentException ecnpe = (EnumConstantNotPresentException)value; 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new EnumConstantNotPresentException(ecnpe.enumType(), ecnpe.constantName()); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (value instanceof ArrayStoreException) { 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ArrayStoreException ase = (ArrayStoreException)value; 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ArrayStoreException(ase.getMessage()); 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // got some other error, have to go with deep cloning 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // via serialization mechanism 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Throwable error = (Throwable)value; 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project StackTraceElement[] ste = error.getStackTrace(); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteArrayOutputStream bos = new ByteArrayOutputStream( 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ste == null ? 512 : (ste.length + 1) * 80); 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ObjectOutputStream oos = new ObjectOutputStream(bos); 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project oos.writeObject(error); 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project oos.flush(); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project oos.close(); 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteArrayInputStream bis = new ByteArrayInputStream(bos 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .toByteArray()); 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ObjectInputStream ois = new ObjectInputStream(bis); 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project error = (Throwable)ois.readObject(); 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ois.close(); 321f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw error; 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 325f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Validates contained value against its member definition 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and if ok returns the value. 329f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Otherwise, if the value type mismatches definition 330f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * or the value itself describes an error, 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * throws appropriate exception. 332f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * <br> Note, this method may return null if this element was constructed 333f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * with such value. 334f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #rethrowError() 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #copyValue() 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return actual valid value or null if no value 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object validateValue() throws Throwable { 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag == ERROR) { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project rethrowError(); 342f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (value == NO_VALUE) { 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 346f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (elementType == value.getClass() 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project || elementType.isInstance(value)) { // nested annotation value 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return copyValue(); 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 350f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new AnnotationTypeMismatchException(definingMethod, 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project value.getClass().getName()); 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 354f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 355f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 358f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Provides mutation-safe access to contained value. That is, caller is free 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to modify the returned value, it will not affect the contained data value. 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return cloned value if it is mutable or the original immutable value 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object copyValue() throws Throwable 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tag != ARRAY || Array.getLength(value) == 0) { 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return value; 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class type = value.getClass(); 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type == int[].class) { 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((int[])value).clone(); 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == byte[].class) { 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((byte[])value).clone(); 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == short[].class) { 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((short[])value).clone(); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == long[].class) { 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((long[])value).clone(); 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == char[].class) { 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((char[])value).clone(); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == boolean[].class) { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((boolean[])value).clone(); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == float[].class) { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((float[])value).clone(); 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (type == double[].class) { 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((double[])value).clone(); 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ((Object[])value).clone(); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 388