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.layoutname }.forEach { 33 val firstVal = it.value[0] 34 tab("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") { 35 if (it.value.size == 1) { 36 if (firstVal.isMerge) { 37 tab("return new ${firstVal.`package`}.${firstVal.implementationName}(bindingComponent, new android.view.View[]{view});") 38 } else { 39 tab("return ${firstVal.`package`}.${firstVal.implementationName}.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.tag}_0\".equals(tag)) {") { 48 if (it.isMerge) { 49 tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, new android.view.View[]{view});") 50 } else { 51 tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, view);") 52 } 53 } tab("}") 54 } 55 tab("throw new java.lang.IllegalArgumentException(\"The tag for ${firstVal.layoutname} 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.layoutname }.forEach { 70 val firstVal = it.value[0] 71 tab("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") { 72 if (it.value.size == 1) { 73 tab("return new ${firstVal.`package`}.${firstVal.implementationName}(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.tag}_0\".equals(tag)) {") { 81 tab("return new ${it.`package`}.${it.implementationName}(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.tag}_0".hashCode()}.forEach { 103 tab("case ${it.key}:") { 104 it.value.forEach { 105 tab("if(tag.equals(\"${it.tag}_0\"))") { 106 tab("return ${it.modulePackage}.R.layout.${it.layoutname};") 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}