FieldAccessExpr.java revision ec2f3896c21a504b464bf591cdb45b62692b6760
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
116            if (mGetter.isStatic() && !isStatic) {
117                // found a static method on an instance. register a new one
118                child.getParents().remove(this);
119                getChildren().remove(child);
120                StaticIdentifierExpr staticId = getModel().staticIdentifierFor(resolvedType);
121                getChildren().add(staticId);
122                staticId.getParents().add(this);
123                child = getChild(); // replace the child for the next if stmt
124            }
125
126            if (mGetter.resolvedType.isObservableField()) {
127                // Make this the ".get()" and add an extra field access for the observable field
128                child.getParents().remove(this);
129                getChildren().remove(child);
130
131                FieldAccessExpr observableField = getModel().observableField(child, mName);
132                observableField.mGetter = mGetter;
133
134                getChildren().add(observableField);
135                observableField.getParents().add(this);
136                mGetter = mGetter.resolvedType.findGetterOrField("get", false);
137                mName = "";
138            }
139        }
140        return mGetter.resolvedType;
141    }
142
143    @Override
144    protected String asPackage() {
145        String parentPackage = getChild().asPackage();
146        return parentPackage == null ? null : parentPackage + "." + mName;
147    }
148}
149