• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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