FieldAccessExpr.java revision c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dc
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
17package android.databinding.tool.expr;
18
19import android.databinding.tool.reflection.Callable;
20import android.databinding.tool.reflection.ModelAnalyzer;
21import android.databinding.tool.reflection.ModelClass;
22import android.databinding.tool.util.L;
23
24import java.util.List;
25
26public class FieldAccessExpr extends Expr {
27    String mName;
28    Callable mGetter;
29    final boolean mIsObservableField;
30
31    FieldAccessExpr(Expr parent, String name) {
32        super(parent);
33        mName = name;
34        mIsObservableField = false;
35    }
36
37    FieldAccessExpr(Expr parent, String name, boolean isObservableField) {
38        super(parent);
39        mName = name;
40        mIsObservableField = isObservableField;
41    }
42
43    public Expr getChild() {
44        return getChildren().get(0);
45    }
46
47    public Callable getGetter() {
48        if (mGetter == null) {
49            getResolvedType();
50        }
51        return mGetter;
52    }
53
54    @Override
55    public boolean isDynamic() {
56        if (mGetter == null) {
57            getResolvedType();
58        }
59        if (mGetter.type != Callable.Type.FIELD) {
60            return true;
61        }
62        // if it is static final, gone
63        if (getChild().isDynamic()) {
64            // if owner is dynamic, then we can be dynamic unless we are static final
65            return !mGetter.isStatic() || mGetter.isDynamic();
66        }
67
68        // if owner is NOT dynamic, we can be dynamic if an only if getter is dynamic
69        return mGetter.isDynamic();
70    }
71
72    public boolean hasBindableAnnotations() {
73        return mGetter.canBeInvalidated();
74    }
75
76    @Override
77    protected List<Dependency> constructDependencies() {
78        final List<Dependency> dependencies = constructDynamicChildrenDependencies();
79        for (Dependency dependency : dependencies) {
80            if (dependency.getOther() == getChild()) {
81                dependency.setMandatory(true);
82            }
83        }
84        return dependencies;
85    }
86
87    @Override
88    protected String computeUniqueKey() {
89        if (mIsObservableField) {
90            return sUniqueKeyJoiner.join(mName, "..", super.computeUniqueKey());
91        }
92        return sUniqueKeyJoiner.join(mName, ".", super.computeUniqueKey());
93    }
94
95    public String getName() {
96        return mName;
97    }
98
99    @Override
100    public void updateExpr(ModelAnalyzer modelAnalyzer) {
101        resolveType(modelAnalyzer);
102        super.updateExpr(modelAnalyzer);
103    }
104
105    @Override
106    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
107        if (mGetter == null) {
108            Expr child = getChild();
109            child.resolveType(modelAnalyzer);
110            boolean isStatic = child instanceof StaticIdentifierExpr;
111            ModelClass resolvedType = child.getResolvedType();
112            L.d("resolving %s. Resolved class type: %s", this, resolvedType);
113
114            mGetter = resolvedType.findGetterOrField(mName, isStatic);
115            if (mGetter.resolvedType.isObservableField()) {
116                // Make this the ".get()" and add an extra field access for the observable field
117                child.getParents().remove(this);
118                getChildren().remove(child);
119
120                FieldAccessExpr observableField = getModel().observableField(child, mName);
121                observableField.mGetter = mGetter;
122
123                getChildren().add(observableField);
124                observableField.getParents().add(this);
125                mGetter = mGetter.resolvedType.findGetterOrField("get", false);
126                mName = "";
127            }
128        }
129        return mGetter.resolvedType;
130    }
131
132    @Override
133    protected String asPackage() {
134        String parentPackage = getChild().asPackage();
135        return parentPackage == null ? null : parentPackage + "." + mName;
136    }
137}
138