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

com.hp.jipp.encoding.KeyValues.kt Maven / Gradle / Ivy

// Copyright 2017 - 2021 HP Development Company, L.P.
// SPDX-License-Identifier: MIT

package com.hp.jipp.encoding

/** A map of keys to values where keys and values are both strings. */
@Suppress("ConstructorParameterNaming") // _encoded is weird but it's supposed to be
class KeyValues(
    /** Pairs of key/values. */
    val pairs: Map = linkedMapOf(),
    /**
     * The original string representation, if known. If present, this exact string will be written instead of
     * the content in [pairs]. This may differ from the calculated representation from [pairs] due to
     * implementations which append a final ";".
     *
     * Note: this field is ignored by equals/hashcode methods.
     */
    val _encoded: String? = null
) : Map by pairs {

    constructor(vararg pairs: Pair) : this(pairs.toMap())

    /** Each key/value pair is supplied as a pair of arguments, e.g. `("key1", "value1", "key2", "value2")`. */
    constructor(vararg keyValues: String) : this(fromPairs(keyValues))

    override fun equals(other: Any?) =
        if (this === other) true else when (other) {
            is KeyValues -> pairs == other.pairs
            is Map<*, *> -> other == this // Fall back to other's equals implementation
            else -> false
        }

    override fun hashCode() = pairs.hashCode()

    companion object {
        private const val ELEMENT_SEPARATOR = ";"
        private const val PART_SEPARATOR = "="
        val codec = Codec(
            Tag.octetString,
            {
                parse(readString())
            },
            {
                // Write the original string, or fall back to pairs if _encoded is not present
                writeStringValue(it._encoded ?: it.combine())
            }
        )

        /** Convert an IPP string to an ordered KeyValues map. */
        fun parse(combined: String) =
            KeyValues(
                combined.split(ELEMENT_SEPARATOR)
                    .map { it.split(PART_SEPARATOR) }
                    .filter { it.size == 2 && it[0].isNotEmpty() && it[1].isNotEmpty() }
                    .map { it[0] to it[1] }
                    .toMap(),
                combined
            )

        /** Convert an array of items (key1, value1, ...) into pairs of items. */
        fun fromPairs(keyValues: Array) =
            keyValues.toList().windowed(2, 2).map { it[0] to it[1] }.toMap()
    }

    /** Return the contents of this map combined into an IPP string representation. */
    fun combine() =
        pairs.entries.joinToString(ELEMENT_SEPARATOR) { "${it.key}$PART_SEPARATOR${it.value}" } + ELEMENT_SEPARATOR

    override fun toString() = "{${combine()}}"
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy