MergedBinding.java revision e52882df6130221462bf07f5f2b52de5c4b0f8de
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; 18 19import android.databinding.tool.expr.ArgListExpr; 20import android.databinding.tool.expr.Expr; 21import android.databinding.tool.expr.ExprModel; 22import android.databinding.tool.reflection.ModelClass; 23import android.databinding.tool.store.SetterStore; 24import android.databinding.tool.util.L; 25import android.databinding.tool.writer.WriterPackage; 26 27import java.lang.reflect.Array; 28import java.util.ArrayList; 29import java.util.Arrays; 30import java.util.List; 31 32/** 33 * Multiple binding expressions can be evaluated using a single adapter. In those cases, 34 * we replace the Binding with a MergedBinding. 35 */ 36public class MergedBinding extends Binding { 37 private final SetterStore.MultiAttributeSetter mMultiAttributeSetter; 38 public MergedBinding(ExprModel model, SetterStore.MultiAttributeSetter multiAttributeSetter, 39 BindingTarget target, Iterable<Binding> bindings) { 40 super(target, createMergedName(bindings), createArgListExpr(model, bindings)); 41 mMultiAttributeSetter = multiAttributeSetter; 42 } 43 44 private static Expr createArgListExpr(ExprModel model, final Iterable<Binding> bindings) { 45 List<Expr> args = new ArrayList<>(); 46 for (Binding binding : bindings) { 47 args.add(binding.getExpr()); 48 } 49 Expr expr = model.argListExpr(args); 50 expr.setBindingExpression(true); 51 return expr; 52 } 53 54 private static String createMergedName(Iterable<Binding> bindings) { 55 StringBuilder sb = new StringBuilder(); 56 for (Binding binding : bindings) { 57 sb.append(binding.getName()); 58 } 59 return sb.toString(); 60 } 61 62 @Override 63 public void resolveListeners() { 64 ModelClass[] params = mMultiAttributeSetter.getParameterTypes(); 65 List<Expr> expressions = getExpr().getChildren(); 66 for (int i = 0; i < params.length; i++) { 67 expressions.get(i).resolveListeners(params[i]); 68 } 69 } 70 71 public Expr[] getComponentExpressions() { 72 ArgListExpr args = (ArgListExpr) getExpr(); 73 return args.getChildren().toArray(new Expr[args.getChildren().size()]); 74 } 75 76 @Override 77 public String getBindingAdapterInstanceClass() { 78 return mMultiAttributeSetter.getBindingAdapterInstanceClass(); 79 } 80 81 @Override 82 public void setBindingAdapterCall(String method) { 83 mMultiAttributeSetter.setBindingAdapterCall(method); 84 } 85 86 @Override 87 public boolean requiresOldValue() { 88 return mMultiAttributeSetter.requiresOldValue(); 89 } 90 91 @Override 92 public int getMinApi() { 93 return 1; 94 } 95 96 @Override 97 public String toJavaCode(String targetViewName, String bindingComponent) { 98 final ArgListExpr args = (ArgListExpr) getExpr(); 99 final List<String> newValues = new ArrayList<>(); 100 for (Expr expr : args.getChildren()) { 101 newValues.add(expr.toCode().generate()); 102 } 103 final List<String> oldValues; 104 if (requiresOldValue()) { 105 oldValues = new ArrayList<>(); 106 for (Expr expr : args.getChildren()) { 107 oldValues.add("this." + WriterPackage.getOldValueName(expr)); 108 } 109 } else { 110 oldValues = Arrays.asList(new String[args.getChildren().size()]); 111 } 112 final String[] expressions = concat(oldValues, newValues, String.class); 113 L.d("merged binding arg: %s", args.getUniqueKey()); 114 return mMultiAttributeSetter.toJava(bindingComponent, targetViewName, expressions); 115 } 116 117 private static <T> T[] concat(List<T> l1, List<T> l2, Class<T> klass) { 118 List<T> result = new ArrayList<>(); 119 result.addAll(l1); 120 result.addAll(l2); 121 return result.toArray((T[]) Array.newInstance(klass, result.size())); 122 } 123} 124