Reworked config builder.

Added parameters' documentation.
This commit is contained in:
Erik C. Thauvin 2024-05-25 20:15:32 -07:00
parent 8332db1a80
commit e6bfcdad80
Signed by: erik
GPG key ID: 776702A6A2DA330E
7 changed files with 217 additions and 58 deletions

16
.idea/misc.xml generated
View file

@ -2,20 +2,8 @@
<project version="4">
<component name="EntryPointsManager">
<pattern value="net.thauvin.erik.JokeApiBuild" method="jacoco" />
</component>
<component name="PDMPlugin">
<option name="customRuleSets">
<list>
<option value="K:\java\semver\config\pmd.xml" />
<option value="$PROJECT_DIR$/../../java/bld-generated-version/config/pmd.xml" />
<option value="$PROJECT_DIR$/../../java/bld-pitest/config/pmd.xml" />
<option value="$PROJECT_DIR$/../../java/bld-jacoco-report/config/pmd.xml" />
<option value="$PROJECT_DIR$/../../java/bld-checkstyle/config/pmd.xml" />
<option value="$PROJECT_DIR$/../../java/bld-exec/config/pmd.xml" />
<option value="$PROJECT_DIR$/../../java/bld-testng/config/pmd.xml" />
</list>
</option>
<option name="skipTestSources" value="false" />
<pattern value="net.thauvin.erik.JokeApiBuild" method="detekt" />
<pattern value="net.thauvin.erik.JokeApiBuild" method="detektBaseline" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build" />

View file

@ -1,12 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues/>
<ManuallySuppressedIssues></ManuallySuppressedIssues>
<CurrentIssues>
<ID>LongParameterList:JokeApi.kt$( amount: Int, categories: Set&lt;Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set&lt;Flag> = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false )</ID>
<ID>LongParameterList:JokeApi.kt$( categories: Set&lt;Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set&lt;Flag> = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false )</ID>
<ID>LongParameterList:JokeApi.kt$( categories: Set&lt;Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set&lt;Flag> = emptySet(), type: Type = Type.ALL, format: Format = Format.JSON, contains: String = "", idRange: IdRange = IdRange(), amount: Int = 1, safe: Boolean = false, auth: String = "" )</ID>
<ID>LongParameterList:JokeConfig.kt$JokeConfig$( val categories: Set&lt;Category>, val language: Language, val flags: Set&lt;Flag>, val type: Type, val format: Format, val contains: String, val idRange: IdRange, val amount: Int, val safe: Boolean, val splitNewLine: Boolean, val auth: String )</ID>
<ID>LongParameterList:JokeException.kt$JokeException$( val internalError: Boolean, val code: Int, message: String, val causedBy: List&lt;String>, val additionalInfo: String, val timestamp: Long, cause: Throwable? = null )</ID>
<ID>LongParameterList:JokeApi.kt$( amount: Int, categories: Set&lt;Category&gt; = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set&lt;Flag&gt; = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false )</ID>
<ID>LongParameterList:JokeApi.kt$( categories: Set&lt;Category&gt; = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set&lt;Flag&gt; = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false )</ID>
<ID>LongParameterList:JokeApi.kt$( categories: Set&lt;Category&gt; = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set&lt;Flag&gt; = emptySet(), type: Type = Type.ALL, format: Format = Format.JSON, contains: String = "", idRange: IdRange = IdRange(), amount: Int = 1, safe: Boolean = false, auth: String = "" )</ID>
<ID>LongParameterList:JokeConfig.kt$JokeConfig$( val categories: Set&lt;Category&gt;, val language: Language, val flags: Set&lt;Flag&gt;, val type: Type, val format: Format, val contains: String, val idRange: IdRange, val amount: Int, val safe: Boolean, val splitNewLine: Boolean, val auth: String )</ID>
<ID>LongParameterList:JokeConfig.kt$JokeConfig$( var categories: Set&lt;Category&gt; = setOf(Category.ANY), var lang: Language = Language.EN, var blacklistFlags: Set&lt;Flag&gt; = emptySet(), var type: Type = Type.ALL, var format: Format = Format.JSON, var contains: String = "", var idRange: IdRange = IdRange(), var amount: Int = 1, var safe: Boolean = false, var splitNewLine: Boolean = false, var auth: String = "" )</ID>
<ID>LongParameterList:JokeException.kt$JokeException$( val internalError: Boolean, val code: Int, message: String, val causedBy: List&lt;String&gt;, val additionalInfo: String, val timestamp: Long, cause: Throwable? = null )</ID>
<ID>MagicNumber:JokeUtil.kt$200</ID>
<ID>MagicNumber:JokeUtil.kt$399</ID>
<ID>MagicNumber:JokeUtil.kt$400</ID>

View file

@ -18,7 +18,7 @@
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.9.24</version>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>

View file

@ -101,8 +101,8 @@ object JokeApi {
fun getRawJokes(config: JokeConfig): String {
return rawJokes(
categories = config.categories,
lang = config.language,
blacklistFlags = config.flags,
lang = config.lang,
blacklistFlags = config.blacklistFlags,
type = config.type,
format = config.format,
contains = config.contains,
@ -124,8 +124,8 @@ object JokeApi {
fun joke(config: JokeConfig = JokeConfig.Builder().build()): Joke {
return joke(
categories = config.categories,
lang = config.language,
blacklistFlags = config.flags,
lang = config.lang,
blacklistFlags = config.blacklistFlags,
type = config.type,
contains = config.contains,
idRange = config.idRange,
@ -145,8 +145,8 @@ object JokeApi {
fun jokes(config: JokeConfig): Array<Joke> {
return jokes(
categories = config.categories,
lang = config.language,
blacklistFlags = config.flags,
lang = config.lang,
blacklistFlags = config.blacklistFlags,
type = config.type,
contains = config.contains,
idRange = config.idRange,
@ -164,6 +164,32 @@ object JokeApi {
*
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
*
* @param categories JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is
* about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] category, dark
* humor will be in the [Category.DARK] category and so on. If you want jokes from all categories, you can instead use
* [Category.ANY], which will make JokeAPI randomly choose a category.
* @param lang There are two types of languages; system languages and joke languages. Both are separate from each other.
* All system messages like errors can have a certain system language, while jokes can only have a joke language.
* It is possible, that system languages don't yet exist for your language while jokes already do.
* If no suitable system language is found, JokeAPI will default to English.
* @param blacklistFlags Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be
* set on each joke, and they tell you something about the offensiveness of each joke.
* @param type Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type
* [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are separated
* because you might want to present the users the delivery after a timeout or in a different section of the UI.
* A joke of type [Type.SINGLE] only has a single string, which is the entire joke.
* @param contains If the search string filter is used, only jokes that contain the specified string will be returned.
* @param idRange If this filter is used, you will only get jokes that are within the provided range of IDs.
* You don't necessarily need to provide an ID range though, a single ID will work just fine as well.
* For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range of 5 will
* mean you will only get the 6th joke.
* @param safe Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for
* everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, its
* references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally marked as
* unsafe.
* @param auth JokeAPI has a way of whitelisting certain clients. This is achieved through an API token.
* At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a business
* and need more than 120 requests per minute.
* @param splitNewLine Split newline within [Type.SINGLE] joke.
*/
fun joke(
@ -201,7 +227,35 @@ fun joke(
*
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
*
* @param amount The required amount of jokes to return.
* @param amount This filter allows you to set a certain amount of jokes to receive in a single call. Setting the
* filter to an invalid number will result in the API defaulting to serving a single joke. Setting it to a number
* larger than 10 will make JokeAPI default to the maximum (10).
* @param categories JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is
* about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] category, dark
* humor will be in the [Category.DARK] category and so on. If you want jokes from all categories, you can instead use
* [Category.ANY], which will make JokeAPI randomly choose a category.
* @param lang There are two types of languages; system languages and joke languages. Both are separate from each other.
* All system messages like errors can have a certain system language, while jokes can only have a joke language.
* It is possible, that system languages don't yet exist for your language while jokes already do.
* If no suitable system language is found, JokeAPI will default to English.
* @param blacklistFlags Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be
* set on each joke, and they tell you something about the offensiveness of each joke.
* @param type Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type
* [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are separated
* because you might want to present the users the delivery after a timeout or in a different section of the UI.
* A joke of type [Type.SINGLE] only has a single string, which is the entire joke.
* @param contains If the search string filter is used, only jokes that contain the specified string will be returned.
* @param idRange If this filter is used, you will only get jokes that are within the provided range of IDs.
* You don't necessarily need to provide an ID range though, a single ID will work just fine as well.
* For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range of 5 will
* mean you will only get the 6th joke.
* @param safe Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for
* everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, its
* references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally marked as
* unsafe.
* @param auth JokeAPI has a way of whitelisting certain clients. This is achieved through an API token.
* At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a business
* and need more than 120 requests per minute.
* @param splitNewLine Split newline within [Type.SINGLE] joke.
*/
fun jokes(
@ -244,7 +298,40 @@ fun jokes(
/**
* Returns one or more jokes.
*
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
* See the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
*
* @param categories JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is
* about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] category, dark
* humor will be in the [Category.DARK] category and so on. If you want jokes from all categories, you can instead use
* [Category.ANY], which will make JokeAPI randomly choose a category.
* @param lang There are two types of languages; system languages and joke languages. Both are separate from each other.
* All system messages like errors can have a certain system language, while jokes can only have a joke language.
* It is possible, that system languages don't yet exist for your language while jokes already do.
* If no suitable system language is found, JokeAPI will default to English.
* @param blacklistFlags Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be
* set on each joke, and they tell you something about the offensiveness of each joke.
* @param type Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type
* [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are separated
* because you might want to present the users the delivery after a timeout or in a different section of the UI.
* A joke of type [Type.SINGLE] only has a single string, which is the entire joke.
* @param contains If the search string filter is used, only jokes that contain the specified string will be returned.
* @param format Response Formats (or just "Formats") are a way to get your data in a different file format.
* Maybe your environment or language doesn't support JSON natively. In that case, JokeAPI is able to convert the
* JSON-formatted joke to a different format for you.
* @param idRange If this filter is used, you will only get jokes that are within the provided range of IDs.
* You don't necessarily need to provide an ID range though, a single ID will work just fine as well.
* For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range of 5 will
* mean you will only get the 6th joke.
* @param amount This filter allows you to set a certain amount of jokes to receive in a single call. Setting the
* filter to an invalid number will result in the API defaulting to serving a single joke. Setting it to a number
* larger than 10 will make JokeAPI default to the maximum (10).
* @param safe Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for
* everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, its
* references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally marked as
* unsafe.
* @param auth JokeAPI has a way of whitelisting certain clients. This is achieved through an API token.
* At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a business
* and need more than 120 requests per minute.
*/
fun rawJokes(
categories: Set<Category> = setOf(Category.ANY),

View file

@ -39,19 +39,33 @@ import net.thauvin.erik.jokeapi.models.*
*
* Use the [Builder] to create a new configuration.
*/
class JokeConfig private constructor(
val categories: Set<Category>,
val language: Language,
val flags: Set<Flag>,
val type: Type,
val format: Format,
val contains: String,
val idRange: IdRange,
val amount: Int,
val safe: Boolean,
val splitNewLine: Boolean,
val auth: String
class JokeConfig(
var categories: Set<Category> = setOf(Category.ANY),
var lang: Language = Language.EN,
var blacklistFlags: Set<Flag> = emptySet(),
var type: Type = Type.ALL,
var format: Format = Format.JSON,
var contains: String = "",
var idRange: IdRange = IdRange(),
var amount: Int = 1,
var safe: Boolean = false,
var splitNewLine: Boolean = false,
var auth: String = ""
) {
constructor(builder: Builder) : this() {
categories = builder.categories
lang = builder.lang
blacklistFlags = builder.blacklistFlags
type = builder.type
format = builder.format
contains = "${builder.safe}:${builder.splitNewLine}"
idRange = builder.idRange
amount = builder.amount
safe = builder.safe
splitNewLine = builder.splitNewLine
auth = builder.auth
}
/**
* [Builds][build] a new configuration.
*
@ -72,20 +86,86 @@ class JokeConfig private constructor(
var splitNewLine: Boolean = false,
var auth: String = ""
) {
fun categories(categories: Set<Category>) = apply { this.categories = categories }
fun lang(language: Language) = apply { lang = language }
fun blacklistFlags(flags: Set<Flag>) = apply { blacklistFlags = flags }
fun type(type: Type) = apply { this.type = type }
fun format(format: Format) = apply { this.format = format }
fun contains(search: String) = apply { contains = search }
fun idRange(idRange: IdRange) = apply { this.idRange = idRange }
fun amount(amount: Int) = apply { this.amount = amount }
fun safe(safe: Boolean) = apply { this.safe = safe }
fun splitNewLine(splitNewLine: Boolean) = apply { this.splitNewLine = splitNewLine }
fun auth(auth: String) = apply { this.auth = auth }
/**
* JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is
* about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING]
* category, dark humor will be in the [Category.DARK] category and so on. If you want jokes from all
* categories, you can instead use [Category.ANY], which will make JokeAPI randomly choose a category.
*/
fun categories(categories: Set<Category>): Builder = apply { this.categories = categories }
fun build() = JokeConfig(
categories, lang, blacklistFlags, type, format, contains, idRange, amount, safe, splitNewLine, auth
)
/**
* There are two types of languages; system languages and joke languages. Both are separate from each other.
* All system messages like errors can have a certain system language, while jokes can only have a joke
* language. It is possible, that system languages don't yet exist for your language while jokes already do.
* If no suitable system language is found, JokeAPI will default to English.
*/
fun lang(language: Language): Builder = apply { lang = language }
/**
* Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be
* set on each joke, and they tell you something about the offensiveness of each joke.
*/
fun blacklistFlags(flags: Set<Flag>): Builder = apply { blacklistFlags = flags }
/**
* Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type
* [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are
* separated because you might want to present the users the delivery after a timeout or in a different section
* of the UI. A joke of type [Type.SINGLE] only has a single string, which is the entire joke.
*/
fun type(type: Type): Builder = apply { this.type = type }
/**
* Response Formats (or just "Formats") are a way to get your data in a different file format.
* Maybe your environment or language doesn't support JSON natively. In that case, JokeAPI is able to convert
* the JSON-formatted joke to a different format for you.
*/
fun format(format: Format): Builder = apply { this.format = format }
/**
* If the search string filter is used, only jokes that contain the specified string will be returned.
*/
fun contains(search: String): Builder = apply { contains = search }
/**
* If this filter is used, you will only get jokes that are within the provided range of IDs.
* You don't necessarily need to provide an ID range though, a single ID will work just fine as well.
* For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range
* of 5 will mean you will only get the 6th joke.
*/
fun idRange(idRange: IdRange): Builder = apply { this.idRange = idRange }
/**
* This filter allows you to set a certain amount of jokes to receive in a single call. Setting the
* filter to an invalid number will result in the API defaulting to serving a single joke. Setting it to a
* number larger than 10 will make JokeAPI default to the maximum (10).
*/
fun amount(amount: Int): Builder = apply { this.amount = amount }
/**
* Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for
* everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language,
* its references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally
* marked as unsafe.
*/
fun safe(safe: Boolean): Builder = apply { this.safe = safe }
/**
* Split newline within [Type.SINGLE] joke.
*/
fun splitNewLine(splitNewLine: Boolean): Builder = apply { this.splitNewLine = splitNewLine }
/**
* JokeAPI has a way of whitelisting certain clients. This is achieved through an API token.
* At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a
* business and need more than 120 requests per minute.
*/
fun auth(auth: String): Builder = apply { this.auth = auth }
/**
* Builds a new comment configuration.
*/
fun build() = JokeConfig(this)
}
}

View file

@ -42,6 +42,9 @@ import java.net.HttpURLConnection
import java.net.URL
import java.util.logging.Level
/**
* Fetch a URL.
*/
internal fun fetchUrl(url: String, auth: String = ""): String {
if (JokeApi.logger.isLoggable(Level.FINE)) {
JokeApi.logger.fine(url)

View file

@ -154,8 +154,8 @@ internal class JokeConfigTest {
}.build()
assertThat(config, "config").all {
prop(JokeConfig::categories).isEqualTo(categories)
prop(JokeConfig::language).isEqualTo(language)
prop(JokeConfig::flags).isEqualTo(flags)
prop(JokeConfig::lang).isEqualTo(language)
prop(JokeConfig::blacklistFlags).isEqualTo(flags)
prop(JokeConfig::type).isEqualTo(type)
prop(JokeConfig::format).isEqualTo(format)
prop(JokeConfig::contains).isEqualTo(search)