Skip to content

Commit

Permalink
Merge pull request #7 from eccyan/features/optional_has_observable
Browse files Browse the repository at this point in the history
Version 1.1.0
  • Loading branch information
eccyan committed Feb 10, 2015
2 parents 532dcd1 + b0aa682 commit 67ae84c
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 87 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
==========

Version 1.1.0
-------------

* Design changed to Optional has Observable

Version 1.0.3
-------------

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pkgGroup=com.eccyan
pkgName=RxJava-Optional
pkgDesc=RxJava-Optional is an library that allows developers to use Optional using RxJava
pkgVersion=1.0.3
pkgVersion=1.1.0
pkgArtifactId=rxjava-optional
pkgSiteUrl=https://github.com/eccyan/RxJava-Optional
67 changes: 23 additions & 44 deletions optional/src/main/java/com/eccyan/optional/Optional.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,55 @@
import java.util.Objects;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Action1;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.internal.operators.OnSubscribeFromIterable;

/**
* Created by Daisuke Sato on 2/5/15.
*/
public class Optional<T> extends Observable<T> {
public class Optional<T> {

public static abstract class Predicate<T> implements Func1<T, Boolean> {

}

public static abstract class Function<T, U> implements Func1<T, U> {

}

public static class OnSubscribeForSingleItem<T> implements OnSubscribe<T> {

private final T item;

public OnSubscribeForSingleItem(final T item) {
this.item = item;
}

@Override
public void call(Subscriber<? super T> subscriber) {
subscriber.onNext(this.item);
subscriber.onCompleted();
}
}
private final Observable<T> observable;

public static <U> Optional<U> of(U data) {
if (data == null) {
throw new NullPointerException();
}

return new Optional<U>(new OnSubscribeForSingleItem<U>(data));
return new Optional<U>(Observable.just(data));
}

public static <U> Optional<U> ofNullable(U data) {
if (data == null) {
return optionalEmpty();
return empty();
} else {
return of(data);
}
}

public static <U> Optional<U> optionalEmpty() {
return new Optional<U>(new OnSubscribeFromIterable<U>(Collections.<U>emptyList()));
public static <U> Optional<U> empty() {
return new Optional<U>(Observable.from(Collections.<U>emptyList()));
}

protected Optional(OnSubscribe<T> f) {
super(f);
protected Optional(Observable<T> observable) {
this.observable = observable;
}

public boolean isPresent() {
return !isEmpty().toBlocking().single();
return !this.observable.isEmpty().toBlocking().single();
}

public void ifPresent(Action1<? super T> action) {
subscribe(action);
this.observable.subscribe(action);
}

public T get() {
return toBlocking().single();
return this.observable.toBlocking().single();
}

public T orElse(T other) {
return defaultIfEmpty(other).toBlocking().single();
return this.observable.defaultIfEmpty(other).toBlocking().single();
}

public T orElseCall(Func0<? extends T> other) {
Expand All @@ -90,36 +67,38 @@ public <X extends Throwable> T orElseThrow(Func0<? extends X> other) throws X {
return get();
}

public Optional<T> filter(final Predicate<T> predicate) {
public Optional<T> filter(final Func1<? super T, Boolean> predicate) {
Objects.requireNonNull(predicate);

return Optional.ofNullable(filter(new Func1<T, Boolean>() {
return Optional.ofNullable(this.observable.filter(new Func1<T, Boolean>() {
@Override
public Boolean call(T t) {
return predicate.call(t);
}
}).toBlocking().singleOrDefault(null));
}

public <U> Optional<U> map(final Function<? super T, ? extends U> mapper) {
public <U> Optional<U> map(final Func1<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);

return Optional.ofNullable(map(new Func1<T, U>() {
return Optional.ofNullable(this.observable.map(new Func1<T, U>() {
@Override
public U call(T t) {
return mapper.call(t);
}
}).toBlocking().singleOrDefault(null));
}

public <U> Optional<U> flatMap(final Function<? super T, Optional<U>> mapper) {
public <U> Optional<U> flatMap(final Func1<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);

return Optional.ofNullable(flatMap(new Func1<T, Optional<U>>() {
final Optional<U> optional = this.observable.flatMap(new Func1<T, Observable<Optional<U>>>() {
@Override
public Optional<U> call(T t) {
return Objects.requireNonNull(mapper.call(t));
public Observable<Optional<U>> call(T t) {
return Observable.just(Objects.requireNonNull(mapper.call(t)));
}
}).toBlocking().singleOrDefault(null));
}).toBlocking().singleOrDefault(Optional.<U>empty());

return optional;
}
}
101 changes: 59 additions & 42 deletions optional/src/test/java/com/eccyan/optional/OptionalTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

import java.util.NoSuchElementException;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import rx.functions.Func1;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

/**
* Created by Daisuke Sato on 2/10/15.
Expand All @@ -19,8 +23,8 @@ public void thisAlwaysPasses() {

@Test(expected = NoSuchElementException.class)
public void optionalEmpty_get_throwsNoSuchElementException() {
final Optional<Integer> actual = Optional.optionalEmpty();
Optional.optionalEmpty().get();
final Optional<Integer> actual = Optional.empty();
Optional.empty().get();
}

@Test
Expand All @@ -38,93 +42,106 @@ public void isPresent_returnsFalseWhenValuePresent() {
@Test
public void filter_returnsOptionalDescribedValueWhenPredicateReturnsTrue() {
final int expected = 12345;
final Optional<Integer> actual = Optional.ofNullable(expected).filter(new Optional.Predicate<Integer>() {
@Override
public Boolean call(Integer integer) {
return true;
}
});
final Optional<Integer> actual = Optional.ofNullable(expected)
.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(
Integer integer) {
return true;
}
});

assertThat(actual.get(), is(expected));
}

@Test
public void filter_returnsEmptyWhenPredicateReturnsFalse() {
final Optional<Integer> actual = Optional.ofNullable(12345).filter(new Optional.Predicate<Integer>() {
@Override
public Boolean call(Integer integer) {
return false;
}
});
final Optional<Integer> actual = Optional.ofNullable(12345)
.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return false;
}
});

assertFalse(actual.isPresent());
}

@Test
public void filter_returnsEmptyWhenValueIsEmpty() {
final Optional<Integer> empty = Optional.ofNullable(null);
final Optional<Integer> actual = empty.filter(new Optional.Predicate<Integer>() {
final Optional<Integer> actual = empty.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return true;
}
});

assertFalse(actual.isPresent());
}

@Test
public void map_returnsOptionalDescribedValueWhenValuePresent() {
final Optional<Integer> actual = Optional.ofNullable(1).map(new Optional.Function<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
return integer + 1;
}
});
final Optional<Integer> actual = Optional.ofNullable(1)
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
return integer + 1;
}
});
assertTrue(actual.isPresent());
assertThat(actual.get(), is(2));
}

@Test
public void map_returnsEmptyWhenValueNotPresent() {
final Optional<Integer> empty = Optional.ofNullable(null);
final Optional<Integer> actual = empty.map(new Optional.Function<Integer, Integer>() {
final Optional<Integer> actual = empty.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
return integer + 1;
}
});

assertFalse(actual.isPresent());
}

@Test
public void flatMap_returnsOptionalDescribedValueWhenValuePresent() {
final Optional<Integer> actual = Optional.ofNullable(1).flatMap(new Optional.Function<Integer, Optional<Integer>>() {
@Override
public Optional<Integer> call(Integer integer) {
return Optional.ofNullable(integer + 2);
}
});
final Optional<Integer> actual = Optional.ofNullable(1)
.flatMap(new Func1<Integer, Optional<Integer>>() {
@Override
public Optional<Integer> call(Integer integer) {
return Optional.ofNullable(integer + 2);
}
});

assertTrue(actual.isPresent());
assertThat(actual.get(), is(3));
}

@Test
public void flatMap_returnsEmptyWhenValueNotPresent() {
final Optional<Integer> empty = Optional.ofNullable(null);
final Optional<Integer> actual = empty.flatMap(new Optional.Function<Integer, Optional<Integer>>() {
@Override
public Optional<Integer> call(Integer integer) {
return Optional.ofNullable(integer + 1);
}
});
final Optional<Integer> actual = empty
.flatMap(new Func1<Integer, Optional<Integer>>() {
@Override
public Optional<Integer> call(Integer integer) {
return Optional.ofNullable(integer + 1);
}
});

assertFalse(actual.isPresent());
}

@Test(expected = NullPointerException.class)
public void flatMap_throwsNullPointerExceptionWhenMapperReturnsNull() {
final Optional<Integer> actual = Optional.ofNullable(1).flatMap(new Optional.Function<Integer, Optional<Integer>>() {
@Override
public Optional<Integer> call(Integer integer) {
return null;
}
});
final Optional<Integer> actual = Optional.ofNullable(1)
.flatMap(new Func1<Integer, Optional<Integer>>() {
@Override
public Optional<Integer> call(Integer integer) {
return null;
}
});
}
}

0 comments on commit 67ae84c

Please sign in to comment.