LayoutBinder.java revision fead9ca09b117136b35bc5bf137340a754f9eddd
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;
18
19import com.google.common.base.Preconditions;
20
21import android.databinding.tool.expr.Dependency;
22import android.databinding.tool.expr.Expr;
23import android.databinding.tool.expr.ExprModel;
24import android.databinding.tool.expr.IdentifierExpr;
25import android.databinding.tool.store.ResourceBundle;
26import android.databinding.tool.util.ParserHelper;
27import android.databinding.tool.writer.LayoutBinderWriter;
28
29import java.util.ArrayList;
30import java.util.HashMap;
31import java.util.List;
32import java.util.Map;
33
34/**
35 * Keeps all information about the bindings per layout file
36 */
37public class LayoutBinder {
38
39    /*
40    * val pkg: String, val projectPackage: String, val baseClassName: String,
41        val layoutName:String, val lb: LayoutExprBinding*/
42    private final ExprModel mExprModel;
43    private final ExpressionParser mExpressionParser;
44    private final List<BindingTarget> mBindingTargets;
45    private String mPackage;
46    private String mModulePackage;
47    private String mProjectPackage;
48    private String mBaseClassName;
49    private final HashMap<String, String> mUserDefinedVariables = new HashMap<String, String>();
50
51    private LayoutBinderWriter mWriter;
52    private ResourceBundle.LayoutFileBundle mBundle;
53
54    public LayoutBinder(ResourceBundle resourceBundle,
55            ResourceBundle.LayoutFileBundle layoutBundle) {
56        mExprModel = new ExprModel();
57        mExpressionParser = new ExpressionParser(mExprModel);
58        mBindingTargets = new ArrayList<BindingTarget>();
59        mBundle = layoutBundle;
60        mProjectPackage = resourceBundle.getAppPackage();
61        mModulePackage = layoutBundle.getModulePackage();
62        mPackage = layoutBundle.getModulePackage() + ".generated";
63        mBaseClassName = ParserHelper.INSTANCE$.toClassName(layoutBundle.getFileName()) + "Binding";
64        // copy over data.
65        for (Map.Entry<String, String> variable : mBundle.getVariables().entrySet()) {
66            addVariable(variable.getKey(), variable.getValue());
67        }
68
69        for (Map.Entry<String, String> userImport : mBundle.getImports().entrySet()) {
70            mExprModel.addImport(userImport.getKey(), userImport.getValue());
71        }
72        for (ResourceBundle.BindingTargetBundle targetBundle : mBundle.getBindingTargetBundles()) {
73            final BindingTarget bindingTarget = createBindingTarget(targetBundle);
74            for (ResourceBundle.BindingTargetBundle.BindingBundle bindingBundle : targetBundle
75                    .getBindingBundleList()) {
76                bindingTarget.addBinding(bindingBundle.getName(), parse(bindingBundle.getExpr()));
77            }
78        }
79    }
80
81    public void resolveWhichExpressionsAreUsed() {
82        List<Expr> used = new ArrayList<Expr>();
83        for (BindingTarget target : mBindingTargets) {
84            for (Binding binding : target.getBindings()) {
85                binding.getExpr().setIsUsed(true);
86                used.add(binding.getExpr());
87            }
88        }
89        while (!used.isEmpty()) {
90            Expr e = used.remove(used.size() - 1);
91            for (Dependency dep : e.getDependencies()) {
92                if (!dep.getOther().isUsed()) {
93                    used.add(dep.getOther());
94                    dep.getOther().setIsUsed(true);
95                }
96            }
97        }
98    }
99
100    public IdentifierExpr addVariable(String name, String type) {
101        Preconditions.checkState(!mUserDefinedVariables.containsKey(name),
102                "%s has already been defined as %s", name, type);
103        final IdentifierExpr id = mExprModel.identifier(name);
104        id.setUserDefinedType(type);
105        id.enableDirectInvalidation();
106        mUserDefinedVariables.put(name, type);
107        return id;
108    }
109
110    public HashMap<String, String> getUserDefinedVariables() {
111        return mUserDefinedVariables;
112    }
113
114    public BindingTarget createBindingTarget(ResourceBundle.BindingTargetBundle targetBundle) {
115        final BindingTarget target = new BindingTarget(targetBundle);
116        mBindingTargets.add(target);
117        target.setModel(mExprModel);
118        return target;
119    }
120
121    public Expr parse(String input) {
122        final Expr parsed = mExpressionParser.parse(input);
123        parsed.setBindingExpression(true);
124        return parsed;
125    }
126
127    public List<BindingTarget> getBindingTargets() {
128        return mBindingTargets;
129    }
130
131    public boolean isEmpty() {
132        return mExprModel.size() == 0;
133    }
134
135    public ExprModel getModel() {
136        return mExprModel;
137    }
138
139    private void ensureWriter() {
140        if (mWriter == null) {
141            mWriter = new LayoutBinderWriter(this);
142        }
143    }
144
145    public String writeViewBinderInterface() {
146        ensureWriter();
147        return mWriter.writeBaseClass();
148    }
149
150
151    public String writeViewBinder() {
152        mExprModel.seal();
153        ensureWriter();
154        Preconditions.checkNotNull(mPackage, "package cannot be null");
155        Preconditions.checkNotNull(mProjectPackage, "project package cannot be null");
156        Preconditions.checkNotNull(mBaseClassName, "base class name cannot be null");
157        return mWriter.write();
158    }
159
160    public String getPackage() {
161        return mPackage;
162    }
163
164    public String getModulePackage() {
165        return mModulePackage;
166    }
167
168    public void setPackage(String aPackage) {
169        mPackage = aPackage;
170    }
171
172    public String getProjectPackage() {
173        return mProjectPackage;
174    }
175
176    public String getLayoutname() {
177        return mBundle.getFileName();
178    }
179
180    public String getClassName() {
181        final String suffix;
182        if (hasVariations()) {
183            suffix = mBundle.getConfigName();
184        } else {
185            suffix = "";
186        }
187        return mBaseClassName + suffix + "Impl";
188
189    }
190
191    public String getInterfaceName() {
192        return mBaseClassName;
193    }
194
195    public int getId() {
196        return mBundle.getLayoutId();
197    }
198
199    public boolean hasVariations() {
200        return mBundle.hasVariations();
201    }
202
203}
204