Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,9 @@ val ids = listOf(
OptableIdentifier.NetId("netid123"),
OptableIdentifier.ID5("id5token"),
OptableIdentifier.Utiq("utiqvalue"),
OptableIdentifier.Custom("v", "vidvalue"),
OptableIdentifier.Custom("c1", "custom one"),
OptableIdentifier.OptableVID("vidvalue"),
OptableIdentifier.Custom("custom"),
OptableIdentifier.Custom(1, "custom one"),
OptableIdentifier.Raw("raw:alreadyEncoded"),
OptableIdentifier.Raw("ultra:someRawValue")
)
Expand All @@ -264,8 +265,9 @@ List<OptableIdentifier> ids = Arrays.asList(
new OptableIdentifier.NetId("netid123"),
new OptableIdentifier.ID5("id5token"),
new OptableIdentifier.Utiq("utiqvalue"),
new OptableIdentifier.Custom("v", "vidvalue"),
new OptableIdentifier.Custom("c1", "custom one"),
new OptableIdentifier.OptableVID("vidvalue"),
new OptableIdentifier.Custom("custom"),
new OptableIdentifier.Custom(1, "custom one"),
new OptableIdentifier.Raw("raw:alreadyEncoded"),
new OptableIdentifier.Raw("ultra:someRawValue")
);
Expand Down Expand Up @@ -439,7 +441,7 @@ val hids = listOf(
OptableIdentifier.IPv6("2001:0db8:5b96:0000:0000:426f:8e17:642a"),
OptableIdentifier.PhoneNumber("+1(555)1234567"),
OptableIdentifier.Email("user@example.com"),
OptableIdentifier.Custom("c1", "puid-value"),
OptableIdentifier.Custom(1, "puid-value"),
)
optable.targeting(ids, hids) { result ->
when (result) {
Expand All @@ -461,7 +463,7 @@ List<OptableIdentifier> hids = Arrays.asList(
new OptableIdentifier.IPv6("2001:0db8:5b96:0000:0000:426f:8e17:642a"),
new OptableIdentifier.PhoneNumber("+1(555)1234567"),
new OptableIdentifier.Email("user@example.com"),
new OptableIdentifier.Custom("c1", "puid-value")
new OptableIdentifier.Custom(1, "puid-value")
);
optable.targeting(ids, hids, result -> {
if (result instanceof OptableResult.Success<OptableTargeting> success) {
Expand Down
16 changes: 12 additions & 4 deletions android_sdk/src/main/java/co/optable/sdk/OptableIdentifier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,19 @@ sealed class OptableIdentifier {
data class Utiq(val value: String) : OptableIdentifier()

/**
* Additional custom identifier.
* The `key` represents the identifier type.
* Encoding: for key "v" whitespace removed; otherwise trimmed.
* Optable visitor ID.
* Encoding: whitespace removed.
*/
data class OptableVID(val value: String) : OptableIdentifier()

/**
* Publisher-provided custom identifier, sent with type "c" when `index` is null or 0, or "c1".."cN" otherwise
* (the absolute value of `index` is used).
* Encoding: trimmed.
*/
data class Custom(val key: String, val value: String) : OptableIdentifier()
data class Custom(val index: Int?, val value: String) : OptableIdentifier() {
constructor(value: String) : this(null, value)
}

/**
* Pre-encoded EID string to include as-is.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.core.net.toUri
import co.optable.sdk.OptableIdentifier
import java.security.MessageDigest
import java.util.*
import kotlin.math.abs

/**
* Utility object responsible for encoding raw identifiers into Optable EIDs.
Expand All @@ -28,6 +29,7 @@ internal class IdentifiersEncoder(
private const val ID5 = "id5"
private const val UTIQ = "utiq"
private const val VID = "v"
private const val CUSTOM = "c"
}


Expand Down Expand Up @@ -55,6 +57,7 @@ internal class IdentifiersEncoder(
is OptableIdentifier.NetId -> result.addIfNotNull(NETID, identifier.value, ::removeWhitespaces)
is OptableIdentifier.ID5 -> result.addIfNotNull(ID5, identifier.value, ::removeWhitespaces)
is OptableIdentifier.Utiq -> result.addIfNotNull(UTIQ, identifier.value, ::normalize)
is OptableIdentifier.OptableVID -> result.addIfNotNull(VID, identifier.value, ::removeWhitespaces)

is OptableIdentifier.GoogleGaid -> {
if (normalize(googleAdId ?: "") == normalize(identifier.value)) {
Expand All @@ -64,11 +67,9 @@ internal class IdentifiersEncoder(
}

is OptableIdentifier.Custom -> {
if (identifier.key == VID) {
result.addIfNotNull(identifier.key, identifier.value, ::removeWhitespaces)
} else {
result.addIfNotNull(identifier.key, identifier.value, ::trim)
}
val index = identifier.index
val key = if (index == null || index == 0) CUSTOM else "$CUSTOM${abs(index)}"
result.addIfNotNull(key, identifier.value, ::trim)
}

is OptableIdentifier.Raw -> result.add(identifier.value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,23 +194,36 @@ class OptableIdentifiersTest {
}

@Test
fun `encode custom vid`() {
fun `encode optable vid`() {
val vid = " vid value "
val ids = listOf(OptableIdentifier.Custom("v", vid))
val ids = listOf(OptableIdentifier.OptableVID(vid))
val actual = identifiersEncoder.encode(ids)
val expected = listOf("v:${removeWhitespaces(vid)}")
assertEquals(expected, actual)
}

@Test
fun `encode custom nonVid`() {
fun `encode custom with index`() {
val c1 = " custom one "
val ids = listOf(OptableIdentifier.Custom("c1", c1))
val ids = listOf(OptableIdentifier.Custom(1, c1))
val actual = identifiersEncoder.encode(ids)
val expected = listOf("c1:${c1.trim()}")
assertEquals(expected, actual)
}

@Test
fun `encode custom without index, with index 0 and with a negative index`() {
val ids = listOf(
OptableIdentifier.Custom("plain"),
OptableIdentifier.Custom(null, "null index"),
OptableIdentifier.Custom(0, "zero index"),
OptableIdentifier.Custom(-3, "negative index"),
)
val actual = identifiersEncoder.encode(ids)
val expected = listOf("c:plain", "c:null index", "c:zero index", "c3:negative index")
assertEquals(expected, actual)
}

@Test
fun `encode raw`() {
val ids = listOf(
Expand Down Expand Up @@ -301,8 +314,8 @@ class OptableIdentifiersTest {
OptableIdentifier.NetId(netId),
OptableIdentifier.ID5(id5),
OptableIdentifier.Utiq(utiq),
OptableIdentifier.Custom("v", vid),
OptableIdentifier.Custom("c1", c1),
OptableIdentifier.OptableVID(vid),
OptableIdentifier.Custom(1, c1),
OptableIdentifier.Raw(raw1),
OptableIdentifier.Raw(raw2)
)
Expand Down Expand Up @@ -348,8 +361,8 @@ class OptableIdentifiersTest {
OptableIdentifier.NetId(" net id 123 "),
OptableIdentifier.ID5(" id5 token "),
OptableIdentifier.Utiq(" UTIQ VALUE "),
OptableIdentifier.Custom("v", " vid value "),
OptableIdentifier.Custom("c1", " custom one "),
OptableIdentifier.OptableVID(" vid value "),
OptableIdentifier.Custom(1, " custom one "),
OptableIdentifier.Raw("raw:alreadyEncoded"),
OptableIdentifier.Raw("x:someRawValue")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,17 @@ class IdentifiersEncoderTest {
val expected = "c:FooBarBAZ-01234#98765.!!!"


assertEquals(expected, encode(OptableIdentifier.Custom("c", "FooBarBAZ-01234#98765.!!!")))
assertEquals(expected, encode(OptableIdentifier.Custom("c", " FooBarBAZ-01234#98765.!!!")))
assertEquals(expected, encode(OptableIdentifier.Custom("c", "FooBarBAZ-01234#98765.!!! ")))
assertEquals(expected, encode(OptableIdentifier.Custom("c", " FooBarBAZ-01234#98765.!!! ")))
assertEquals(expected, encode(OptableIdentifier.Custom("FooBarBAZ-01234#98765.!!!")))
assertEquals(expected, encode(OptableIdentifier.Custom(" FooBarBAZ-01234#98765.!!!")))
assertEquals(expected, encode(OptableIdentifier.Custom("FooBarBAZ-01234#98765.!!! ")))
assertEquals(expected, encode(OptableIdentifier.Custom(" FooBarBAZ-01234#98765.!!! ")))
}

@Test
fun cid_isCaseSensitive() {
val unexpected = "c:FooBarBAZ-01234#98765.!!!"

val actual = encode(OptableIdentifier.Custom("c", "foobarBAZ-01234#98765.!!!"))
val actual = encode(OptableIdentifier.Custom("foobarBAZ-01234#98765.!!!"))
assertNotEquals(unexpected, actual)
}

Expand Down
Loading