1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.databinding.tool.reflection.annotation;
18
19import android.databinding.tool.reflection.ModelClass;
20import android.databinding.tool.reflection.ModelMethod;
21import android.databinding.tool.reflection.TypeUtil;
22
23import java.util.List;
24
25import javax.lang.model.type.ArrayType;
26import javax.lang.model.type.ExecutableType;
27import javax.lang.model.type.TypeMirror;
28import javax.lang.model.type.TypeVariable;
29
30public class AnnotationTypeUtil extends TypeUtil {
31    javax.lang.model.util.Types mTypes;
32
33    public AnnotationTypeUtil(
34            AnnotationAnalyzer annotationAnalyzer) {
35        mTypes = annotationAnalyzer.getTypeUtils();
36    }
37
38    @Override
39    public String getDescription(ModelClass modelClass) {
40        // TODO use interface
41        return modelClass.getCanonicalName().replace('.', '/');
42    }
43
44    @Override
45    public String getDescription(ModelMethod modelMethod) {
46        // TODO use interface
47        return modelMethod.getName() + getDescription(
48                ((AnnotationMethod) modelMethod).mExecutableElement.asType());
49    }
50
51    private String getDescription(TypeMirror typeMirror) {
52        if (typeMirror == null) {
53            throw new UnsupportedOperationException();
54        }
55        switch (typeMirror.getKind()) {
56            case BOOLEAN:
57                return BOOLEAN;
58            case BYTE:
59                return BYTE;
60            case SHORT:
61                return SHORT;
62            case INT:
63                return INT;
64            case LONG:
65                return LONG;
66            case CHAR:
67                return CHAR;
68            case FLOAT:
69                return FLOAT;
70            case DOUBLE:
71                return DOUBLE;
72            case DECLARED:
73                return CLASS_PREFIX + mTypes.erasure(typeMirror).toString().replace('.', '/') + CLASS_SUFFIX;
74            case VOID:
75                return VOID;
76            case ARRAY:
77                final ArrayType arrayType = (ArrayType) typeMirror;
78                final String componentType = getDescription(arrayType.getComponentType());
79                return ARRAY + componentType;
80            case TYPEVAR:
81                final TypeVariable typeVariable = (TypeVariable) typeMirror;
82                final String name = typeVariable.toString();
83                return CLASS_PREFIX + name.replace('.', '/') + CLASS_SUFFIX;
84            case EXECUTABLE:
85                final ExecutableType executableType = (ExecutableType) typeMirror;
86                final int argStart = mTypes.erasure(executableType).toString().indexOf('(');
87                final String methodName = executableType.toString().substring(0, argStart);
88                final String args = joinArgs(executableType.getParameterTypes());
89                // TODO detect constructor?
90                return methodName + "(" + args + ")" + getDescription(
91                        executableType.getReturnType());
92            default:
93                throw new UnsupportedOperationException("cannot understand type "
94                        + typeMirror.toString() + ", kind:" + typeMirror.getKind().name());
95        }
96    }
97
98    private String joinArgs(List<? extends TypeMirror> mirrorList) {
99        StringBuilder result = new StringBuilder();
100        for (TypeMirror mirror : mirrorList) {
101            result.append(getDescription(mirror));
102        }
103        return result.toString();
104    }
105}
106