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