AnnotationFactory.java revision 6aa068b481cc4cca7765ce90fdf32f3eb2b5a77c
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
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.lang.annotation;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.annotation.Annotation;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.annotation.IncompleteAnnotationException;
257365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.lang.reflect.InvocationHandler;
267365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.lang.reflect.Method;
277365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.lang.reflect.Proxy;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Map;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.WeakHashMap;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport static org.apache.harmony.lang.annotation.AnnotationMember.ARRAY;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport static org.apache.harmony.lang.annotation.AnnotationMember.ERROR;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The annotation implementation based on dynamically generated proxy instances.
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It conforms to all requirements stated in public APIs, see in particular
38f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * {@link java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedElement}
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and {@link java.lang.annotation.Annotation java.lang.annotation.Annotation}.
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Namely, annotation instances are immutable and serializable; they provide
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * conforming access to annotation member values and required implementations of
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * methods declared in Annotation interface.
43f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see android.lang.annotation.AnnotationMember
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.annotation.Annotation
46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Alexey V. Varlamov, Serguei S. Zapreyev
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @version $Revision$
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project@SuppressWarnings({"serial"})
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class AnnotationFactory implements InvocationHandler, Serializable {
52f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private static final transient
54f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    Map<Class<? extends Annotation>, AnnotationMember[]>
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    cache = new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>();
56f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
58f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Reflects specified annotation type and returns an array
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of member element definitions with default values.
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType ) {
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        AnnotationMember[] desc = cache.get(annotationType);
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (desc == null) {
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!annotationType.isAnnotation()) {
65f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                throw new IllegalArgumentException("Type is not annotation: "
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + annotationType.getName());
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Method[] m = annotationType.getDeclaredMethods();
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            desc = new AnnotationMember[m.length];
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int idx = 0;
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for(Method element : m) {
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String name = element.getName();
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Class<?> type = element.getReturnType();
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                try {
75f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    desc[idx] = new AnnotationMember(name,
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            element.getDefaultValue(), type, element);
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } catch (Throwable t) {
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    desc[idx] = new AnnotationMember(name, t, type, element);
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                idx++;
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cache.put(annotationType, desc);
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return desc;
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
86f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Provides a new annotation instance.
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param annotationType the annotation type definition
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param elements name-value pairs representing elements of the annotation
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a new annotation instance
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static Annotation createAnnotation(
94f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            Class<? extends Annotation> annotationType,
95f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            AnnotationMember[] elements)
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    {
97f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        AnnotationFactory antn = new AnnotationFactory(annotationType, elements);
98f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        return (Annotation)Proxy.newProxyInstance( annotationType.getClassLoader(),
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                new Class[]{annotationType}, antn);
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final Class<? extends Annotation> klazz;
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private AnnotationMember[] elements;
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * New instances should not be created directly, use factory method
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link #createAnnotation(Class, AnnotationMember[]) createAnnotation()}
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * instead.
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param klzz class defining the annotation type
111f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @param values actual element values
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private AnnotationFactory(Class<? extends Annotation> klzz, AnnotationMember[] values) {
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        klazz = klzz;
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        AnnotationMember[] defs = getElementsDescription(klazz);
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (values == null) {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            elements = defs;
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //merge default and actual values
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            elements = new AnnotationMember[defs.length];
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            next: for (int i = elements.length - 1; i >= 0; i-- ){
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (AnnotationMember val : values){
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (val.name.equals(defs[i].name)) {
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        elements[i] = val.setDefinition(defs[i]);
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        continue next;
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                elements[i] = defs[i];
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
132f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
134f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Reads the object, obtains actual member definitions for the annotation type,
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and merges deserialized values with the new definitions.
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
137f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private void readObject(ObjectInputStream os) throws IOException,
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ClassNotFoundException {
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        os.defaultReadObject();
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Annotation type members can be changed arbitrarily
141f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // So there may be zombi elements from the previous life;
142f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // they hardly fit into this new annotation's incarnation,
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // as we have no defining methods for them.
144f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // Reasonably just drop such elements,
145f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // but seems better to keep them for compatibility
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        AnnotationMember[] defs = getElementsDescription(klazz);
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        AnnotationMember[] old = elements;
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        List<AnnotationMember> merged = new ArrayList<AnnotationMember>(
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                defs.length + old.length);
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextOld: for (AnnotationMember el1 : old) {
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (AnnotationMember el2 : defs) {
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (el2.name.equals(el1.name)) {
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue nextOld;
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            merged.add(el1); //phantom element
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextNew: for (AnnotationMember def : defs){
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (AnnotationMember val : old){
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (val.name.equals(def.name)) {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // nothing to do about cached errors (if any)
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // anyway they remain relevant to values
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    merged.add(val.setDefinition(def));
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue nextNew;
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            merged.add(def); // brand new element
168f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        }
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        elements = merged.toArray(new AnnotationMember[merged.size()]);
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
171f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the specified object represents the same annotation instance.
174f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * That is, if it implements the same annotation type and
175f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * returns the same element values.
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <br>Note, actual underlying implementation mechanism does not matter - it may
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * differ completely from this class.
178f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @return true if the passed object is equivalent annotation instance,
179f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * false otherwise.
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see android.lang.annotation.AnnotationMember#equals(Object)
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object obj) {
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (obj == this) {
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!klazz.isInstance(obj)) {
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Object handler = null;
190f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        if (Proxy.isProxyClass(obj.getClass())
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory ) {
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            AnnotationFactory other = (AnnotationFactory) handler;
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (elements.length != other.elements.length) {
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return false;
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            next: for (AnnotationMember el1 : elements){
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (AnnotationMember el2 : other.elements) {
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (el1.equals(el2)) {
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        continue next;
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return false;
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // encountered foreign annotation implementaton
207f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // so have to obtain element values via invocation
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // of corresponding methods
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (final AnnotationMember el : elements) {
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (el.tag == ERROR) {
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // undefined value is incomparable (transcendent)
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return false;
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                try {
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (!el.definingMethod.isAccessible()) {
216ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                        el.definingMethod.setAccessible(true);
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    Object otherValue = el.definingMethod.invoke(obj);
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (otherValue != null ) {
220f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                        if (el.tag == ARRAY) {
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            if (!el.equalArrayValue(otherValue)) {
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                return false;
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            }
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } else {
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            if (!el.value.equals(otherValue)) {
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                return false;
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            }
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else if (el.value != AnnotationMember.NO_VALUE) {
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return false;
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } catch (Throwable e) {
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return false;
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
241f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Returns a hash code composed as a sum of hash codes of member elements,
242f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * including elements with default values.
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see android.lang.annotation.AnnotationMember#hashCode()
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int hashCode() {
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int hash = 0;
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (AnnotationMember element : elements) {
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hash += element.hashCode();
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return hash;
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Provides detailed description of this annotation instance,
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * including all member name-values pairs.
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return string representation of this annotation
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
2596aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        StringBuilder result = new StringBuilder();
2606aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        result.append('@');
2616aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        result.append(klazz.getName());
2626aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        result.append('(');
2636aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        for(int i = 0; i < elements.length; ++i) {
2646aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes            if (i != 0) {
2656aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes                result.append(", ");
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
2676aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes            result.append(elements[i]);
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
2696aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        result.append(')');
2706aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes        return result.toString();
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
272f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes a method invocation request to this annotation instance.
275f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Recognizes the methods declared in the
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link java.lang.annotation.Annotation java.lang.annotation.Annotation}
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * interface, and member-defining methods of the implemented annotation type.
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException If the specified method is none of the above
279f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @return the invocation result
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    {
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String name = method.getName();
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Class[] params = method.getParameterTypes();
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (params.length == 0) {
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ("annotationType".equals(name)) {
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return klazz;
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if ("toString".equals(name)) {
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return toString();
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if ("hashCode".equals(name)) {
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return hashCode();
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
293f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // this must be element value request
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            AnnotationMember element = null;
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (AnnotationMember el : elements) {
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (name.equals(el.name)) {
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    element = el;
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
300f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                }
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (element == null || !method.equals(element.definingMethod)) {
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException(method.toString());
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Object value = element.validateValue();
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (value == null) {
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IncompleteAnnotationException(klazz, name);
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return value;
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)){
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return Boolean.valueOf(equals(args[0]));
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new IllegalArgumentException(
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Invalid method for annotation type: " + method);
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
318