Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2017 - 2023 HP Development Company, L.P.
// SPDX-License-Identifier: MIT
package com.hp.jipp.encoding
import com.hp.jipp.model.JobState
import com.hp.jipp.model.JobStateReason
import com.hp.jipp.model.Operation
import com.hp.jipp.model.Status
import com.hp.jipp.model.Types
import com.hp.jipp.util.PrettyPrinter
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.net.URI
/**
* An IPP packet consisting of header information and zero or more attribute groups.
*/
@Suppress("TooManyFunctions")
data class IppPacket constructor(
val versionNumber: Int = DEFAULT_VERSION_NUMBER,
val code: Int,
val requestId: Int,
val attributeGroups: List = listOf()
) {
@JvmOverloads
constructor(
versionNumber: Int = DEFAULT_VERSION_NUMBER,
code: Int,
requestId: Int,
vararg groups: AttributeGroup
) : this(versionNumber, code, requestId, groups.toList())
constructor(status: Status, requestId: Int, vararg groups: AttributeGroup) :
this(code = status.code, requestId = requestId, attributeGroups = groups.toList())
constructor(operation: Operation, requestId: Int, vararg groups: AttributeGroup) :
this(code = operation.code, requestId = requestId, attributeGroups = groups.toList())
/** Return this response packet's code as a [Status]. */
val status: Status by lazy {
Status[code]
}
/** Return this request packet's code as an [Operation] */
val operation: Operation by lazy {
Operation[code]
}
/** Get the attribute group having a delimiter */
operator fun get(groupDelimiter: Tag): AttributeGroup? =
attributeGroups.firstOrNull { it.tag == groupDelimiter }
/** Return all values found within the specified group and having the same attribute type */
fun getValues(groupDelimiter: Tag, type: AttributeSetType): List =
this[groupDelimiter]?.getValues(type) ?: listOf()
/** Return the first value within the group of [groupDelimiter] and [type]. */
fun getValue(groupDelimiter: Tag, type: AttributeType): T? =
this[groupDelimiter]?.get(type)?.get(0)
/** Return the string form of any attribute values within the group of [groupDelimiter] and [type]. */
fun getStrings(groupDelimiter: Tag, type: AttributeSetType): List =
this[groupDelimiter]?.getStrings(type) ?: listOf()
/** Return the string form of the first attribute value within the group of [groupDelimiter] and [type]. */
fun getString(groupDelimiter: Tag, type: AttributeType): String? =
this[groupDelimiter]?.getString(type)
/** Make a copy of this packet but replace with the supplied attribute groups */
fun withAttributeGroups(attributeGroups: List): IppPacket =
copy(attributeGroups = attributeGroups)
/** Write this packet to the [OutputStream] as per RFC2910. */
@Throws(IOException::class)
@Deprecated(
"use IppInputStream.write()",
ReplaceWith("write()", "com.hp.jipp.encoding.IppInputStream")
)
fun write(output: OutputStream) {
val ippOutput = IppOutputStream(output)
ippOutput.write(this)
}
/** Return a pretty-printed version of this packet (including separators and line breaks) */
fun prettyPrint(maxWidth: Int, indent: String) = PrettyPrinter(prefix(), PrettyPrinter.OBJECT, indent, maxWidth)
.addAll(attributeGroups)
.print()
private fun prefix(): String {
return "IppPacket(v=0x" + Integer.toHexString(versionNumber) +
", c=" + statusOrOperationString(code) +
", r=0x" + Integer.toHexString(requestId) +
")"
}
private fun statusOrOperationString(code: Int) =
(Operation.all[code] ?: Status.all[code] ?: code).toString()
override fun toString(): String {
return prefix() + " " + attributeGroups
}
class Builder
@JvmOverloads
constructor(
@set:JvmSynthetic
var code: Int,
@set:JvmSynthetic
var versionNumber: Int = DEFAULT_VERSION_NUMBER,
@set:JvmSynthetic
var requestId: Int = DEFAULT_REQUEST_ID
) {
@JvmOverloads
constructor(
status: Status,
versionNumber: Int = DEFAULT_VERSION_NUMBER,
requestId: Int = DEFAULT_REQUEST_ID
) : this(status.code, versionNumber, requestId)
@JvmOverloads
constructor(
operation: Operation,
versionNumber: Int = DEFAULT_VERSION_NUMBER,
requestId: Int = DEFAULT_REQUEST_ID
) : this(operation.code, versionNumber, requestId)
private val groups: MutableList = mutableListOf()
init {
// All packets must have an operation attributes group with these initial attributes
putOperationAttributes(
Types.attributesCharset.of(DEFAULT_CHARSET),
Types.attributesNaturalLanguage.of(DEFAULT_LANGUAGE)
)
}
@set:JvmSynthetic
var status
get() = Status[code]
set(value) { code = value.code }
fun setStatus(status: Status) = apply {
this.status = status
}
@set:JvmSynthetic
var operation
get() = Operation[code]
set(value) { code = value.code }
fun setOperation(operation: Operation) = apply {
this.operation = operation
}
fun setVersionNumber(versionNumber: Int) = apply {
this.versionNumber = versionNumber
}
fun setRequestId(requestId: Int) = apply {
this.requestId = requestId
}
fun setCode(code: Int) = apply {
this.code = code
}
/** Append a new [AttributeGroup] after other groups. */
fun addGroup(group: AttributeGroup) = apply {
groups.add(group.toMutable())
}
/** Look up or create a group for [tag] and populate it with [func]. */
fun group(tag: DelimiterTag) =
groups.findLast { it.tag == tag } ?: MutableAttributeGroup(tag).also { groups.add(it) }
/** Return the last [Tag.operationAttributes] group, creating it if necessary. */
val operationAttributes
get() = group(Tag.operationAttributes)
/** Return the last [Tag.printerAttributes] group, creating it if necessary. */
val printerAttributes
get() = group(Tag.printerAttributes)
/** Return the last [Tag.jobAttributes] group, creating it if necessary. */
val jobAttributes
get() = group(Tag.jobAttributes)
/** Return the last [Tag.unsupportedAttributes] group, creating it if necessary. */
val unsupportedAttributes
get() = group(Tag.unsupportedAttributes)
/** Return the last [Tag.subscriptionAttributes] group, creating it if necessary. */
val subscriptionAttributes
get() = group(Tag.subscriptionAttributes)
/** Return the last [Tag.eventNotificationAttributes] group, creating it if necessary. */
val eventNotificationAttributes
get() = group(Tag.eventNotificationAttributes)
/** Return the last [Tag.documentAttributes] group, creating it if necessary. */
val documentAttributes
get() = group(Tag.documentAttributes)
/** Look up or create a group for [tag] and populate it with [func]. */
@Suppress("DEPRECATION")
@Deprecated("Use .group", ReplaceWith("group(tag, func)"))
fun extend(tag: DelimiterTag, func: MutableAttributeGroup.() -> Unit) =
group(tag).apply { func() }
/** Get or create a group with [tag] and add or replace [attributes] in it. */
fun putAttributes(tag: DelimiterTag, attributes: Iterable>) = apply {
group(tag) += attributes
}
/** Get or create a group with [tag] and add or replace [attributes] in it. */
fun putAttributes(tag: DelimiterTag, vararg attributes: Attribute<*>) =
putAttributes(tag, attributes.toList())
/** Get the [Tag.operationAttributes] group and add or replace [attributes] in it. */
fun putOperationAttributes(attributes: Iterable>) =
putAttributes(Tag.operationAttributes, attributes)
/** Get the [Tag.operationAttributes] group and add or replace [attributes] in it. */
fun putOperationAttributes(vararg attributes: Attribute<*>) =
putOperationAttributes(attributes.toList())
/** Get or create the [Tag.jobAttributes] group and add or replace [attributes] in it. */
fun putJobAttributes(attributes: Iterable>) =
putAttributes(Tag.jobAttributes, attributes)
/** Get or create the [Tag.jobAttributes] group and add or replace [attributes] in it. */
fun putJobAttributes(vararg attributes: Attribute<*>) =
putJobAttributes(attributes.toList())
/** Get or create the [Tag.printerAttributes] group and add or replace [attributes] in it. */
fun putPrinterAttributes(attributes: Iterable>) =
putAttributes(Tag.printerAttributes, attributes)
/** Get or create the [Tag.printerAttributes] group and add or replace [attributes] in it. */
fun putPrinterAttributes(vararg attributes: Attribute<*>) =
putPrinterAttributes(attributes.toList())
/** Get or create the [Tag.unsupportedAttributes] group and add or replace [attributes] in it. */
fun putUnsupportedAttributes(attributes: Iterable>) =
putAttributes(Tag.unsupportedAttributes, attributes)
/** Get or create the [Tag.unsupportedAttributes] group and add or replace [attributes] in it. */
fun putUnsupportedAttributes(vararg attributes: Attribute<*>) =
putUnsupportedAttributes(attributes.toList())
/** Get or create the [Tag.subscriptionAttributes] group and add or replace [attributes] in it. */
fun putSubscriptionAttributes(attributes: Iterable>) =
putAttributes(Tag.subscriptionAttributes, attributes)
/** Get or create the [Tag.subscriptionAttributes] group and add or replace [attributes] in it. */
fun putSubscriptionAttributes(vararg attributes: Attribute<*>) =
putSubscriptionAttributes(attributes.toList())
/** Get or create the [Tag.eventNotificationAttributes] group and add or replace [attributes] in it. */
fun putEventNotificationAttributes(attributes: Iterable>) =
putAttributes(Tag.eventNotificationAttributes, attributes)
/** Get or create the [Tag.eventNotificationAttributes] group and add or replace [attributes] in it. */
fun putEventNotificationAttributes(vararg attributes: Attribute<*>) =
putEventNotificationAttributes(attributes.toList())
/** Get or create the [Tag.documentAttributes] group and add or replace [attributes] in it. */
fun putDocumentAttributes(attributes: Iterable>) =
putAttributes(Tag.documentAttributes, attributes)
/** Get or create the [Tag.documentAttributes] group and add or replace [attributes] in it. */
fun putDocumentAttributes(vararg attributes: Attribute<*>) =
putDocumentAttributes(attributes.toList())
/** Add a new [Tag.jobAttributes] group containing default attributes. */
@JvmOverloads
fun addJobAttributesGroup(
/** The job-id to be used to identify this job in future requests. */
jobId: Int,
/** The job-uri to be used as a target for future requests. */
jobUri: URI,
/** The current job-state. */
jobState: JobState,
/** A list of job-state-reasons, if any. */
jobStateReasons: List = listOf(JobStateReason.none),
/** Other job attributes, if any. */
vararg attributes: Attribute<*>
) = apply {
addGroup(
MutableAttributeGroup(
Tag.jobAttributes,
listOf(
Types.jobId.of(jobId),
Types.jobUri.of(jobUri),
Types.jobState.of(jobState),
Types.jobStateReasons.of(jobStateReasons)
) + attributes.toList()
)
)
}
/** Construct and return an [IppPacket] containing all settings given to this [Builder]. */
fun build() = IppPacket(
versionNumber, code, requestId,
// Strip out any empty unsupported-attributes or job-attributes groups.
groups.filterNot { (it.tag == Tag.unsupportedAttributes || it.tag == Tag.jobAttributes) && it.isEmpty() }
)
}
companion object {
/** Default version number for IPP packets (0x200 for IPP 2.0). */
const val DEFAULT_VERSION_NUMBER = 0x0200
/** Default request ID (1). */
const val DEFAULT_REQUEST_ID = 1
/** Default language to use in operation groups ("en-us"). */
const val DEFAULT_LANGUAGE = "en-us"
/** Default charset to use in operation groups ("utf-8"). */
const val DEFAULT_CHARSET = "utf-8"
@JvmStatic
@Throws(IOException::class)
@Deprecated(
"use IppInputStream.readPacket()",
ReplaceWith("readPacket()", "com.hp.jipp.encoding.IppInputStream")
)
fun parse(input: InputStream): IppPacket =
(input as? IppInputStream ?: IppInputStream(input)).readPacket()
@JvmStatic
@Throws(IOException::class)
@Deprecated(
"use IppInputStream.readPacket()",
ReplaceWith("readPacket()", "com.hp.jipp.encoding.IppInputStream")
)
fun read(input: InputStream) =
(input as? IppInputStream ?: IppInputStream(input)).readPacket()
/** Return a Get-Printer-Attributes request [Builder]. */
@JvmStatic
fun getPrinterAttributes(
printerUri: URI,
/** Printer attributes of interest. */
types: Iterable>
) = Builder(Operation.getPrinterAttributes.code)
.putAttributes(Tag.operationAttributes, Types.printerUri.of(printerUri))
.putRequestedAttributes(types.toList())
/** Return a Get-Printer-Attributes request [Builder]. */
@JvmStatic
fun getPrinterAttributes(
printerUri: URI,
/** Printer attributes of interest. */
vararg types: AttributeType<*>
) = getPrinterAttributes(printerUri, types.toList())
/** If supplied types are not empty, attach them as requested attributes. */
private fun Builder.putRequestedAttributes(types: List>) = apply {
if (types.isNotEmpty()) {
putAttributes(
Tag.operationAttributes,
Types.requestedAttributes.of(types.toList().map { it.name })
)
}
}
/** Return a Validate-Job request [Builder]. */
@JvmStatic
fun validateJob(
printerUri: URI
) = Builder(Operation.validateJob.code)
.putAttributes(Tag.operationAttributes, Types.printerUri.of(printerUri))
/** Return a Print-Job request [Builder]. */
@JvmStatic
fun printJob(
printerUri: URI
) = Builder(code = Operation.printJob.code)
.putAttributes(Tag.operationAttributes, Types.printerUri.of(printerUri))
/** Return a Create-Job request [Builder]. */
@JvmStatic
fun createJob(
printerUri: URI
) = Builder(Operation.createJob.code)
.putAttributes(Tag.operationAttributes, Types.printerUri.of(printerUri))
/** Return a Get-Jobs request [Builder]. */
@JvmStatic
fun getJobs(
printerUri: URI,
/** Job attributes of interest. */
vararg types: AttributeType<*>
) = Builder(Operation.getJobs.code)
.putAttributes(Tag.operationAttributes, Types.printerUri.of(printerUri))
.putRequestedAttributes(types.toList())
/** Return a Send-Document request [Builder]. */
@JvmStatic
fun sendDocument(
printerUri: URI,
jobId: Int
) = Builder(Operation.sendDocument.code)
.putAttributes(
Tag.operationAttributes,
Types.printerUri.of(printerUri),
Types.jobId.of(jobId)
)
/** Return a Send-Document request [Builder] */
@JvmStatic
fun sendDocument(
jobUri: URI,
/** Job attributes of interest. */
vararg types: AttributeType<*>
) = Builder(Operation.sendDocument.code)
.putAttributes(Tag.operationAttributes, Types.jobUri.of(jobUri))
.putRequestedAttributes(types.toList())
/** Return a Get-Job-Attributes request [Builder]. */
@JvmStatic
fun getJobAttributes(
printerUri: URI,
jobId: Int,
/** Job attributes of interest. */
vararg types: AttributeType<*>
) = Builder(Operation.getJobAttributes.code)
.putAttributes(
Tag.operationAttributes,
Types.printerUri.of(printerUri),
Types.jobId.of(jobId)
)
.putRequestedAttributes(types.toList())
/** Return a Get-Job-Attributes request [Builder]. */
@JvmStatic
fun getJobAttributes(
jobUri: URI,
/** Types of interest, if any. */
vararg types: AttributeType<*>
) = Builder(Operation.getJobAttributes.code)
.putAttributes(Tag.operationAttributes, Types.jobUri.of(jobUri))
.putRequestedAttributes(types.toList())
/** Return a Cancel-Job request [Builder]. */
@JvmStatic
fun cancelJob(
printerUri: URI,
jobId: Int
) = Builder(Operation.cancelJob.code)
.putAttributes(
Tag.operationAttributes,
Types.printerUri.of(printerUri),
Types.jobId.of(jobId)
)
/** Return a Cancel-Job request [Builder]. */
@JvmStatic
fun cancelJob(
jobUri: URI
) = Builder(Operation.cancelJob.code)
.putAttributes(Tag.operationAttributes, Types.jobUri.of(jobUri))
/** Return a generic response [Builder]. */
@JvmStatic
fun response(
status: Status
) = Builder(status.code)
.putAttributes(Tag.unsupportedAttributes)
/** Return a job-related response packet [Builder]. */
@JvmStatic
@JvmOverloads
@Suppress("LongParameterList") // All of these parameters required in Job responses.
fun jobResponse(
/** The status code for the request. */
status: Status,
/** The job-id to be used to identify this job in future requests. */
jobId: Int,
/** The job-uri to be used as a target for future requests. */
jobUri: URI,
/** The current job-state. */
jobState: JobState,
/** A list of job-state-reasons, if any. */
jobStateReasons: List = listOf(JobStateReason.none)
) = Builder(status.code)
.putAttributes(Tag.unsupportedAttributes)
.addJobAttributesGroup(jobId, jobUri, jobState, jobStateReasons)
}
}