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