All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.remal.gradle_plugins.dsl.extensions.kotlin.Any.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.dsl.extensions

import groovy.lang.Closure
import name.remal.fromUpperCamelToLowerCamel
import name.remal.lambda.Function1
import name.remal.lambda.VoidFunction1
import name.remal.orNull
import name.remal.uncheckedCast
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.repositories.ArtifactRepository
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.internal.HasConvention
import org.gradle.api.internal.IConventionAware
import org.gradle.api.plugins.Convention
import org.gradle.api.provider.Provider
import java.lang.reflect.Array
import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.CompletionStage
import java.util.concurrent.Future
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.atomic.AtomicReference
import java.util.function.*
import kotlin.DeprecationLevel.HIDDEN
import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.javaMethod
import java.util.function.Function as JFunction
import kotlin.Function1 as KFunction1
import kotlin.reflect.KFunction1 as KReflectFunction1

val Any.convention: Convention
    get() = when (this) {
        is Project -> this.convention
        is Task -> this.convention
        else -> (this as HasConvention).convention
    }

val Any.conventionOrNull: Convention?
    get() = when (this) {
        is Project -> this.convention
        is Task -> this.convention
        is HasConvention -> this.convention
        else -> null
    }


fun Any.addObjectMarker(markerType: Class): Boolean {
    val convention = conventionOrNull ?: return false
    if (markerType in convention) return false
    val marker = markerType.getDeclaredConstructor()
        .apply { isAccessible = true }
        .newInstance()
    convention.addPlugin(marker)
    return true
}

fun Any.hasObjectMarker(markerType: Class) = markerType in conventionOrNull

interface ObjectMarker


data class ConventionWithSelf(val convention: Convention, val self: T)

val  T.conventionWithSelf: ConventionWithSelf get() = ConventionWithSelf(this.convention, this)


fun  T.defaultPropertyValue(property: KProperty1, func: (self: T) -> P) {
    this as IConventionAware
    conventionMapping.map(property.name) { func(this) }
}

fun  T.defaultPropertyValue(property: KReflectFunction1, func: (self: T) -> P) {
    val method = property.javaMethod ?: throw IllegalArgumentException("$property is not a method reference")
    val name: String
    if (method.name.length > 3 && method.name.startsWith("get") && method.name[3].isUpperCase()) {
        name = method.name.substring(3).fromUpperCamelToLowerCamel()
    } else if (method.name.length > 2 && method.name.startsWith("is") && method.name[2].isUpperCase()) {
        name = method.name.substring(2).fromUpperCamelToLowerCamel()
    } else {
        throw IllegalArgumentException("Property name can't be retrieved for $property")
    }
    this as IConventionAware
    conventionMapping.map(name) { func(this) }
}


@Suppress("ComplexMethod")
fun  T.configureWith(configurer: Any?): T = apply {
    if (configurer == null) {
        // do nothing
    } else if (configurer is Action<*>) {
        configurer.uncheckedCast>().execute(this)
    } else if (configurer is Closure<*>) {
        configurer.toConfigureAction().execute(this)
    } else if (configurer is Consumer<*>) {
        configurer.uncheckedCast>().toConfigureAction().execute(this)
    } else if (configurer is JFunction<*, *>) {
        configurer.uncheckedCast>().toConfigureAction().execute(this)
    } else if (configurer is KFunction1<*, *>) {
        configurer.uncheckedCast>().toConfigureAction().execute(this)
    } else if (configurer is KReflectFunction1<*, *>) {
        configurer.uncheckedCast>().toConfigureAction().execute(this)
    } else if (configurer is Function1<*, *>) {
        configurer.uncheckedCast>().toConfigureAction().execute(this)
    } else if (configurer is VoidFunction1<*>) {
        configurer.uncheckedCast>().toConfigureAction().execute(this)
    } else {
        throw IllegalArgumentException("Unsupported configurer: ${configurer.javaClass.name}")
    }
}


@Suppress("ComplexMethod")
fun Any?.unwrapProviders(): Any? = when (this) {
    null -> null
    is Optional<*> -> this.orNull.unwrapProviders()
    is Provider<*> -> this.orNull.unwrapProviders()
    is Callable<*> -> this.call().unwrapProviders()
    is Supplier<*> -> this.get().unwrapProviders()
    is BooleanSupplier -> this.asBoolean.unwrapProviders()
    is IntSupplier -> this.asInt.unwrapProviders()
    is LongSupplier -> this.asLong.unwrapProviders()
    is DoubleSupplier -> this.asDouble.unwrapProviders()
    is Future<*> -> this.get().unwrapProviders()
    is CompletionStage<*> -> this.toCompletableFuture().get().unwrapProviders()
    is AtomicBoolean -> this.get().unwrapProviders()
    is AtomicInteger -> this.get().unwrapProviders()
    is AtomicLong -> this.get().unwrapProviders()
    is AtomicReference<*> -> this.get().unwrapProviders()
    is Lazy<*> -> this.value.unwrapProviders()
    is Closure<*> -> this.call().unwrapProviders()
    else -> this
}


@Suppress("ReturnCount")
fun Any?.toStringSmart(): String {
    if (this == null) return "null"

    if (this.javaClass.isArray) {
        return buildString {
            append("[")
            (0 until Array.getLength(this@toStringSmart)).joinTo(this, ", ", transform = { Array.get(this@toStringSmart, it).toStringSmart() })
            append("]")
        }
    }

    if (this is Iterable<*>) {
        return buildString {
            append("[")
            [email protected](this, ", ", transform = { it.toStringSmart() })
            append("]")
        }
    }

    val toStringDeclaringClass = this.javaClass.getMethod("toString").declaringClass
    if (Any::class.java == toStringDeclaringClass || toStringDeclaringClass.isInterface) {
        when (this) {
            is MavenArtifactRepository -> return "$name($url)"
            is ArtifactRepository -> return name
        }
    }

    return toString()
}

fun Any.invokeCompatibleMethod(name: String, vararg params: Any) {
    val method = javaClass.getCompatibleMethod(name, *params.map(Any::javaClass).toTypedArray())
    method.isAccessible = true
    method.invoke(this, *params)
}

fun  Any.invokeCompatibleMethod(returnType: Class, name: String, vararg params: Any): R {
    val method = javaClass.getCompatibleMethod(returnType, name, *params.map(Any::javaClass).toTypedArray())
    method.isAccessible = true
    val result = method.invoke(this, *params)
        ?: throw IllegalStateException("$method returned NULL")
    return result.uncheckedCast()
}

fun  Any.invokeNullableCompatibleMethod(returnType: Class, name: String, vararg params: Any): R? {
    val method = javaClass.getCompatibleMethod(returnType, name, *params.map(Any::javaClass).toTypedArray())
    method.isAccessible = true
    return method.invoke(this, *params)?.uncheckedCast()
}

@Deprecated("invokeCompatibleMethod() can't be called on Unit", level = HIDDEN)
@Suppress("unused", "UNUSED_PARAMETER")
fun Unit.invokeCompatibleMethod(name: String, vararg params: Any) {
    throw UnsupportedOperationException()
}

@Deprecated("invokeCompatibleMethod() can't be called on Unit", level = HIDDEN)
@Suppress("unused", "UNUSED_PARAMETER")
fun  Unit.invokeCompatibleMethod(returnType: Class, name: String, vararg params: Any): R {
    throw UnsupportedOperationException()
}

@Deprecated("invokeNullableCompatibleMethod() can't be called on Unit", level = HIDDEN)
@Suppress("unused", "UNUSED_PARAMETER")
fun  Unit.invokeNullableCompatibleMethod(returnType: Class, name: String, vararg params: Any): R? {
    throw UnsupportedOperationException()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy