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.expr;
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
19731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.Scope;
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.Callable;
21716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.reflection.Callable.Type;
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer;
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass;
24716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.reflection.ModelMethod;
25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.L;
26d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.ArrayList;
28d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class FieldAccessExpr extends Expr {
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    String mName;
32e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount    Callable mGetter;
337920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount    final boolean mIsObservableField;
34716ba89e7f459f49ea85070d4710c1d79d715298George Mount    private List<ModelMethod> mListenerMethods;
35716ba89e7f459f49ea85070d4710c1d79d715298George Mount    private List<ModelMethod> mCalledMethods;
36716ba89e7f459f49ea85070d4710c1d79d715298George Mount    private List<ModelClass> mListenerTypes;
37716ba89e7f459f49ea85070d4710c1d79d715298George Mount    private List<ModelMethod> mPotentialListeners;
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    FieldAccessExpr(Expr parent, String name) {
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        super(parent);
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mName = name;
427920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        mIsObservableField = false;
437920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount    }
447920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount
457920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount    FieldAccessExpr(Expr parent, String name, boolean isObservableField) {
467920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        super(parent);
477920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        mName = name;
487920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        mIsObservableField = isObservableField;
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
51a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount    public Expr getChild() {
527920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        return getChildren().get(0);
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
55e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount    public Callable getGetter() {
569e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar        if (mGetter == null) {
579e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar            getResolvedType();
589e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar        }
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mGetter;
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
62716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public List<ModelMethod> getListenerMethods() {
63716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return mListenerMethods;
64716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
65716ba89e7f459f49ea85070d4710c1d79d715298George Mount
66716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public List<ModelMethod> getCalledMethods() {
67716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return mCalledMethods;
68716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
69716ba89e7f459f49ea85070d4710c1d79d715298George Mount
70716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public List<ModelClass> getListenerTypes() { return mListenerTypes; }
71716ba89e7f459f49ea85070d4710c1d79d715298George Mount
72716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public boolean isListener() {
73716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return mListenerMethods != null && !mListenerMethods.isEmpty();
74716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
75716ba89e7f459f49ea85070d4710c1d79d715298George Mount
76716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public int getMinApi() {
77716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (isListener()) {
78716ba89e7f459f49ea85070d4710c1d79d715298George Mount            int minApi = 1;
79716ba89e7f459f49ea85070d4710c1d79d715298George Mount            for (ModelClass listener : mListenerTypes) {
80716ba89e7f459f49ea85070d4710c1d79d715298George Mount                int listenerApi = listener.getMinApi();
81716ba89e7f459f49ea85070d4710c1d79d715298George Mount                minApi = Math.max(minApi, listenerApi);
82716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
83716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return minApi;
84716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
85716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return mGetter.getMinApi();
86716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
87716ba89e7f459f49ea85070d4710c1d79d715298George Mount
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public boolean isDynamic() {
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (mGetter == null) {
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            getResolvedType();
92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
93716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (mGetter == null || mGetter.type == Type.METHOD) {
94716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return !isListener();
95019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        }
96019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        // if it is static final, gone
97019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        if (getChild().isDynamic()) {
98019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            // if owner is dynamic, then we can be dynamic unless we are static final
99019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            return !mGetter.isStatic() || mGetter.isDynamic();
100019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        }
101019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar
102019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        // if owner is NOT dynamic, we can be dynamic if an only if getter is dynamic
103019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        return mGetter.isDynamic();
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
106c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount    public boolean hasBindableAnnotations() {
107c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount        return mGetter.canBeInvalidated();
108c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount    }
109c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
111716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public boolean resolveListeners(ModelClass listener) {
112716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (mPotentialListeners == null) {
113716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return false;
114716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
115716ba89e7f459f49ea85070d4710c1d79d715298George Mount
116716ba89e7f459f49ea85070d4710c1d79d715298George Mount        List<ModelMethod> abstractMethods = listener.getAbstractMethods();
117716ba89e7f459f49ea85070d4710c1d79d715298George Mount        int numberOfAbstractMethods = abstractMethods == null ? 0 : abstractMethods.size();
118716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (numberOfAbstractMethods != 1) {
119716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (mGetter == null) {
120716ba89e7f459f49ea85070d4710c1d79d715298George Mount                L.e("Could not find accessor %s.%s and %s has %d abstract methods, so is" +
121716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                " not resolved as a listener",
122716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        getChild().getResolvedType().getCanonicalName(), mName,
123716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        listener.getCanonicalName(), numberOfAbstractMethods);
124716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
125716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return false;
126716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
127716ba89e7f459f49ea85070d4710c1d79d715298George Mount
128716ba89e7f459f49ea85070d4710c1d79d715298George Mount        // See if we've already resolved this listener type
129716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (mListenerMethods == null) {
130716ba89e7f459f49ea85070d4710c1d79d715298George Mount            mListenerMethods = new ArrayList<ModelMethod>();
131716ba89e7f459f49ea85070d4710c1d79d715298George Mount            mCalledMethods = new ArrayList<ModelMethod>();
132716ba89e7f459f49ea85070d4710c1d79d715298George Mount            mListenerTypes = new ArrayList<ModelClass>();
133716ba89e7f459f49ea85070d4710c1d79d715298George Mount        } else {
134716ba89e7f459f49ea85070d4710c1d79d715298George Mount            for (ModelClass previousListeners : mListenerTypes) {
135716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (previousListeners.equals(listener)) {
136716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    return false;
137716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
138716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
139716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
140716ba89e7f459f49ea85070d4710c1d79d715298George Mount
141716ba89e7f459f49ea85070d4710c1d79d715298George Mount        // Look for a signature matching the abstract method
142716ba89e7f459f49ea85070d4710c1d79d715298George Mount        final ModelMethod listenerMethod = abstractMethods.get(0);
143716ba89e7f459f49ea85070d4710c1d79d715298George Mount        final ModelClass[] listenerParameters = listenerMethod.getParameterTypes();
144716ba89e7f459f49ea85070d4710c1d79d715298George Mount        for (ModelMethod method : mPotentialListeners) {
145716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (acceptsParameters(method, listenerParameters)) {
146716ba89e7f459f49ea85070d4710c1d79d715298George Mount                mListenerTypes.add(listener);
147716ba89e7f459f49ea85070d4710c1d79d715298George Mount                mListenerMethods.add(listenerMethod);
148716ba89e7f459f49ea85070d4710c1d79d715298George Mount                mCalledMethods.add(method);
149716ba89e7f459f49ea85070d4710c1d79d715298George Mount                resetResolvedType();
150716ba89e7f459f49ea85070d4710c1d79d715298George Mount                return true;
151716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
152716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
153716ba89e7f459f49ea85070d4710c1d79d715298George Mount
154716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (mGetter == null) {
155716ba89e7f459f49ea85070d4710c1d79d715298George Mount            L.e("Listener class %s with method %s did not match signature of any method %s.%s",
156716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    listener.getCanonicalName(), listenerMethod.getName(),
157716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    getChild().getResolvedType().getCanonicalName(), mName);
158716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
159716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return false;
160716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
161716ba89e7f459f49ea85070d4710c1d79d715298George Mount
162716ba89e7f459f49ea85070d4710c1d79d715298George Mount    private boolean acceptsParameters(ModelMethod method, ModelClass[] listenerParameters) {
163716ba89e7f459f49ea85070d4710c1d79d715298George Mount        ModelClass[] parameters = method.getParameterTypes();
164716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (parameters.length != listenerParameters.length) {
165716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return false;
166716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
167716ba89e7f459f49ea85070d4710c1d79d715298George Mount        for (int i = 0; i < parameters.length; i++) {
168716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (!parameters[i].isAssignableFrom(listenerParameters[i])) {
169716ba89e7f459f49ea85070d4710c1d79d715298George Mount                return false;
170716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
171716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
172716ba89e7f459f49ea85070d4710c1d79d715298George Mount        return true;
173716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
174716ba89e7f459f49ea85070d4710c1d79d715298George Mount
175716ba89e7f459f49ea85070d4710c1d79d715298George Mount    @Override
176dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar    protected List<Dependency> constructDependencies() {
177dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar        final List<Dependency> dependencies = constructDynamicChildrenDependencies();
178dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar        for (Dependency dependency : dependencies) {
179a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            if (dependency.getOther() == getChild()) {
180dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar                dependency.setMandatory(true);
181dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar            }
182dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar        }
183dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar        return dependencies;
184dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar    }
185dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar
186dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar    @Override
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    protected String computeUniqueKey() {
1887920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        if (mIsObservableField) {
1892611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar            return join(mName, "..", super.computeUniqueKey());
1907920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        }
1912611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar        return join(mName, ".", super.computeUniqueKey());
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public String getName() {
195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mName;
196d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
19979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public void updateExpr(ModelAnalyzer modelAnalyzer) {
200731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        try {
201731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            Scope.enter(this);
202731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            resolveType(modelAnalyzer);
203731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            super.updateExpr(modelAnalyzer);
204731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        } finally {
205731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            Scope.exit();
206731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
20718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount    }
20818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount
20918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount    @Override
21018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
2117920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        if (mGetter == null) {
212716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (mPotentialListeners != null) {
213716ba89e7f459f49ea85070d4710c1d79d715298George Mount                return modelAnalyzer.findClass(Object.class);
214716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
215a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            Expr child = getChild();
216731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            child.getResolvedType();
217a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            boolean isStatic = child instanceof StaticIdentifierExpr;
218f9e51c010bd2eab9cca01baaccc0e5a73b8b72c9Yigit Boyar            ModelClass resolvedType = child.getResolvedType();
219e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar            L.d("resolving %s. Resolved class type: %s", this, resolvedType);
220f9e51c010bd2eab9cca01baaccc0e5a73b8b72c9Yigit Boyar
221fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mGetter = resolvedType.findGetterOrField(mName, isStatic);
222716ba89e7f459f49ea85070d4710c1d79d715298George Mount            mPotentialListeners = resolvedType.findMethods(mName, isStatic);
223716ba89e7f459f49ea85070d4710c1d79d715298George Mount
224716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (mGetter == null) {
225716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (mPotentialListeners == null) {
226716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    L.e("Could not find accessor %s.%s", resolvedType.getCanonicalName(), mName);
227716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
228716ba89e7f459f49ea85070d4710c1d79d715298George Mount                return modelAnalyzer.findClass(Object.class);
229716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
230ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar
231ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar            if (mGetter.isStatic() && !isStatic) {
232ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                // found a static method on an instance. register a new one
233ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                child.getParents().remove(this);
234ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                getChildren().remove(child);
235ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                StaticIdentifierExpr staticId = getModel().staticIdentifierFor(resolvedType);
236ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                getChildren().add(staticId);
237ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                staticId.getParents().add(this);
238ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar                child = getChild(); // replace the child for the next if stmt
239ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar            }
240ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar
241fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            if (mGetter.resolvedType.isObservableField()) {
2427920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                // Make this the ".get()" and add an extra field access for the observable field
243a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount                child.getParents().remove(this);
244a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount                getChildren().remove(child);
2457920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount
246a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount                FieldAccessExpr observableField = getModel().observableField(child, mName);
2477920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                observableField.mGetter = mGetter;
2487920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount
2497920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                getChildren().add(observableField);
2507920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                observableField.getParents().add(this);
251fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount                mGetter = mGetter.resolvedType.findGetterOrField("get", false);
2527920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                mName = "";
2537920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount            }
2547920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        }
255716ba89e7f459f49ea85070d4710c1d79d715298George Mount        if (isListener()) {
256716ba89e7f459f49ea85070d4710c1d79d715298George Mount            return modelAnalyzer.findClass(Object.class);
257716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
25818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount        return mGetter.resolvedType;
2597920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount    }
2607920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount
2617920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount    @Override
26218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount    protected String asPackage() {
263a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount        String parentPackage = getChild().asPackage();
26418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount        return parentPackage == null ? null : parentPackage + "." + mName;
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
267