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.LayoutBinderWriterKt; 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 @Override 45 public void resolveListeners() { 46 ModelClass[] parameters = mMultiAttributeSetter.getParameterTypes(); 47 List<Expr> children = getExpr().getChildren(); 48 final Expr expr = getExpr(); 49 for (int i = 0; i < children.size(); i++) { 50 final Expr child = children.get(i); 51 child.resolveListeners(parameters[i], expr); 52 } 53 } 54 55 private static Expr createArgListExpr(ExprModel model, final Iterable<Binding> bindings) { 56 List<Expr> args = new ArrayList<Expr>(); 57 for (Binding binding : bindings) { 58 args.add(binding.getExpr()); 59 } 60 Expr expr = model.argListExpr(args); 61 expr.setBindingExpression(true); 62 return expr; 63 } 64 65 private static String createMergedName(Iterable<Binding> bindings) { 66 StringBuilder sb = new StringBuilder(); 67 for (Binding binding : bindings) { 68 sb.append(binding.getName()); 69 } 70 return sb.toString(); 71 } 72 73 public Expr[] getComponentExpressions() { 74 ArgListExpr args = (ArgListExpr) getExpr(); 75 return args.getChildren().toArray(new Expr[args.getChildren().size()]); 76 } 77 78 public String[] getAttributes() { 79 return mMultiAttributeSetter.attributes; 80 } 81 82 @Override 83 public String getBindingAdapterInstanceClass() { 84 return mMultiAttributeSetter.getBindingAdapterInstanceClass(); 85 } 86 87 @Override 88 public boolean requiresOldValue() { 89 return mMultiAttributeSetter.requiresOldValue(); 90 } 91 92 @Override 93 public int getMinApi() { 94 return 1; 95 } 96 97 @Override 98 public String toJavaCode(String targetViewName, String bindingComponent) { 99 final ArgListExpr args = (ArgListExpr) getExpr(); 100 final List<String> newValues = new ArrayList<String>(); 101 for (Expr expr : args.getChildren()) { 102 newValues.add(expr.toCode().generate()); 103 } 104 final List<String> oldValues; 105 if (requiresOldValue()) { 106 oldValues = new ArrayList<String>(); 107 for (Expr expr : args.getChildren()) { 108 oldValues.add("this." + LayoutBinderWriterKt.getOldValueName(expr)); 109 } 110 } else { 111 oldValues = Arrays.asList(new String[args.getChildren().size()]); 112 } 113 final String[] expressions = concat(oldValues, newValues, String.class); 114 L.d("merged binding arg: %s", args.getUniqueKey()); 115 return mMultiAttributeSetter.toJava(bindingComponent, targetViewName, expressions); 116 } 117 118 private static <T> T[] concat(List<T> l1, List<T> l2, Class<T> klass) { 119 List<T> result = new ArrayList<T>(); 120 result.addAll(l1); 121 result.addAll(l2); 122 return result.toArray((T[]) Array.newInstance(klass, result.size())); 123 } 124} 125