Skip to content

Commit

Permalink
Merge pull request #100 from Parsely/issue/migrate_events_builder_to_…
Browse files Browse the repository at this point in the history
…kotlin

Migrate `EventsBuilder` to Kotlin
  • Loading branch information
wzieba authored Jan 11, 2024
2 parents fe141cf + 2c64338 commit 9cbf080
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class FunctionalTests {

// when
startTimestamp = System.currentTimeMillis().milliseconds
parselyTracker.trackPageview("url", null, null, null)
parselyTracker.startEngagement(engagementUrl, null)
}

Expand Down

This file was deleted.

63 changes: 63 additions & 0 deletions parsely/src/main/java/com/parsely/parselyandroid/EventsBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.parsely.parselyandroid

import com.parsely.parselyandroid.Logging.log
import java.util.Calendar
import java.util.TimeZone

internal class EventsBuilder(
private val deviceInfoRepository: DeviceInfoRepository,
private val siteId: String,
private val clock: Clock,
) {
/**
* Create an event Map
*
* @param url The URL identifying the pageview/heartbeat
* @param action Action to use (e.g. pageview, heartbeat, videostart, vheartbeat)
* @param metadata Metadata to attach to the event.
* @param extraData A Map of additional information to send with the event.
* @return A Map object representing the event to be sent to Parse.ly.
*/
fun buildEvent(
url: String,
urlRef: String,
action: String,
metadata: ParselyMetadata?,
extraData: Map<String, Any>?,
uuid: String
): Map<String, Any> {
log("buildEvent called for %s/%s", action, url)

// Main event info
val event: MutableMap<String, Any> = HashMap()
event["url"] = url
event["urlref"] = urlRef
event["idsite"] = siteId
event["action"] = action

// Make a copy of extraData and add some things.
val data: MutableMap<String, Any> = HashMap()
if (extraData != null) {
data.putAll(extraData)
}
val deviceInfo = deviceInfoRepository.collectDeviceInfo()
data["ts"] = clock.now.inWholeMilliseconds
data.putAll(deviceInfo)
event["data"] = data
metadata?.let {
event["metadata"] = it.toMap()
}
if (action == "videostart" || action == "vheartbeat") {
event[VIDEO_START_ID_KEY] = uuid
}
if (action == "pageview" || action == "heartbeat") {
event[PAGE_VIEW_ID_KEY] = uuid
}
return event
}

companion object {
private const val VIDEO_START_ID_KEY = "vsid"
private const val PAGE_VIEW_ID_KEY = "pvid"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.parsely.parselyandroid

import java.util.Formatter

object Logging {
internal object Logging {

/**
* Log a message to the console.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ open class ParselyMetadata
*
* @return a Map object representing the metadata.
*/
open fun toMap(): Map<String, Any?>? {
open fun toMap(): Map<String, Any?> {
val output: MutableMap<String, Any?> = HashMap()
if (authors != null) {
output["authors"] = authors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ public class ParselyTracker {
*/
protected ParselyTracker(String siteId, int flushInterval, Context c) {
Context context = c.getApplicationContext();
clock = new Clock();
eventsBuilder = new EventsBuilder(
new AndroidDeviceInfoRepository(
new AdvertisementIdProvider(context, ParselyCoroutineScopeKt.getSdkScope()),
new AndroidIdProvider(context)
), siteId);
), siteId, clock);
LocalStorageRepository localStorageRepository = new LocalStorageRepository(context);
flushManager = new ParselyFlushManager(new Function0<Unit>() {
@Override
Expand All @@ -88,7 +89,6 @@ public Unit invoke() {
return Unit.INSTANCE;
});
flushQueue = new FlushQueue(flushManager, localStorageRepository, new ParselyAPIConnection(ROOT_URL + "mobileproxy"), ParselyCoroutineScopeKt.getSdkScope(), new AndroidConnectivityStatusProvider(context));
clock = new Clock();
intervalCalculator = new HeartbeatIntervalCalculator(clock);

// get the adkey straight away on instantiation
Expand Down Expand Up @@ -266,6 +266,10 @@ public void startEngagement(
log("url cannot be empty");
return;
}
if (lastPageviewUuid == null) {
log("engagement session cannot start without calling trackPageview first");
return;
}

// Blank urlref is better than null
if (urlRef == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class ParselyVideoMetadata
*
* @return a Map object representing the metadata.
*/
override fun toMap(): Map<String, Any?>? {
val output = super.toMap()?.toMutableMap()
output?.put("duration", durationSeconds)
override fun toMap(): Map<String, Any?> {
val output = super.toMap().toMutableMap()
output["duration"] = durationSeconds
return output
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package com.parsely.parselyandroid

import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.MapAssert
import org.junit.Before
import org.junit.Test

internal class EventsBuilderTest {
private lateinit var sut: EventsBuilder
private val clock = FakeClock()

@Before
fun setUp() {
sut = EventsBuilder(
FakeDeviceInfoRepository(),
TEST_SITE_ID,
clock
)
}

Expand Down Expand Up @@ -187,20 +191,22 @@ internal class EventsBuilderTest {
assertThat(it)
.hasSize(2)
.containsAllEntriesOf(FAKE_DEVICE_INFO)
.hasEntrySatisfying("ts") { timestamp ->
assertThat(timestamp as Long).isBetween(1111111111111, 9999999999999)
}
}

companion object {
const val TEST_SITE_ID = "Example"
const val TEST_URL = "http://example.com/some-old/article.html"
const val TEST_UUID = "123e4567-e89b-12d3-a456-426614174000"

val FAKE_DEVICE_INFO = mapOf("device" to "info")
val FAKE_NOW = 15.hours
val FAKE_DEVICE_INFO = mapOf("device" to "info", "ts" to FAKE_NOW.inWholeMilliseconds.toString())
}

class FakeDeviceInfoRepository: DeviceInfoRepository {
override fun collectDeviceInfo(): Map<String, String> = FAKE_DEVICE_INFO
}

class FakeClock() : Clock() {
override val now: Duration = FAKE_NOW
}
}

0 comments on commit 9cbf080

Please sign in to comment.