1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/*
2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License.
5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at
6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software
8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and
11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License.
12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
14fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.ext
15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
167b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.expr.VersionProvider
17d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport kotlin.properties.ReadOnlyProperty
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport kotlin.properties.Delegates
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.joinToCamelCase
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.joinToCamelCaseAsVar
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
24d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarprivate class LazyExt<K, T>(private val initializer: (k : K) -> T) : ReadOnlyProperty<K, T> {
26d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private val mapping = hashMapOf<K, T>()
27d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    override fun get(thisRef: K, desc: PropertyMetadata): T {
28d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val t = mapping.get(thisRef)
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (t != null) {
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return t
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
32d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val result = initializer(thisRef)
33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mapping.put(thisRef, result)
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return result
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
387b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarprivate class VersionedLazyExt<K, T>(private val initializer: (k : K) -> T) : ReadOnlyProperty<K, T> {
397b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar    private val mapping = hashMapOf<K, VersionedResult<T>>()
407b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar    override fun get(thisRef: K, desc: PropertyMetadata): T {
417b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        val t = mapping.get(thisRef)
427b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        val version = if(thisRef is VersionProvider) thisRef.getVersion() else 1
437b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        if (t != null && version == t.version) {
447b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            return t.result
457b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        }
467b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        val result = initializer(thisRef)
477b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        mapping.put(thisRef, VersionedResult(version, result))
487b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar        return result
497b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar    }
507b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar}
517b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar
527b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyardata class VersionedResult<T>(val version : Int, val result : T)
537b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Delegates.lazy<K, T>(initializer: (k : K) -> T): ReadOnlyProperty<K, T> = LazyExt(initializer)
557b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarfun Delegates.versionedLazy<K, T>(initializer: (k : K) -> T): ReadOnlyProperty<K, T> = VersionedLazyExt(initializer)
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
5771eb6908f2689bd17000237eb645896c36da0138George Mountpublic fun Class<*>.toJavaCode() : String {
5871eb6908f2689bd17000237eb645896c36da0138George Mount    val name = getName();
5971eb6908f2689bd17000237eb645896c36da0138George Mount    if (name.startsWith('[')) {
6071eb6908f2689bd17000237eb645896c36da0138George Mount        val numArray = name.lastIndexOf('[') + 1;
6171eb6908f2689bd17000237eb645896c36da0138George Mount        val componentType : String;
6271eb6908f2689bd17000237eb645896c36da0138George Mount        when (name.charAt(numArray)) {
6371eb6908f2689bd17000237eb645896c36da0138George Mount            'Z' -> componentType = "boolean"
6471eb6908f2689bd17000237eb645896c36da0138George Mount            'B' -> componentType = "byte"
6571eb6908f2689bd17000237eb645896c36da0138George Mount            'C' -> componentType = "char"
6671eb6908f2689bd17000237eb645896c36da0138George Mount            'L' -> componentType = name.substring(numArray + 1, name.length() - 1).replace('$', '.');
6771eb6908f2689bd17000237eb645896c36da0138George Mount            'D' -> componentType = "double"
6871eb6908f2689bd17000237eb645896c36da0138George Mount            'F' -> componentType = "float"
6971eb6908f2689bd17000237eb645896c36da0138George Mount            'I' -> componentType = "int"
7071eb6908f2689bd17000237eb645896c36da0138George Mount            'J' -> componentType = "long"
7171eb6908f2689bd17000237eb645896c36da0138George Mount            'S' -> componentType = "short"
7271eb6908f2689bd17000237eb645896c36da0138George Mount            else -> componentType = name.substring(numArray)
7371eb6908f2689bd17000237eb645896c36da0138George Mount        }
7471eb6908f2689bd17000237eb645896c36da0138George Mount        val arrayComp = name.substring(0, numArray).replace("[", "[]");
7571eb6908f2689bd17000237eb645896c36da0138George Mount        return componentType + arrayComp;
7671eb6908f2689bd17000237eb645896c36da0138George Mount    } else {
7771eb6908f2689bd17000237eb645896c36da0138George Mount        return name.replace("$", ".")
7871eb6908f2689bd17000237eb645896c36da0138George Mount    }
7971eb6908f2689bd17000237eb645896c36da0138George Mount}
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
81fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyarpublic fun String.androidId() : String = this.splitBy("/")[1]
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic fun String.toCamelCase() : String {
84fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    val split = this.splitBy("_")
85fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    if (split.size() == 0) return ""
86fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    if (split.size() == 1) return split[0].capitalize()
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return split.joinToCamelCase()
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic fun String.toCamelCaseAsVar() : String {
91fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    val split = this.splitBy("_")
92fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    if (split.size() == 0) return ""
93fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    if (split.size() == 1) return split[0]
94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return split.joinToCamelCaseAsVar()
9543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar}
9643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
9743596c2b2997e40b709627419732100d78a62ff0Yigit Boyarpublic fun String.br() : String =
98a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar    "BR.${if (this == "") "_all" else this}"
99