Skip to content

Commit

Permalink
Add RxJava2 extensions for Observable. (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
artem-zinnatullin authored Jun 1, 2017
1 parent a0867dd commit 3a98d92
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 139 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,34 @@ val v = when (optional) {
is Some -> optional.value // Smart Casts Optional to Some and allows you access its value.
is None -> "fallback"
}

// Filter only Some values emitted by RxJava2 Observable.
val values: Observable<String> = Observable
.just(Some("a"), None, Some("b"))
.filterSome()

// Filter only None values emitted by RxJava2 Observable.
val nones: Observable<Unit> = Observable
.just(Some("a"), None, Some("b"))
.filterNone()
```

### Download

Koptional is [available on jcenter](https://jcenter.bintray.com/com/gojuno/koptional).

Optional type:

```groovy
compile 'com.gojuno.koptional:koptional:put-some-version'
```

[RxJava 2][rxjava2] extensions:

```groovy
compile 'com.gojuno.koptional:koptional-rxjava2-extensions:put-some-version'
```

All the releases and changelogs can be found on [Releases Page](https://github.com/gojuno/koptional/releases).

### How to build
Expand Down Expand Up @@ -67,3 +85,5 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

[rxjava2]: https://github.com/ReactiveX/RxJava/
32 changes: 0 additions & 32 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,3 @@ allprojects {

apply plugin: 'com.github.ben-manes.versions'
}

def gitTag() {
def tag = 'git tag --list --points-at HEAD'.execute((List) null, rootProject.projectDir).text.trim()

if (tag.split(System.lineSeparator()).length > 1) {
throw new IllegalStateException("gitTag is accessed but commit has multiple tags: $tag")
}

return tag
}

def projectVersion() {
def tag = gitTag()

if (tag.startsWith('v')) {
return tag.substring(1)
} else if (tag.isEmpty()) {
return "development"
}

return tag
}

def validateTagAndVersion() {
if (gitTag().isEmpty()) {
throw new IllegalStateException('Publishing is not allowed because current commit has no tag')
}

if (projectVersion().isEmpty()) {
throw new IllegalStateException('Publishing is not allowed because current projectVersion is empty')
}
}
30 changes: 18 additions & 12 deletions dependencies.gradle
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
ext.versions = [
kotlin : '1.1.1',
kotlin : '1.1.1',
rxJava2 : '2.1.0',

junit : '4.12',
junitPlatform : '1.0.0-M4',
spek : '1.1.2',
assertJ : '3.5.2',
junit : '4.12',
junitPlatform: '1.0.0-M4',
spek : '1.1.2',
assertJ : '3.5.2',
]

ext.libraries = [
kotlinStd : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin",
kotlinRuntime : "org.jetbrains.kotlin:kotlin-runtime:$versions.kotlin",
kotlinReflect : "org.jetbrains.kotlin:kotlin-reflect:$versions.kotlin",
koptional : project(':koptional'),
koptionalRxJava2Extensions: project(':koptional-rxjava2-extensions'),

junit : "junit:junit:$versions.junit",
spek : "org.jetbrains.spek:spek-api:$versions.spek",
spekJunitPlatformEngine: "org.jetbrains.spek:spek-junit-platform-engine:$versions.spek",
assertJ : "org.assertj:assertj-core:$versions.assertJ",
kotlinStd : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin",
kotlinRuntime : "org.jetbrains.kotlin:kotlin-runtime:$versions.kotlin",
kotlinReflect : "org.jetbrains.kotlin:kotlin-reflect:$versions.kotlin",
rxJava2 : "io.reactivex.rxjava2:rxjava:$versions.rxJava2",


junit : "junit:junit:$versions.junit",
spek : "org.jetbrains.spek:spek-api:$versions.spek",
spekJunitPlatformEngine : "org.jetbrains.spek:spek-junit-platform-engine:$versions.spek",
assertJ : "org.assertj:assertj-core:$versions.assertJ",
]
119 changes: 119 additions & 0 deletions gradle/publishing.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'

def gitTag() {
def tag = 'git tag --list --points-at HEAD'.execute((List) null, rootProject.projectDir).text.trim()

if (tag.split(System.lineSeparator()).length > 1) {
throw new IllegalStateException("gitTag is accessed but commit has multiple tags: $tag")
}

return tag
}

def projectVersion() {
def tag = gitTag()

if (tag.startsWith('v')) {
return tag.substring(1)
} else if (tag.isEmpty()) {
return "development"
}

return tag
}

def validateTagAndVersion() {
if (gitTag().isEmpty()) {
throw new IllegalStateException('Publishing is not allowed because current commit has no tag')
}

if (projectVersion().isEmpty()) {
throw new IllegalStateException('Publishing is not allowed because current projectVersion is empty')
}
}

def pomConfig = {
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'repo'
}
}
developers {
developer {
id 'gojuno'
name 'Juno Inc.'
email 'opensource@gojuno.com'
}
}
}


task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

task validatePublishing {
doLast {
validateTagAndVersion()
}
}

bintrayUpload.dependsOn validatePublishing

publishing {
publications {
KoptionalPublication(MavenPublication) {
from components.java

artifact sourcesJar
artifact javadocJar

groupId 'com.gojuno.koptional'
artifactId project.name
version projectVersion()

pom.withXml {
def root = asNode()
root.appendNode('description', project.description)
root.appendNode('name', project.name)
root.appendNode('url', 'https://github.com/gojuno/koptional')
root.children().last() + pomConfig
}
}
}
}

bintray {
user = System.getenv('BINTRAY_USER')
key = System.getenv('BINTRAY_API_KEY')
publish = true

pkg {
repo = 'maven'
name = 'koptional'
licenses = ['Apache-2.0']
vcsUrl = 'https://github.com/gojuno/koptional.git'
issueTrackerUrl = 'https://github.com/gojuno/koptional/issues'
publications = ['KoptionalPublication']

version {
name = projectVersion()
vcsTag = gitTag()

gpg {
sign = true
passphrase = System.getenv('BINTRAY_GPG_PASSPHRASE')
}
}
}
}
24 changes: 24 additions & 0 deletions koptional-rxjava2-extensions/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apply plugin: 'kotlin'
apply plugin: 'org.junit.platform.gradle.plugin'
apply from: '../gradle/publishing.gradle'

dependencies {
compile libraries.koptional
compile libraries.rxJava2
}

dependencies {
testCompile libraries.spek
testCompile libraries.spekJunitPlatformEngine
testCompile libraries.assertJ
}

junitPlatform {
platformVersion = versions.junitPlatform

filters {
engines {
include 'spek'
}
}
}
1 change: 1 addition & 0 deletions koptional-rxjava2-extensions/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
description=Extensions to work with Optional in RxJava2 streams.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.gojuno.koptional.rxjava2

import com.gojuno.koptional.None
import com.gojuno.koptional.Optional
import com.gojuno.koptional.Some
import io.reactivex.Observable

private inline fun <reified R : Any> Observable<*>.ofType(): Observable<R> = ofType(R::class.java)

/**
* Filters items emitted by an ObservableSource by only emitting those that are `Some`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Observable that emits `Some.value` of those items emitted by the source ObservableSource that are `Some`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Observable<Optional<T>>.filterSome(): Observable<T> = ofType<Some<T>>().map { it.value }

/**
* Filters items emitted by an ObservableSource by only emitting those that are `None`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Observable that emits `Unit` for each item emitted by the source ObservableSource that is `None`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Observable<Optional<T>>.filterNone(): Observable<Unit> = ofType<None>().map { Unit }
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.gojuno.koptional.rxjava2

import com.gojuno.koptional.None
import com.gojuno.koptional.Some
import io.reactivex.Observable
import io.reactivex.observers.TestObserver
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.context
import org.jetbrains.spek.api.dsl.it

class RxJava2ExtensionsSpec : Spek({

val stream by memoized {
Observable.just(Some("a"), None, Some("b"), Some("c"), None)
}

context("filterSome") {

val subscriber by memoized {
TestObserver<String>().apply {
stream
.filterSome()
.subscribe(this)
}
}

it("passes only Some values") {
subscriber.assertValues("a", "b", "c")
}

it("completes stream") {
subscriber.assertComplete()
}

it("does not emit error") {
subscriber.assertNoErrors()
}
}

context("filterNone") {

val subscriber by memoized {
TestObserver<Unit>().apply {
stream
.filterNone()
.subscribe(this)
}
}

it("passes only None values as Unit") {
subscriber.assertValues(Unit, Unit)
}

it("completes stream") {
subscriber.assertComplete()
}

it("does not emit error") {
subscriber.assertNoErrors()
}
}
})
Loading

0 comments on commit 3a98d92

Please sign in to comment.