com.hp.jipp.encoding.AttributeCollection.kt Maven / Gradle / Ivy
// Copyright 2017 - 2020 HP Development Company, L.P.
// SPDX-License-Identifier: MIT
package com.hp.jipp.encoding
import com.hp.jipp.util.PrettyPrintable
import com.hp.jipp.util.PrettyPrinter
/** An ordered collection of attributes as defined in [RFC3382](https://www.iana.org/go/rfc3382). */
interface AttributeCollection : PrettyPrintable {
val attributes: List>
override fun print(printer: PrettyPrinter) {
printer.open(PrettyPrinter.OBJECT)
printer.addAll(attributes)
printer.close()
}
/**
* An [AttributeType] for a value of an [AttributeCollection] subclass.
*
* Note: subclasses may only represent recognizable data types in the type. If additional data is required,
* it may be necessary to extract the original attribute list using an [UntypedCollection] instance.
*/
class Type(
name: String,
private val converter: Converter
) : AttributeTypeImpl(name, converter.cls) {
@Suppress("UNCHECKED_CAST")
override fun coerce(value: Any): T? =
super.coerce(value) ?: when (value) {
is AttributeCollection -> converter.convert(value.attributes)
else -> null
}
}
/**
* An [AttributeType] for a multiple values of an [AttributeCollection] subclass.
*
* Note: subclasses may only represent recognizable data types in the type. If additional data is required,
* it may be necessary to extract the original attribute list using an [UntypedCollection] instance.
*/
class SetType(
override val name: String,
private val converter: Converter
) : AttributeSetType {
override fun coerce(value: Any): T? =
when {
converter.cls.isInstance(value) ->
@Suppress("UNCHECKED_CAST") // We just checked it
value as T
value is AttributeCollection -> converter.convert(value.attributes)
else -> null
}
}
/** Converts a [List] of [Attribute] objects into an [AttributeCollection]. */
interface Converter {
/** Class of T. */
val cls: Class
/**
* Progressively convert attributes into the destination type
*/
fun convert(attributes: List>): T
/** Returns the first value of attribute [type] from [attributes]. */
fun extractOne(attributes: List>, type: AttributeType): T? =
coerced(attributes, type)?.let {
when (it.size) {
0 -> null
else -> it[0]
}
}
/** Returns all values of attribute [type] from [attributes]. */
fun extractAll(attributes: List>, type: AttributeType): List? =
coerced(attributes, type)?.let {
when (it.size) {
0 -> null
else -> it
}
}
/** Return the attribute having the same name and coerced into the given attribute type, if possible. */
fun coerced(attributes: List>, type: AttributeType): Attribute? =
attributes.find { it.name == type.name }?.let {
type.coerce(it)
}
}
}