Add store-kotlin module (#229)
* Add store-kotlin module * Remove useless file * Fix package in AndroidManifest * Refactor module tests to assertJ * Remove wrong annotation * Add store-kotlin artifact to README * Add module README * Add KDoc to Javadoc jar * Add Experimental annotation * Mark all public store-kotlin classes as @Experimental * Replace use of rx's @Experimental with local one instead
This commit is contained in:
parent
9926293696
commit
10d0cf6d07
25 changed files with 586 additions and 13 deletions
|
@ -293,6 +293,11 @@ public class SampleStore extends RealStore<String, BarCode> {
|
|||
```groovy
|
||||
compile 'com.nytimes.android:store3:CurrentVersion'
|
||||
```
|
||||
+ **Store-Kotlin** Store plus a couple of added Kotlin classes for more idiomatic usage.
|
||||
|
||||
```groovy
|
||||
compile 'com.nytimes.android:store-kotlin3:CurrentVersion'
|
||||
```
|
||||
+ **Middleware** Sample Gson parsers, (feel free to create more and open PRs)
|
||||
|
||||
```groovy
|
||||
|
|
|
@ -15,6 +15,10 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
|
||||
rootProject.ext.versions = [
|
||||
kotlin: '1.1.2-5'
|
||||
]
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.2'
|
||||
classpath 'com.google.gms:google-services:3.0.0'
|
||||
|
@ -22,6 +26,8 @@ buildscript {
|
|||
classpath 'me.tatarka:gradle-retrolambda:3.6.1'
|
||||
classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
|
||||
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.8'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.ext.versions.kotlin"
|
||||
classpath 'org.jetbrains.dokka:dokka-gradle-plugin:0.9.14'
|
||||
}
|
||||
|
||||
// this corresponds to the lombok.ast included above. fixes lint for retro-lambda
|
||||
|
|
|
@ -12,7 +12,7 @@ allprojects {
|
|||
}
|
||||
}
|
||||
|
||||
ext.versions = [
|
||||
ext.versions += [
|
||||
minSdk : 16,
|
||||
targetSdk : 25,
|
||||
compileSdk : 25,
|
||||
|
@ -52,6 +52,7 @@ ext.versions = [
|
|||
autoCommon : '0.6',
|
||||
javaWriter : '2.5.1',
|
||||
javax : '1',
|
||||
commonsLang3 : '3.0',
|
||||
|
||||
// Debugging & Inspecting.
|
||||
slf4j : '1.7.19',
|
||||
|
@ -116,6 +117,8 @@ ext.libraries = [
|
|||
autoCommon : "com.google.auto:auto-common:$versions.autoCommon",
|
||||
javaWriter : "com.squareup:javawriter:$versions.javaWriter",
|
||||
javax : "javax.inject:javax.inject:$versions.javax",
|
||||
kotlinStdLib : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin",
|
||||
commonsLang3 : "org.apache.commons:commons-lang3:$versions.commonsLang3",
|
||||
|
||||
// Debugging & Inspecting.
|
||||
slf4jNoOp : "org.slf4j:slf4j-api:$versions.slf4j",
|
||||
|
|
|
@ -47,7 +47,6 @@ afterEvaluate { project ->
|
|||
repositories {
|
||||
mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
pom.groupId = GROUP
|
||||
pom.artifactId = POM_ARTIFACT_ID
|
||||
pom.version = VERSION_NAME
|
||||
|
@ -195,6 +194,11 @@ afterEvaluate { project ->
|
|||
classifier = 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
task kotlinJavadocJar(type: Jar, dependsOn:javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from "$buildDir/dokka"
|
||||
}
|
||||
}
|
||||
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
|
@ -212,7 +216,11 @@ afterEvaluate { project ->
|
|||
archives androidJavadocsJar
|
||||
} else {
|
||||
archives sourcesJar
|
||||
archives javadocJar
|
||||
if (project.getPlugins().hasPlugin('kotlin')) {
|
||||
archives kotlinJavadocJar
|
||||
} else {
|
||||
archives javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ package com.nytimes.android.external.store3.middleware.jackson;
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.nytimes.android.external.fs3.ObjectToSourceTransformer;
|
||||
import com.nytimes.android.external.store3.annotations.Experimental;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.reactivex.annotations.Experimental;
|
||||
|
||||
/**
|
||||
* Factory which returns Jackson {@link io.reactivex.SingleTransformer} implementations.
|
||||
*/
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package com.nytimes.android.external.store3.middleware.moshi;
|
||||
|
||||
import com.nytimes.android.external.fs3.ObjectToSourceTransformer;
|
||||
import com.nytimes.android.external.store3.annotations.Experimental;
|
||||
import com.squareup.moshi.Moshi;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.reactivex.annotations.Experimental;
|
||||
|
||||
/**
|
||||
* Factory which returns Moshi {@link io.reactivex.SingleTransformer} implementations.
|
||||
*/
|
||||
|
|
|
@ -2,11 +2,10 @@ package com.nytimes.android.external.store3.middleware;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.nytimes.android.external.fs3.ObjectToSourceTransformer;
|
||||
import com.nytimes.android.external.store3.annotations.Experimental;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.reactivex.annotations.Experimental;
|
||||
|
||||
/**
|
||||
* Factory which returns Gson {@link io.reactivex.SingleTransformer} implementations.
|
||||
*/
|
||||
|
|
|
@ -1 +1 @@
|
|||
include ':app', ':store', ':middleware', ':cache', ':filesystem', ':middleware-moshi', ':middleware-jackson'
|
||||
include ':app', ':store', ':store-kotlin', ':middleware', ':cache', ':filesystem', ':middleware-moshi', ':middleware-jackson'
|
||||
|
|
40
store-kotlin/README.md
Normal file
40
store-kotlin/README.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
# store-kotlin
|
||||
|
||||
Store with bindings for Kotlin.
|
||||
|
||||
## Usage
|
||||
|
||||
StoreBuilder:
|
||||
|
||||
```kotlin
|
||||
FluentStoreBuilder.barcode(myFetcher) {
|
||||
persister = myPersister
|
||||
memoryPolicy = myMemoryPolicy
|
||||
stalePolicy = myStalePolicy
|
||||
}
|
||||
FluentStoreBuilder.key().fetcher(myFetcher) {
|
||||
persister = myPersister
|
||||
memoryPolicy = myMemoryPolicy
|
||||
stalePolicy = myStalePolicy
|
||||
}
|
||||
FluentStoreBuilder.parsedWithKey<Key, Raw, Parsed>(myFetcher) {
|
||||
persister = myPersister
|
||||
memoryPolicy = myMemoryPolicy
|
||||
stalePolicy = myStalePolicy
|
||||
parser = myParser
|
||||
parsers = myParsers
|
||||
}
|
||||
```
|
||||
|
||||
MemoryPolicyBuilder:
|
||||
|
||||
```kotlin
|
||||
FluentMemoryPolicyBuilder.build {
|
||||
expireAfterWrite = expireAfterWriteValue
|
||||
expireAfterAccess = expireAfterWriteAccess
|
||||
expireAfterTimeUnit = expireAfterTimeUnitValue
|
||||
memorySize = maxSizeValue
|
||||
}
|
||||
```
|
||||
|
||||
And you can always omit the configuration block if you're happy with the defaults!
|
26
store-kotlin/build.gradle
Normal file
26
store-kotlin/build.gradle
Normal file
|
@ -0,0 +1,26 @@
|
|||
apply plugin: 'java'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'org.jetbrains.dokka'
|
||||
|
||||
group = GROUP
|
||||
version = VERSION_NAME
|
||||
|
||||
compileKotlin {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
javadoc.dependsOn dokka
|
||||
|
||||
dependencies {
|
||||
compile project(':store')
|
||||
compile libraries.kotlinStdLib
|
||||
|
||||
testCompile libraries.mockito
|
||||
testCompile libraries.junit
|
||||
testCompile libraries.commonsLang3
|
||||
testCompile libraries.assertJ
|
||||
}
|
||||
|
||||
apply from: rootProject.file("gradle/maven-push.gradle")
|
3
store-kotlin/gradle.properties
Normal file
3
store-kotlin/gradle.properties
Normal file
|
@ -0,0 +1,3 @@
|
|||
POM_NAME=com.nytimes.android
|
||||
POM_ARTIFACT_ID=store-kotlin3
|
||||
POM_PACKAGING=aar
|
3
store-kotlin/src/main/AndroidManifest.xml
Normal file
3
store-kotlin/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
package="com.nytimes.android.external.store-kotlin"/>
|
|
@ -0,0 +1,31 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.annotations.Experimental
|
||||
|
||||
/**
|
||||
* Wraps methods for fluent MemoryPolicy instantiation.
|
||||
*/
|
||||
@Experimental
|
||||
class FluentMemoryPolicyBuilder private constructor() {
|
||||
companion object {
|
||||
/**
|
||||
* Builds a MemoryPolicy.
|
||||
* @param config The desired configuration for the memory policy.
|
||||
* @return A MemoryPolicy with the desired parameters or default ones if none were provided.
|
||||
*/
|
||||
fun build(config: (MemoryPolicyParameters.() -> Unit)? = null): MemoryPolicy =
|
||||
MemoryPolicyParameters().apply { config?.invoke(this) }.let {
|
||||
MemoryPolicy.builder()
|
||||
.apply {
|
||||
if (it.expireAfterAccess != MemoryPolicy.DEFAULT_POLICY) {
|
||||
this.setExpireAfterAccess(it.expireAfterAccess)
|
||||
} else if (it.expireAfterWrite != MemoryPolicy.DEFAULT_POLICY) {
|
||||
this.setExpireAfterWrite(it.expireAfterWrite)
|
||||
}
|
||||
}
|
||||
.setExpireAfterTimeUnit(it.expireAfterTimeUnit)
|
||||
.setMemorySize(it.memorySize)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.base.Fetcher
|
||||
import com.nytimes.android.external.store3.base.Parser
|
||||
import com.nytimes.android.external.store3.base.Persister
|
||||
import com.nytimes.android.external.store3.util.KeyParser
|
||||
|
||||
/**
|
||||
* A fluent builder for Store instantiation.
|
||||
* @param fetcher The fetcher for the created instance.
|
||||
*/
|
||||
internal class FluentRealStoreBuilder<Raw, Parsed, Key> constructor(
|
||||
private val fetcher: Fetcher<Raw, Key>,
|
||||
private val persister: Persister<Raw, Key>?,
|
||||
private val keyParser: KeyParser<Key, Raw, Parsed>?,
|
||||
private val parsers: List<Parser<Raw, Parsed>>?,
|
||||
private val memoryPolicy: MemoryPolicy?,
|
||||
private val stalePolicy: StalePolicy) {
|
||||
/**
|
||||
* Creates the Store instance.
|
||||
* @return The created Store with the parameters passed into the constructor.
|
||||
*/
|
||||
fun open(): Store<Parsed, Key> {
|
||||
var builder = StoreBuilder.parsedWithKey<Key, Raw, Parsed>()
|
||||
.fetcher(fetcher)
|
||||
if (persister != null) {
|
||||
builder = builder.persister(persister)
|
||||
}
|
||||
if (keyParser != null) {
|
||||
builder = builder.parser(keyParser)
|
||||
} else {
|
||||
if (parsers != null) {
|
||||
builder = builder.parsers(parsers)
|
||||
}
|
||||
}
|
||||
if (memoryPolicy != null) {
|
||||
builder = builder.memoryPolicy(memoryPolicy)
|
||||
}
|
||||
when (stalePolicy) {
|
||||
StalePolicy.REFRESH_ON_STALE -> builder = builder.refreshOnStale()
|
||||
StalePolicy.NETWORK_BEFORE_STALE -> builder = builder.networkBeforeStale()
|
||||
StalePolicy.UNSPECIFIED -> { } // Do nothing
|
||||
}
|
||||
return builder.open()
|
||||
}
|
||||
}
|
60
store-kotlin/src/main/kotlin/com/nytimes/android/external/store3/base/impl/FluentStoreBuilder.kt
vendored
Normal file
60
store-kotlin/src/main/kotlin/com/nytimes/android/external/store3/base/impl/FluentStoreBuilder.kt
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.annotations.Experimental
|
||||
import com.nytimes.android.external.store3.base.Fetcher
|
||||
|
||||
/**
|
||||
* Wraps methods for fluent Store instantiation.
|
||||
*/
|
||||
@Experimental
|
||||
class FluentStoreBuilder private constructor() {
|
||||
companion object {
|
||||
/**
|
||||
* Provides a fluent builder to instantiate a Store that uses BarCode objects as keys.
|
||||
* @param fetcher Fetcher for the Store.
|
||||
* @param config Optional configuration block.
|
||||
*/
|
||||
fun <Parsed> barcode(
|
||||
fetcher: Fetcher<Parsed, BarCode>,
|
||||
config: (StoreParameters<Parsed, BarCode>.() -> Unit)? = null) =
|
||||
key(fetcher, config)
|
||||
|
||||
/**
|
||||
* Provides a fluent builder to instantiate a Store with a custom type for keys.
|
||||
* @param fetcher Fetcher for the Store.
|
||||
* @param config Optional configuration block.
|
||||
*/
|
||||
fun <Parsed, Key> key(
|
||||
fetcher: Fetcher<Parsed, Key>,
|
||||
config: (StoreParameters<Parsed, Key>.() -> Unit)? = null) =
|
||||
StoreParameters(fetcher).apply {
|
||||
if (config != null) {
|
||||
this.config()
|
||||
}
|
||||
}.let {
|
||||
FluentRealStoreBuilder<Parsed, Parsed, Key>(
|
||||
fetcher, it.persister, null, null, it.memoryPolicy, it.stalePolicy)
|
||||
.open()
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a fluent builder to instantiate a Store with a custom type for keys and
|
||||
* conversion between raw and parsed types.
|
||||
* @param fetcher Fetcher for the Store.
|
||||
* @param config Optional configuration block.
|
||||
*/
|
||||
fun <Key, Raw, Parsed> parsedWithKey(
|
||||
fetcher: Fetcher<Raw, Key>,
|
||||
config: (ParsableStoreParameters<Raw, Parsed, Key>.() -> Unit)? = null) =
|
||||
ParsableStoreParameters<Raw, Parsed, Key>(fetcher).apply {
|
||||
if (config != null) {
|
||||
this.config()
|
||||
}
|
||||
}.let {
|
||||
FluentRealStoreBuilder(
|
||||
fetcher, it.persister, it.parser, it.parsers, it.memoryPolicy,
|
||||
it.stalePolicy)
|
||||
.open()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.annotations.Experimental
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
* A parameter box for MemoryPolicy instantiation.
|
||||
*/
|
||||
@Experimental
|
||||
class MemoryPolicyParameters {
|
||||
var expireAfterWrite by Delegates.vetoable(MemoryPolicy.DEFAULT_POLICY) {
|
||||
_, _, newValue -> newValue >= 0
|
||||
}
|
||||
var expireAfterAccess by Delegates.vetoable(MemoryPolicy.DEFAULT_POLICY) {
|
||||
_, _, newValue -> newValue >= 0
|
||||
}
|
||||
var expireAfterTimeUnit = TimeUnit.SECONDS
|
||||
var memorySize by Delegates.vetoable(1L) {
|
||||
_, _, newValue -> newValue >= 1
|
||||
}
|
||||
}
|
41
store-kotlin/src/main/kotlin/com/nytimes/android/external/store3/base/impl/StoreParameters.kt
vendored
Normal file
41
store-kotlin/src/main/kotlin/com/nytimes/android/external/store3/base/impl/StoreParameters.kt
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.annotations.Experimental
|
||||
import com.nytimes.android.external.store3.base.Fetcher
|
||||
import com.nytimes.android.external.store3.base.Parser
|
||||
import com.nytimes.android.external.store3.base.Persister
|
||||
import com.nytimes.android.external.store3.util.KeyParser
|
||||
|
||||
/**
|
||||
* A parameter box for Store instantiation, used for Stores the do not make use of parsing.
|
||||
* @param fetcher The fetcher for the Store.
|
||||
*/
|
||||
@Experimental
|
||||
open class StoreParameters<Raw, Key> internal constructor(private val fetcher: Fetcher<Raw, Key>) {
|
||||
var persister: Persister<Raw, Key>? = null
|
||||
var memoryPolicy: MemoryPolicy? = null
|
||||
var stalePolicy: StalePolicy = StalePolicy.UNSPECIFIED
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter box for Store instantiation, used for Stores that can have parsing.
|
||||
* @param fetcher The fetcher for the Store.
|
||||
*/
|
||||
@Experimental
|
||||
class ParsableStoreParameters<Raw, Parsed, Key> internal constructor(fetcher: Fetcher<Raw, Key>)
|
||||
: StoreParameters<Raw, Key>(fetcher) {
|
||||
var parser: KeyParser<Key, Raw, Parsed>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != null) {
|
||||
parsers = null
|
||||
}
|
||||
}
|
||||
var parsers: List<Parser<Raw, Parsed>>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != null) {
|
||||
parser = null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Spec for FluentMemoryPolicyBuilder.
|
||||
*/
|
||||
class FluentMemoryPolicyBuilderSpec {
|
||||
@Test
|
||||
fun shouldBuildAnEquivalentObjectWithAfterWrite() {
|
||||
val expireAfterWriteValue = 10L
|
||||
val expireAfterTimeUnitValue = TimeUnit.MILLISECONDS
|
||||
val maxSizeValue = 1000L
|
||||
val javaResult = MemoryPolicy.builder()
|
||||
.setExpireAfterWrite(expireAfterWriteValue)
|
||||
.setExpireAfterTimeUnit(expireAfterTimeUnitValue)
|
||||
.setMemorySize(maxSizeValue)
|
||||
.build()
|
||||
val kotlinResult = FluentMemoryPolicyBuilder.build {
|
||||
expireAfterWrite = expireAfterWriteValue
|
||||
expireAfterTimeUnit = expireAfterTimeUnitValue
|
||||
memorySize = maxSizeValue
|
||||
}
|
||||
assertEquivalent(javaResult, kotlinResult)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldBuildAnEquivalentObjectWithAfterAccess() {
|
||||
val expireAfterAccessValue = 20L
|
||||
val expireAfterTimeUnitValue = TimeUnit.MILLISECONDS
|
||||
val maxSizeValue = 1000L
|
||||
val javaResult = MemoryPolicy.builder()
|
||||
.setExpireAfterAccess(expireAfterAccessValue)
|
||||
.setExpireAfterTimeUnit(expireAfterTimeUnitValue)
|
||||
.setMemorySize(maxSizeValue)
|
||||
.build()
|
||||
val kotlinResult = FluentMemoryPolicyBuilder.build {
|
||||
expireAfterAccess = expireAfterAccessValue
|
||||
expireAfterTimeUnit = expireAfterTimeUnitValue
|
||||
memorySize = maxSizeValue
|
||||
}
|
||||
assertEquivalent(javaResult, kotlinResult)
|
||||
}
|
||||
|
||||
private fun assertEquivalent(expected: MemoryPolicy, actual: MemoryPolicy) =
|
||||
EqualsBuilder.reflectionEquals(expected, actual)
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.base.Fetcher
|
||||
import com.nytimes.android.external.store3.base.Parser
|
||||
import com.nytimes.android.external.store3.base.Persister
|
||||
import com.nytimes.android.external.store3.util.KeyParser
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.mock
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Spec for FluentRealStoreBuilder.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class FluentRealStoreBuilderSpec {
|
||||
@Test
|
||||
fun shouldOpenAnEquivalentObject() {
|
||||
val fetcher = mock(Fetcher::class.java) as Fetcher<Int, Int>
|
||||
val persister = mock(Persister::class.java) as Persister<Int, Int>
|
||||
val keyParser = mock(KeyParser::class.java) as KeyParser<Int, Int, Int>
|
||||
val parsers = listOf<Parser<Int, Int>>()
|
||||
val memoryPolicy = mock(MemoryPolicy::class.java)
|
||||
`when`(memoryPolicy.expireAfterTimeUnit).thenReturn(TimeUnit.MILLISECONDS)
|
||||
val stalePolicy = StalePolicy.NETWORK_BEFORE_STALE
|
||||
val javaResult = RealStoreBuilder.builder<Int, Int, Int>()
|
||||
.fetcher(fetcher)
|
||||
.persister(persister)
|
||||
.parser(keyParser)
|
||||
.parsers(parsers)
|
||||
.memoryPolicy(memoryPolicy)
|
||||
.networkBeforeStale()
|
||||
.open()
|
||||
val kotlinResult = FluentRealStoreBuilder(fetcher, persister, keyParser, parsers,
|
||||
memoryPolicy, stalePolicy
|
||||
).open()
|
||||
assertEquivalent(javaResult, kotlinResult)
|
||||
}
|
||||
|
||||
private fun <T, V> assertEquivalent(expected: Store<T, V>, actual: Store<T, V>) =
|
||||
EqualsBuilder.reflectionEquals(expected, actual)
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.base.Fetcher
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito
|
||||
|
||||
/**
|
||||
* Spec for FluentStoreBuilder.
|
||||
*/
|
||||
class FluentStoreBuilderSpec {
|
||||
@Test
|
||||
fun equivalentBarcode() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val fetcher = Mockito.mock(Fetcher::class.java) as Fetcher<Any, BarCode>
|
||||
val javaResult = StoreBuilder.barcode<Any>()
|
||||
.fetcher(fetcher)
|
||||
.open()
|
||||
val kotlinResult = FluentStoreBuilder.barcode(fetcher)
|
||||
assertEquivalent(javaResult, kotlinResult)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun equivalentKey() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val fetcher = Mockito.mock(Fetcher::class.java) as Fetcher<Any, BarCode>
|
||||
val javaResult = StoreBuilder.key<BarCode, Any>()
|
||||
.fetcher(fetcher)
|
||||
.open()
|
||||
val kotlinResult = FluentStoreBuilder.key(fetcher)
|
||||
assertEquivalent(javaResult, kotlinResult)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun equivalentParsedWithKey() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val fetcher = Mockito.mock(Fetcher::class.java) as Fetcher<Any, BarCode>
|
||||
val javaResult = StoreBuilder.parsedWithKey<BarCode, Any, Any>()
|
||||
.fetcher(fetcher)
|
||||
.open()
|
||||
val kotlinResult = FluentStoreBuilder.parsedWithKey<BarCode, Any, Any>(fetcher)
|
||||
assertEquivalent(javaResult, kotlinResult)
|
||||
}
|
||||
|
||||
private fun <T, V> assertEquivalent(expected: Store<T, V>, actual: Store<T, V>) =
|
||||
EqualsBuilder.reflectionEquals(expected, actual)
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Spec for MemoryPolicyParameters.
|
||||
*/
|
||||
class MemoryPolicyParametersSpec {
|
||||
@Test
|
||||
fun shouldHaveExpireAfterWriteBeMemoryPolicyDEFAULT_POLICY() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
assertThat(sut.expireAfterWrite).isEqualTo(MemoryPolicy.DEFAULT_POLICY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldHaveExpireAfterAccessBeMemoryPolicyDEFAULT_POLICY() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
assertThat(sut.expireAfterAccess).isEqualTo(MemoryPolicy.DEFAULT_POLICY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldHaveExpireAfterTimeUnitBeTimeUnitSECONDS() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
assertThat(sut.expireAfterTimeUnit).isEqualTo(TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldHaveMemorySizeBe1() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
assertThat(sut.memorySize).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun expiredAfterWriteMustBeGreaterThanOrEqualTo0() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
val validValue = 82L
|
||||
val invalidValue = -1L
|
||||
sut.expireAfterWrite = validValue
|
||||
assertThat(sut.expireAfterWrite).isEqualTo(validValue)
|
||||
sut.expireAfterWrite = invalidValue
|
||||
assertThat(sut.expireAfterWrite).isEqualTo(validValue)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun expiredAfterAccessMustBeGreaterThanOrEqualTo0() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
val validValue = 82L
|
||||
val invalidValue = -1L
|
||||
sut.expireAfterAccess = validValue
|
||||
assertThat(sut.expireAfterAccess).isEqualTo(validValue)
|
||||
sut.expireAfterAccess = invalidValue
|
||||
assertThat(sut.expireAfterAccess).isEqualTo(validValue)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun memorySizeShouldBeGreaterThanOrEqualTo1() {
|
||||
val sut = MemoryPolicyParameters()
|
||||
val validValue = 3L
|
||||
val invalidValue = -1L
|
||||
sut.memorySize = validValue
|
||||
assertThat(sut.memorySize).isEqualTo(validValue)
|
||||
sut.memorySize = invalidValue
|
||||
assertThat(sut.memorySize).isEqualTo(validValue)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.nytimes.android.external.store3.base.impl
|
||||
|
||||
import com.nytimes.android.external.store3.base.Fetcher
|
||||
import com.nytimes.android.external.store3.base.Parser
|
||||
import com.nytimes.android.external.store3.util.KeyParser
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.mock
|
||||
|
||||
/**
|
||||
* Spec for StoreParameters.
|
||||
*/
|
||||
open class StoreParametersSpec {
|
||||
@Test
|
||||
fun defaultPersisterIsNull() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sut = StoreParameters(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
assertThat(sut.persister).isNull()
|
||||
}
|
||||
@Test
|
||||
fun defaultMemoryPolicyIsNull() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sut = StoreParameters(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
assertThat(sut.memoryPolicy).isNull()
|
||||
}
|
||||
@Test
|
||||
fun defaultStalePolicyIsUnspecified() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sut = StoreParameters(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
assertThat(sut.stalePolicy).isEqualTo(StalePolicy.UNSPECIFIED)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spec for ParsableStoreParameters.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class ParsableStoreParametersSpec : StoreParametersSpec() {
|
||||
@Test
|
||||
fun defaultParserIsNull() {
|
||||
val sut = ParsableStoreParameters<Any, Any, Any>(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
assertThat(sut.parser).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultParsersIsNull() {
|
||||
val sut = ParsableStoreParameters<Any, Any, Any>(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
assertThat(sut.parsers).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldMakeParserNullWhenParsersIsAssigned() {
|
||||
val sut = ParsableStoreParameters<Any, Any, Any>(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
sut.parser = mock(KeyParser::class.java) as KeyParser<Any, Any, Any>
|
||||
sut.parsers = mock(List::class.java) as List<Parser<Any, Any>>
|
||||
assertThat(sut.parser).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldMakeParsersNullWhenParserIsAssigned() {
|
||||
val sut = ParsableStoreParameters<Any, Any, Any>(mock(Fetcher::class.java) as Fetcher<Any, Any>)
|
||||
sut.parsers = mock(List::class.java) as List<Parser<Any, Any>>
|
||||
sut.parser = mock(KeyParser::class.java) as KeyParser<Any, Any, Any>
|
||||
assertThat(sut.parsers).isNull()
|
||||
}
|
||||
}
|
8
store/src/main/java/com/nytimes/android/external/store3/annotations/Experimental.java
vendored
Normal file
8
store/src/main/java/com/nytimes/android/external/store3/annotations/Experimental.java
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.nytimes.android.external.store3.annotations;
|
||||
|
||||
/**
|
||||
* Indicates the feature is in experimental state: its existence, signature or behavior
|
||||
* might change without warning from one release to the next.
|
||||
*/
|
||||
public @interface Experimental {
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.nytimes.android.external.store3.base.impl;
|
||||
|
||||
import com.nytimes.android.external.cache3.Cache;
|
||||
import com.nytimes.android.external.store3.annotations.Experimental;
|
||||
import com.nytimes.android.external.store3.base.Fetcher;
|
||||
import com.nytimes.android.external.store3.base.InternalStore;
|
||||
import com.nytimes.android.external.store3.base.Persister;
|
||||
|
@ -15,7 +16,6 @@ import javax.annotation.Nullable;
|
|||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.annotations.Experimental;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.nytimes.android.external.store3.base.impl;
|
||||
|
||||
|
||||
import com.nytimes.android.external.store3.annotations.Experimental;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.annotations.Experimental;
|
||||
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue