From 44774ac727385dd2556efd04b7e6bdffd3e5afec Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 28 Jun 2023 21:08:19 +0200 Subject: [PATCH] Add kDoc to Kotlin classes --- .../wot/dijkstra/sq/CertSynopsis.kt | 8 ++++ .../wot/dijkstra/sq/Certification.kt | 23 +++++++++++ .../wot/dijkstra/sq/CertificationSet.kt | 33 +++++++++++++++ .../org/pgpainless/wot/dijkstra/sq/Depth.kt | 35 +++++++++++++--- .../org/pgpainless/wot/dijkstra/sq/Network.kt | 8 ++++ .../org/pgpainless/wot/dijkstra/sq/Path.kt | 41 +++++++++++++++++++ .../org/pgpainless/wot/dijkstra/sq/Paths.kt | 23 ++++++++++- .../wot/dijkstra/sq/ReferenceTime.kt | 13 ++++++ .../pgpainless/wot/dijkstra/sq/RegexSet.kt | 17 ++++++++ 9 files changed, 193 insertions(+), 8 deletions(-) diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertSynopsis.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertSynopsis.kt index 58767789..061dd524 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertSynopsis.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertSynopsis.kt @@ -8,6 +8,14 @@ import org.pgpainless.algorithm.RevocationState import org.pgpainless.key.OpenPgpFingerprint import java.util.* +/** + * A [CertSynopsis] is a proxy object containing information about a certificate. + * + * @param fingerprint [OpenPgpFingerprint] of the certificate + * @param expirationTime optional expiration time of the certificate + * @param revocationState [RevocationState] denoting whether the certificate is revoked or not + * @param userIds [Map] of user-ids on the certificate, along with their revocation states + */ data class CertSynopsis( val fingerprint: OpenPgpFingerprint, val expirationTime: Date?, diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Certification.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Certification.kt index 52307624..35f14c08 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Certification.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Certification.kt @@ -6,6 +6,20 @@ package org.pgpainless.wot.dijkstra.sq import java.util.* +/** + * A [Certification] is a signature issued by one certificate over a datum on another target certificate. + * Such a datum could be either a user-id, or the primary key of the target certificate. + * + * @param issuer synopsis of the certificate that issued the [Certification] + * @param target synopsis of the certificate that is target of this [Certification] + * @param userId optional user-id. If this is null, the [Certification] is made over the primary key of the target. + * @param creationTime creation time of the [Certification] + * @param expirationTime optional expiration time of the [Certification] + * @param exportable if false, the certification is marked as "not exportable" + * @param trustAmount amount of trust the issuer places in the binding + * @param trustDepth degree to which the issuer trusts the target as trusted introducer + * @param regexes regular expressions for user-ids which the target is allowed to introduce + */ data class Certification( val issuer: CertSynopsis, val target: CertSynopsis, @@ -18,6 +32,15 @@ data class Certification( val regexes: RegexSet ) { + /** + * Construct a [Certification] with default values. The result is non-expiring, will be exportable and has a + * trust amount of 120, a depth of 0 and a wildcard regex. + * + * @param issuer synopsis of the certificate that issued the [Certification] + * @param target synopsis of the certificate that is target of this [Certification] + * @param targetUserId optional user-id. If this is null, the [Certification] is made over the primary key of the target. + * @param creationTime creation time of the [Certification] + */ constructor( issuer: CertSynopsis, targetUserId: String?, diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertificationSet.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertificationSet.kt index 0562db53..9139fc83 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertificationSet.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/CertificationSet.kt @@ -4,6 +4,17 @@ package org.pgpainless.wot.dijkstra.sq +/** + * A [CertificationSet] is a set of [Certifications][Certification] made by the same issuer, on the same + * target certificate. + * In some sense, a [CertificationSet] can be considered an edge in the web of trust. + * + * @param issuer synopsis of the certificate that issued the [Certifications][Certification] + * @param target synopsis of the certificate that is targeted by the [Certifications][Certification] + * @param certifications [MutableMap] keyed by user-ids, whose values are [MutableLists][MutableList] of + * [Certifications][Certification] that are calculated over the key user-id. Note, that the key can also be null for + * [Certifications][Certification] over the targets primary key. + */ data class CertificationSet( val issuer: CertSynopsis, val target: CertSynopsis, @@ -11,11 +22,22 @@ data class CertificationSet( companion object { + /** + * Create an empty [CertificationSet]. + * + * @param issuer the certificate that issued the [Certifications][Certification]. + * @param target the certificate that is targeted by the [Certifications][Certification]. + */ @JvmStatic fun empty(issuer: CertSynopsis, target: CertSynopsis): CertificationSet { return CertificationSet(issuer, target, HashMap()) } + /** + * Create a [CertificationSet] from a single [Certification]. + * + * @param certification certification + */ @JvmStatic fun fromCertification(certification: Certification) : CertificationSet { val set = empty(certification.issuer, certification.target) @@ -24,6 +46,12 @@ data class CertificationSet( } } + /** + * Merge the given [CertificationSet] into this. + * This method copies all [Certifications][Certification] from the other [CertificationSet] into [certifications]. + * + * @param other [CertificationSet] with the same issuer fingerprint and target fingerprint as this object. + */ fun merge(other: CertificationSet) { if (other == this) { return @@ -39,6 +67,11 @@ data class CertificationSet( } } + /** + * Add a single [Certification] into this objects [certifications]. + * + * @param certification [Certification] with the same issuer fingerprint and target fingerprint as this object. + */ fun add(certification : Certification) { require(issuer.fingerprint == certification.issuer.fingerprint) { "Issuer fingerprint mismatch." } require(target.fingerprint == certification.target.fingerprint) { "Target fingerprint mismatch." } diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Depth.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Depth.kt index c930e291..2ca59152 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Depth.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Depth.kt @@ -4,22 +4,34 @@ package org.pgpainless.wot.dijkstra.sq +/** + * Depth of a trust signature. + */ class Depth(val limit: Int?) : Comparable { companion object { + /** + * The target is trusted to an unlimited degree. + */ @JvmStatic fun unconstrained() : Depth { return Depth(null) } + /** + * The target is trusted to a limited degree. + */ @JvmStatic fun limited(limit: Int): Depth { - require(limit in 0..255) { - "Trust depth MUST be a value between 0 and 255." + require(limit in 0..254) { + "Trust depth MUST be a value between 0 and 254." } return Depth(limit) } + /** + * Deduce the trust degree automatically. + */ @JvmStatic fun auto(limit: Int): Depth { return if (limit == 255) { @@ -30,10 +42,18 @@ class Depth(val limit: Int?) : Comparable { } } + /** + * Return true, if the [Depth] is unconstrained. + */ fun isUnconstrained() : Boolean { return limit == null } + /** + * Decrease the trust depth by one and return the result. + * If the [Depth] is unconstrained, the result will still be unconstrained. + * @throws IllegalArgumentException if the [Depth] cannot be decreased any further + */ fun decrease(value : Int) : Depth { return if (isUnconstrained()) { unconstrained() @@ -46,6 +66,9 @@ class Depth(val limit: Int?) : Comparable { } } + /** + * Return the minimum [Depth] of this and the other [Depth]. + */ fun min(other: Depth) : Depth { return if (compareTo(other) <= 0) { this @@ -54,18 +77,18 @@ class Depth(val limit: Int?) : Comparable { } } - override fun compareTo(o: Depth): Int { + override fun compareTo(other: Depth): Int { return if (isUnconstrained()) { - if (o.isUnconstrained()) { + if (other.isUnconstrained()) { 0 } else { 1 } } else { - if (o.isUnconstrained()) { + if (other.isUnconstrained()) { -1 } else { - limit!!.compareTo(o.limit!!) + limit!!.compareTo(other.limit!!) } } } diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Network.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Network.kt index 23eb088f..07a2e062 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Network.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Network.kt @@ -30,11 +30,19 @@ class Network( } } + /** + * The total number of edges on the network. + * + * @return number of edges + */ val numberOfEdges: Int get() { return edges.values.sumOf { it.size } } + /** + * The total number of signatures the network comprises. + */ val numberOfSignatures: Int get() { return edges.values diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Path.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Path.kt index 1ed7cd38..59244d1f 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Path.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Path.kt @@ -6,14 +6,33 @@ package org.pgpainless.wot.dijkstra.sq import kotlin.math.min +/** + * A [Path] comprises a root [CertSynopsis], a list of edges ([Certifications][Certification]), as well as a + * residual depth. + * + * @param root root of the path + * @param edges list of edges from the root to the target + * @param residualDepth residual depth that is decreased each time another edge is appended + */ class Path( val root: CertSynopsis, val edges: MutableList, var residualDepth: Depth ) { + + /** + * Construct a [Path] only consisting of the trust root. + * The [Path] will have an empty list of edges and an unconstrained residual [Depth]. + * + * @param root trust root + */ constructor(root: CertSynopsis) : this( root, mutableListOf(), Depth.unconstrained()) + /** + * Current target of the path. + * This corresponds to the target of the last entry in the edge list. + */ val target: CertSynopsis get() { return if (edges.isEmpty()) { @@ -23,6 +42,10 @@ class Path( } } + /** + * List of [CertSynopses][CertSynopsis] (nodes) of the path. + * The first entry is the [root]. The other entries are the targets of the edges. + */ val certificates: List get() { val certs: MutableList = ArrayList() @@ -33,12 +56,23 @@ class Path( return certs } + /** + * The length of the path, counted in nodes. + * A path with a single edge between node A and B has length 2, the empty path with only a trust root has length 1. + */ val length: Int get() = edges.size + 1 + /** + * List of edges. + */ val certifications: List get() = ArrayList(edges) + /** + * Trust amount of the path. + * This corresponds to the smallest trust amount of any edge in the path. + */ val amount: Int get() = if (edges.isEmpty()) { 120 @@ -50,6 +84,13 @@ class Path( min } + /** + * Append an edge to the path and decrease the [residualDepth] of the path by 1. + * + * @throws IllegalArgumentException if the target at the end of the path is not equal to the issuer of the edge. + * @throws IllegalArgumentException if the path runs out of residual depth + * @throws IllegalArgumentException if the addition of the [Certification] would result in a cyclic path + */ fun append(certification: Certification) { require(target.fingerprint == certification.issuer.fingerprint) { "Cannot append certification to path: Path's tail is not issuer of the certification." diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Paths.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Paths.kt index 5020c061..7da2fbb9 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Paths.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/Paths.kt @@ -4,11 +4,23 @@ package org.pgpainless.wot.dijkstra.sq +/** + * List of individual [Paths][Path]. + * + * @param paths list of paths + */ class Paths(val paths: MutableList) { - constructor(): - this(mutableListOf()) + /** + * Empty collection of paths. + */ + constructor(): this(mutableListOf()) + /** + * Add a [Path] to the list. + * + * @throws IllegalArgumentException if the given amount is smaller of equal to the paths trust amount. + */ fun add(path: Path, amount: Int) { require(amount <= path.amount) { "Amount too small. TODO: Better error message" @@ -16,11 +28,18 @@ class Paths(val paths: MutableList) { paths.add(Item(path, amount)) } + /** + * The summed trust amount of all paths in this collection. + */ val amount: Int get() { return paths.sumOf { it.amount } } + /** + * @param path path + * @param amount trust amount + */ data class Item(val path: Path, val amount: Int) { } diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/ReferenceTime.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/ReferenceTime.kt index bd05ca54..1cea10ff 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/ReferenceTime.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/ReferenceTime.kt @@ -6,11 +6,21 @@ package org.pgpainless.wot.dijkstra.sq import java.util.* +/** + * Reference time for Web of Trust calculations. + */ interface ReferenceTime { + /** + * Timestamp as [Date]. + */ val timestamp: Date companion object { + + /** + * Create a [ReferenceTime] with a timestamp that corresponds to the current time. + */ @JvmStatic fun now(): ReferenceTime { val now = Date() @@ -20,6 +30,9 @@ interface ReferenceTime { } } + /** + * Create a [ReferenceTime] from the given [stamp] timestamp. + */ @JvmStatic fun timestamp(stamp: Date): ReferenceTime { return object: ReferenceTime { diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/RegexSet.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/RegexSet.kt index 8af6b95b..ce332dbb 100644 --- a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/RegexSet.kt +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/sq/RegexSet.kt @@ -6,25 +6,42 @@ package org.pgpainless.wot.dijkstra.sq import java.util.regex.Pattern +/** + * Set of regular expressions. + */ data class RegexSet(val regexStrings: Set) { companion object { + + /** + * Create a [RegexSet] from the given [List] of RegEx strings. + */ @JvmStatic fun fromExpressionList(regexList: List): RegexSet { return RegexSet(regexList.toSet()) } + /** + * Create a [RegexSet] from a single RegEx string. + */ @JvmStatic fun fromExpression(regex: String): RegexSet { return fromExpressionList(listOf(regex)) } + /** + * Create a wildcard RegEx (empty list of RegEx strings). + */ @JvmStatic fun wildcard(): RegexSet { return fromExpressionList(listOf()) } } + /** + * Return true if the given [string] matches the [RegexSet]. + * That is if at least one RegEx in the set matches the [string], or if the set represents a wildcard. + */ fun matches(string: String): Boolean { if (regexStrings.isEmpty()) { return true