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

main.com.vmware.aria.operations.Key.kt Maven / Gradle / Ivy

/*
 * Copyright 2023 VMware, Inc.
 * SPDX-License-Identifier: Apache-2.0
 */
package com.vmware.aria.operations

import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient

/**
 * Object's Key class, used for identifying VMware Aria Operation [Objects][Object].
 *
 * Objects are identified by the Adapter Type, Object Type, and one or more Identifiers.
 *
 * Identifiers can be either the Object's [name], or one or more [Identifier] key-value pairs.
 * In order for an 'Identifier' to be used for identification, it must have
 * [isPartOfUniqueness][Identifier.isPartOfUniqueness] set to true (this is the default).
 *
 * Two Objects with the same Key are not permitted in a [CollectResult].
 *
 * Objects must be created with the full key. Keys cannot change after the Object has been created.
 *
 * All Objects with the same Adapter Type and Object Type must have the same set of Identifiers.
 *
 * @property adapterType The Adapter Type this Object is associated with.
 * @property objectType The Object Type (e.g., class) of this Object.
 * @property name A human-readable name for this Object. Should be unique if possible.
 * @property identifiers A list of [Identifiers][Identifier] that uniquely identify the Object. If none are present than
 * the name must be unique and is used for identification. All Objects with the same adapter type and Object
 * type must have the same set of identifiers.
 */
@Serializable
class Key @OptIn(ExperimentalSerializationApi::class)
@JvmOverloads constructor(
    @SerialName("adapterKind") val adapterType: String,
    @SerialName("objectKind") val objectType: String,
    val name: String,
    @EncodeDefault(EncodeDefault.Mode.ALWAYS) val identifiers: List = emptyList(),
) {
    @Transient private val identifierMap = identifiers.associateBy(Identifier::key)

    override fun toString(): String {
        return "$adapterType:$objectType:$identifiers"
    }

    /**
     * Return a list of data and identifiers that determine uniqueness
     */
    private val internalKey: List
        get() {
            // Sort all identifiers by 'key' that are part of uniqueness
            val uniqueIdentifiers =
                identifiers.filter { identifier -> identifier.isPartOfUniqueness }
            val key = mutableListOf()
            key.add(adapterType)
            key.add(objectType)
            if (uniqueIdentifiers.isEmpty()) {
                //If there are no identifiers, or if all identifiers are not part of
                // uniqueness, the name is used as uniquely identifying
                key.add(name)
            } else {
                // Otherwise,if there is at least one identifier that is part of
                // uniqueness, name is not used for
                // identification. Add each of the unique identifiers to the list, sorted
                // by key
                key.addAll(uniqueIdentifiers.sortedBy { identifier -> identifier.key })
            }
            return key
        }

    /**
     * @return True if the keys will resolve to the same object, false otherwise.
     */
    override fun equals(other: Any?) = other is Key && internalKey == other.internalKey

    /**
     * Return a hashcode of this Key, respecting the rules of key uniqueness
     */
    override fun hashCode(): Int =
        internalKey.fold(0) { acc, id -> acc xor id.hashCode() }

    /**
     * Return the value for the given identifier key.
     * @param key The identifier key.
     * @param defaultValue An optional default value.
     * @return The value associated with the identifier.
     * If the value associated with the identifier is empty and 'defaultValue' is
     * provided, returns 'defaultValue'.
     * If the identifier does not exist, returns defaultValue if provided, else 'null'.
     */
    @JvmOverloads
    fun getIdentifier(key: String, defaultValue: String? = null): String? {
        val value = identifierMap[key]?.value
        return if (value?.isBlank() != false) {
            defaultValue ?: value
        } else {
            value
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy