Skip to content

Commit c6cffd6

Browse files
author
Adrian Tosca
committed
add isId convenience method
1 parent 556b534 commit c6cffd6

File tree

4 files changed

+125
-9
lines changed

4 files changed

+125
-9
lines changed

README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# typeid-kotlin
22
![Build Status](https://github.com/aleris/typeid-kotlin/actions/workflows/build-on-push.yml/badge.svg)
3-
![Current Version](https://img.shields.io/badge/Version-0.0.14-blue)
3+
![Current Version](https://img.shields.io/badge/Version-0.0.15-blue)
44

55

66
## A Kotlin implementation of [TypeID](https://github.com/jetpack-io/typeid).
@@ -25,14 +25,14 @@ To use with Maven:
2525
<dependency>
2626
<groupId>earth.adi</groupId>
2727
<artifactId>typeid-kotlin</artifactId>
28-
<version>0.0.14</version>
28+
<version>0.0.15</version>
2929
</dependency>
3030
```
3131

3232
To use via Gradle:
3333

3434
```kotlin
35-
implementation("earth.adi:typeid-kotlin:0.0.14")
35+
implementation("earth.adi:typeid-kotlin:0.0.15")
3636
```
3737

3838

@@ -199,6 +199,19 @@ These approaches are much faster when the input is untrusted and can result in l
199199
(see [Benchmarks](#benchmarks)).
200200

201201

202+
### isId
203+
204+
Check if a string is a valid id of the given type:
205+
206+
```kotlin
207+
val isUserId = typeId.isId<UserId>("user_01h455vb4pex5vsknk084sn02q")
208+
```
209+
210+
Is a convenience method that uses `parseToValidated` and returns a boolean.
211+
It can be used to check if a string is a valid id of an expected type
212+
as it returns `false` if the id is valid but of a different type.
213+
214+
202215
### Type safety
203216

204217
At its base, a `typeid` is just a prefix followed by `_` and an encoded UUID
@@ -293,7 +306,7 @@ for Java, Kotlin (kotlinx.serialization), and Jackson.
293306

294307
#### Kotlin (kotlinx.serialization)
295308

296-
Both [Id] and [RawId] have `@Serializable` and can be used with `kotlinx.serialization`.
309+
Both `Id` and `RawId` have `@Serializable` and can be used with `kotlinx.serialization`.
297310
You need to include the actual serialization dependency in your project.
298311

299312
For example, with CBOR:

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ plugins {
1515

1616
group = "earth.adi"
1717

18-
version = "0.0.14"
18+
version = "0.0.15"
1919

2020
repositories { mavenCentral() }
2121

src/main/kotlin/earth/adi/typeid/TypeId.kt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,30 @@ class TypeId(private var uuidGenerator: Supplier<UUID>) {
212212
return factory.parseToValidatedRaw(id)
213213
}
214214

215+
/**
216+
* Checks if the given string is a valid [Id] for the inferred entity type.
217+
*
218+
* @param TEntity the inferred entity type
219+
* @param id the string typeid representation of the [Id]
220+
* @return `true` if the string is a valid [Id], `false` otherwise
221+
*/
222+
inline fun <reified TEntity> isId(id: String): Boolean {
223+
return isId(TEntity::class.java, id)
224+
}
225+
226+
/**
227+
* Checks if the given string is a valid [Id] for the given entity type.
228+
*
229+
* @param TEntity the entity type
230+
* @param entityType the entity type class
231+
* @param id the string typeid representation of the [Id]
232+
* @return `true` if the string is a valid [Id], `false` otherwise
233+
*/
234+
fun <TEntity> isId(entityType: Class<out TEntity>, id: String): Boolean {
235+
val validated = parseToValidated(entityType, id)
236+
return validated.map { true }.orElse(false)
237+
}
238+
215239
/**
216240
* Sets a custom UUID generator for generating new UUIDs. This replaces the default UUIDv7
217241
* generator.
@@ -448,6 +472,29 @@ class TypeId(private var uuidGenerator: Supplier<UUID>) {
448472
return DEFAULT.parseToValidated(entityType, id)
449473
}
450474

475+
/**
476+
* Checks if the given string is a valid [Id] for the inferred entity type.
477+
*
478+
* @param TEntity the inferred entity type
479+
* @param id the string typeid representation of the [Id]
480+
* @return `true` if the string is a valid [Id], `false` otherwise
481+
*/
482+
inline fun <reified TEntity> isId(id: String): Boolean {
483+
return DEFAULT.isId<TEntity>(id)
484+
}
485+
486+
/**
487+
* Checks if the given string is a valid [Id] for the given entity type.
488+
*
489+
* @param TEntity the entity type
490+
* @param entityType the entity type class
491+
* @param id the string typeid representation of the [Id]
492+
* @return `true` if the string is a valid [Id], `false` otherwise
493+
*/
494+
fun <TEntity> isId(entityType: Class<out TEntity>, id: String): Boolean {
495+
return DEFAULT.isId(entityType, id)
496+
}
497+
451498
/**
452499
* Parses an untyped [RawId] from a string and returns a [Validated] result. If the string is
453500
* valid a [Validated.Valid] result is returned, otherwise it returns an [Validated.Invalid].

src/test/kotlin/earth/adi/typeid/TypeIdTest.kt

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,24 @@ class TypeIdTest {
9898
Validated.Invalid<User>("Id with empty prefix must not contain the separator '_'"))
9999
}
100100

101+
@Test
102+
fun `default isId true`() {
103+
val organizationId = TypeId.randomId<Organization>()
104+
assertThat(TypeId.isId<Organization>(organizationId.toString())).isTrue()
105+
}
106+
107+
@Test
108+
fun `default isId true with entity type`() {
109+
val organizationId = TypeId.randomId<Organization>()
110+
assertThat(TypeId.isId(Organization::class.java, organizationId.toString())).isTrue()
111+
}
112+
113+
@Test
114+
fun `default isId false`() {
115+
val organizationId = TypeId.randomId<Organization>()
116+
assertThat(TypeId.isId<User>(organizationId.toString())).isFalse()
117+
}
118+
101119
@Test
102120
fun `default parseToValidated with entity type`() {
103121
val userId = TypeId.randomId<User>()
@@ -159,28 +177,37 @@ class TypeIdTest {
159177
}
160178

161179
@Test
162-
fun `tryParse valid`() {
180+
fun `parse valid`() {
163181
val organizationId = typeId.randomId<Organization>()
164182
val parsedUserId = typeId.parse<Organization>(organizationId.toString())
165183
assertThat(parsedUserId).isEqualTo(organizationId)
166184
}
167185

168186
@Test
169-
fun `tryParse invalid`() {
187+
fun `parse invalid`() {
170188
assertThatThrownBy { typeId.parse<Organization>("_") }
171189
.isInstanceOf(IllegalArgumentException::class.java)
172190
}
173191

174192
@Test
175-
fun `parse valid`() {
193+
fun `parseToValidated valid`() {
176194
val organizationId = typeId.randomId<Organization>()
177195
val parsedOrganizationId = typeId.parseToValidated<Organization>(organizationId.toString())
178196
assertThat(parsedOrganizationId).isInstanceOf(Validated.Valid::class.java)
179197
assertThat(parsedOrganizationId).isEqualTo(Validated.Valid(organizationId))
180198
}
181199

182200
@Test
183-
fun `parse invalid`() {
201+
fun `parseToValidated valid with entity type`() {
202+
val organizationId = typeId.randomId<Organization>()
203+
val parsedOrganizationId =
204+
typeId.parseToValidated(Organization::class.java, organizationId.toString())
205+
assertThat(parsedOrganizationId).isInstanceOf(Validated.Valid::class.java)
206+
assertThat(parsedOrganizationId).isEqualTo(Validated.Valid(organizationId))
207+
}
208+
209+
@Test
210+
fun `parseToValidated invalid`() {
184211
val parsedOrganizationId = typeId.parseToValidated<Organization>("_")
185212
assertThat(parsedOrganizationId).isInstanceOf(Validated.Invalid::class.java)
186213
assertThat(parsedOrganizationId)
@@ -189,6 +216,35 @@ class TypeIdTest {
189216
"Id with empty prefix must not contain the separator '_'"))
190217
}
191218

219+
@Test
220+
fun `isId true`() {
221+
val organizationId = typeId.randomId<Organization>()
222+
assertThat(typeId.isId<Organization>(organizationId.toString())).isTrue()
223+
}
224+
225+
@Test
226+
fun `isId true with entity type`() {
227+
val organizationId = typeId.randomId<Organization>()
228+
assertThat(typeId.isId(Organization::class.java, organizationId.toString())).isTrue()
229+
}
230+
231+
@Test
232+
fun `isId false for other type`() {
233+
val organizationId = typeId.randomId<Organization>()
234+
assertThat(typeId.isId<User>(organizationId.toString())).isFalse()
235+
}
236+
237+
@Test
238+
fun `isId false for other type with entitytype`() {
239+
val organizationId = typeId.randomId<Organization>()
240+
assertThat(typeId.isId(User::class.java, organizationId.toString())).isFalse()
241+
}
242+
243+
@Test
244+
fun `isId false for invalid`() {
245+
assertThat(typeId.isId<User>("user_not_valid_id")).isFalse()
246+
}
247+
192248
@Test
193249
fun `type safe parsing`() {
194250
val userId = typeId.randomId<User>()

0 commit comments

Comments
 (0)