1d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount/* 2d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * Copyright (C) 2015 The Android Open Source Project 3d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * 4d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 5d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * you may not use this file except in compliance with the License. 6d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * You may obtain a copy of the License at 7d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * 8d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * http://www.apache.org/licenses/LICENSE-2.0 9d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * 10d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * Unless required by applicable law or agreed to in writing, software 11d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * distributed under the License is distributed on an "AS IS" BASIS, 12d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * See the License for the specific language governing permissions and 14d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * limitations under the License. 15d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount */ 16d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 17d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountpackage android.databinding.tool; 18d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 19bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mountimport android.databinding.tool.expr.CallbackArgExpr; 20bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mountimport android.databinding.tool.expr.CallbackExprModel; 21d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.expr.Expr; 22d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.expr.ExprModel; 23d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.expr.FieldAccessExpr; 24bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mountimport android.databinding.tool.expr.IdentifierExpr; 25d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.processing.ErrorMessages; 26d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.processing.Scope; 27d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.processing.scopes.LocationScopeProvider; 28d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.reflection.ModelAnalyzer; 29d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.reflection.ModelClass; 30bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mountimport android.databinding.tool.solver.ExecutionPath; 31d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.store.Location; 32d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.store.SetterStore; 33d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.store.SetterStore.BindingGetterCall; 34d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.store.SetterStore.BindingSetterCall; 35d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.util.L; 36d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 37d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport java.util.ArrayList; 38d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport java.util.List; 39d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 40d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountpublic class InverseBinding implements LocationScopeProvider { 41d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 42d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount private final String mName; 43d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount private final Expr mExpr; 44d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount private final BindingTarget mTarget; 45d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount private BindingGetterCall mGetterCall; 46d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount private final ArrayList<FieldAccessExpr> mChainedExpressions = new ArrayList<FieldAccessExpr>(); 47bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount private final CallbackExprModel mCallbackExprModel; 48bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount private final Expr mInverseExpr; 49bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount private final CallbackArgExpr mVariableExpr; 50bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount private final ExecutionPath mExecutionPath; 51bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 52bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public InverseBinding(BindingTarget target, String name, Expr expr, String bindingClassName) { 53bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mTarget = target; 54bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mName = name; 55bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mCallbackExprModel = new CallbackExprModel(expr.getModel()); 56bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mExpr = expr.cloneToModel(mCallbackExprModel); 57bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount setGetterCall(mExpr); 58bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mVariableExpr = mCallbackExprModel.callbackArg("callbackArg_0"); 59bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); 60bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount ModelClass type = modelAnalyzer.findClass(getGetterCall().getGetterType(), null); 61bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mVariableExpr.setClassFromCallback(type); 62bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mVariableExpr.setUserDefinedType(getGetterCall().getGetterType()); 63bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mInverseExpr = 64bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mExpr.generateInverse(mCallbackExprModel, mVariableExpr, bindingClassName); 65bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mExecutionPath = ExecutionPath.createRoot(); 66bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mInverseExpr.toExecutionPath(mExecutionPath); 67bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mCallbackExprModel.seal(); 68bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 69d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 70bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public InverseBinding(BindingTarget target, String name, BindingGetterCall getterCall) { 71d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount mTarget = target; 72d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount mName = name; 73bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mExpr = null; 74bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mCallbackExprModel = null; 75bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mInverseExpr = null; 76bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mVariableExpr = null; 77bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mExecutionPath = null; 78bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount setGetterCall(getterCall); 79d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 80d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 81d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount @Override 82d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public List<Location> provideScopeLocation() { 83d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount if (mExpr != null) { 84d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mExpr.getLocations(); 85d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } else { 86d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mChainedExpressions.get(0).getLocations(); 87d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 88d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 89d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 90bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount private void setGetterCall(BindingGetterCall getterCall) { 91d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount mGetterCall = getterCall; 92d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 93d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 94d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public void addChainedExpression(FieldAccessExpr expr) { 95d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount mChainedExpressions.add(expr); 96d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 97d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 98d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public boolean isOnBinder() { 99d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mTarget.getResolvedType().isViewDataBinding(); 100d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 101d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 102bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount private void setGetterCall(Expr expr) { 103bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount try { 104bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount Scope.enter(mTarget); 105bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount Scope.enter(this); 106bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount ModelClass viewType = mTarget.getResolvedType(); 107bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); 108bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount final ModelClass resolvedType = expr == null ? null : expr.getResolvedType(); 109bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mGetterCall = setterStore.getGetterCall(mName, viewType, resolvedType, 110bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount expr.getModel().getImports()); 111bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount if (mGetterCall == null) { 112bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount L.e(ErrorMessages.CANNOT_FIND_GETTER_CALL, mName, 113bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount expr == null ? "Unknown" : mExpr.getResolvedType(), 114bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount mTarget.getResolvedType()); 115d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 116bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } finally { 117bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount Scope.exit(); 118bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount Scope.exit(); 119d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 120d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 121d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 122bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public SetterStore.BindingGetterCall getGetterCall() { 123bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mGetterCall; 124d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 125d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 126d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public BindingTarget getTarget() { 127d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mTarget; 128d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 129d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 130bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public Expr getExpr() { 131bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mExpr; 132bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 133bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 134bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public Expr getInverseExpr() { 135bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mInverseExpr; 136bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 137bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 138bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public IdentifierExpr getVariableExpr() { 139bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mVariableExpr; 140bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 141bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 142bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public ExecutionPath getExecutionPath() { 143bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mExecutionPath; 144bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 145bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 146bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public CallbackExprModel getCallbackExprModel() { 147bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mCallbackExprModel; 148bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 149bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 150bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public List<FieldAccessExpr> getChainedExpressions() { 151bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return mChainedExpressions; 152d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 153d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 154d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public String getBindingAdapterInstanceClass() { 155d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return getGetterCall().getBindingAdapterInstanceClass(); 156d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 157d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 158d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount /** 159d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * The min api level in which this binding should be executed. 160d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * <p> 161d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * This should be the minimum value among the dependencies of this binding. 162d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount */ 163d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public int getMinApi() { 164d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final BindingGetterCall getterCall = getGetterCall(); 165d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return Math.max(getterCall.getMinApi(), getterCall.getEvent().getMinApi()); 166d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 167d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 168d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public BindingSetterCall getEventSetter() { 169d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final BindingGetterCall getterCall = getGetterCall(); 170d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return getterCall.getEvent(); 171d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 172d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 173d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public String getName() { 174d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mName; 175d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 176d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 177d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public String getEventAttribute() { 178d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return getGetterCall().getEventAttribute(); 179d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 180d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 181d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public ExprModel getModel() { 182d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount if (mExpr != null) { 183d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mExpr.getModel(); 184d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 185d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mChainedExpressions.get(0).getModel(); 186d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 187d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount} 188