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 17 package android.databinding.tool; 18 19 import android.databinding.tool.expr.CallbackArgExpr; 20 import android.databinding.tool.expr.CallbackExprModel; 21 import android.databinding.tool.expr.Expr; 22 import android.databinding.tool.expr.ExprModel; 23 import android.databinding.tool.expr.FieldAccessExpr; 24 import android.databinding.tool.expr.IdentifierExpr; 25 import android.databinding.tool.processing.ErrorMessages; 26 import android.databinding.tool.processing.Scope; 27 import android.databinding.tool.processing.scopes.LocationScopeProvider; 28 import android.databinding.tool.reflection.ModelAnalyzer; 29 import android.databinding.tool.reflection.ModelClass; 30 import android.databinding.tool.solver.ExecutionPath; 31 import android.databinding.tool.store.Location; 32 import android.databinding.tool.store.SetterStore; 33 import android.databinding.tool.store.SetterStore.BindingGetterCall; 34 import android.databinding.tool.store.SetterStore.BindingSetterCall; 35 import android.databinding.tool.util.L; 36 37 import java.util.ArrayList; 38 import java.util.List; 39 40 public class InverseBinding implements LocationScopeProvider { 41 42 private final String mName; 43 private final Expr mExpr; 44 private final BindingTarget mTarget; 45 private BindingGetterCall mGetterCall; 46 private final ArrayList<FieldAccessExpr> mChainedExpressions = new ArrayList<FieldAccessExpr>(); 47 private final CallbackExprModel mCallbackExprModel; 48 private final Expr mInverseExpr; 49 private final CallbackArgExpr mVariableExpr; 50 private final ExecutionPath mExecutionPath; 51 InverseBinding(BindingTarget target, String name, Expr expr, String bindingClassName)52 public InverseBinding(BindingTarget target, String name, Expr expr, String bindingClassName) { 53 mTarget = target; 54 mName = name; 55 mCallbackExprModel = new CallbackExprModel(expr.getModel()); 56 mExpr = expr.cloneToModel(mCallbackExprModel); 57 setGetterCall(mExpr); 58 mVariableExpr = mCallbackExprModel.callbackArg("callbackArg_0"); 59 ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); 60 ModelClass type = modelAnalyzer.findClass(getGetterCall().getGetterType(), null); 61 mVariableExpr.setClassFromCallback(type); 62 mVariableExpr.setUserDefinedType(getGetterCall().getGetterType()); 63 mInverseExpr = 64 mExpr.generateInverse(mCallbackExprModel, mVariableExpr, bindingClassName); 65 mExecutionPath = ExecutionPath.createRoot(); 66 mInverseExpr.toExecutionPath(mExecutionPath); 67 mCallbackExprModel.seal(); 68 } 69 InverseBinding(BindingTarget target, String name, BindingGetterCall getterCall)70 public InverseBinding(BindingTarget target, String name, BindingGetterCall getterCall) { 71 mTarget = target; 72 mName = name; 73 mExpr = null; 74 mCallbackExprModel = null; 75 mInverseExpr = null; 76 mVariableExpr = null; 77 mExecutionPath = null; 78 setGetterCall(getterCall); 79 } 80 81 @Override provideScopeLocation()82 public List<Location> provideScopeLocation() { 83 if (mExpr != null) { 84 return mExpr.getLocations(); 85 } else { 86 return mChainedExpressions.get(0).getLocations(); 87 } 88 } 89 setGetterCall(BindingGetterCall getterCall)90 private void setGetterCall(BindingGetterCall getterCall) { 91 mGetterCall = getterCall; 92 } 93 addChainedExpression(FieldAccessExpr expr)94 public void addChainedExpression(FieldAccessExpr expr) { 95 mChainedExpressions.add(expr); 96 } 97 isOnBinder()98 public boolean isOnBinder() { 99 return mTarget.getResolvedType().isViewDataBinding(); 100 } 101 setGetterCall(Expr expr)102 private void setGetterCall(Expr expr) { 103 try { 104 Scope.enter(mTarget); 105 Scope.enter(this); 106 ModelClass viewType = mTarget.getResolvedType(); 107 final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); 108 final ModelClass resolvedType = expr == null ? null : expr.getResolvedType(); 109 mGetterCall = setterStore.getGetterCall(mName, viewType, resolvedType, 110 expr.getModel().getImports()); 111 if (mGetterCall == null) { 112 L.e(ErrorMessages.CANNOT_FIND_GETTER_CALL, mName, 113 expr == null ? "Unknown" : mExpr.getResolvedType(), 114 mTarget.getResolvedType()); 115 } 116 } finally { 117 Scope.exit(); 118 Scope.exit(); 119 } 120 } 121 getGetterCall()122 public SetterStore.BindingGetterCall getGetterCall() { 123 return mGetterCall; 124 } 125 getTarget()126 public BindingTarget getTarget() { 127 return mTarget; 128 } 129 getExpr()130 public Expr getExpr() { 131 return mExpr; 132 } 133 getInverseExpr()134 public Expr getInverseExpr() { 135 return mInverseExpr; 136 } 137 getVariableExpr()138 public IdentifierExpr getVariableExpr() { 139 return mVariableExpr; 140 } 141 getExecutionPath()142 public ExecutionPath getExecutionPath() { 143 return mExecutionPath; 144 } 145 getCallbackExprModel()146 public CallbackExprModel getCallbackExprModel() { 147 return mCallbackExprModel; 148 } 149 getChainedExpressions()150 public List<FieldAccessExpr> getChainedExpressions() { 151 return mChainedExpressions; 152 } 153 getBindingAdapterInstanceClass()154 public String getBindingAdapterInstanceClass() { 155 return getGetterCall().getBindingAdapterInstanceClass(); 156 } 157 158 /** 159 * The min api level in which this binding should be executed. 160 * <p> 161 * This should be the minimum value among the dependencies of this binding. 162 */ getMinApi()163 public int getMinApi() { 164 final BindingGetterCall getterCall = getGetterCall(); 165 return Math.max(getterCall.getMinApi(), getterCall.getEvent().getMinApi()); 166 } 167 getEventSetter()168 public BindingSetterCall getEventSetter() { 169 final BindingGetterCall getterCall = getGetterCall(); 170 return getterCall.getEvent(); 171 } 172 getName()173 public String getName() { 174 return mName; 175 } 176 getEventAttribute()177 public String getEventAttribute() { 178 return getGetterCall().getEventAttribute(); 179 } 180 getModel()181 public ExprModel getModel() { 182 if (mExpr != null) { 183 return mExpr.getModel(); 184 } 185 return mChainedExpressions.get(0).getModel(); 186 } 187 } 188