diff --git a/README.md b/README.md
index e3ba552..f31ede5 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
[](https://opensource.org/licenses/BSD-3-Clause)
-[](https://kotlinlang.org/)
+[](https://kotlinlang.org/)
[](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/isgd-shorten/)
[](https://github.com/ethauvin/isgd-shorten/releases/latest)
-[](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/isgd-shorten)
+[](https://central.sonatype.com/artifact/net.thauvin.erik/isgd-shorten)
[](https://sonarcloud.io/dashboard?id=ethauvin_isgd-shorten)
[](https://github.com/ethauvin/isgd-shorten/actions/workflows/gradle.yml)
@@ -67,8 +67,31 @@ dependencies {
implementation("net.thauvin.erik:isgd-shorten:0.9.2")
}
```
-Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/isgd-shorten).
+Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://central.sonatype.com/artifact/net.thauvin.erik/isgd-shorten).
+## Java
+
+To make it easier to use the library with Java, configuration builders are available:
+
+```java
+var config = new Config.Builder()
+ .url("https://www.example.com/")
+ .shorturl("foobar")
+ .callback("test")
+ .logstats(true)
+ .format(Format.JSON)
+ .build();
+
+Isgd.shorten(config);
+```
+```java
+var config = new Config.Builder()
+ .shortUrl("https://is.gd/Pt2sET")
+ .format(Format.XML)
+ .build();
+
+Isgd.lookup(config)
+```
### Errors
An `IsgdException` is thrown when an API error occurs. The error message (text, XML or JSON) and HTTP status code can be retrieved as follows:
diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml
index f7b49af..693c365 100644
--- a/config/detekt/baseline.xml
+++ b/config/detekt/baseline.xml
@@ -5,5 +5,6 @@
LongParameterList:Isgd.kt$Isgd.Companion$( url: String, shorturl: String = "", callback: String = "", logstats: Boolean = false, format: Format = Format.SIMPLE, isVgd: Boolean = false )
MagicNumber:Isgd.kt$Isgd.Companion$200
MagicNumber:Isgd.kt$Isgd.Companion$399
+ WildcardImport:IsgdTest.kt$import assertk.assertions.*
diff --git a/src/main/kotlin/net/thauvin/erik/isgd/Config.kt b/src/main/kotlin/net/thauvin/erik/isgd/Config.kt
new file mode 100644
index 0000000..f6bcb9d
--- /dev/null
+++ b/src/main/kotlin/net/thauvin/erik/isgd/Config.kt
@@ -0,0 +1,72 @@
+/*
+ * Config.kt
+ *
+ * Copyright 2023 Erik C. Thauvin (erik@thauvin.net)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of this project nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.thauvin.erik.isgd
+
+/**
+ * Provides a builder to create/lookup an is.gd shortlink.
+ */
+class Config private constructor(
+ val url: String,
+ val shorturl: String,
+ val callback: String,
+ val logstats: Boolean,
+ val format: Format,
+ val isVgd: Boolean
+) {
+ /**
+ * Configures the parameters to create/lookup an is.gd shortlink.
+ */
+ data class Builder(
+ var url: String = "",
+ var shorturl: String = "",
+ var callback: String = "",
+ var logstats: Boolean = false,
+ var format: Format = Format.SIMPLE,
+ var isVgd: Boolean = false
+ ) {
+ fun url(url: String) = apply { this.url = url }
+ fun shorturl(shorturl: String) = apply { this.shorturl = shorturl }
+ fun callback(callback: String) = apply { this.callback = callback }
+ fun logstats(logstats: Boolean) = apply { this.logstats = logstats }
+ fun format(format: Format) = apply { this.format = format }
+ fun isVgd(isVgd: Boolean) = apply { this.isVgd = isVgd }
+
+ fun build() = Config(
+ url,
+ shorturl,
+ callback,
+ logstats,
+ format,
+ isVgd
+ )
+ }
+}
diff --git a/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt b/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt
index 27b2af7..4c6728c 100644
--- a/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt
+++ b/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt
@@ -31,7 +31,7 @@
package net.thauvin.erik.isgd
-import net.thauvin.erik.urlencoder.UrlEncoder
+import net.thauvin.erik.urlencoder.UrlEncoderUtil
import java.net.HttpURLConnection
import java.net.URL
@@ -42,7 +42,7 @@ enum class Format(val type: String) {
WEB("web"), SIMPLE("simple"), XML("xml"), JSON("json")
}
-fun String.encode(): String = UrlEncoder.encode(this)
+fun String.encode(): String = UrlEncoderUtil.encode(this)
/**
* Implements the [is.gd API](https://is.gd/developers.php).
@@ -69,6 +69,24 @@ class Isgd private constructor() {
}
/**
+ * Lookup a shortlink.
+ *
+ * See the [is.gd API](https://is.gd/apilookupreference.php).
+ */
+ @JvmStatic
+ @Throws(IsgdException::class)
+ fun lookup(config: Config): String {
+ return lookup(
+ config.shorturl,
+ config.callback,
+ config.format,
+ config.isVgd
+ )
+ }
+
+ /**
+ * Lookup a shortlink.
+ *
* See the [is.gd API](https://is.gd/apilookupreference.php).
*/
@JvmStatic
@@ -94,6 +112,26 @@ class Isgd private constructor() {
}
/**
+ * Shortens a link.
+ *
+ * See the [is.gd API](https://is.gd/apishorteningreference.php).
+ */
+ @JvmStatic
+ @Throws(IsgdException::class)
+ fun shorten(config: Config): String {
+ return shorten(
+ config.url,
+ config.shorturl,
+ config.callback,
+ config.logstats,
+ config.format,
+ config.isVgd
+ )
+ }
+
+ /**
+ * Shortens a link.
+ *
* See the [is.gd API](https://is.gd/apishorteningreference.php).
*/
@JvmStatic
diff --git a/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt b/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt
index 59ca783..e01e4ee 100644
--- a/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt
+++ b/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt
@@ -33,12 +33,7 @@ package net.thauvin.erik.isgd
import assertk.all
import assertk.assertThat
-import assertk.assertions.contains
-import assertk.assertions.isEqualTo
-import assertk.assertions.isNotNull
-import assertk.assertions.matches
-import assertk.assertions.prop
-import assertk.assertions.startsWith
+import assertk.assertions.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@@ -66,6 +61,15 @@ class IsgdTest {
}
}
+ @Test
+ fun testExceptionConfig() {
+ assertFailsWith(
+ message = "shorten(config:duplicate)",
+ exceptionClass = IsgdException::class,
+ block = { Isgd.shorten(Config.Builder().url(shortUrl).build()) }
+ )
+ }
+
@Test
fun testLookup() {
assertFailsWith(
@@ -75,15 +79,35 @@ class IsgdTest {
)
}
+ @Test
+ fun testLookupConfig() {
+ assertFailsWith(
+ message = "lookup(config:empty)",
+ exceptionClass = IllegalArgumentException::class,
+ block = { Isgd.lookup(Config.Builder().shorturl("").build()) }
+ )
+ }
+
@Test
fun testLookupDefault() {
assertEquals(url, Isgd.lookup(shortUrl))
assertEquals(url, Isgd.lookup(shortVgdUrl, isVgd = true), "lookup(isVgd)")
}
+ @Test
+ fun testLookupDefaultConfig() {
+ assertEquals(url, Isgd.lookup(Config.Builder().shorturl(shortUrl).build()), "lookup(config)")
+ assertEquals(
+ url, Isgd.lookup(
+ Config.Builder().shorturl(shortVgdUrl).isVgd(true).build()
+ ), "lookup(config:isVgd)"
+ )
+ }
+
@Test
fun testLookupJson() {
assertEquals("{ \"url\": \"$url\" }", Isgd.lookup(shortUrl, format = Format.JSON))
+
assertEquals(
"test({ \"url\": \"$url\" });",
Isgd.lookup(shortUrl, callback = "test", format = Format.JSON),
@@ -91,6 +115,20 @@ class IsgdTest {
)
}
+ @Test
+ fun testLookupJsonConfig() {
+ assertEquals(
+ "{ \"url\": \"$url\" }",
+ Isgd.lookup(Config.Builder().shorturl(shortUrl).format(Format.JSON).build()), "lookup(config)"
+ )
+
+ assertEquals(
+ "test({ \"url\": \"$url\" });",
+ Isgd.lookup(Config.Builder().shorturl(shortUrl).callback("test").format(Format.JSON).build()),
+ "lookup(config:callback)"
+ )
+ }
+
@Test
fun testLookupXml() {
assertEquals(
@@ -99,6 +137,15 @@ class IsgdTest {
)
}
+ @Test
+ fun testLookupXmlConfig() {
+ assertEquals(
+ "",
+ Isgd.lookup(Config.Builder().shorturl(shortUrl).format(Format.XML).build()),
+ "lookup(config:xml)"
+ )
+ }
+
@Test
fun testShorten() {
assertFailsWith(
@@ -114,13 +161,38 @@ class IsgdTest {
)
}
+ @Test
+ fun testShortenConfig() {
+ assertFailsWith(
+ message = "shorten(config:empty)",
+ exceptionClass = IllegalArgumentException::class,
+ block = { Isgd.shorten(Config.Builder().url("").build()) }
+ )
+
+ assertFailsWith(
+ message = "shorten(config:shorturl)",
+ exceptionClass = IsgdException::class,
+ block = { Isgd.shorten(Config.Builder(url).shorturl("test").build()) }
+ )
+ }
+
@Test
fun testShortenDefault() {
assertEquals(shortUrl, Isgd.shorten(url), "shorten(url)")
assertEquals(shortVgdUrl, Isgd.shorten(url, isVgd = true), "shorten(isVgd)")
assertThat(Isgd.shorten(url, logstats = true), "shorten(callback)").matches("https://is.gd/\\w{6}".toRegex())
+ }
-
+ @Test
+ fun testShortenDefaultConfig() {
+ assertEquals(shortUrl, Isgd.shorten(Config.Builder().url(url).build()), "shorten(config:url)")
+ assertEquals(
+ shortVgdUrl,
+ Isgd.shorten(Config.Builder().url(url).isVgd(true).build()),
+ "shorten(config:isVgd)"
+ )
+ assertThat(Isgd.shorten(Config.Builder().url(url).logstats(true).build()), "shorten(config:callback)")
+ .matches("https://is.gd/\\w{6}".toRegex())
}
@Test
@@ -133,6 +205,19 @@ class IsgdTest {
)
}
+ @Test
+ fun testShortenJsonConfig() {
+ assertEquals(
+ "{ \"shorturl\": \"$shortUrl\" }",
+ Isgd.shorten(Config.Builder().url(url).format(Format.JSON).build()), "shorten(config:json)"
+ )
+ assertEquals(
+ "test({ \"shorturl\": \"$shortUrl\" });",
+ Isgd.shorten(Config.Builder().url(url).callback("test").format(Format.JSON).build()),
+ "shorten(config:callback,json)"
+ )
+ }
+
@Test
fun testShortenXml() {
assertEquals(
@@ -142,8 +227,24 @@ class IsgdTest {
)
}
+ @Test
+ fun testShortenXmlConfig() {
+ assertEquals(
+ "" +
+ "",
+ Isgd.shorten(Config.Builder().url(url).format(Format.XML).build()),
+ "shorten(config:xml)"
+ )
+ }
+
@Test
fun testShortenWeb() {
assertThat(Isgd.shorten(url, format = Format.WEB)).contains(shortUrl)
}
+
+ @Test
+ fun testShortenWebConfig() {
+ assertThat(Isgd.shorten(Config.Builder().url(url).format(Format.WEB).build()), "shorten(config:web)")
+ .contains(shortUrl)
+ }
}