LayoutBinder.java revision 8b1da958f181639d33dfaa907c0ee66add2decd6
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
19d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport com.google.common.base.Preconditions;
20d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Dependency;
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr;
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel;
24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.IdentifierExpr;
25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.store.ResourceBundle;
2634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport android.databinding.tool.store.ResourceBundle.BindingTargetBundle;
27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.LayoutBinderWriter;
2834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport android.databinding.tool.writer.WriterPackage;
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList;
3134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.Collections;
3234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.Comparator;
335bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyarimport java.util.HashMap;
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
355bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyarimport java.util.Map;
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/**
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Keeps all information about the bindings per layout file
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class LayoutBinder {
4134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    private static final Comparator<BindingTarget> COMPARE_FIELD_NAME = new Comparator<BindingTarget>() {
4234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        @Override
4334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        public int compare(BindingTarget first, BindingTarget second) {
4434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            final String fieldName1 = WriterPackage.getFieldName(first);
4534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            final String fieldName2 = WriterPackage.getFieldName(second);
4634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            return fieldName1.compareTo(fieldName2);
4734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
4834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    };
493bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    /*
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    * val pkg: String, val projectPackage: String, val baseClassName: String,
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val layoutName:String, val lb: LayoutExprBinding*/
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final ExprModel mExprModel;
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final ExpressionParser mExpressionParser;
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final List<BindingTarget> mBindingTargets;
5696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    private final List<BindingTarget> mSortedBindingTargets;
57a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    private String mModulePackage;
58895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    private final HashMap<String, String> mUserDefinedVariables = new HashMap<String, String>();
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
6043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    private LayoutBinderWriter mWriter;
613bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    private ResourceBundle.LayoutFileBundle mBundle;
62c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount    private static final String[] sJavaLangClasses = {
63c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Deprecated",
64c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Override",
65c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SafeVarargs",
66c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SuppressWarnings",
67c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Appendable",
68c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "AutoCloseable",
69c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "CharSequence",
70c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Cloneable",
71c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Comparable",
72c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Iterable",
73c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Readable",
74c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Runnable",
75c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Thread.UncaughtExceptionHandler",
76c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Boolean",
77c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Byte",
78c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Character",
79c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Character.Subset",
80c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Character.UnicodeBlock",
81c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Class",
82c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassLoader",
83c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Compiler",
84c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Double",
85c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Enum",
86c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Float",
87c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InheritableThreadLocal",
88c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Integer",
89c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Long",
90c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Math",
91c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Number",
92c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Object",
93c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Package",
94c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Process",
95c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ProcessBuilder",
96c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Runtime",
97c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "RuntimePermission",
98c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SecurityManager",
99c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Short",
100c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StackTraceElement",
101c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StrictMath",
102c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "String",
103c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StringBuffer",
104c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StringBuilder",
105c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "System",
106c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Thread",
107c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ThreadGroup",
108c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ThreadLocal",
109c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Throwable",
110c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Void",
111c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Thread.State",
112c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ArithmeticException",
113c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ArrayIndexOutOfBoundsException",
114c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ArrayStoreException",
115c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassCastException",
116c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassNotFoundException",
117c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "CloneNotSupportedException",
118c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "EnumConstantNotPresentException",
119c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Exception",
120c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalAccessException",
121c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalArgumentException",
122c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalMonitorStateException",
123c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalStateException",
124c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalThreadStateException",
125c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IndexOutOfBoundsException",
126c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InstantiationException",
127c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InterruptedException",
128c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NegativeArraySizeException",
129c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchFieldException",
130c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchMethodException",
131c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NullPointerException",
132c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NumberFormatException",
133c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ReflectiveOperationException",
134c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "RuntimeException",
135c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "SecurityException",
136c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StringIndexOutOfBoundsException",
137c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "TypeNotPresentException",
138c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnsupportedOperationException",
139c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "AbstractMethodError",
140c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "AssertionError",
141c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassCircularityError",
142c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ClassFormatError",
143c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "Error",
144c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ExceptionInInitializerError",
145c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IllegalAccessError",
146c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "IncompatibleClassChangeError",
147c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InstantiationError",
148c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "InternalError",
149c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "LinkageError",
150c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoClassDefFoundError",
151c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchFieldError",
152c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "NoSuchMethodError",
153c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "OutOfMemoryError",
154c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "StackOverflowError",
155c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "ThreadDeath",
156c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnknownError",
157c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnsatisfiedLinkError",
158c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "UnsupportedClassVersionError",
159c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "VerifyError",
160c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            "VirtualMachineError",
161c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount    };
16243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
1637ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    public LayoutBinder(ResourceBundle.LayoutFileBundle layoutBundle) {
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mExprModel = new ExprModel();
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mExpressionParser = new ExpressionParser(mExprModel);
166895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        mBindingTargets = new ArrayList<BindingTarget>();
1673bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        mBundle = layoutBundle;
168a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        mModulePackage = layoutBundle.getModulePackage();
1693bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        // copy over data.
1703bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        for (Map.Entry<String, String> variable : mBundle.getVariables().entrySet()) {
1713bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            addVariable(variable.getKey(), variable.getValue());
1723bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
1733bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
1743bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        for (Map.Entry<String, String> userImport : mBundle.getImports().entrySet()) {
175a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount            mExprModel.addImport(userImport.getKey(), userImport.getValue());
1763bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
177c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount        for (String javaLangClass : sJavaLangClasses) {
178c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount            mExprModel.addImport(javaLangClass, "java.lang." + javaLangClass);
179c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount        }
18034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        for (BindingTargetBundle targetBundle : mBundle.getBindingTargetBundles()) {
1813bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            final BindingTarget bindingTarget = createBindingTarget(targetBundle);
1823bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (ResourceBundle.BindingTargetBundle.BindingBundle bindingBundle : targetBundle
1833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    .getBindingBundleList()) {
1843bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                bindingTarget.addBinding(bindingBundle.getName(), parse(bindingBundle.getExpr()));
1853bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
186e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar            bindingTarget.resolveMultiSetters();
1873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
18896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        mSortedBindingTargets = new ArrayList<BindingTarget>(mBindingTargets);
18996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        Collections.sort(mSortedBindingTargets, COMPARE_FIELD_NAME);
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
1925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public void resolveWhichExpressionsAreUsed() {
193895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        List<Expr> used = new ArrayList<Expr>();
1945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        for (BindingTarget target : mBindingTargets) {
1955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            for (Binding binding : target.getBindings()) {
1965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                binding.getExpr().setIsUsed(true);
1975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                used.add(binding.getExpr());
1985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
1995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
2005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        while (!used.isEmpty()) {
2015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            Expr e = used.remove(used.size() - 1);
2025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            for (Dependency dep : e.getDependencies()) {
2035bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                if (!dep.getOther().isUsed()) {
2045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                    used.add(dep.getOther());
2055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                    dep.getOther().setIsUsed(true);
2065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                }
2075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
2085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
2095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
2105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public IdentifierExpr addVariable(String name, String type) {
2125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        Preconditions.checkState(!mUserDefinedVariables.containsKey(name),
2135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                "%s has already been defined as %s", name, type);
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        final IdentifierExpr id = mExprModel.identifier(name);
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        id.setUserDefinedType(type);
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        id.enableDirectInvalidation();
2175bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        mUserDefinedVariables.put(name, type);
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return id;
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
220d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2215bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public HashMap<String, String> getUserDefinedVariables() {
2225bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return mUserDefinedVariables;
2235bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
2245bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
2253bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    public BindingTarget createBindingTarget(ResourceBundle.BindingTargetBundle targetBundle) {
2263bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        final BindingTarget target = new BindingTarget(targetBundle);
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mBindingTargets.add(target);
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        target.setModel(mExprModel);
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return target;
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr parse(String input) {
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        final Expr parsed = mExpressionParser.parse(input);
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        parsed.setBindingExpression(true);
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return parsed;
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public List<BindingTarget> getBindingTargets() {
239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mBindingTargets;
240d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
241d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
24296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public List<BindingTarget> getSortedTargets() {
24396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return mSortedBindingTargets;
24496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount
246d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public boolean isEmpty() {
247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mExprModel.size() == 0;
248d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public ExprModel getModel() {
251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mExprModel;
252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
25443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    private void ensureWriter() {
25543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        if (mWriter == null) {
25643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            mWriter = new LayoutBinderWriter(this);
25743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }
25843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
2593bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
2608b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    public String writeViewBinderBaseClass(boolean forLibrary) {
26143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        ensureWriter();
2628b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar        return mWriter.writeBaseClass(forLibrary);
26343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
26443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
26543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
26696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public String writeViewBinder(int minSdk) {
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mExprModel.seal();
26843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        ensureWriter();
2697ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        Preconditions.checkNotNull(getPackage(), "package cannot be null");
2707ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        Preconditions.checkNotNull(getClassName(), "base class name cannot be null");
27196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return mWriter.write(minSdk);
272d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
274d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public String getPackage() {
2757ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        return mBundle.getBindingClassPackage();
276d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public boolean isMerge() {
27996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return mBundle.isMerge();
28096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
28196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
282a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    public String getModulePackage() {
283a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        return mModulePackage;
284a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    }
285a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
286d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public String getLayoutname() {
2873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        return mBundle.getFileName();
288d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
289d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
290dea555cf42dc3583604699c8c018d22681f56166George Mount    public String getImplementationName() {
2915bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        if (hasVariations()) {
2927ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mBundle.getBindingClassName() + mBundle.getConfigName() + "Impl";
2935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        } else {
2947ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mBundle.getBindingClassName();
2955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
296d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
2973bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
298dea555cf42dc3583604699c8c018d22681f56166George Mount    public String getClassName() {
2997ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        return mBundle.getBindingClassName();
30043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
3015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3020390898cf7c4fcad255e8cfd6802f722b516cb2cGeorge Mount    public String getTag() {
3030390898cf7c4fcad255e8cfd6802f722b516cb2cGeorge Mount        return mBundle.getDirectory() + "/" + mBundle.getFileName();
3045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
3055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public boolean hasVariations() {
3073bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        return mBundle.hasVariations();
3085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
310