-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
397 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.featurevisor.sdk | ||
|
||
import com.featurevisor.types.Attribute | ||
import com.featurevisor.types.AttributeKey | ||
import com.featurevisor.types.DatafileContent | ||
import com.featurevisor.types.Feature | ||
import com.featurevisor.types.FeatureKey | ||
import com.featurevisor.types.Segment | ||
import com.featurevisor.types.SegmentKey | ||
|
||
class DataFileReader constructor( | ||
datafileJson: DatafileContent, | ||
) { | ||
private val schemaVersion: String = datafileJson.schemaVersion | ||
private val revision: String = datafileJson.revision | ||
private val attributes: List<Attribute> = datafileJson.attributes | ||
private val segments: List<Segment> = datafileJson.segments | ||
private val features: List<Feature> = datafileJson.features | ||
|
||
fun getRevision(): String = revision | ||
|
||
fun getSchemaVersion(): String = schemaVersion | ||
|
||
fun getAllAttributes(): List<Attribute> = attributes | ||
|
||
fun getAttribute(attributeKey: AttributeKey): Attribute? = | ||
attributes.find { attribute -> attribute.key == attributeKey } | ||
|
||
fun getSegment(segmentKey: SegmentKey): Segment? = | ||
segments.find { segment -> segment.key == segmentKey } | ||
|
||
fun getFeature(featureKey: FeatureKey): Feature? = | ||
features.find { feature -> feature.key == featureKey } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.featurevisor.sdk | ||
|
||
import com.featurevisor.types.EventName | ||
|
||
class Emitter { | ||
private val listeners = mutableMapOf<EventName, () -> Unit>() | ||
|
||
fun addListener(event: EventName, listener: () -> Unit) { | ||
listeners.putIfAbsent(event, listener) | ||
} | ||
|
||
fun removeListener(event: EventName) { | ||
listeners.remove(event) | ||
} | ||
|
||
fun removeAllListeners() { | ||
listeners.clear() | ||
} | ||
|
||
fun emit(event: EventName) { | ||
listeners.getOrDefault(event, null)?.invoke() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.featurevisor.types | ||
|
||
/** | ||
* Datafile-only types | ||
*/ | ||
// 0 to 100,000 | ||
typealias Percentage = Int | ||
|
||
data class Range( | ||
val start: Percentage, | ||
val end: Percentage, | ||
) | ||
|
||
data class Allocation( | ||
val variation: VariationValue, | ||
val range: Range, | ||
) | ||
|
||
data class Traffic( | ||
val key: RuleKey, | ||
val segments: GroupSegment, | ||
val percentage: Percentage, | ||
|
||
val enabled: Boolean?, | ||
val variation: VariationValue?, | ||
val variables: VariableValues?, | ||
|
||
val allocation: List<Allocation>, | ||
) | ||
|
||
typealias PlainBucketBy = String | ||
|
||
typealias AndBucketBy = List<BucketBy> | ||
|
||
data class OrBucketBy( | ||
val or: List<String>, | ||
) | ||
|
||
sealed class BucketBy { | ||
data class Single(val bucketBy: PlainBucketBy) : BucketBy() | ||
data class And(val bucketBy: AndBucketBy) : BucketBy() | ||
data class Or(val bucketBy: OrBucketBy) : BucketBy() | ||
} | ||
|
||
data class RequiredWithVariation( | ||
val key: FeatureKey, | ||
val variation: VariationValue, | ||
) | ||
|
||
sealed class Required { | ||
data class FeatureKey(val required: FeatureKey) : Required() | ||
data class WithVariation(val required: RequiredWithVariation) : Required() | ||
} | ||
|
||
data class Feature( | ||
val key: FeatureKey, | ||
val deprecated: Boolean?, | ||
val variablesSchema: List<VariableSchema>?, | ||
val variations: List<Variation>?, | ||
val bucketBy: BucketBy, | ||
val required: List<Required>?, | ||
val traffic: List<Traffic>, | ||
val force: List<Force>?, | ||
|
||
// if in a Group (mutex), these are available slot ranges | ||
val ranges: List<Range>?, | ||
) | ||
|
||
data class DatafileContent( | ||
val schemaVersion: String, | ||
val revision: String, | ||
val attributes: List<Attribute>, | ||
val segments: List<Segment>, | ||
val features: List<Feature>, | ||
) | ||
|
||
data class OverrideFeature( | ||
val enabled: Boolean, | ||
val variation: VariationValue?, | ||
val variables: VariableValues?, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.featurevisor.types | ||
|
||
enum class EventName { | ||
READY, | ||
REFRESH, | ||
UPDATE, | ||
ACTIVATION, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package com.featurevisor.types | ||
|
||
typealias SegmentKey = String | ||
|
||
data class Segment( | ||
val archived: Boolean?, | ||
val key: SegmentKey, | ||
val conditions: Condition, | ||
) | ||
|
||
typealias PlainGroupSegment = SegmentKey | ||
|
||
data class AndGroupSegment( | ||
val and: List<GroupSegment>, | ||
) | ||
|
||
data class OrGroupSegment( | ||
val or: List<GroupSegment>, | ||
) | ||
|
||
data class NotGroupSegment( | ||
val not: List<GroupSegment>, | ||
) | ||
|
||
sealed class GroupSegment { | ||
data class Plain(val segment: PlainGroupSegment) : GroupSegment() | ||
data class Multiple(val segments: List<GroupSegment>) : GroupSegment() | ||
|
||
data class And(val segment: AndGroupSegment) : GroupSegment() | ||
data class Or(val segment: OrGroupSegment) : GroupSegment() | ||
data class Not(val segment: NotGroupSegment) : GroupSegment() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
src/test/kotlin/com/featurevisor/sdk/DataFileReaderTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.featurevisor.sdk | ||
|
||
import com.featurevisor.sdk.factory.DatafileContentFactory | ||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
|
||
class DataFileReaderTest { | ||
|
||
private val systemUnderTest = DataFileReader( | ||
datafileJson = DatafileContentFactory.get() | ||
) | ||
|
||
@Test | ||
fun `getRevision() returns correct value`() { | ||
systemUnderTest.getRevision() shouldBe "revision" | ||
} | ||
|
||
@Test | ||
fun `getSchemaVersion returns correct value`() { | ||
systemUnderTest.getSchemaVersion() shouldBe "schemaVersion" | ||
} | ||
|
||
@Test | ||
fun `getAllAttributes() returns correct list`() { | ||
systemUnderTest.getAllAttributes() shouldBe DatafileContentFactory.getAttributes() | ||
} | ||
|
||
@Test | ||
fun `getAttribute() returns correct value`() { | ||
systemUnderTest.getAttribute("browser_type") shouldBe DatafileContentFactory.getAttributes().first() | ||
} | ||
|
||
@Test | ||
fun `getSegment() returns correct value`() { | ||
systemUnderTest.getSegment("netherlands") shouldBe DatafileContentFactory.getSegments().first() | ||
} | ||
|
||
@Test | ||
fun `getFeature() returns correct value`() { | ||
systemUnderTest.getFeature("landing_page") shouldBe DatafileContentFactory.getFeatures().first() | ||
} | ||
|
||
@Test | ||
fun `return null if key not present in collection`() { | ||
systemUnderTest.getAttribute("country") shouldBe null | ||
systemUnderTest.getSegment("germany") shouldBe null | ||
systemUnderTest.getFeature("key_moments") shouldBe null | ||
} | ||
} |
Oops, something went wrong.