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.ext
15
16import android.databinding.tool.expr.VersionProvider
17import kotlin.properties.ReadOnlyProperty
18import kotlin.properties.Delegates
19import android.databinding.tool.ext.joinToCamelCase
20import android.databinding.tool.ext.joinToCamelCaseAsVar
21import android.databinding.tool.reflection.ModelAnalyzer
22import android.databinding.tool.reflection.ModelClass
23import android.databinding.tool.reflection.ModelAnalyzer
24
25private class LazyExt<K, T>(private val initializer: (k : K) -> T) : ReadOnlyProperty<K, T> {
26    private val mapping = hashMapOf<K, T>()
27    override fun get(thisRef: K, desc: PropertyMetadata): T {
28        val t = mapping.get(thisRef)
29        if (t != null) {
30            return t
31        }
32        val result = initializer(thisRef)
33        mapping.put(thisRef, result)
34        return result
35    }
36}
37
38private class VersionedLazyExt<K, T>(private val initializer: (k : K) -> T) : ReadOnlyProperty<K, T> {
39    private val mapping = hashMapOf<K, VersionedResult<T>>()
40    override fun get(thisRef: K, desc: PropertyMetadata): T {
41        val t = mapping.get(thisRef)
42        val version = if(thisRef is VersionProvider) thisRef.getVersion() else 1
43        if (t != null && version == t.version) {
44            return t.result
45        }
46        val result = initializer(thisRef)
47        mapping.put(thisRef, VersionedResult(version, result))
48        return result
49    }
50}
51
52data class VersionedResult<T>(val version : Int, val result : T)
53
54fun Delegates.lazy<K, T>(initializer: (k : K) -> T): ReadOnlyProperty<K, T> = LazyExt(initializer)
55fun Delegates.versionedLazy<K, T>(initializer: (k : K) -> T): ReadOnlyProperty<K, T> = VersionedLazyExt(initializer)
56
57public fun Class<*>.toJavaCode() : String {
58    val name = getName();
59    if (name.startsWith('[')) {
60        val numArray = name.lastIndexOf('[') + 1;
61        val componentType : String;
62        when (name.charAt(numArray)) {
63            'Z' -> componentType = "boolean"
64            'B' -> componentType = "byte"
65            'C' -> componentType = "char"
66            'L' -> componentType = name.substring(numArray + 1, name.length() - 1).replace('$', '.');
67            'D' -> componentType = "double"
68            'F' -> componentType = "float"
69            'I' -> componentType = "int"
70            'J' -> componentType = "long"
71            'S' -> componentType = "short"
72            else -> componentType = name.substring(numArray)
73        }
74        val arrayComp = name.substring(0, numArray).replace("[", "[]");
75        return componentType + arrayComp;
76    } else {
77        return name.replace("$", ".")
78    }
79}
80
81public fun String.androidId() : String = this.splitBy("/")[1]
82
83public fun String.toCamelCase() : String {
84    val split = this.splitBy("_")
85    if (split.size() == 0) return ""
86    if (split.size() == 1) return split[0].capitalize()
87    return split.joinToCamelCase()
88}
89
90public fun String.toCamelCaseAsVar() : String {
91    val split = this.splitBy("_")
92    if (split.size() == 0) return ""
93    if (split.size() == 1) return split[0]
94    return split.joinToCamelCaseAsVar()
95}
96
97public fun String.br() : String =
98    "BR.${if (this == "") "_all" else this}"
99