/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.databinding.tool; import android.databinding.tool.expr.CallbackArgExpr; import android.databinding.tool.expr.CallbackExprModel; import android.databinding.tool.expr.Expr; import android.databinding.tool.expr.ExprModel; import android.databinding.tool.expr.FieldAccessExpr; import android.databinding.tool.expr.IdentifierExpr; import android.databinding.tool.processing.ErrorMessages; import android.databinding.tool.processing.Scope; import android.databinding.tool.processing.scopes.LocationScopeProvider; import android.databinding.tool.reflection.ModelAnalyzer; import android.databinding.tool.reflection.ModelClass; import android.databinding.tool.solver.ExecutionPath; import android.databinding.tool.store.Location; import android.databinding.tool.store.SetterStore; import android.databinding.tool.store.SetterStore.BindingGetterCall; import android.databinding.tool.store.SetterStore.BindingSetterCall; import android.databinding.tool.util.L; import java.util.ArrayList; import java.util.List; public class InverseBinding implements LocationScopeProvider { private final String mName; private final Expr mExpr; private final BindingTarget mTarget; private BindingGetterCall mGetterCall; private final ArrayList mChainedExpressions = new ArrayList(); private final CallbackExprModel mCallbackExprModel; private final Expr mInverseExpr; private final CallbackArgExpr mVariableExpr; private final ExecutionPath mExecutionPath; public InverseBinding(BindingTarget target, String name, Expr expr, String bindingClassName) { mTarget = target; mName = name; mCallbackExprModel = new CallbackExprModel(expr.getModel()); mExpr = expr.cloneToModel(mCallbackExprModel); setGetterCall(mExpr); mVariableExpr = mCallbackExprModel.callbackArg("callbackArg_0"); ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); ModelClass type = modelAnalyzer.findClass(getGetterCall().getGetterType(), null); mVariableExpr.setClassFromCallback(type); mVariableExpr.setUserDefinedType(getGetterCall().getGetterType()); mInverseExpr = mExpr.generateInverse(mCallbackExprModel, mVariableExpr, bindingClassName); mExecutionPath = ExecutionPath.createRoot(); mInverseExpr.toExecutionPath(mExecutionPath); mCallbackExprModel.seal(); } public InverseBinding(BindingTarget target, String name, BindingGetterCall getterCall) { mTarget = target; mName = name; mExpr = null; mCallbackExprModel = null; mInverseExpr = null; mVariableExpr = null; mExecutionPath = null; setGetterCall(getterCall); } @Override public List provideScopeLocation() { if (mExpr != null) { return mExpr.getLocations(); } else { return mChainedExpressions.get(0).getLocations(); } } private void setGetterCall(BindingGetterCall getterCall) { mGetterCall = getterCall; } public void addChainedExpression(FieldAccessExpr expr) { mChainedExpressions.add(expr); } public boolean isOnBinder() { return mTarget.getResolvedType().isViewDataBinding(); } private void setGetterCall(Expr expr) { try { Scope.enter(mTarget); Scope.enter(this); ModelClass viewType = mTarget.getResolvedType(); final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); final ModelClass resolvedType = expr == null ? null : expr.getResolvedType(); mGetterCall = setterStore.getGetterCall(mName, viewType, resolvedType, expr.getModel().getImports()); if (mGetterCall == null) { L.e(ErrorMessages.CANNOT_FIND_GETTER_CALL, mName, expr == null ? "Unknown" : mExpr.getResolvedType(), mTarget.getResolvedType()); } } finally { Scope.exit(); Scope.exit(); } } public SetterStore.BindingGetterCall getGetterCall() { return mGetterCall; } public BindingTarget getTarget() { return mTarget; } public Expr getExpr() { return mExpr; } public Expr getInverseExpr() { return mInverseExpr; } public IdentifierExpr getVariableExpr() { return mVariableExpr; } public ExecutionPath getExecutionPath() { return mExecutionPath; } public CallbackExprModel getCallbackExprModel() { return mCallbackExprModel; } public List getChainedExpressions() { return mChainedExpressions; } public String getBindingAdapterInstanceClass() { return getGetterCall().getBindingAdapterInstanceClass(); } /** * The min api level in which this binding should be executed. *

* This should be the minimum value among the dependencies of this binding. */ public int getMinApi() { final BindingGetterCall getterCall = getGetterCall(); return Math.max(getterCall.getMinApi(), getterCall.getEvent().getMinApi()); } public BindingSetterCall getEventSetter() { final BindingGetterCall getterCall = getGetterCall(); return getterCall.getEvent(); } public String getName() { return mName; } public String getEventAttribute() { return getGetterCall().getEventAttribute(); } public ExprModel getModel() { if (mExpr != null) { return mExpr.getModel(); } return mChainedExpressions.get(0).getModel(); } }