DataBinderWriter.kt revision d3dc1b70aa71e8343dbf5e05a2feeb72bb29b6ec
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *      http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 */
13
14package android.databinding.tool.writer
15
16import android.databinding.tool.LayoutBinder
17
18class DataBinderWriter(val pkg: String, val projectPackage: String, val className: String,
19        val layoutBinders : List<LayoutBinder>, val minSdk : kotlin.Int) {
20    fun write(brWriter : BRWriter) = kcode("") {
21        nl("package $pkg;")
22        nl("import $projectPackage.BR;")
23        nl("class $className {") {
24            tab("final static int TARGET_MIN_SDK = ${minSdk};")
25            nl("")
26            tab("public $className() {") {
27            }
28            tab("}")
29            nl("")
30            tab("public android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View view, int layoutId) {") {
31                tab("switch(layoutId) {") {
32                    layoutBinders.groupBy{it.getLayoutname()}.forEach {
33                        val firstVal = it.value.get(0)
34                        tab("case ${firstVal.getModulePackage()}.R.layout.${firstVal.getLayoutname()}:") {
35                            if (it.value.size() == 1) {
36                                if (firstVal.isMerge()) {
37                                    tab("return new ${firstVal.getPackage()}.${firstVal.getImplementationName()}(bindingComponent, new android.view.View[]{view});")
38                                } else {
39                                    tab("return ${firstVal.getPackage()}.${firstVal.getImplementationName()}.bind(view, bindingComponent);")
40                                }
41                            } else {
42                                // we should check the tag to decide which layout we need to inflate
43                                tab("{") {
44                                    tab("final Object tag = view.getTag();")
45                                    tab("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");")
46                                    it.value.forEach {
47                                        tab("if (\"${it.getTag()}_0\".equals(tag)) {") {
48                                            if (it.isMerge()) {
49                                                tab("return new ${it.getPackage()}.${it.getImplementationName()}(bindingComponent, new android.view.View[]{view});")
50                                            } else {
51                                                tab("return new ${it.getPackage()}.${it.getImplementationName()}(bindingComponent, view);")
52                                            }
53                                        } tab("}")
54                                    }
55                                    tab("throw new java.lang.IllegalArgumentException(\"The tag for ${firstVal.getLayoutname()} is invalid. Received: \" + tag);");
56                                }tab("}")
57                            }
58
59                        }
60                    }
61                }
62                tab("}")
63                tab("return null;")
64            }
65            tab("}")
66
67            tab("android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View[] views, int layoutId) {") {
68                tab("switch(layoutId) {") {
69                    layoutBinders.filter{it.isMerge()}.groupBy{it.getLayoutname()}.forEach {
70                        val firstVal = it.value.get(0)
71                        tab("case ${firstVal.getModulePackage()}.R.layout.${firstVal.getLayoutname()}:") {
72                            if (it.value.size() == 1) {
73                                tab("return new ${firstVal.getPackage()}.${firstVal.getImplementationName()}(bindingComponent, views);")
74                            } else {
75                                // we should check the tag to decide which layout we need to inflate
76                                tab("{") {
77                                    tab("final Object tag = views[0].getTag();")
78                                    tab("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");")
79                                    it.value.forEach {
80                                        tab("if (\"${it.getTag()}_0\".equals(tag)) {") {
81                                            tab("return new ${it.getPackage()}.${it.getImplementationName()}(bindingComponent, views);")
82                                        } tab("}")
83                                    }
84                                }tab("}")
85                            }
86                        }
87                    }
88                }
89                tab("}")
90                tab("return null;")
91            }
92            tab("}")
93
94            tab("int getLayoutId(String tag) {") {
95                tab("if (tag == null) {") {
96                    tab("return 0;");
97                }
98                tab("}")
99                // String.hashCode is well defined in the API so we can rely on it being the same on the device and the host machine
100                tab("final int code = tag.hashCode();");
101                tab("switch(code) {") {
102                    layoutBinders.groupBy {"${it.getTag()}_0".hashCode()}.forEach {
103                        tab("case ${it.key}:") {
104                            it.value.forEach {
105                                tab("if(tag.equals(\"${it.getTag()}_0\"))") {
106                                    tab("return ${it.getModulePackage()}.R.layout.${it.getLayoutname()};")
107                                }
108                            }
109                            tab("break;")
110                        }
111
112                    }
113                }
114                tab("}")
115                tab("return 0;")
116            }
117            tab("}")
118
119            tab("String convertBrIdToString(int id) {") {
120                tab("if (id < 0 || id >= InnerBrLookup.sKeys.length) {") {
121                    tab("return null;")
122                } tab("}")
123                tab("return InnerBrLookup.sKeys[id];")
124            } tab("}")
125
126            tab("private static class InnerBrLookup {") {
127                tab("static String[] sKeys = new String[]{") {
128                    tab("\"_all\"")
129                    brWriter.indexedProps.forEach {
130                        tab(",\"${it.value}\"")
131                    }
132                }.app("};")
133            } tab("}")
134        }
135        nl("}")
136    }.generate()
137}