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
19c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.misc.Nullable;
20c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Dependency;
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr;
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel;
24716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.expr.ExprModel.ResolveListenersCallback;
25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.IdentifierExpr;
26731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.Scope;
27731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.scopes.FileScopeProvider;
28c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport android.databinding.tool.store.Location;
29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.store.ResourceBundle;
3034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport android.databinding.tool.store.ResourceBundle.BindingTargetBundle;
312611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport android.databinding.tool.util.Preconditions;
32fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.LayoutBinderWriter;
3334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport android.databinding.tool.writer.WriterPackage;
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList;
3634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.Collections;
3734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.Comparator;
385bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyarimport java.util.HashMap;
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/**
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Keeps all information about the bindings per layout file
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
44731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarpublic class LayoutBinder implements ResolveListenersCallback, FileScopeProvider {
4534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    private static final Comparator<BindingTarget> COMPARE_FIELD_NAME = new Comparator<BindingTarget>() {
4634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        @Override
4734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        public int compare(BindingTarget first, BindingTarget second) {
4834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            final String fieldName1 = WriterPackage.getFieldName(first);
4934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            final String fieldName2 = WriterPackage.getFieldName(second);
5034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            return fieldName1.compareTo(fieldName2);
5134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
5234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    };
533bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    /*
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    * val pkg: String, val projectPackage: String, val baseClassName: String,
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val layoutName:String, val lb: LayoutExprBinding*/
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final ExprModel mExprModel;
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final ExpressionParser mExpressionParser;
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final List<BindingTarget> mBindingTargets;
6096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    private final List<BindingTarget> mSortedBindingTargets;
61a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    private String mModulePackage;
62895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    private final HashMap<String, String> mUserDefinedVariables = new HashMap<String, String>();
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
6443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    private LayoutBinderWriter mWriter;
653bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    private ResourceBundle.LayoutFileBundle mBundle;
66c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount    private static final String[] sJavaLangClasses = {
67c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Deprecated",
68c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Override",
69c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SafeVarargs",
70c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SuppressWarnings",
71c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Appendable",
72c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "AutoCloseable",
73c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "CharSequence",
74c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Cloneable",
75c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Comparable",
76c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Iterable",
77c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Readable",
78c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Runnable",
79c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Thread.UncaughtExceptionHandler",
80c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Boolean",
81c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Byte",
82c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Character",
83c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Character.Subset",
84c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Character.UnicodeBlock",
85c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Class",
86c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassLoader",
87c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Compiler",
88c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Double",
89c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Enum",
90c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Float",
91c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InheritableThreadLocal",
92c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Integer",
93c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Long",
94c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Math",
95c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Number",
96c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Object",
97c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Package",
98c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Process",
99c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ProcessBuilder",
100c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Runtime",
101c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "RuntimePermission",
102c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SecurityManager",
103c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Short",
104c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StackTraceElement",
105c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StrictMath",
106c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "String",
107c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StringBuffer",
108c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StringBuilder",
109c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "System",
110c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Thread",
111c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ThreadGroup",
112c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ThreadLocal",
113c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Throwable",
114c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Void",
115c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Thread.State",
116c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ArithmeticException",
117c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ArrayIndexOutOfBoundsException",
118c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ArrayStoreException",
119c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassCastException",
120c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassNotFoundException",
121c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "CloneNotSupportedException",
122c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "EnumConstantNotPresentException",
123c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Exception",
124c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalAccessException",
125c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalArgumentException",
126c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalMonitorStateException",
127c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalStateException",
128c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalThreadStateException",
129c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IndexOutOfBoundsException",
130c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InstantiationException",
131c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InterruptedException",
132c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NegativeArraySizeException",
133c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchFieldException",
134c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchMethodException",
135c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NullPointerException",
136c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NumberFormatException",
137c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ReflectiveOperationException",
138c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "RuntimeException",
139c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SecurityException",
140c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StringIndexOutOfBoundsException",
141c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "TypeNotPresentException",
142c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnsupportedOperationException",
143c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "AbstractMethodError",
144c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "AssertionError",
145c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassCircularityError",
146c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassFormatError",
147c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Error",
148c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ExceptionInInitializerError",
149c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalAccessError",
150c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IncompatibleClassChangeError",
151c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InstantiationError",
152c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InternalError",
153c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "LinkageError",
154c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoClassDefFoundError",
155c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchFieldError",
156c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchMethodError",
157c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "OutOfMemoryError",
158c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StackOverflowError",
159c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ThreadDeath",
160c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnknownError",
161c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnsatisfiedLinkError",
162c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnsupportedClassVersionError",
163c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "VerifyError",
164c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "VirtualMachineError",
165c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount    };
16643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
1677ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    public LayoutBinder(ResourceBundle.LayoutFileBundle layoutBundle) {
168731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        try {
169731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            Scope.enter(this);
170731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mExprModel = new ExprModel();
171731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mExpressionParser = new ExpressionParser(mExprModel);
172731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mBindingTargets = new ArrayList<BindingTarget>();
173731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mBundle = layoutBundle;
174731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mModulePackage = layoutBundle.getModulePackage();
175731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            // copy over data.
176731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            for (ResourceBundle.NameTypeLocation variable : mBundle.getVariables()) {
177731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                addVariable(variable.name, variable.type, variable.location);
178731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
1793bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
180731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            for (ResourceBundle.NameTypeLocation userImport : mBundle.getImports()) {
181731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mExprModel.addImport(userImport.name, userImport.type, userImport.location);
182731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
183731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            for (String javaLangClass : sJavaLangClasses) {
184731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mExprModel.addImport(javaLangClass, "java.lang." + javaLangClass, null);
1853bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
186731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            for (BindingTargetBundle targetBundle : mBundle.getBindingTargetBundles()) {
187731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                try {
188731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    Scope.enter(targetBundle);
189731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    final BindingTarget bindingTarget = createBindingTarget(targetBundle);
190731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    for (BindingTargetBundle.BindingBundle bindingBundle : targetBundle
191731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                            .getBindingBundleList()) {
192731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                        bindingTarget.addBinding(bindingBundle.getName(),
193731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                                parse(bindingBundle.getExpr(), bindingBundle.getValueLocation()));
194731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    }
195731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    bindingTarget.resolveMultiSetters();
196731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                } finally {
197731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    Scope.exit();
198731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                }
199731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
200731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mSortedBindingTargets = new ArrayList<BindingTarget>(mBindingTargets);
201731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            Collections.sort(mSortedBindingTargets, COMPARE_FIELD_NAME);
202731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        } finally {
203731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            Scope.exit();
2043bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public void resolveWhichExpressionsAreUsed() {
208895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        List<Expr> used = new ArrayList<Expr>();
2095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        for (BindingTarget target : mBindingTargets) {
2105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            for (Binding binding : target.getBindings()) {
2115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                binding.getExpr().setIsUsed(true);
2125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                used.add(binding.getExpr());
2135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
2145bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
2155bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        while (!used.isEmpty()) {
2165bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            Expr e = used.remove(used.size() - 1);
2175bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            for (Dependency dep : e.getDependencies()) {
2185bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                if (!dep.getOther().isUsed()) {
2195bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                    used.add(dep.getOther());
2205bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                    dep.getOther().setIsUsed(true);
2215bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                }
2225bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
2235bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
2245bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
2255bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
226c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public IdentifierExpr addVariable(String name, String type, Location location) {
2272611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar        Preconditions.check(!mUserDefinedVariables.containsKey(name),
2285bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                "%s has already been defined as %s", name, type);
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        final IdentifierExpr id = mExprModel.identifier(name);
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        id.setUserDefinedType(type);
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        id.enableDirectInvalidation();
232c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (location != null) {
233c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            id.addLocation(location);
234c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
2355bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        mUserDefinedVariables.put(name, type);
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return id;
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2395bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public HashMap<String, String> getUserDefinedVariables() {
2405bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return mUserDefinedVariables;
2415bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
2425bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
2433bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    public BindingTarget createBindingTarget(ResourceBundle.BindingTargetBundle targetBundle) {
2443bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        final BindingTarget target = new BindingTarget(targetBundle);
245d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mBindingTargets.add(target);
246d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        target.setModel(mExprModel);
247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return target;
248d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
250c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public Expr parse(String input, @Nullable Location locationInFile) {
251c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        final Expr parsed = mExpressionParser.parse(input, locationInFile);
252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        parsed.setBindingExpression(true);
253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return parsed;
254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public List<BindingTarget> getBindingTargets() {
257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mBindingTargets;
258d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
26096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public List<BindingTarget> getSortedTargets() {
26196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return mSortedBindingTargets;
26296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
26396e1c821dd446d1ed78f8ae61131550588f60a24George Mount
264d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public boolean isEmpty() {
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mExprModel.size() == 0;
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
268d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public ExprModel getModel() {
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mExprModel;
270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    private void ensureWriter() {
27343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        if (mWriter == null) {
27443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            mWriter = new LayoutBinderWriter(this);
27543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }
27643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
2773bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
278e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    public void sealModel() {
279e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        mExprModel.seal(this);
280e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    }
281e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
2828b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    public String writeViewBinderBaseClass(boolean forLibrary) {
28343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        ensureWriter();
2848b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar        return mWriter.writeBaseClass(forLibrary);
28543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
28643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
28796e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public String writeViewBinder(int minSdk) {
28843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        ensureWriter();
2897ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        Preconditions.checkNotNull(getPackage(), "package cannot be null");
2907ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        Preconditions.checkNotNull(getClassName(), "base class name cannot be null");
29196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return mWriter.write(minSdk);
292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public String getPackage() {
2957ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        return mBundle.getBindingClassPackage();
296d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
297d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
29896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public boolean isMerge() {
29996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return mBundle.isMerge();
30096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
30196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
302a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    public String getModulePackage() {
303a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        return mModulePackage;
304a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    }
305a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
306d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public String getLayoutname() {
3073bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        return mBundle.getFileName();
308d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
310dea555cf42dc3583604699c8c018d22681f56166George Mount    public String getImplementationName() {
3115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        if (hasVariations()) {
3127ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mBundle.getBindingClassName() + mBundle.getConfigName() + "Impl";
3135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        } else {
3147ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mBundle.getBindingClassName();
3155bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
3173bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
318dea555cf42dc3583604699c8c018d22681f56166George Mount    public String getClassName() {
3197ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        return mBundle.getBindingClassName();
32043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
3215bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3220390898cf7c4fcad255e8cfd6802f722b516cb2cGeorge Mount    public String getTag() {
3230390898cf7c4fcad255e8cfd6802f722b516cb2cGeorge Mount        return mBundle.getDirectory() + "/" + mBundle.getFileName();
3245bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
3255bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3265bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public boolean hasVariations() {
3273bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        return mBundle.hasVariations();
3285bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
329716ba89e7f459f49ea85070d4710c1d79d715298George Mount
330716ba89e7f459f49ea85070d4710c1d79d715298George Mount    @Override
331716ba89e7f459f49ea85070d4710c1d79d715298George Mount    public void resolveListeners() {
332716ba89e7f459f49ea85070d4710c1d79d715298George Mount        for (BindingTarget target : mBindingTargets) {
333716ba89e7f459f49ea85070d4710c1d79d715298George Mount            for (Binding binding : target.getBindings()) {
334716ba89e7f459f49ea85070d4710c1d79d715298George Mount                binding.resolveListeners();
335716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
336716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
337716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
338731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
339731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    @Override
340731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public String provideScopeFilePath() {
341731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        return mBundle.getAbsoluteFilePath();
342731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    }
343d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
344