1793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount/*
2793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * Copyright (C) 2015 The Android Open Source Project
3793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount *
4793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * Licensed under the Apache License, Version 2.0 (the "License");
5793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * you may not use this file except in compliance with the License.
6793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * You may obtain a copy of the License at
7793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount *
8793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount *      http://www.apache.org/licenses/LICENSE-2.0
9793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount *
10793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * Unless required by applicable law or agreed to in writing, software
11793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * distributed under the License is distributed on an "AS IS" BASIS,
12793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * See the License for the specific language governing permissions and
14793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * limitations under the License.
15793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount */
16793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
17793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountpackage android.databinding.tool.expr;
18793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
19793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.reflection.ModelAnalyzer;
20793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.reflection.ModelClass;
21793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.reflection.ModelMethod;
22793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.writer.KCode;
2359229481aec5a284d322a2ca80dff836485feb0cYigit Boyarimport android.databinding.tool.writer.LayoutBinderWriterKt;
24793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
25793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport java.util.ArrayList;
26793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport java.util.List;
27793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
28793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount/**
29793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * This wraps an expression, but makes it unique for a particular event listener type.
30793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * This is used to differentiate listener methods. For example:
31793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * <pre>
32793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount *     public void onFoo(String str) {...}
33793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount *     public void onFoo(int i) {...}
34793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount * </pre>
35793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount */
36793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountpublic class ListenerExpr extends Expr {
37793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    private final String mName;
38793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    private final ModelClass mListenerType;
39793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    private final ModelMethod mMethod;
40793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
41793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    ListenerExpr(Expr expr, String name, ModelClass listenerType, ModelMethod method) {
42793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        super(expr);
43793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        mName = name;
44793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        mListenerType = listenerType;
45793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        mMethod = method;
46793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
47793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
48793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    @Override
49793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
50793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return mListenerType;
51793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
52793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
53793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    public ModelMethod getMethod() {
54793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return mMethod;
55793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
56793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
57793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    public Expr getChild() {
58793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return getChildren().get(0);
59793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
60793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
61793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    public String getName() {
62793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return mName;
63793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
64793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
65793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    @Override
66793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    public boolean isDynamic() {
67793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return getChild().isDynamic();
68793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
69793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
70793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    @Override
71793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    protected List<Dependency> constructDependencies() {
729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        final List<Dependency> dependencies = new ArrayList<Dependency>();
73793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        Dependency dependency = new Dependency(this, getChild());
74793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        dependency.setMandatory(true);
75793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        dependencies.add(dependency);
76793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return dependencies;
77793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
78793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
79793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    protected String computeUniqueKey() {
80793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return join(getResolvedType().getCanonicalName(), getChild().computeUniqueKey(), mName);
81793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
82793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount
83793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    @Override
84d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    public KCode generateCode(boolean expand) {
85793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        KCode code = new KCode("(");
86793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        final int minApi = Math.max(mListenerType.getMinApi(), mMethod.getMinApi());
87793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        if (minApi > 1) {
88793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            code.app("(getBuildSdkInt() < " + minApi + ") ? null : ");
89793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        }
9059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        final String fieldName = LayoutBinderWriterKt.getFieldName(this);
9159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        final String listenerClassName = LayoutBinderWriterKt.getListenerClassName(this);
92793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        final KCode value = getChild().toCode();
93793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            code.app("((")
94793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(fieldName)
95793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(" == null) ? (")
96793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(fieldName)
97793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(" = new ")
98793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(listenerClassName)
99793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app("()) : ")
100793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(fieldName)
101793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(")");
102793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        if (getChild().isDynamic()) {
103793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            code.app(".setValue(", value)
104793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    .app(")");
105793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        }
106793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        code.app(")");
107793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        return code;
108793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    }
109d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
110d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    @Override
111d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    public String getInvertibleError() {
112d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return "Listeners cannot be the target of a two-way binding";
113d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
114793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount}
115