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