1e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar/* 2e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * Copyright (C) 2015 The Android Open Source Project 3e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * 4e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * you may not use this file except in compliance with the License. 6e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * You may obtain a copy of the License at 7e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * 8e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * 10e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * Unless required by applicable law or agreed to in writing, software 11e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * See the License for the specific language governing permissions and 14e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * limitations under the License. 15e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar */ 16e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 17e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarpackage android.databinding.tool; 18e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 19e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.expr.ArgListExpr; 20e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.expr.Expr; 21e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.expr.ExprModel; 22975c05c00dae9193a636c4775df81d8665fc6749George Mountimport android.databinding.tool.reflection.ModelClass; 23e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.store.SetterStore; 24e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.util.L; 2559229481aec5a284d322a2ca80dff836485feb0cYigit Boyarimport android.databinding.tool.writer.LayoutBinderWriterKt; 26e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 272611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport java.lang.reflect.Array; 282611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport java.util.ArrayList; 2920c7182163d99575d382e065f5a5fe45ed6b87e2George Mountimport java.util.Arrays; 30e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport java.util.List; 31e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 32e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar/** 33e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * Multiple binding expressions can be evaluated using a single adapter. In those cases, 34e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar * we replace the Binding with a MergedBinding. 35e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar */ 36e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarpublic class MergedBinding extends Binding { 37e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar private final SetterStore.MultiAttributeSetter mMultiAttributeSetter; 38e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar public MergedBinding(ExprModel model, SetterStore.MultiAttributeSetter multiAttributeSetter, 39e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar BindingTarget target, Iterable<Binding> bindings) { 40e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar super(target, createMergedName(bindings), createArgListExpr(model, bindings)); 41e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar mMultiAttributeSetter = multiAttributeSetter; 42e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 43e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 44975c05c00dae9193a636c4775df81d8665fc6749George Mount @Override 45975c05c00dae9193a636c4775df81d8665fc6749George Mount public void resolveListeners() { 46975c05c00dae9193a636c4775df81d8665fc6749George Mount ModelClass[] parameters = mMultiAttributeSetter.getParameterTypes(); 47975c05c00dae9193a636c4775df81d8665fc6749George Mount List<Expr> children = getExpr().getChildren(); 48975c05c00dae9193a636c4775df81d8665fc6749George Mount final Expr expr = getExpr(); 49975c05c00dae9193a636c4775df81d8665fc6749George Mount for (int i = 0; i < children.size(); i++) { 50975c05c00dae9193a636c4775df81d8665fc6749George Mount final Expr child = children.get(i); 51975c05c00dae9193a636c4775df81d8665fc6749George Mount child.resolveListeners(parameters[i], expr); 52975c05c00dae9193a636c4775df81d8665fc6749George Mount } 53975c05c00dae9193a636c4775df81d8665fc6749George Mount } 54975c05c00dae9193a636c4775df81d8665fc6749George Mount 55e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar private static Expr createArgListExpr(ExprModel model, final Iterable<Binding> bindings) { 569784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Expr> args = new ArrayList<Expr>(); 572611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Binding binding : bindings) { 582611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar args.add(binding.getExpr()); 592611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 602611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Expr expr = model.argListExpr(args); 61e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar expr.setBindingExpression(true); 62e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar return expr; 63e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 64e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 65e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar private static String createMergedName(Iterable<Binding> bindings) { 662611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar StringBuilder sb = new StringBuilder(); 672611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Binding binding : bindings) { 682611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar sb.append(binding.getName()); 692611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 702611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return sb.toString(); 71e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 72e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 7320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount public Expr[] getComponentExpressions() { 7420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount ArgListExpr args = (ArgListExpr) getExpr(); 7520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount return args.getChildren().toArray(new Expr[args.getChildren().size()]); 7620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount } 7720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount 78d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public String[] getAttributes() { 79d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mMultiAttributeSetter.attributes; 80d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 81d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 8220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount @Override 83e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public String getBindingAdapterInstanceClass() { 84e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return mMultiAttributeSetter.getBindingAdapterInstanceClass(); 85e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount } 86e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount 87e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount @Override 8820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount public boolean requiresOldValue() { 8920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount return mMultiAttributeSetter.requiresOldValue(); 9020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount } 9120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount 92e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar @Override 93e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar public int getMinApi() { 94e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar return 1; 95e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 96e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 97e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar @Override 98e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public String toJavaCode(String targetViewName, String bindingComponent) { 9920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount final ArgListExpr args = (ArgListExpr) getExpr(); 1009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final List<String> newValues = new ArrayList<String>(); 1012611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr expr : args.getChildren()) { 102e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount newValues.add(expr.toCode().generate()); 1032611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 1042611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar final List<String> oldValues; 10520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount if (requiresOldValue()) { 1069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar oldValues = new ArrayList<String>(); 1072611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr expr : args.getChildren()) { 10859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar oldValues.add("this." + LayoutBinderWriterKt.getOldValueName(expr)); 1092611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 11020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount } else { 11120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount oldValues = Arrays.asList(new String[args.getChildren().size()]); 11220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount } 1132611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar final String[] expressions = concat(oldValues, newValues, String.class); 114e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar L.d("merged binding arg: %s", args.getUniqueKey()); 115e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return mMultiAttributeSetter.toJava(bindingComponent, targetViewName, expressions); 116e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 1172611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar 1182611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private static <T> T[] concat(List<T> l1, List<T> l2, Class<T> klass) { 1199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<T> result = new ArrayList<T>(); 1202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.addAll(l1); 1212611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.addAll(l2); 1222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result.toArray((T[]) Array.newInstance(klass, result.size())); 1232611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 124e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar} 125