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