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
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr;
20731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.ErrorMessages;
21731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.Scope;
22731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.scopes.LocationScopeProvider;
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer;
24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass;
25731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.store.Location;
26fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.store.SetterStore;
27d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.store.SetterStore.BindingSetterCall;
28de38dd3ef0577d25b2d59863603abe5750d0c231George Mountimport android.databinding.tool.store.SetterStore.SetterCall;
29716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.util.L;
3059229481aec5a284d322a2ca80dff836485feb0cYigit Boyarimport android.databinding.tool.writer.LayoutBinderWriterKt;
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
32731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.util.List;
33731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
34731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarpublic class Binding implements LocationScopeProvider {
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final String mName;
37975c05c00dae9193a636c4775df81d8665fc6749George Mount    private Expr mExpr;
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final BindingTarget mTarget;
39d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    private BindingSetterCall mSetterCall;
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Binding(BindingTarget target, String name, Expr expr) {
42d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        this(target, name, expr, null);
43d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
44d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
45d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    public Binding(BindingTarget target, String name, Expr expr, BindingSetterCall setterCall) {
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mTarget = target;
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mName = name;
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mExpr = expr;
49d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        mSetterCall = setterCall;
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
52731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    @Override
53731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public List<Location> provideScopeLocation() {
54731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return mExpr.getLocations();
55731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
56731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
57975c05c00dae9193a636c4775df81d8665fc6749George Mount    public void resolveListeners() {
58975c05c00dae9193a636c4775df81d8665fc6749George Mount        final ModelClass listenerParameter = getListenerParameter(mTarget, mName, mExpr);
59975c05c00dae9193a636c4775df81d8665fc6749George Mount        Expr listenerExpr = mExpr.resolveListeners(listenerParameter, null);
60975c05c00dae9193a636c4775df81d8665fc6749George Mount        if (listenerExpr != mExpr) {
61975c05c00dae9193a636c4775df81d8665fc6749George Mount            listenerExpr.setBindingExpression(true);
62975c05c00dae9193a636c4775df81d8665fc6749George Mount            mExpr = listenerExpr;
63975c05c00dae9193a636c4775df81d8665fc6749George Mount        }
64975c05c00dae9193a636c4775df81d8665fc6749George Mount    }
65975c05c00dae9193a636c4775df81d8665fc6749George Mount
66d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    public void resolveTwoWayExpressions() {
67d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        Expr expr = mExpr.resolveTwoWayExpressions(null);
68d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        if (expr != mExpr) {
69d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            mExpr = expr;
70d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
71d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
72d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
73e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar    private SetterStore.BindingSetterCall getSetterCall() {
7497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if (mSetterCall == null) {
75731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            try {
76731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                Scope.enter(getTarget());
77731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                Scope.enter(this);
78731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                resolveSetterCall();
79731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                if (mSetterCall == null) {
80731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    L.e(ErrorMessages.CANNOT_FIND_SETTER_CALL, mName, mExpr.getResolvedType());
81de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
82731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            } finally {
83731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                Scope.exit();
84731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                Scope.exit();
85de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
8697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        }
8797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        return mSetterCall;
8897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    }
8997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
90731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    private void resolveSetterCall() {
91731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        ModelClass viewType = mTarget.getResolvedType();
92731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        if (viewType != null && viewType.extendsViewStub()) {
93793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            if (isListenerAttribute(mName)) {
94731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
95731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                ModelClass viewStubProxy = modelAnalyzer.
96731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                        findClass("android.databinding.ViewStubProxy", null);
97731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mSetterCall = SetterStore.get(modelAnalyzer).getSetterCall(mName,
98731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                        viewStubProxy, mExpr.getResolvedType(), mExpr.getModel().getImports());
99793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            } else if (isViewStubAttribute(mName)) {
100731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mSetterCall = new ViewStubDirectCall(mName, viewType, mExpr);
101731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            } else {
102731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mSetterCall = new ViewStubSetterCall(mName);
103731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
104731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        } else {
105793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance());
106793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            mSetterCall = setterStore.getSetterCall(mName,
107731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    viewType, mExpr.getResolvedType(), mExpr.getModel().getImports());
108731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
109731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
110731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
111716ba89e7f459f49ea85070d4710c1d79d715298George Mount    /**
112716ba89e7f459f49ea85070d4710c1d79d715298George Mount     * Similar to getSetterCall, but assumes an Object parameter to find the best matching listener.
113716ba89e7f459f49ea85070d4710c1d79d715298George Mount     */
114793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    private static ModelClass getListenerParameter(BindingTarget target, String name, Expr expr) {
115793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        ModelClass viewType = target.getResolvedType();
116716ba89e7f459f49ea85070d4710c1d79d715298George Mount        SetterCall setterCall;
117716ba89e7f459f49ea85070d4710c1d79d715298George Mount        ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
118716ba89e7f459f49ea85070d4710c1d79d715298George Mount        ModelClass objectParameter = modelAnalyzer.findClass(Object.class);
119793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        SetterStore setterStore = SetterStore.get(modelAnalyzer);
120716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (viewType != null && viewType.extendsViewStub()) {
121793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            if (isListenerAttribute(name)) {
122716ba89e7f459f49ea85070d4710c1d79d715298George Mount                ModelClass viewStubProxy = modelAnalyzer.
123716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        findClass("android.databinding.ViewStubProxy", null);
124793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                setterCall = SetterStore.get(modelAnalyzer).getSetterCall(name,
125793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        viewStubProxy, objectParameter, expr.getModel().getImports());
126793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            } else if (isViewStubAttribute(name)) {
127793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                setterCall = new ViewStubDirectCall(name, viewType, expr);
128716ba89e7f459f49ea85070d4710c1d79d715298George Mount            } else {
129793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                setterCall = new ViewStubSetterCall(name);
130716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
131716ba89e7f459f49ea85070d4710c1d79d715298George Mount        } else {
132793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            setterCall = setterStore.getSetterCall(name, viewType, objectParameter,
133793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    expr.getModel().getImports());
134793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        }
135793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        if (setterCall != null) {
136793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            return setterCall.getParameterTypes()[0];
137716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
138793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        List<SetterStore.MultiAttributeSetter> setters =
139793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                setterStore.getMultiAttributeSetterCalls(new String[]{name}, viewType,
140793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                new ModelClass[] {modelAnalyzer.findClass(Object.class)});
141793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        if (setters.isEmpty()) {
142716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return null;
143793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        } else {
144793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            return setters.get(0).getParameterTypes()[0];
145716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
146716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
147716ba89e7f459f49ea85070d4710c1d79d715298George Mount
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public BindingTarget getTarget() {
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mTarget;
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
152e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    public String toJavaCode(String targetViewName, String bindingComponent) {
15320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        final String currentValue = requiresOldValue()
15459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                ? "this." + LayoutBinderWriterKt.getOldValueName(mExpr) : null;
155e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount        final String argCode = getExpr().toCode().generate();
156e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        return getSetterCall().toJava(bindingComponent, targetViewName, currentValue, argCode);
157e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    }
158e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
159e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    public String getBindingAdapterInstanceClass() {
160e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        return getSetterCall().getBindingAdapterInstanceClass();
161e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    }
162e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
16320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    public Expr[] getComponentExpressions() {
16420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        return new Expr[] { mExpr };
16520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    }
16620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
16720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    public boolean requiresOldValue() {
16820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        return getSetterCall().requiresOldValue();
16997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    }
17097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
17197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    /**
17297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar     * The min api level in which this binding should be executed.
17397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar     * <p>
17497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar     * This should be the minimum value among the dependencies of this binding. For now, we only
17597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar     * check the setter.
17697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar     */
17797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public int getMinApi() {
17897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        return getSetterCall().getMinApi();
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public String getName() {
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mName;
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr getExpr() {
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mExpr;
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
188de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
189793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    private static boolean isViewStubAttribute(String name) {
190793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return ("android:inflatedId".equals(name) ||
191793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                "android:layout".equals(name) ||
192793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                "android:visibility".equals(name) ||
193793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                "android:layoutInflater".equals(name));
194716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
195716ba89e7f459f49ea85070d4710c1d79d715298George Mount
196793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    private static boolean isListenerAttribute(String name) {
197793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return ("android:onInflate".equals(name) ||
198793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                "android:onInflateListener".equals(name));
199de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
200de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
201de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    private static class ViewStubSetterCall extends SetterCall {
202de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        private final String mName;
203de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
204de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        public ViewStubSetterCall(String name) {
205de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            mName = name.substring(name.lastIndexOf(':') + 1);
206de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
207de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
208de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        @Override
209e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        protected String toJavaInternal(String componentExpression, String viewExpression,
210e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                String converted) {
211de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            return "if (" + viewExpression + ".isInflated()) " + viewExpression +
212de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    ".getBinding().setVariable(BR." + mName + ", " + converted + ")";
213de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
214de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
215de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        @Override
216e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        protected String toJavaInternal(String componentExpression, String viewExpression,
217e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                String oldValue, String converted) {
21820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            return null;
21920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        }
22020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
22120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        @Override
222de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        public int getMinApi() {
223de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            return 0;
224de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
22520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
22620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        @Override
22720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        public boolean requiresOldValue() {
22820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            return false;
22920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        }
230716ba89e7f459f49ea85070d4710c1d79d715298George Mount
231716ba89e7f459f49ea85070d4710c1d79d715298George Mount        @Override
232716ba89e7f459f49ea85070d4710c1d79d715298George Mount        public ModelClass[] getParameterTypes() {
233716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return new ModelClass[] {
234716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    ModelAnalyzer.getInstance().findClass(Object.class)
235716ba89e7f459f49ea85070d4710c1d79d715298George Mount            };
236716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
237e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
238e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        @Override
239e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        public String getBindingAdapterInstanceClass() {
240e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            return null;
241e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
242de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
243de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
244de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    private static class ViewStubDirectCall extends SetterCall {
245de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        private final SetterCall mWrappedCall;
246de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
247de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        public ViewStubDirectCall(String name, ModelClass viewType, Expr expr) {
248de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            mWrappedCall = SetterStore.get(ModelAnalyzer.getInstance()).getSetterCall(name,
249de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    viewType, expr.getResolvedType(), expr.getModel().getImports());
250716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (mWrappedCall == null) {
251716ba89e7f459f49ea85070d4710c1d79d715298George Mount                L.e("Cannot find the setter for attribute '%s' on %s with parameter type %s.",
252716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        name, viewType, expr.getResolvedType());
253716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
254de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
255de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
256de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        @Override
257e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        protected String toJavaInternal(String componentExpression, String viewExpression,
258e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                String converted) {
259de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            return "if (!" + viewExpression + ".isInflated()) " +
260e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    mWrappedCall.toJava(componentExpression, viewExpression + ".getViewStub()",
261e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                            null, converted);
26220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        }
26320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
26420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        @Override
265e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        protected String toJavaInternal(String componentExpression, String viewExpression,
266e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                String oldValue, String converted) {
26720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            return null;
268de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
269de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
270de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        @Override
271de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        public int getMinApi() {
272de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            return 0;
273de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
27420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
27520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        @Override
27620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        public boolean requiresOldValue() {
27720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            return false;
27820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        }
279716ba89e7f459f49ea85070d4710c1d79d715298George Mount
280716ba89e7f459f49ea85070d4710c1d79d715298George Mount        @Override
281716ba89e7f459f49ea85070d4710c1d79d715298George Mount        public ModelClass[] getParameterTypes() {
282716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return new ModelClass[] {
283716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    ModelAnalyzer.getInstance().findClass(Object.class)
284716ba89e7f459f49ea85070d4710c1d79d715298George Mount            };
285716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
286e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
287e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        @Override
288e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        public String getBindingAdapterInstanceClass() {
289e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            return mWrappedCall.getBindingAdapterInstanceClass();
290e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
291de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
293