Home | History | Annotate | Download | only in writer
      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 
     14 package android.databinding.tool.writer
     15 
     16 import android.databinding.tool.LayoutBinder
     17 
     18 class 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 }