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 block("class $className") { 24 nl("final static int TARGET_MIN_SDK = $minSdk;") 25 nl("") 26 block("public $className()") { 27 } 28 nl("") 29 block("public android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View view, int layoutId)") { 30 block("switch(layoutId)") { 31 layoutBinders.groupBy{it.layoutname }.forEach { 32 val firstVal = it.value[0] 33 tab("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") { 34 if (it.value.size == 1) { 35 if (firstVal.isMerge) { 36 tab("return new ${firstVal.`package`}.${firstVal.implementationName}(bindingComponent, new android.view.View[]{view});") 37 } else { 38 tab("return ${firstVal.`package`}.${firstVal.implementationName}.bind(view, bindingComponent);") 39 } 40 } else { 41 // we should check the tag to decide which layout we need to inflate 42 block("") { 43 tab("final Object tag = view.getTag();") 44 tab("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");") 45 it.value.forEach { 46 block("if (\"${it.tag}_0\".equals(tag))") { 47 if (it.isMerge) { 48 tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, new android.view.View[]{view});") 49 } else { 50 tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, view);") 51 } 52 } 53 } 54 tab("throw new java.lang.IllegalArgumentException(\"The tag for ${firstVal.layoutname} is invalid. Received: \" + tag);"); 55 } 56 } 57 58 } 59 } 60 } 61 nl("return null;") 62 } 63 block("android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View[] views, int layoutId)") { 64 block("switch(layoutId)") { 65 layoutBinders.filter{it.isMerge }.groupBy{it.layoutname }.forEach { 66 val firstVal = it.value[0] 67 block("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") { 68 if (it.value.size == 1) { 69 tab("return new ${firstVal.`package`}.${firstVal.implementationName}(bindingComponent, views);") 70 } else { 71 // we should check the tag to decide which layout we need to inflate 72 nl("final Object tag = views[0].getTag();") 73 nl("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");") 74 it.value.forEach { 75 block("if (\"${it.tag}_0\".equals(tag))") { 76 nl("return new ${it.`package`}.${it.implementationName}(bindingComponent, views);") 77 } 78 } 79 } 80 } 81 } 82 } 83 nl("return null;") 84 } 85 86 block("int getLayoutId(String tag)") { 87 block("if (tag == null)") { 88 nl("return 0;"); 89 } 90 // String.hashCode is well defined in the API so we can rely on it being the same on the device and the host machine 91 nl("final int code = tag.hashCode();"); 92 block("switch(code)") { 93 layoutBinders.groupBy {"${it.tag}_0".hashCode()}.forEach { 94 block("case ${it.key}:") { 95 it.value.forEach { 96 block("if(tag.equals(\"${it.tag}_0\"))") { 97 nl("return ${it.modulePackage}.R.layout.${it.layoutname};") 98 } 99 } 100 nl("break;") 101 } 102 103 } 104 } 105 nl("return 0;") 106 } 107 108 block("String convertBrIdToString(int id)") { 109 block("if (id < 0 || id >= InnerBrLookup.sKeys.length)") { 110 nl("return null;") 111 } 112 nl("return InnerBrLookup.sKeys[id];") 113 } 114 115 block("private static class InnerBrLookup") { 116 nl("static String[] sKeys = new String[]{") { 117 tab("\"_all\"") 118 brWriter.indexedProps.forEach { 119 tab(",\"${it.value}\"") 120 } 121 }.app("};") 122 } 123 } 124 }.generate() 125}