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

love.forte.simbot.Attribute.kt Maven / Gradle / Ivy

There is a newer version: 3.0.0.preview.0.4
Show newest version
/*
 *  Copyright (c) 2021-2021 ForteScarlet 
 *
 *  根据 Apache License 2.0 获得许可;
 *  除非遵守许可,否则您不得使用此文件。
 *  您可以在以下网址获取许可证副本:
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *   有关许可证下的权限和限制的具体语言,请参见许可证。
 */

@file:JvmName("Attributes")

package love.forte.simbot

import kotlinx.serialization.Serializable
import love.forte.simbot.SimbotComponent.name
import kotlin.reflect.KClass
import kotlin.reflect.full.cast
import kotlin.reflect.full.safeCast


/*
 * 参考自 gradle-7.1 代码 org.gradle.api.attributes.Attribute, 下述原文LICENSE
 *
 * Copyright 2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * 一个属性。
 *
 * 此类型通常使用在 [Component.attributes], 或者作为事件处理中的上下文使用。
 *
 * [Attribute] 拥有一个 [属性名][name] 和此属性对应的 [类型][type], 其中,
 *
 * 对于一个 [Attribute], 它的 [Attribute.hashcode] 将会直接与 [name] 一致,因此可以直接将 [Attribute] 作为一个 [Map] 的 Key.
 *
 * 但是在进行 [Attribute.equals] 比较的时候,会同时对 [name] 和 [type] 进行比较。
 *
 * @see AttributeMap
 *
 */
@Serializable
public class Attribute private constructor(
    public val name: String,
    public val type: KClass
) {
    private val hashcode: Int get() = name.hashCode()

    override fun hashCode(): Int = hashcode
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is Attribute<*>) return false

        if (name != other.name) return false
        return type == other.type
    }

    override fun toString(): String = name

    public companion object {
        @Api4J
        @JvmStatic
        public fun  of(name: String, type: Class): Attribute = of(name, type.kotlin)

        /**
         * @see attribute
         */
        @JvmSynthetic
        public fun  of(name: String, type: KClass): Attribute = Attribute(name, type)
    }


}

@JvmSynthetic
public fun  attribute(name: String, type: KClass): Attribute = Attribute.of(name, type)
public inline fun  attribute(name: String): Attribute = attribute(name, T::class)
public inline fun  attribute(): Attribute =
    with(T::class) { attribute(qualifiedName ?: name, this) }


/**
 * 一个通过 [Attribute] 作为键值来界定其元素类型的映射表。
 *
 * [AttributeMap]与名称字符串为键的映射表相比,其没有明确的值类型,取而代之的是通过 [Attribute] 来规定元素类型的。
 *
 *
 * [AttributeMap] 中的Key即为 [Attribute], 并且以类型作为 [equals] 条件之一,
 * 因此在使用 [AttributeMap] 的时候,应当避免出现相同 [Attribute.name] 但是 [Attribute.type] 不同的情况。
 *
 *
 * [AttributeMap] 不允许存入null值。
 *
 *
 * example:
 * ```kotlin
 * class Foo
 *
 * fun test() {
 *      val fooAttr = attribute("foo")
 *
 *      val map = AttributeHashMap()
 *      val foo = Foo()
 *      map[fooAttr] = foo
 *      val foo1 = map[fooAttr]!!
 *      val foo2 = map[attribute("foo")]!! // by a new instance
 *
 *      println(foo1 === foo2) // true
 *  }
 * ```
 *
 * @see AttributeHashMap
 */
public interface AttributeMap {

    /**
     * 通过 [attribute] 得到对应的数据。
     *
     * @throws ClassCastException 如果存在对应名称但是类型不匹配的键与值。
     */
    public operator fun  get(attribute: Attribute): T?


    /**
     * 判断是否存在对应键名与类型的键。
     */
    public fun  contains(attribute: Attribute): Boolean

    /**
     * 数量
     */
    public fun size(): Int

    public object Empty : AttributeMap {
        override fun  get(attribute: Attribute): T? = null
        override fun  contains(attribute: Attribute): Boolean = false
        override fun size(): Int = 0
    }
}


/**
 * [MutableAttributeMap] 是 [AttributeMap] 的子类型,代表一个允许变化的 [AttributeMap], 类似于 [Map] 与 [MutableMap] 之间的关系。
 */
public interface MutableAttributeMap : AttributeMap {

    /**
     * 存入一个值。
     *
     * @throws IllegalStateException 如果已经存在重名但是类型不同的键
     */
    public fun  put(attribute: Attribute, value: T): T?


    /**
     * 移除对应键名的值。
     *
     * @throws ClassCastException 如果类型不匹配
     */
    public fun  remove(attribute: Attribute): T?
}





public operator fun  MutableAttributeMap.set(attribute: Attribute, value: T) {
    put(attribute, value)
}






public class AttributeHashMap : MutableAttributeMap {
    private val values = mutableMapOf, Any>()

    public val entries: MutableSet, Any>>
        get() = values.entries

    override fun size(): Int = values.size

    override fun  get(attribute: Attribute): T? {
        val got = values[attribute] ?: return null
        return attribute.type.cast(got)
    }

    override fun  put(attribute: Attribute, value: T): T? {
        val type = attribute.type
        val result = values.put(attribute, type.cast(value))
        return type.safeCast(result)
    }

    override fun  contains(attribute: Attribute): Boolean {
        return attribute in values
    }


    override fun  remove(attribute: Attribute): T? {
        val removedValue = values.remove(attribute) ?: return null
        return removedValue.let { attribute.type.safeCast(it) }
    }

    override fun toString(): String = values.toString()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy