LayoutBinder.java revision fead9ca09b117136b35bc5bf137340a754f9eddd
1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/* 2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project 3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License. 6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at 7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and 14d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License. 15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 16d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool; 18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 19d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport com.google.common.base.Preconditions; 20d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Dependency; 22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr; 23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel; 24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.IdentifierExpr; 25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.store.ResourceBundle; 26fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.ParserHelper; 27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.LayoutBinderWriter; 28d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList; 305bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyarimport java.util.HashMap; 31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List; 325bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyarimport java.util.Map; 33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/** 35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Keeps all information about the bindings per layout file 36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class LayoutBinder { 383bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar 39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /* 40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * val pkg: String, val projectPackage: String, val baseClassName: String, 41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar val layoutName:String, val lb: LayoutExprBinding*/ 42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private final ExprModel mExprModel; 43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private final ExpressionParser mExpressionParser; 44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private final List<BindingTarget> mBindingTargets; 45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private String mPackage; 46a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private String mModulePackage; 47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private String mProjectPackage; 48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private String mBaseClassName; 49895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar private final HashMap<String, String> mUserDefinedVariables = new HashMap<String, String>(); 50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 5143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar private LayoutBinderWriter mWriter; 523bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar private ResourceBundle.LayoutFileBundle mBundle; 5343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar 543bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar public LayoutBinder(ResourceBundle resourceBundle, 553bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar ResourceBundle.LayoutFileBundle layoutBundle) { 56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = new ExprModel(); 57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExpressionParser = new ExpressionParser(mExprModel); 58895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar mBindingTargets = new ArrayList<BindingTarget>(); 593bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar mBundle = layoutBundle; 603bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar mProjectPackage = resourceBundle.getAppPackage(); 61a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mModulePackage = layoutBundle.getModulePackage(); 62a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mPackage = layoutBundle.getModulePackage() + ".generated"; 634c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount mBaseClassName = ParserHelper.INSTANCE$.toClassName(layoutBundle.getFileName()) + "Binding"; 643bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar // copy over data. 653bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar for (Map.Entry<String, String> variable : mBundle.getVariables().entrySet()) { 663bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar addVariable(variable.getKey(), variable.getValue()); 673bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar } 683bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar 693bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar for (Map.Entry<String, String> userImport : mBundle.getImports().entrySet()) { 70a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount mExprModel.addImport(userImport.getKey(), userImport.getValue()); 713bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar } 723bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar for (ResourceBundle.BindingTargetBundle targetBundle : mBundle.getBindingTargetBundles()) { 733bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar final BindingTarget bindingTarget = createBindingTarget(targetBundle); 743bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar for (ResourceBundle.BindingTargetBundle.BindingBundle bindingBundle : targetBundle 753bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar .getBindingBundleList()) { 763bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar bindingTarget.addBinding(bindingBundle.getName(), parse(bindingBundle.getExpr())); 773bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar } 783bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar } 79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 815bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar public void resolveWhichExpressionsAreUsed() { 82895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar List<Expr> used = new ArrayList<Expr>(); 835bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar for (BindingTarget target : mBindingTargets) { 845bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar for (Binding binding : target.getBindings()) { 855bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar binding.getExpr().setIsUsed(true); 865bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar used.add(binding.getExpr()); 875bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 885bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 895bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar while (!used.isEmpty()) { 905bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar Expr e = used.remove(used.size() - 1); 915bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar for (Dependency dep : e.getDependencies()) { 925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar if (!dep.getOther().isUsed()) { 935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar used.add(dep.getOther()); 945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar dep.getOther().setIsUsed(true); 955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public IdentifierExpr addVariable(String name, String type) { 1015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar Preconditions.checkState(!mUserDefinedVariables.containsKey(name), 1025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar "%s has already been defined as %s", name, type); 103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final IdentifierExpr id = mExprModel.identifier(name); 104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar id.setUserDefinedType(type); 105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar id.enableDirectInvalidation(); 1065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar mUserDefinedVariables.put(name, type); 107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return id; 108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar public HashMap<String, String> getUserDefinedVariables() { 1115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar return mUserDefinedVariables; 1125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 1135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 1143bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar public BindingTarget createBindingTarget(ResourceBundle.BindingTargetBundle targetBundle) { 1153bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar final BindingTarget target = new BindingTarget(targetBundle); 116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mBindingTargets.add(target); 117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar target.setModel(mExprModel); 118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return target; 119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public Expr parse(String input) { 122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final Expr parsed = mExpressionParser.parse(input); 123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar parsed.setBindingExpression(true); 124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return parsed; 125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<BindingTarget> getBindingTargets() { 128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mBindingTargets; 129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean isEmpty() { 132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprModel.size() == 0; 133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public ExprModel getModel() { 136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprModel; 137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 13943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar private void ensureWriter() { 14043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar if (mWriter == null) { 14143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar mWriter = new LayoutBinderWriter(this); 14243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar } 14343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar } 1443bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar 14543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar public String writeViewBinderInterface() { 14643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar ensureWriter(); 1474c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount return mWriter.writeBaseClass(); 14843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar } 14943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar 15043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar 15143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar public String writeViewBinder() { 152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.seal(); 15343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar ensureWriter(); 154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Preconditions.checkNotNull(mPackage, "package cannot be null"); 155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Preconditions.checkNotNull(mProjectPackage, "project package cannot be null"); 156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Preconditions.checkNotNull(mBaseClassName, "base class name cannot be null"); 15743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar return mWriter.write(); 158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getPackage() { 161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mPackage; 162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 164a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public String getModulePackage() { 165a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mModulePackage; 166a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 167a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setPackage(String aPackage) { 169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mPackage = aPackage; 170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getProjectPackage() { 173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mProjectPackage; 174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getLayoutname() { 1773bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar return mBundle.getFileName(); 178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getClassName() { 1815bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar final String suffix; 1825bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar if (hasVariations()) { 1833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar suffix = mBundle.getConfigName(); 1845bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } else { 1855bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar suffix = ""; 1865bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 1875bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar return mBaseClassName + suffix + "Impl"; 1885bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1903bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar 19143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar public String getInterfaceName() { 19243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar return mBaseClassName; 19343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar } 1945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 1955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar public int getId() { 1963bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar return mBundle.getLayoutId(); 1975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 1985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 1995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar public boolean hasVariations() { 2003bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar return mBundle.hasVariations(); 2015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 2025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar} 204