179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount/*
279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * Copyright (C) 2015 The Android Open Source Project
379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount *
479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * Licensed under the Apache License, Version 2.0 (the "License");
579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * you may not use this file except in compliance with the License.
679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * You may obtain a copy of the License at
779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount *
879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount *      http://www.apache.org/licenses/LICENSE-2.0
979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount *
1079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * Unless required by applicable law or agreed to in writing, software
1179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * distributed under the License is distributed on an "AS IS" BASIS,
1279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * See the License for the specific language governing permissions and
1479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount * limitations under the License.
1579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount */
16fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.reflection.annotation;
1797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
18fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.Bindable;
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass;
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelMethod;
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.SdkUtil;
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.TypeUtil;
23fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
2479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountimport java.util.List;
2579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
26d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport javax.lang.model.element.Element;
27d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport javax.lang.model.element.ElementKind;
2879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountimport javax.lang.model.element.ExecutableElement;
2979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountimport javax.lang.model.element.Modifier;
30d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport javax.lang.model.element.TypeElement;
3179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountimport javax.lang.model.type.DeclaredType;
3279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountimport javax.lang.model.type.ExecutableType;
33fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mountimport javax.lang.model.type.TypeKind;
3479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountimport javax.lang.model.type.TypeMirror;
35d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport javax.lang.model.util.Elements;
36a7e767e576adebcddf043ad34ccb8dd167f777b3George Mountimport javax.lang.model.util.Types;
3779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
38fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mountclass AnnotationMethod extends ModelMethod {
39a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount    final ExecutableType mMethod;
4079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    final DeclaredType mDeclaringType;
41a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount    final ExecutableElement mExecutableElement;
4297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    int mApiLevel = -1; // calculated on demand
43d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    ModelClass mReceiverType;
4479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
45a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount    public AnnotationMethod(DeclaredType declaringType, ExecutableElement executableElement) {
4679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        mDeclaringType = declaringType;
47a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        mExecutableElement = executableElement;
4897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        Types typeUtils = AnnotationAnalyzer.get().getTypeUtils();
49a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        mMethod = (ExecutableType) typeUtils.asMemberOf(declaringType, executableElement);
5079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
5179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
5279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    @Override
5379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public ModelClass getDeclaringClass() {
54d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        if (mReceiverType == null) {
55d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            mReceiverType = findReceiverType(mDeclaringType);
56d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            if (mReceiverType == null) {
57d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                mReceiverType = new AnnotationClass(mDeclaringType);
58d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            }
59d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
60d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return mReceiverType;
61d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
62d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
63d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    // TODO: When going to Java 1.8, use mExecutableElement.getReceiverType()
64d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    private ModelClass findReceiverType(DeclaredType subType) {
65d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        List<? extends TypeMirror> supers = getTypeUtils().directSupertypes(subType);
66d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        for (TypeMirror superType : supers) {
67d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            if (superType.getKind() == TypeKind.DECLARED) {
68d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                DeclaredType declaredType = (DeclaredType) superType;
69d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                ModelClass inSuper = findReceiverType(declaredType);
70d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                if (inSuper != null) {
71d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                    return inSuper;
72d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                } else if (hasExecutableMethod(declaredType)) {
73d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                    return new AnnotationClass(declaredType);
74d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                }
75d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            }
76d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
77d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return null;
78d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
79d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
80d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    private boolean hasExecutableMethod(DeclaredType declaredType) {
81d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        Elements elementUtils = getElementUtils();
82d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        TypeElement enclosing = (TypeElement) mExecutableElement.getEnclosingElement();
83d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        TypeElement typeElement = (TypeElement) declaredType.asElement();
84d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        for (Element element : typeElement.getEnclosedElements()) {
85d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            if (element.getKind() == ElementKind.METHOD) {
86d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                ExecutableElement executableElement = (ExecutableElement) element;
87d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                if (executableElement.equals(mExecutableElement) ||
88d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                        elementUtils.overrides(mExecutableElement, executableElement, enclosing)) {
89d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                    return true;
90d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                }
91d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            }
92d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
93d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return false;
9479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
9579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
9679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    @Override
9779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public ModelClass[] getParameterTypes() {
98a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        List<? extends TypeMirror> parameters = mMethod.getParameterTypes();
9979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        ModelClass[] parameterTypes = new ModelClass[parameters.size()];
10079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        for (int i = 0; i < parameters.size(); i++) {
101a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount            parameterTypes[i] = new AnnotationClass(parameters.get(i));
10279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        }
10379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        return parameterTypes;
10479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
10579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
10679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    @Override
10779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public String getName() {
108a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        return mExecutableElement.getSimpleName().toString();
10979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
11079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
11179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    @Override
11279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public ModelClass getReturnType(List<ModelClass> args) {
113a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        TypeMirror returnType = mMethod.getReturnType();
11479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        // TODO: support argument-supplied types
11579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        // for example: public T[] toArray(T[] arr)
11679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        return new AnnotationClass(returnType);
11779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
11879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
11979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    @Override
120fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    public boolean isVoid() {
121fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mMethod.getReturnType().getKind() == TypeKind.VOID;
122fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
123fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
124fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    @Override
12579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public boolean isPublic() {
126a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        return mExecutableElement.getModifiers().contains(Modifier.PUBLIC);
12779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
12879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount
12979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    @Override
130bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount    public boolean isProtected() {
131bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount        return mExecutableElement.getModifiers().contains(Modifier.PROTECTED);
132bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount    }
133bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount
134bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount    @Override
13579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public boolean isStatic() {
136a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount        return mExecutableElement.getModifiers().contains(Modifier.STATIC);
13779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    }
13897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
13997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    @Override
140716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public boolean isAbstract() {
141716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return mExecutableElement.getModifiers().contains(Modifier.ABSTRACT);
142716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
143716ba89e7f459f49ea85070d4710c1d79d715298George Mount
144716ba89e7f459f49ea85070d4710c1d79d715298George Mount    @Override
145fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    public boolean isBindable() {
146fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mExecutableElement.getAnnotation(Bindable.class) != null;
147fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
148fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
149fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    @Override
15097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public int getMinApi() {
15197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if (mApiLevel == -1) {
15297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            mApiLevel = SdkUtil.getMinApi(this);
15397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        }
15497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        return mApiLevel;
15597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    }
15697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
15797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    @Override
15897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public String getJniDescription() {
15997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        return TypeUtil.getInstance().getDescription(this);
16097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    }
16197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
16297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    @Override
163fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    public boolean isVarArgs() {
164fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mExecutableElement.isVarArgs();
165fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
166fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
167d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    private static Types getTypeUtils() {
168d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return AnnotationAnalyzer.get().mProcessingEnv.getTypeUtils();
169d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
170d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
171d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    private static Elements getElementUtils() {
172d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return AnnotationAnalyzer.get().mProcessingEnv.getElementUtils();
173d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
174d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
175fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    @Override
17697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public String toString() {
17797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        return "AnnotationMethod{" +
17897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                "mMethod=" + mMethod +
17997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                ", mDeclaringType=" + mDeclaringType +
18097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                ", mExecutableElement=" + mExecutableElement +
18197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                ", mApiLevel=" + mApiLevel +
18297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                '}';
18397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    }
18479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount}
185