ResourceExpr.java revision 2611838bffef5a009ca71e3e9e59a93f29b098ed
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 */
16package android.databinding.tool.expr;
17
18import android.databinding.tool.reflection.ModelAnalyzer;
19import android.databinding.tool.reflection.ModelClass;
20import android.databinding.tool.writer.WriterPackage;
21
22import java.util.HashMap;
23import java.util.List;
24import java.util.Map;
25
26public class ResourceExpr extends Expr {
27
28    private final static Map<String, String> RESOURCE_TYPE_TO_R_OBJECT;
29    static {
30        RESOURCE_TYPE_TO_R_OBJECT = new HashMap<>();
31        RESOURCE_TYPE_TO_R_OBJECT.put("colorStateList", "color  ");
32        RESOURCE_TYPE_TO_R_OBJECT.put("dimenOffset", "dimen  ");
33        RESOURCE_TYPE_TO_R_OBJECT.put("dimenSize", "dimen  ");
34        RESOURCE_TYPE_TO_R_OBJECT.put("intArray", "array  ");
35        RESOURCE_TYPE_TO_R_OBJECT.put("stateListAnimator", "animator  ");
36        RESOURCE_TYPE_TO_R_OBJECT.put("stringArray", "array  ");
37        RESOURCE_TYPE_TO_R_OBJECT.put("typedArray", "array");
38    }
39    // lazily initialized
40    private Map<String, ModelClass> mResourceToTypeMapping;
41
42    protected final String mPackage;
43
44    protected final String mResourceType;
45
46    protected final String mResourceId;
47
48    public ResourceExpr(String packageName, String resourceType, String resourceName,
49            List<Expr> args) {
50        super(args);
51        if ("android".equals(packageName)) {
52            mPackage = "android.";
53        } else {
54            mPackage = "";
55        }
56        mResourceType = resourceType;
57        mResourceId = resourceName;
58    }
59
60    private Map<String, ModelClass> getResourceToTypeMapping(ModelAnalyzer modelAnalyzer) {
61        if (mResourceToTypeMapping == null) {
62            final Map<String, String> imports = getModel().getImports();
63            mResourceToTypeMapping = new HashMap<>();
64            mResourceToTypeMapping.put("anim", modelAnalyzer.findClass("android.view.animation.Animation",
65                            imports));
66            mResourceToTypeMapping.put("animator", modelAnalyzer.findClass("android.animation.Animator",
67                            imports));
68            mResourceToTypeMapping.put("colorStateList",
69                            modelAnalyzer.findClass("android.content.res.ColorStateList",
70                                    imports));
71            mResourceToTypeMapping.put("drawable", modelAnalyzer.findClass("android.graphics.drawable.Drawable",
72                            imports));
73            mResourceToTypeMapping.put("stateListAnimator",
74                            modelAnalyzer.findClass("android.animation.StateListAnimator",
75                                    imports));
76            mResourceToTypeMapping.put("transition", modelAnalyzer.findClass("android.transition.Transition",
77                            imports));
78            mResourceToTypeMapping.put("typedArray", modelAnalyzer.findClass("android.content.res.TypedArray",
79                            imports));
80            mResourceToTypeMapping.put("interpolator",
81                            modelAnalyzer.findClass("android.view.animation.Interpolator", imports));
82            mResourceToTypeMapping.put("bool", modelAnalyzer.findClass(boolean.class));
83            mResourceToTypeMapping.put("color", modelAnalyzer.findClass(int.class));
84            mResourceToTypeMapping.put("dimenOffset", modelAnalyzer.findClass(int.class));
85            mResourceToTypeMapping.put("dimenSize", modelAnalyzer.findClass(int.class));
86            mResourceToTypeMapping.put("id", modelAnalyzer.findClass(int.class));
87            mResourceToTypeMapping.put("integer", modelAnalyzer.findClass(int.class));
88            mResourceToTypeMapping.put("layout", modelAnalyzer.findClass(int.class));
89            mResourceToTypeMapping.put("dimen", modelAnalyzer.findClass(float.class));
90            mResourceToTypeMapping.put("fraction", modelAnalyzer.findClass(float.class));
91            mResourceToTypeMapping.put("intArray", modelAnalyzer.findClass(int[].class));
92            mResourceToTypeMapping.put("string", modelAnalyzer.findClass(String.class));
93            mResourceToTypeMapping.put("stringArray", modelAnalyzer.findClass(String[].class));
94        }
95        return mResourceToTypeMapping;
96    }
97
98    @Override
99    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
100        final Map<String, ModelClass> mapping = getResourceToTypeMapping(
101                modelAnalyzer);
102        final ModelClass modelClass = mapping.get(mResourceType);
103        if (modelClass != null) {
104            return modelClass;
105        }
106        if ("plurals".equals(mResourceType)) {
107            if (getChildren().isEmpty()) {
108                return modelAnalyzer.findClass(int.class);
109            } else {
110                return modelAnalyzer.findClass(String.class);
111            }
112        }
113        return modelAnalyzer.findClass(mResourceType, getModel().getImports());
114    }
115
116    @Override
117    protected List<Dependency> constructDependencies() {
118        return constructDynamicChildrenDependencies();
119    }
120
121    @Override
122    protected String computeUniqueKey() {
123        String base;
124        if (mPackage == null) {
125            base = "@" + mResourceType + "/" + mResourceId;
126        } else {
127            base = "@" + "android:" + mResourceType + "/" + mResourceId;
128        }
129        return join(base, computeChildrenKey());
130    }
131
132    public String getResourceId() {
133        return mPackage + "R." + getResourceObject() + "." + mResourceId;
134    }
135
136    public String toJava() {
137        final String context = "getRoot().getContext()";
138        final String resources = "getRoot().getResources()";
139        final String resourceName = mPackage + "R." + getResourceObject() + "." + mResourceId;
140        if ("anim".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadAnimation(" + context + ", " + resourceName + ")";
141        if ("animator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadAnimator(" + context + ", " + resourceName + ")";
142        if ("bool".equals(mResourceType)) return resources + ".getBoolean(" + resourceName + ")";
143        if ("color".equals(mResourceType)) return resources + ".getColor(" + resourceName + ")";
144        if ("colorStateList".equals(mResourceType)) return resources + ".getColorStateList(" + resourceName + ")";
145        if ("dimen".equals(mResourceType)) return resources + ".getDimension(" + resourceName + ")";
146        if ("dimenOffset".equals(mResourceType)) return resources + ".getDimensionPixelOffset(" + resourceName + ")";
147        if ("dimenSize".equals(mResourceType)) return resources + ".getDimensionPixelSize(" + resourceName + ")";
148        if ("drawable".equals(mResourceType)) return resources + ".getDrawable(" + resourceName + ")";
149        if ("fraction".equals(mResourceType)) {
150            String base = getChildCode(0, "1");
151            String pbase = getChildCode(1, "1");
152            return resources + ".getFraction(" + resourceName + ", " + base + ", " + pbase +
153                    ")";
154        }
155        if ("id".equals(mResourceType)) return resourceName;
156        if ("intArray".equals(mResourceType)) return resources + ".getIntArray(" + resourceName + ")";
157        if ("integer".equals(mResourceType)) return resources + ".getInteger(" + resourceName + ")";
158        if ("interpolator".equals(mResourceType))  return "android.view.animation.AnimationUtils.loadInterpolator(" + context + ", " + resourceName + ")";
159        if ("layout".equals(mResourceType)) return resourceName;
160        if ("plurals".equals(mResourceType)) {
161            if (getChildren().isEmpty()) {
162                return resourceName;
163            } else {
164                return makeParameterCall(resourceName, "getQuantityString");
165            }
166        }
167        if ("stateListAnimator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadStateListAnimator(" + context + ", " + resourceName + ")";
168        if ("string".equals(mResourceType)) return makeParameterCall(resourceName, "getString");
169        if ("stringArray".equals(mResourceType)) return resources + ".getStringArray(" + resourceName + ")";
170        if ("transition".equals(mResourceType)) return "android.transition.TransitionInflater.from(" + context + ").inflateTransition(" + resourceName + ")";
171        if ("typedArray".equals(mResourceType)) return resources + ".obtainTypedArray(" + resourceName + ")";
172        final String property = Character.toUpperCase(mResourceType.charAt(0)) +
173                mResourceType.substring(1);
174        return resources + ".get" + property + "(" + resourceName + ")";
175
176    }
177
178    private String getChildCode(int childIndex, String defaultValue) {
179        if (getChildren().size() <= childIndex) {
180            return defaultValue;
181        } else {
182            return WriterPackage.toCode(getChildren().get(childIndex), false).generate();
183        }
184    }
185
186    private String makeParameterCall(String resourceName, String methodCall) {
187        StringBuilder sb = new StringBuilder("getRoot().getResources().");
188        sb.append(methodCall).append("(").append(resourceName);
189        for (Expr expr : getChildren()) {
190            sb.append(", ").append(WriterPackage.toCode(expr, false).generate());
191        }
192        sb.append(")");
193        return sb.toString();
194    }
195
196    private String getResourceObject() {
197        String rFileObject = RESOURCE_TYPE_TO_R_OBJECT.get(mResourceType);
198        if (rFileObject == null) {
199            rFileObject = mResourceType;
200        }
201        return rFileObject;
202    }
203}
204