Skip to content

Instantly share code, notes, and snippets.

@kwanCCC
Forked from Ahmed-Adel-Ismail/IfElse.java
Created December 18, 2018 09:39
Show Gist options
  • Save kwanCCC/9b77db5acfb64783b4e82e5652d06bb1 to your computer and use it in GitHub Desktop.
Save kwanCCC/9b77db5acfb64783b4e82e5652d06bb1 to your computer and use it in GitHub Desktop.

Revisions

  1. @Ahmed-Adel-Ismail Ahmed-Adel-Ismail revised this gist Sep 24, 2017. 1 changed file with 21 additions and 0 deletions.
    21 changes: 21 additions & 0 deletions IfElse.java
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,27 @@
    * of {@link Predicate} as key and a {@link Function} as value ... the if any emitted item passes
    * the {@link Predicate}, this emitted item will be passed to the {@link Function} mapped to it,
    * and this item will be invoked and it's result will continue down the stream
    * <p>
    * sample code :
    * <p>
    * {@code List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);}<br>
    * {@code Map<Predicate<Integer>, Function<Integer, String>> blocks = new LinkedHashMap<>(2)}<br>
    * {@code blocks.put(i -> i % 2 == 0, i -> "Even number : " + i);}<br>
    * {@code blocks.put(i -> i % 2 != 0, i -> "Odd number : " + i);}<br>
    * <p>
    * {@code Observable.fromIterable(list)}<br>
    * {@code .lift(new IfElse<>(blocks))}<br>
    * {@code .subscribe(System.out::println);}<br>
    * <p>
    * // result :<br>
    * Odd number : 1<br>
    * Even number : 2<br>
    * Odd number : 3<br>
    * Even number : 4<br>
    * Odd number : 5<br>
    * Even number : 6<br>
    * Odd number : 7<br>
    * Even number : 8
    */
    public class IfElse<T, R> implements ObservableOperator<R, T> {

  2. @Ahmed-Adel-Ismail Ahmed-Adel-Ismail renamed this gist Sep 24, 2017. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. @Ahmed-Adel-Ismail Ahmed-Adel-Ismail revised this gist Sep 24, 2017. 1 changed file with 74 additions and 0 deletions.
    74 changes: 74 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    /**
    * an {@link ObservableOperator} that simulates an if-else in an RxJava Stream, it takes a {@link Map}
    * of {@link Predicate} as key and a {@link Function} as value ... the if any emitted item passes
    * the {@link Predicate}, this emitted item will be passed to the {@link Function} mapped to it,
    * and this item will be invoked and it's result will continue down the stream
    */
    public class IfElse<T, R> implements ObservableOperator<R, T> {

    private final Map<Predicate<T>, Function<T, R>> blocks = new LinkedHashMap<>();

    /**
    * create a {@link IfElse} operator, if any {@link Function} returned {@code null}, the
    * whole operation will crash
    *
    * @param blocks the map that holds {@link Function} that are the if-else blocks
    */
    public IfElse(@NonNull Map<Predicate<T>, Function<T, R>> blocks) {
    if (blocks != null) {
    this.blocks.putAll(blocks);
    }
    }

    @Override
    public Observer<? super T> apply(final Observer<? super R> observer) throws Exception {
    return createResultObserver(observer);
    }

    private Observer<T> createResultObserver(final Observer<? super R> observer) {
    return new Observer<T>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onNext(@NonNull T emittedItem) {

    List<Function<T, R>> validBlocks = Observable.fromIterable(blocks.keySet())
    .filter(key -> key.test(emittedItem))
    .map(blocks::get)
    .toList()
    .flatMapMaybe(Maybe::just)
    .blockingGet();


    if (validBlocks == null) {
    return;
    }

    try {
    for (Function<T, R> block : validBlocks) {
    invokeOnNext(observer, block.apply(emittedItem));
    }
    } catch (Throwable e) {
    onError(e);
    }
    }

    @Override
    public void onError(@NonNull Throwable e) {
    observer.onError(e);
    }

    @Override
    public void onComplete() {
    observer.onComplete();
    }
    };
    }

    private void invokeOnNext(Observer<? super R> observer, R onNextValue) {
    observer.onNext(onNextValue);
    }
    }
  4. @Ahmed-Adel-Ismail Ahmed-Adel-Ismail revised this gist Sep 23, 2017. 1 changed file with 4 additions and 6 deletions.
    10 changes: 4 additions & 6 deletions SwitchCase.java
    Original file line number Diff line number Diff line change
    @@ -29,7 +29,7 @@
    */
    public class SwitchCase<T, R> implements ObservableOperator<R, T> {

    final Map<T, Function<T, R>> caseBlocks;
    final Map<T, Function<T, R>> caseBlocks = new LinkedHashMap<>();

    /**
    * create a {@link SwitchCase} operator, if any {@link Function} returned {@code null}, the
    @@ -39,13 +39,11 @@ public class SwitchCase<T, R> implements ObservableOperator<R, T> {
    * switch-case
    */
    public SwitchCase(@NonNull Map<T, Function<T, R>> caseBlocks) {
    if (caseBlocks == null) {
    this.caseBlocks = new LinkedHashMap<>(0);
    } else {
    this.caseBlocks = caseBlocks;
    if (caseBlocks != null) {
    this.caseBlocks.putAll(caseBlocks);
    }
    }

    @Override
    public Observer<? super T> apply(final Observer<? super R> observer) throws Exception {
    return createResultObserver(observer);
  5. @Ahmed-Adel-Ismail Ahmed-Adel-Ismail created this gist Sep 23, 2017.
    98 changes: 98 additions & 0 deletions SwitchCase.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    /**
    * An {@link ObservableOperator} that enables the switch-case behavior in Rx-Java, it uses
    * a table look up technique to simulate a switch-case behavior
    * <p>
    * you must supply a {@link Map} that holds functions that will be executed if the emitted
    * item matches the key they are mapped to
    * <p>
    * if multiple emitted items matches several keys, all there functions will be executed and
    * will emit there results, if you want the first match to disable the rest of the checks,
    * you can use {@link SwitchCaseBreak} instead
    * <p>
    * sample code :
    * <p>
    * {@code List<Integer> list = Arrays.asList(1, 2, 3, 4);}<br>
    * {@code Map<Integer, Function<Integer, String>> caseBlocks = new HashMap<>(2);}<br>
    * {@code caseBlocks.put(2, (i) -> "TWO SELECTED");}<br>
    * {@code caseBlocks.put(3, (i) -> "THREE SELECTED");}<br>
    * <p>
    * {@code Observable.fromIterable(list)}<br>
    * {@code .lift(new SwitchCase<>(caseBlocks))}<br>
    * {@code .subscribe(System.out::println);}<br>
    * <p>
    * // result :<br>
    * TWO SELECTED<br>
    * THREE SELECTED<br>
    *
    * @param <T> the type of the items that will be passed to the {@code switch} statement
    * @param <R> the type of the items that will be returned from the {@code case} block execution
    */
    public class SwitchCase<T, R> implements ObservableOperator<R, T> {

    final Map<T, Function<T, R>> caseBlocks;

    /**
    * create a {@link SwitchCase} operator, if any {@link Function} returned {@code null}, the
    * whole operation will crash
    *
    * @param caseBlocks the map that holds {@link Function} that are the case-blocks in this
    * switch-case
    */
    public SwitchCase(@NonNull Map<T, Function<T, R>> caseBlocks) {
    if (caseBlocks == null) {
    this.caseBlocks = new LinkedHashMap<>(0);
    } else {
    this.caseBlocks = caseBlocks;
    }
    }

    @Override
    public Observer<? super T> apply(final Observer<? super R> observer) throws Exception {
    return createResultObserver(observer);
    }

    private Observer<T> createResultObserver(final Observer<? super R> observer) {
    return new Observer<T>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onNext(@NonNull T switchOn) {

    Function<T, R> block = Maybe.just(caseBlocks)
    .filter(map -> map.containsKey(switchOn))
    .map(map -> map.get(switchOn))
    .blockingGet();

    if (block == null) {
    return;
    }

    try {
    invokeOnNext(observer, block.apply(switchOn));
    } catch (Throwable e) {
    onError(e);
    }

    }

    @Override
    public void onError(@NonNull Throwable e) {
    observer.onError(e);
    }

    @Override
    public void onComplete() {
    observer.onComplete();
    }
    };
    }

    void invokeOnNext(Observer<? super R> observer, R onNextValue) {
    observer.onNext(onNextValue);
    }

    }

    30 changes: 30 additions & 0 deletions SwitchCaseBreak.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    /**
    * same as {@link SwitchCase} but it emits only one item which is the result of the
    * {@link Function} mapped to the key matching the first emitted value
    * <p>
    * sample code :
    * <p>
    * {@code List<Integer> list = Arrays.asList(1, 2, 3, 4);}<br>
    * {@code Map<Integer, Function<Integer, String>> caseBlocks = new HashMap<>(2);}<br>
    * {@code caseBlocks.put(2, (i) -> "TWO SELECTED");}<br>
    * {@code caseBlocks.put(3, (i) -> "THREE SELECTED");}<br>
    * <p>
    * {@code Observable.fromIterable(list)}<br>
    * {@code .lift(new SwitchCaseBreak<>(caseBlocks))}<br>
    * {@code .subscribe(System.out::println);}<br>
    * <p>
    * // result :<br>
    * TWO SELECTED<br>
    */
    public class SwitchCaseBreak<T, R> extends SwitchCase<T, R> {

    public SwitchCaseBreak(Map<T, Function<T, R>> caseBlocks) {
    super(caseBlocks);
    }

    @Override
    void invokeOnNext(Observer<? super R> observer, R onNextValue) {
    super.invokeOnNext(observer, onNextValue);
    caseBlocks.clear();
    }
    }