Skip to content

Commit fc2f3bc

Browse files
committed
fix spotify URIs and remove URI deserialization
1 parent 7ea34b3 commit fc2f3bc

File tree

4 files changed

+60
-96
lines changed

4 files changed

+60
-96
lines changed

build.gradle.kts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
import org.jetbrains.dokka.gradle.DokkaTask
23
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
34

@@ -14,7 +15,7 @@ plugins {
1415
}
1516

1617
group = "com.adamratzman"
17-
version = "3.0.0-rc.3"
18+
version = "3.0.0-rc.5"
1819

1920
java {
2021
withSourcesJar()
@@ -34,9 +35,9 @@ kotlin {
3435
targets {
3536
sourceSets {
3637
val coroutineVersion = "1.3.2"
37-
val serializationVersion = "0.13.0"
38+
val serializationVersion = "0.14.0"
3839
val spekVersion = "2.0.8"
39-
val ktorVersion = "1.2.5"
40+
val ktorVersion = "1.2.6"
4041

4142
val commonMain by getting {
4243
dependencies {
@@ -123,6 +124,7 @@ nexusStaging {
123124
packageGroup = "com.adamratzman"
124125
}
125126

127+
126128
publishing {
127129
publications {
128130
val jvm by getting(MavenPublication::class) {
@@ -258,4 +260,4 @@ tasks {
258260
dependsOn.add(dokka)
259261
dependsOn.add("publishJvmPublicationToNexusRepository")
260262
}
261-
}
263+
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
#Sat Nov 30 21:26:10 EST 2019
2+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
13
distributionBase=GRADLE_USER_HOME
24
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
4-
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6+
zipStoreBase=GRADLE_USER_HOME

src/commonMain/kotlin/com.adamratzman.spotify/models/SpotifyUris.kt

Lines changed: 32 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
/* Spotify Web API - Kotlin Wrapper; MIT License, 2019; Original author: Adam Ratzman */
22
package com.adamratzman.spotify.models
33

4-
import kotlinx.serialization.Decoder
5-
import kotlinx.serialization.Encoder
6-
import kotlinx.serialization.KSerializer
7-
import kotlinx.serialization.SerialDescriptor
84
import kotlinx.serialization.Serializable
95
import kotlinx.serialization.Serializer
10-
import kotlinx.serialization.internal.StringDescriptor
6+
import kotlinx.serialization.Transient
117

128
private fun String.matchType(type: String): String? {
139
val typeRegex = "^spotify:(?:.*:)*$type:([^:]+)(?::.*)*$|^([^:]+)$".toRegex()
@@ -29,20 +25,14 @@ private fun String.remove(type: String): String {
2925
throw SpotifyUriException("Illegal Spotify ID/URI: '$this' isn't convertible to '$type' id")
3026
}
3127

32-
private class SimpleUriSerializer<T : SpotifyUri>(val ctor: (String) -> T) : KSerializer<T> {
33-
override val descriptor: SerialDescriptor = StringDescriptor
34-
override fun deserialize(decoder: Decoder): T = ctor(decoder.decodeString())
35-
override fun serialize(encoder: Encoder, obj: T) = encoder.encodeString(obj.uri)
36-
}
37-
3828
/**
3929
* Represents a Spotify URI, parsed from either a Spotify ID or taken from an endpoint.
4030
*
4131
* @property uri retrieve this URI as a string
4232
* @property id representation of this uri as an id
4333
*/
4434
@Serializable
45-
sealed class SpotifyUri(val input: String, type: String) {
35+
sealed class SpotifyUri(val input: String, val type: String) {
4636
val uri: String
4737
val id: String
4838

@@ -54,7 +44,7 @@ sealed class SpotifyUri(val input: String, type: String) {
5444
}
5545

5646
override fun equals(other: Any?): Boolean {
57-
val spotifyUri = other as? SpotifyUri ?: return false
47+
val spotifyUri = other as? SpotifyUri ?: return (other as? String)?.let { this.uri == it } ?: false
5848
return spotifyUri.uri == this.uri
5949
}
6050

@@ -68,12 +58,7 @@ sealed class SpotifyUri(val input: String, type: String) {
6858
return "SpotifyUri($uri)"
6959
}
7060

71-
@Serializer(forClass = SpotifyUri::class)
72-
companion object : KSerializer<SpotifyUri> {
73-
override val descriptor: SerialDescriptor = StringDescriptor
74-
override fun deserialize(decoder: Decoder): SpotifyUri = SpotifyUri(decoder.decodeString())
75-
override fun serialize(encoder: Encoder, obj: SpotifyUri) = encoder.encodeString(obj.uri)
76-
61+
companion object {
7762
/**
7863
* This function safely instantiates a SpotifyUri from given constructor.
7964
* */
@@ -89,9 +74,12 @@ sealed class SpotifyUri(val input: String, type: String) {
8974
* Creates a abstract SpotifyUri of given input. Doesn't allow ambiguity by disallowing creation by id.
9075
* */
9176
operator fun invoke(input: String): SpotifyUri {
92-
val constructors = listOf(::AlbumUri, ::ArtistUri, TrackUri.Companion::invoke, ::UserUri, ::PlaylistUri)
77+
val constructors = listOf(::AlbumUri, ::ArtistUri, ::LocalTrackUri, ::PlaylistUri, ::SpotifyTrackUri, ::UserUri)
9378
for (ctor in constructors) {
94-
safeInitiate(input, ctor)?.takeIf { it.uri == input }?.also { return it }
79+
safeInitiate(input, ctor)?.takeIf {
80+
@Suppress("ReplaceCallWithBinaryOperator")
81+
it.equals(input)
82+
}?.also { return it }
9583
}
9684

9785
throw SpotifyUriException("Illegal Spotify ID/URI: '$input' isn't convertible to any arbitrary id")
@@ -129,10 +117,7 @@ sealed class SpotifyUri(val input: String, type: String) {
129117
* Represents a Spotify **Album** URI, parsed from either a Spotify ID or taken from an endpoint.
130118
*/
131119
@Serializable
132-
class AlbumUri(input: String) : SpotifyUri(input, "album") {
133-
@Serializer(forClass = AlbumUri::class)
134-
companion object : KSerializer<AlbumUri> by SimpleUriSerializer(::AlbumUri)
135-
}
120+
class AlbumUri(@Transient private val _input: String = TRANSIENT_EMPTY_STRING) : SpotifyUri(_input, "album")
136121

137122
@Deprecated("renamed", ReplaceWith("AlbumUri", "com.adamratzman.spotify.models.AlbumUri"))
138123
typealias AlbumURI = AlbumUri
@@ -141,22 +126,15 @@ typealias AlbumURI = AlbumUri
141126
* Represents a Spotify **Artist** URI, parsed from either a Spotify ID or taken from an endpoint.
142127
*/
143128
@Serializable
144-
class ArtistUri(input: String) : SpotifyUri(input, "artist") {
145-
@Serializer(forClass = ArtistUri::class)
146-
companion object : KSerializer<ArtistUri> by SimpleUriSerializer(::ArtistUri)
147-
}
148-
129+
class ArtistUri(@Transient private val _input: String = TRANSIENT_EMPTY_STRING) : SpotifyUri(_input, "artist")
149130
@Deprecated("renamed", ReplaceWith("ArtistUri", "com.adamratzman.spotify.models.ArtistUri"))
150131
typealias ArtistURI = ArtistUri
151132

152133
/**
153134
* Represents a Spotify **User** URI, parsed from either a Spotify ID or taken from an endpoint.
154135
*/
155136
@Serializable
156-
class UserUri(input: String) : SpotifyUri(input, "user") {
157-
@Serializer(forClass = UserUri::class)
158-
companion object : KSerializer<UserUri> by SimpleUriSerializer(::UserUri)
159-
}
137+
class UserUri(@Transient private val _input: String = TRANSIENT_EMPTY_STRING) : SpotifyUri(_input, "user")
160138

161139
@Deprecated("renamed", ReplaceWith("UserUri", "com.adamratzman.spotify.models.UserUri"))
162140
typealias UserURI = UserUri
@@ -165,9 +143,17 @@ typealias UserURI = UserUri
165143
* Represents a Spotify **Playlist** URI, parsed from either a Spotify ID or taken from an endpoint.
166144
*/
167145
@Serializable
168-
class PlaylistUri(input: String) : SpotifyUri(input, "playlist") {
169-
@Serializer(forClass = PlaylistUri::class)
170-
companion object : KSerializer<PlaylistUri> by SimpleUriSerializer(::PlaylistUri)
146+
class PlaylistUri(@Transient private val _input: String = TRANSIENT_EMPTY_STRING) : SpotifyUri(_input, "playlist") {
147+
override fun equals(other: Any?): Boolean {
148+
val spotifyUri = other as? SpotifyUri ?: return (other as? String)?.endsWith(this.uri.removePrefix("spotify")) ?: false
149+
return spotifyUri.uri == this.uri
150+
}
151+
152+
override fun hashCode(): Int {
153+
var result = super.hashCode()
154+
result = 31 * result + _input.hashCode()
155+
return result
156+
}
171157
}
172158

173159
@Deprecated("renamed", ReplaceWith("PlaylistUri", "com.adamratzman.spotify.models.PlaylistUri"))
@@ -178,13 +164,14 @@ typealias PlaylistURI = PlaylistUri
178164
* from an endpoint
179165
* */
180166
@Serializable
181-
sealed class TrackUri(input: String, type: String) : SpotifyUri(input, type) {
182-
@Serializer(forClass = TrackUri::class)
183-
companion object : KSerializer<TrackUri> {
184-
override val descriptor: SerialDescriptor = StringDescriptor
185-
override fun deserialize(decoder: Decoder): TrackUri = TrackUri(decoder.decodeString())
186-
override fun serialize(encoder: Encoder, obj: TrackUri) = encoder.encodeString(obj.uri)
167+
sealed class TrackUri(
168+
@Transient private val _input: String = TRANSIENT_EMPTY_STRING,
169+
@Transient private val _type: String = TRANSIENT_EMPTY_STRING
170+
) :
171+
SpotifyUri(_input, _type) {
187172

173+
@Serializer(forClass = TrackUri::class)
174+
companion object {
188175
/**
189176
* Creates a abstract TrackURI of given input. Prefers SpotifyTrackUri if the input is ambiguous.
190177
* */
@@ -205,19 +192,13 @@ typealias TrackURI = TrackUri
205192
* Represents a Spotify **Track** URI, parsed from either a Spotify ID or taken from an endpoint.
206193
*/
207194
@Serializable
208-
class SpotifyTrackUri(input: String) : TrackUri(input, "track") {
209-
@Serializer(forClass = SpotifyTrackUri::class)
210-
companion object : KSerializer<SpotifyTrackUri> by SimpleUriSerializer(::SpotifyTrackUri)
211-
}
195+
class SpotifyTrackUri(@Transient private val _input: String = TRANSIENT_EMPTY_STRING) : TrackUri(_input, "track")
212196

213197
/**
214198
* Represents a Spotify **local track** URI
215199
*/
216200
@Serializable
217-
class LocalTrackUri(input: String) : TrackUri(input, "local") {
218-
@Serializer(forClass = LocalTrackUri::class)
219-
companion object : KSerializer<LocalTrackUri> by SimpleUriSerializer(::LocalTrackUri)
220-
}
201+
class LocalTrackUri(@Transient private val _input: String = TRANSIENT_EMPTY_STRING) : TrackUri(_input, "local")
221202

222203
@Deprecated("renamed", ReplaceWith("LocalTrackUri", "com.adamratzman.spotify.models.LocalTrackUri"))
223204
typealias LocalTrackURI = LocalTrackUri

src/commonTest/kotlin/com.adamratzman/spotify/utilities/UrisTests.kt

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@ import com.adamratzman.spotify.models.SpotifyUri
1010
import com.adamratzman.spotify.models.SpotifyUriException
1111
import com.adamratzman.spotify.models.TrackUri
1212
import com.adamratzman.spotify.models.UserUri
13+
import org.spekframework.spek2.Spek
14+
import org.spekframework.spek2.style.specification.describe
1315
import kotlin.test.assertEquals
1416
import kotlin.test.assertFailsWith
1517
import kotlin.test.assertFalse
1618
import kotlin.test.assertTrue
17-
import kotlinx.serialization.json.Json
18-
import kotlinx.serialization.json.JsonConfiguration
19-
import org.spekframework.spek2.Spek
20-
import org.spekframework.spek2.style.specification.describe
2119

2220
class UrisTests : Spek({
2321
describe("Uris tests") {
@@ -186,6 +184,16 @@ class UrisTests : Spek({
186184
UserUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83").uri
187185
)
188186

187+
assertEquals(
188+
"spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83",
189+
SpotifyUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83").uri
190+
)
191+
192+
assertEquals(
193+
UserUri::class,
194+
SpotifyUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83")::class
195+
)
196+
189197
assertEquals(
190198
"7r7uq6qxa4ymx3wnjd9mm6i83",
191199
UserUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83").id
@@ -255,7 +263,12 @@ class UrisTests : Spek({
255263

256264
assertEquals(
257265
"spotify:playlist:66wcLiS5R50akaQ3onDyZd",
258-
PlaylistUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83:playlist:66wcLiS5R50akaQ3onDyZd").uri
266+
SpotifyUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83:playlist:66wcLiS5R50akaQ3onDyZd").uri
267+
)
268+
269+
assertEquals(
270+
PlaylistUri::class,
271+
SpotifyUri("spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83:playlist:66wcLiS5R50akaQ3onDyZd")::class
259272
)
260273

261274
assertEquals(
@@ -349,40 +362,7 @@ class UrisTests : Spek({
349362
}
350363
}
351364
}
352-
describe("Uri serialization test") {
353-
val json = Json(JsonConfiguration.Stable)
354-
it("create UserUri from json by using SpotifyUri.serializer()") {
355-
val spotifyUri: SpotifyUri =
356-
json.parse(SpotifyUri.serializer(), "\"spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83\"")
357-
assertEquals(
358-
UserUri::class,
359-
spotifyUri::class
360-
)
361-
assertEquals(
362-
"spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83",
363-
spotifyUri.uri
364-
)
365-
}
366-
it("create UserUri from json by using UserUri.serializer()") {
367-
val userUri = json.parse(UserUri.serializer(), "\"spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83\"")
368-
assertEquals(
369-
"spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83",
370-
userUri.uri
371-
)
372-
}
373-
it("try creating UserUri from json with id by using SpotifyUri.serializer()") {
374-
assertFailsWith<SpotifyUriException> {
375-
json.parse(SpotifyUri.serializer(), "\"7r7uq6qxa4ymx3wnjd9mm6i83\"")
376-
}
377-
}
378-
it("create UserUri from json with id by using UserUri.serializer()") {
379-
val userUri = json.parse(UserUri.serializer(), "\"7r7uq6qxa4ymx3wnjd9mm6i83\"")
380-
assertEquals(
381-
"spotify:user:7r7uq6qxa4ymx3wnjd9mm6i83",
382-
userUri.uri
383-
)
384-
}
385-
}
365+
386366
describe("Uri types test") {
387367
it("test user uri string is a UserUri") {
388368
assertTrue {

0 commit comments

Comments
 (0)