master ef53aec9cd43 cached
146 files
217.1 KB
59.6k tokens
814 symbols
1 requests
Download .txt
Showing preview only (255K chars total). Download the full file or copy to clipboard to get everything.
Repository: nurkiewicz/rxjava-book-examples
Branch: master
Commit: ef53aec9cd43
Files: 146
Total size: 217.1 KB

Directory structure:
gitextract_yjbw__u9/

├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src/
    └── test/
        └── java/
            └── com/
                └── oreilly/
                    └── rxjava/
                        ├── appendix1/
                        │   ├── ClientConnection.java
                        │   ├── HttpServer.java
                        │   ├── SingleThread.java
                        │   ├── ThreadPerConnection.java
                        │   └── ThreadPool.java
                        ├── ch1/
                        │   ├── Callback.java
                        │   └── Chapter1.java
                        ├── ch2/
                        │   ├── Chapter2.java
                        │   ├── Config.java
                        │   ├── Data.java
                        │   ├── LazyTwitterObservable.java
                        │   ├── NaturalNumbersIterator.java
                        │   ├── Tweet.java
                        │   ├── TwitterSample.java
                        │   └── TwitterSubject.java
                        ├── ch3/
                        │   ├── Car.java
                        │   ├── CarPhoto.java
                        │   ├── CashTransfer.java
                        │   ├── CassandraFactStore.java
                        │   ├── Chapter3.java
                        │   ├── City.java
                        │   ├── CustomOperators.java
                        │   ├── Customer.java
                        │   ├── Data.java
                        │   ├── FactStore.java
                        │   ├── Flight.java
                        │   ├── Hotel.java
                        │   ├── LicensePlate.java
                        │   ├── Licenses.java
                        │   ├── OperatorMap.java
                        │   ├── Order.java
                        │   ├── Profile.java
                        │   ├── Rating.java
                        │   ├── Reservation.java
                        │   ├── ReservationEvent.java
                        │   ├── Reservations.java
                        │   ├── Shakespeare.java
                        │   ├── Sound.java
                        │   ├── User.java
                        │   ├── Vacation.java
                        │   ├── Weather.java
                        │   └── WeatherStation.java
                        ├── ch4/
                        │   ├── Book.java
                        │   ├── Chapter4.java
                        │   ├── Flight.java
                        │   ├── Flights.java
                        │   ├── Item.java
                        │   ├── JmsConsumer.java
                        │   ├── Messaging.java
                        │   ├── Passenger.java
                        │   ├── Person.java
                        │   ├── PersonDao.java
                        │   ├── RxGroceries.java
                        │   ├── Schedulers.java
                        │   ├── SimplifiedHandlerScheduler.java
                        │   ├── SmtpResponse.java
                        │   └── Ticket.java
                        ├── ch5/
                        │   ├── Chapter5.java
                        │   ├── CompletableFutures.java
                        │   ├── EurUsdCurrencyTcpServer.java
                        │   ├── Flight.java
                        │   ├── GeoLocation.java
                        │   ├── HttpHandler.java
                        │   ├── HttpInitializer.java
                        │   ├── HttpTcpNettyServer.java
                        │   ├── HttpTcpRxNettyServer.java
                        │   ├── Postgres.java
                        │   ├── RestCurrencyServer.java
                        │   ├── RxNettyHttpServer.java
                        │   ├── SingleThread.java
                        │   ├── Singles.java
                        │   ├── Ticket.java
                        │   ├── TravelAgency.java
                        │   ├── User.java
                        │   └── Util.java
                        ├── ch6/
                        │   ├── Backpressure.java
                        │   ├── Chapter6.java
                        │   ├── Debounce.java
                        │   ├── Dish.java
                        │   ├── KeyEvent.java
                        │   ├── Record.java
                        │   ├── Repository.java
                        │   ├── TeleData.java
                        │   └── TradingPlatform.java
                        ├── ch7/
                        │   ├── Agreement.java
                        │   ├── Chapter7.java
                        │   ├── Confirmation.java
                        │   ├── Monitoring.java
                        │   ├── MyService.java
                        │   ├── MyServiceWithTimeout.java
                        │   ├── Person.java
                        │   ├── PrintHouse.java
                        │   ├── RetryTimeouts.java
                        │   ├── Testing.java
                        │   └── TrackingId.java
                        ├── ch8/
                        │   ├── Android.java
                        │   ├── ApiFactory.java
                        │   ├── Chapter8.java
                        │   ├── Cities.java
                        │   ├── City.java
                        │   ├── GeoNames.java
                        │   ├── Geoname.java
                        │   ├── Incident.java
                        │   ├── Insurance.java
                        │   ├── MeetupApi.java
                        │   ├── Person.java
                        │   ├── Picture.java
                        │   ├── SearchResult.java
                        │   ├── hystrix/
                        │   │   ├── BlockingCmd.java
                        │   │   ├── Book.java
                        │   │   ├── CitiesCmd.java
                        │   │   ├── FetchManyRatings.java
                        │   │   ├── FetchRatingsCollapser.java
                        │   │   └── Hystrix.java
                        │   ├── rxandroid/
                        │   │   ├── AndroidSchedulers.java
                        │   │   ├── LooperScheduler.java
                        │   │   ├── MainActivity.java
                        │   │   ├── MainThreadSubscription.java
                        │   │   ├── RxAndroidPlugins.java
                        │   │   └── RxAndroidSchedulersHook.java
                        │   └── rxbinding/
                        │       ├── RxTextView.java
                        │       ├── RxView.java
                        │       ├── TextViewAfterTextChangeEvent.java
                        │       ├── TextViewAfterTextChangeEventOnSubscribe.java
                        │       ├── TextViewBeforeTextChangeEvent.java
                        │       ├── TextViewBeforeTextChangeEventOnSubscribe.java
                        │       ├── TextViewEditorActionEvent.java
                        │       ├── TextViewEditorActionEventOnSubscribe.java
                        │       ├── TextViewEditorActionOnSubscribe.java
                        │       ├── TextViewTextChangeEvent.java
                        │       ├── TextViewTextChangeEventOnSubscribe.java
                        │       ├── TextViewTextOnSubscribe.java
                        │       ├── ViewClickOnSubscribe.java
                        │       ├── ViewEvent.java
                        │       └── internal/
                        │           ├── Functions.java
                        │           └── Preconditions.java
                        ├── ch9/
                        │   └── Chapter9.java
                        └── util/
                            └── Sleeper.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
build
.gradle
*.iml
.idea


================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) 2019 Tomasz Nurkiewicz

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Source code of examples from _Reactive Programming with RxJava_

Book is available on [O'Reilly](http://shop.oreilly.com/product/0636920042228.do) and [Amazon](http://amzn.to/2gJ6Vhx).

If you find any example incomplete or broken, please [submit a PR](https://github.com/nurkiewicz/rxjava-book-examples/pulls) or [create an issue](https://github.com/nurkiewicz/rxjava-book-examples/issues/new).

* [Chapter 1](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch1)
* [Chapter 2](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch2)
* [Chapter 3](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch3)
* [Chapter 4](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch4)
* [Chapter 5](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch5)
* [Chapter 6](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch6)
* [Chapter 7](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch7)
* [Chapter 8](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch8)
* [Chapter 9](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/ch9)
* [Appendix 1](https://github.com/nurkiewicz/rxjava-book-examples/tree/master/src/test/java/com/oreilly/rxjava/appendix1)

# Remarks

1. Some examples were slightly modified to support newer versions of dependent libraries
2. Java projects can't simply import Android `.aar` libraries. Therefore parts of [RxAndroid](https://github.com/ReactiveX/RxAndroid) and [RxBinding](https://github.com/JakeWharton/RxBinding) source code were copied directly.


================================================
FILE: build.gradle
================================================
apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    testCompile 'io.reactivex:rxjava:1.2.2'
    testCompile 'io.reactivex:rxnetty-http:0.5.2-rc.4'
    testCompile 'com.netflix.hystrix:hystrix-core:1.5.8'
    testCompile 'com.netflix.hystrix:hystrix-metrics-event-stream:1.5.8'

    testCompile 'com.google.guava:guava:18.0'
    testCompile 'org.apache.commons:commons-collections4:4.1'
    testCompile 'org.apache.commons:commons-lang3:3.5'
    testCompile 'commons-dbutils:commons-dbutils:1.6'
    testCompile 'commons-io:commons-io:2.5'
    testCompile 'commons-dbutils:commons-dbutils:1.6'

    testCompile 'ch.qos.logback:logback-classic:1.1.7'
    testCompile 'org.slf4j:slf4j-api:1.7.21'
    testCompile 'io.dropwizard:dropwizard-metrics:1.0.3'

    testCompile 'org.springframework:spring-context:4.3.4.RELEASE'
    testCompile 'org.springframework:spring-jms:4.3.4.RELEASE'
    testCompile 'org.springframework:spring-jdbc:4.3.4.RELEASE'

    testCompile 'com.google.android:android:4.1.1.4'
//    testCompile 'com.jakewharton.rxbinding:rxbinding:0.4.0'

    testCompile 'org.postgresql:postgresql:9.4-1206-jdbc42'
    testCompile 'org.twitter4j:twitter4j-stream:4.0.5'
    testCompile 'com.ning:async-http-client:1.9.40'

    testCompile 'javax.jms:jms-api:1.1-rev-1'
    testCompile 'org.apache.activemq:activemq-client:5.14.1'
    testCompile 'org.eclipse.jetty:jetty-servlet:9.4.0.RC2'

    testCompile 'com.couchbase.client:java-client:2.3.5'
    testCompile 'org.mongodb:mongodb-driver-rx:1.2.0'

    testCompile 'org.apache.camel:camel-rx:2.17.3'
    testCompile 'org.apache.camel:camel-kafka:2.17.3'
    testCompile 'org.apache.activemq:activemq-camel:5.14.0'
    testCompile 'org.apache.activemq:activemq-client:5.14.0'

    testCompile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
    testCompile 'com.squareup.retrofit2:converter-jackson:2.0.1'

    testCompile 'junit:junit:4.12'
    testCompile 'org.assertj:assertj-core:3.5.2'
    testCompile 'org.mockito:mockito-core:2.2.15'
}

task wrapper(type: Wrapper) {
    gradleVersion = '3.1'
}


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Sat Nov 19 14:44:58 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip


================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
  cd "$(dirname "$0")"
fi

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: src/test/java/com/oreilly/rxjava/appendix1/ClientConnection.java
================================================
package com.oreilly.rxjava.appendix1;

import org.apache.commons.io.IOUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

class ClientConnection implements Runnable {

    public static final byte[] RESPONSE = (
            "HTTP/1.1 200 OK\r\n" +
            "Content-length: 2\r\n" +
            "\r\n" +
            "OK").getBytes();

    public static final byte[] SERVICE_UNAVAILABLE = (
            "HTTP/1.1 503 Service unavailable\r\n").getBytes();

    private final Socket client;

    ClientConnection(Socket client) {
        this.client = client;
    }

    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                readFullRequest();
                client.getOutputStream().write(RESPONSE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            IOUtils.closeQuietly(client);
        }
    }

    private void readFullRequest() throws IOException {
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
        String line = reader.readLine();
        while (line != null && !line.isEmpty()) {
            line = reader.readLine();
        }
    }

    public void serviceUnavailable() {
        try {
            client.getOutputStream().write(SERVICE_UNAVAILABLE);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/appendix1/HttpServer.java
================================================
package com.oreilly.rxjava.appendix1;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

abstract class HttpServer  {

    void run(int port) throws IOException {
        final ServerSocket serverSocket = new ServerSocket(port, 100);
        while (!Thread.currentThread().isInterrupted()) {
            final Socket client = serverSocket.accept();
            handle(new ClientConnection(client));
        }
    }

    abstract void handle(ClientConnection clientConnection);
}


================================================
FILE: src/test/java/com/oreilly/rxjava/appendix1/SingleThread.java
================================================
package com.oreilly.rxjava.appendix1;

public class SingleThread extends HttpServer {

    public static void main(String[] args) throws Exception {
        new SingleThread().run(8080);
    }

    @Override
    void handle(ClientConnection clientConnection) {
        clientConnection.run();
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/appendix1/ThreadPerConnection.java
================================================
package com.oreilly.rxjava.appendix1;

import java.io.IOException;

public class ThreadPerConnection extends HttpServer {

    public static void main(String[] args) throws IOException {
        new ThreadPerConnection().run(8080);
    }

    @Override
    void handle(ClientConnection clientConnection) {
        new Thread(clientConnection).start();
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/appendix1/ThreadPool.java
================================================
package com.oreilly.rxjava.appendix1;

import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

class ThreadPool extends HttpServer {

    private final ThreadPoolExecutor executor;

    public static void main(String[] args) throws IOException {
        new ThreadPool().run(8080);
    }

    public ThreadPool() {
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1000);
        executor = new ThreadPoolExecutor(100, 100, 0L,
                                MILLISECONDS, workQueue,
                (r, ex) -> {
                    ((ClientConnection) r).serviceUnavailable();
                });
    }

    @Override
    void handle(ClientConnection clientConnection) {
        executor.execute(clientConnection);
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch1/Callback.java
================================================
package com.oreilly.rxjava.ch1;

import java.util.function.Consumer;

class Callback {
	private Consumer<String> onResponse = x -> {};
	private Consumer<Exception> onFailure = x -> {};

	Callback onResponse(Consumer<String> consumer) {
		this.onResponse = consumer;
		return this;
	}

	Callback onFailure(Consumer<Exception> consumer) {
		this.onFailure = consumer;
		return this;
	}

	public Consumer<String> getOnResponse() {
		return onResponse;
	}

	public Consumer<Exception> getOnFailure() {
		return onFailure;
	}
}

================================================
FILE: src/test/java/com/oreilly/rxjava/ch1/Chapter1.java
================================================
package com.oreilly.rxjava.ch1;

import com.oreilly.rxjava.util.Sleeper;
import org.junit.Ignore;
import org.junit.Test;
import rx.Completable;
import rx.Observable;
import rx.Single;
import rx.schedulers.Schedulers;

import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;

@Ignore
public class Chapter1 {

	private static final String SOME_KEY = "FOO";

	@Test
	public void sample_6() throws Exception {
		Observable.create(s -> {
			s.onNext("Hello World!");
			s.onCompleted();
		}).subscribe(hello -> System.out.println(hello));
	}

	@Test
	public void sample_17() throws Exception {
		Map<String, String> cache = new ConcurrentHashMap<>();
		cache.put(SOME_KEY, "123");

		Observable.create(s -> {
			s.onNext(cache.get(SOME_KEY));
			s.onCompleted();
		}).subscribe(value -> System.out.println(value));
	}

	@Test
	public void sample_35() throws Exception {
		// pseudo-code
		Observable.create(s -> {
			String fromCache = getFromCache(SOME_KEY);
			if (fromCache != null) {
				// emit synchronously
				s.onNext(fromCache);
				s.onCompleted();
			} else {
				// fetch asynchronously
				getDataAsynchronously(SOME_KEY)
						.onResponse(v -> {
							putInCache(SOME_KEY, v);
							s.onNext(v);
							s.onCompleted();
						})
						.onFailure(exception -> {
							s.onError(exception);
						});
			}
		}).subscribe(s -> System.out.println(s));

		Sleeper.sleep(Duration.ofSeconds(2));
	}

	private void putInCache(String key, String value) {
		//do nothing
	}

	private Callback getDataAsynchronously(String key) {
		final Callback callback = new Callback();
		new Thread(() -> {
			Sleeper.sleep(Duration.ofSeconds(1));
			callback.getOnResponse().accept(key + ":123");
		}).start();
		return callback;
	}

	private String getFromCache(String key) {
//		return null;
		return key + ":123";
	}

	@Test
	public void sample_81() throws Exception {
		Observable<Integer> o = Observable.create(s -> {
			s.onNext(1);
			s.onNext(2);
			s.onNext(3);
			s.onCompleted();
		});

		o.map(i -> "Number " + i)
				.subscribe(s -> System.out.println(s));
	}

	@Test
	public void sample_94() throws Exception {
		Observable.<Integer>create(s -> {
			//... async subscription and data emission ...
			new Thread(() -> s.onNext(42), "MyThread").start();
		})
				.doOnNext(i -> System.out.println(Thread.currentThread()))
				.filter(i -> i % 2 == 0)
				.map(i -> "Value " + i + " processed on " + Thread.currentThread())
				.subscribe(s -> System.out.println("SOME VALUE =>" + s));
		System.out.println("Will print BEFORE values are emitted because Observable is async");
		Sleeper.sleep(Duration.ofSeconds(1));
	}

	@Test
	public void sample_108() throws Exception {
		Observable.create(s -> {
			new Thread(() -> {
				s.onNext("one");
				s.onNext("two");
				s.onNext("three");
				s.onNext("four");
				s.onCompleted();
			}).start();
		});
	}

	@Test
	public void sample_121() throws Exception {
		// DO NOT DO THIS
		Observable.create(s -> {
			// Thread A
			new Thread(() -> {
				s.onNext("one");
				s.onNext("two");
			}).start();

			// Thread B
			new Thread(() -> {
				s.onNext("three");
				s.onNext("four");
			}).start();

			// ignoring need to emit s.onCompleted() due to race of threads
		});
		// DO NOT DO THIS
	}

	@Test
	public void sample_142() throws Exception {
		Observable<String> a = Observable.create(s -> {
			new Thread(() -> {
				s.onNext("one");
				s.onNext("two");
				s.onCompleted();
			}).start();
		});

		Observable<String> b = Observable.create(s -> {
			new Thread(() -> {
				s.onNext("three");
				s.onNext("four");
				s.onCompleted();
			}).start();
		});

		// this subscribes to a and b concurrently, and merges into a third sequential stream
		Observable<String> c = Observable.merge(a, b);
	}

	@Test
	public void sample_164() throws Exception {
		String args = SOME_KEY;
		Observable<String> someData = Observable.create(s -> {
			getDataFromServerWithCallback(args, data -> {
				s.onNext(data);
				s.onCompleted();
			});
		});

		someData.subscribe(s -> System.out.println("Subscriber 1: " + s));
		someData.subscribe(s -> System.out.println("Subscriber 2: " + s));

		Observable<String> lazyFallback = Observable.just("Fallback");
		someData
				.onErrorResumeNext(lazyFallback)
				.subscribe(s -> System.out.println(s));

	}

	private void getDataFromServerWithCallback(String args, Consumer<String> consumer) {
		consumer.accept("Random: " + Math.random());
	}

	@Test
	public void sample_188() throws Exception {
		// Iterable<String> as Stream<String>
		// that contains 75 strings
		getDataFromLocalMemorySynchronously()
				.skip(10)
				.limit(5)
				.map(s -> s + "_transformed")
				.forEach(System.out::println);
	}

	private Stream<String> getDataFromLocalMemorySynchronously() {
		return IntStream
				.range(0, 100)
				.mapToObj(Integer::toString);
	}

	@Test
	public void sample_205() throws Exception {
		// Observable<String>
// that emits 75 strings
		getDataFromNetworkAsynchronously()
				.skip(10)
				.take(5)
				.map(s -> s + "_transformed")
				.subscribe(System.out::println);
	}

	private Observable<String> getDataFromNetworkAsynchronously() {
		return Observable
				.range(0, 100)
				.map(Object::toString);
	}

	@Test
	public void sample_225() throws Exception {
		CompletableFuture<String> f1 = getDataAsFuture(1);
		CompletableFuture<String> f2 = getDataAsFuture(2);

		CompletableFuture<String> f3 = f1.thenCombine(f2, (x, y) -> {
			return x+y;
		});
	}

	private CompletableFuture<String> getDataAsFuture(int i) {
		return CompletableFuture.completedFuture("Done: " + i + "\n");
	}

	@Test
	public void sample_240() throws Exception {
		Observable<String> o1 = getDataAsObservable(1);
		Observable<String> o2 = getDataAsObservable(2);

		Observable<String> o3 = Observable.zip(o1, o2, (x, y) -> {
			return x+y;
		});
	}

	private Observable<String> getDataAsObservable(int i) {
		return Observable.just("Done: " + i + "\n");
	}

	@Test
	public void sample_254() throws Exception {
		Observable<String> o1 = getDataAsObservable(1);
		Observable<String> o2 = getDataAsObservable(2);

		// o3 is now a stream of o1 and o2 that emits each item without waiting
		Observable<String> o3 = Observable.merge(o1, o2);
	}

	@Test
	public void sample_265() throws Exception {
		// merge a & b into an Observable stream of 2 values
		Observable<String> a_merge_b = getDataA().mergeWith(getDataB());
	}

	public static Single<String> getDataA() {
		return Single.<String> create(o -> {
			o.onSuccess("DataA");
		}).subscribeOn(Schedulers.io());
	}

	@Test
	public void sample_277() throws Exception {
		// Observable<String> o1 = getDataAsObservable(1);
		// Observable<String> o2 = getDataAsObservable(2);

		Single<String> s1 = getDataAsSingle(1);
		Single<String> s2 = getDataAsSingle(2);

		// o3 is now a stream of s1 and s2 that emits each item without waiting
		Observable<String> o3 = Single.merge(s1, s2);
	}

	private Single<String> getDataAsSingle(int i) {
		return Single.just("Done: " + i);
	}

	public static Single<String> getDataB() {
		return Single.just("DataB")
				.subscribeOn(Schedulers.io());
	}

	static Completable writeToDatabase(Object data) {
		return Completable.create(s -> {
			doAsyncWrite(data,
					// callback for successful completion
					() -> s.onCompleted(),
					// callback for failure with Throwable
					error -> s.onError(error));
		});
	}

	static void doAsyncWrite(Object data, Runnable onSuccess, Consumer<Exception> onError) {
		//store data an run asynchronously:
		onSuccess.run();
	}

}



================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/Chapter2.java
================================================
package com.oreilly.rxjava.ch2;

import com.oreilly.rxjava.util.Sleeper;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.Subscription;
import rx.subscriptions.Subscriptions;

import java.math.BigInteger;
import java.time.Duration;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static java.math.BigInteger.ONE;
import static java.math.BigInteger.ZERO;
import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

@Ignore
public class Chapter2 {

	@Test
	public void sample_6() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

		tweets.subscribe((Tweet tweet) ->
				System.out.println(tweet));
	}

	@Test
	public void sample_17() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

		tweets.subscribe(
				(Tweet tweet) -> { System.out.println(tweet); },
				(Throwable t) -> { t.printStackTrace(); }
		);
	}

	@Test
	public void sample_27() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

		tweets.subscribe(
				(Tweet tweet) -> { System.out.println(tweet); },
				(Throwable t) -> { t.printStackTrace(); },
				() -> {this.noMore();}
		);
	}

	@Test
	public void sample_38() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

			tweets.subscribe(
				System.out::println,
				Throwable::printStackTrace,
				this::noMore);
	}

	private void noMore() {
	}

	@Test
	public void sample_51() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

		Observer<Tweet> observer = new Observer<Tweet>() {
			@Override
			public void onNext(Tweet tweet) {
				System.out.println(tweet);
			}

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

			@Override
			public void onCompleted() {
				noMore();
			}
		};

		//...

		tweets.subscribe(observer);
	}

	@Test
	public void sample_78() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

		Subscription subscription =
				tweets.subscribe(System.out::println);

		//...

		subscription.unsubscribe();
	}

	@Test
	public void sample_91() throws Exception {
		Observable<Tweet> tweets = Observable.empty(); //...

		Subscriber<Tweet> subscriber = new Subscriber<Tweet>() {
			@Override
			public void onNext(Tweet tweet) {
				if (tweet.getText().contains("Java")) {
					unsubscribe();
				}
			}

			@Override
			public void onCompleted() {}

			@Override
			public void onError(Throwable e) {
				e.printStackTrace();
			}
		};
		tweets.subscribe(subscriber);
	}

	private static void log(Object msg) {
		System.out.println(
				Thread.currentThread().getName() +
						": " + msg);
	}

	@Test
	public void sample_117() throws Exception {
		log("Before");
		Observable
				.range(5, 3)
				.subscribe(i -> {
					log(i);
				});
		log("After");

	}

	@Test
	public void sample_135() throws Exception {
		Observable<Integer> ints = Observable
				.create(new Observable.OnSubscribe<Integer>() {
					@Override
					public void call(Subscriber<? super Integer> subscriber) {
						log("Create");
						subscriber.onNext(5);
						subscriber.onNext(6);
						subscriber.onNext(7);
						subscriber.onCompleted();
						log("Completed");
					}
				});
		log("Starting");
		ints.subscribe(i -> log("Element: " + i));
		log("Exit");
	}

	static <T> Observable<T> just(T x) {
		return Observable.create(subscriber -> {
					subscriber.onNext(x);
					subscriber.onCompleted();
				}
		);
	}

	@Test
	public void sample_162() throws Exception {
		Observable<Integer> ints =
				Observable.create(subscriber -> {
							log("Create");
							subscriber.onNext(42);
							subscriber.onCompleted();
						}
				);
		log("Starting");
		ints.subscribe(i -> log("Element A: " + i));
		ints.subscribe(i -> log("Element B: " + i));
		log("Exit");
	}

	@Test
	public void sample_177() throws Exception {
		Observable<Integer> ints =
				Observable.<Integer>create(subscriber -> {
							//...
						}
				)
						.cache();
	}

	@Test
	public void sample_187() throws Exception {
		//BROKEN! Don't do this
		Observable<BigInteger> naturalNumbers = Observable.create(
				subscriber -> {
					BigInteger i = ZERO;
					while (true) {  //don't do this!
						subscriber.onNext(i);
						i = i.add(ONE);
					}
				});
		naturalNumbers.subscribe(x -> log(x));
	}

	private Observable<BigInteger> naturalNumbers() {
		Observable<BigInteger> naturalNumbers = Observable.create(
				subscriber -> {
					Runnable r = () -> {
						BigInteger i = ZERO;
						while (!subscriber.isUnsubscribed()) {
							subscriber.onNext(i);
							i = i.add(ONE);
						}
					};
					new Thread(r).start();
				});
		return naturalNumbers;
	}

	@Test
	public void sample_221() throws Exception {
		final Observable<BigInteger> naturalNumbers = naturalNumbers();
		Subscription subscription = naturalNumbers.subscribe(x -> log(x));
		//after some time...
		subscription.unsubscribe();
	}

	static <T> Observable<T> delayed(T x) {
		return Observable.create(
				subscriber -> {
					Runnable r = () -> {
						sleep(10, SECONDS);
						if (!subscriber.isUnsubscribed()) {
							subscriber.onNext(x);
							subscriber.onCompleted();
						}
					};
					new Thread(r).start();
				});
	}

	static void sleep(int timeout, TimeUnit unit) {
		try {
			unit.sleep(timeout);
		} catch (InterruptedException ignored) {
			//intentionally ignored
		}
	}

	static <T> Observable<T> delayed2(T x) {
		return Observable.create(
				subscriber -> {
					Runnable r = () -> {/* ... */};
					final Thread thread = new Thread(r);
					thread.start();
					subscriber.add(Subscriptions.create(thread::interrupt));
				});
	}

	Observable<Data> loadAll(Collection<Integer> ids) {
		return Observable.create(subscriber -> {
			ExecutorService pool = Executors.newFixedThreadPool(10);
			AtomicInteger countDown = new AtomicInteger(ids.size());
			//DANGER, violates Rx contract. Don't do this!
			ids.forEach(id -> pool.submit(() -> {
				final Data data = load(id);
				subscriber.onNext(data);
				if (countDown.decrementAndGet() == 0) {
					pool.shutdownNow();
					subscriber.onCompleted();
				}
			}));
		});
	}

	private Data load(Integer id) {
		return new Data();
	}

	Observable<Data> rxLoad(int id) {
		return Observable.create(subscriber -> {
			try {
				subscriber.onNext(load(id));
				subscriber.onCompleted();
			} catch (Exception e) {
				subscriber.onError(e);
			}
		});
	}

	Observable<Data> rxLoad2(int id) {
		return Observable.fromCallable(() ->
				load(id));
	}

	@Test
	public void sample_304() throws Exception {
		Observable
				.timer(1, TimeUnit.SECONDS)
				.subscribe((Long zero) -> log(zero));
		Sleeper.sleep(Duration.ofSeconds(2));
	}

	@Test
	public void sample_311() throws Exception {
		Observable
				.interval(1_000_000 / 60, MICROSECONDS)
				.subscribe((Long i) -> log(i));
		Sleeper.sleep(Duration.ofSeconds(2));
	}


}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/Config.java
================================================
package com.oreilly.rxjava.ch2;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import rx.Observable;
import rx.observables.ConnectableObservable;
import twitter4j.Status;

@Configuration
class Config implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger log = LoggerFactory.getLogger(Config.class);

    private final ConnectableObservable<Status> observable =
        Observable.<Status>create(subscriber -> {
            log.info("Starting");
            //...
        }).publish();

    @Bean
    public Observable<Status> observable() {
        return observable;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("Connecting");
        observable.connect();
    }
}

@Component
class Foo {

    private static final Logger log = LoggerFactory.getLogger(Foo.class);

    @Autowired
    public Foo(Observable<Status> tweets) {
        tweets.subscribe(status -> {
            log.info(status.getText());
        });
        log.info("Subscribed");
    }
}

@Component
class Bar {

    private static final Logger log = LoggerFactory.getLogger(Bar.class);

    @Autowired
    public Bar(Observable<Status> tweets) {
        tweets.subscribe(status -> {
            log.info(status.getText());
        });
        log.info("Subscribed");
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/Data.java
================================================
package com.oreilly.rxjava.ch2;

class Data {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/LazyTwitterObservable.java
================================================
package com.oreilly.rxjava.ch2;

import rx.Observable;
import rx.Subscriber;
import rx.subscriptions.Subscriptions;
import twitter4j.*;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

//DON'T DO THIS, Very brittle and error prone
class LazyTwitterObservable {

	private final Set<Subscriber<? super Status>> subscribers =
			new CopyOnWriteArraySet<>();

	private final TwitterStream twitterStream;

	public LazyTwitterObservable() {
		this.twitterStream = new TwitterStreamFactory().getInstance();
		this.twitterStream.addListener(new StatusListener() {
			@Override
			public void onStatus(Status status) {
				subscribers.forEach(s -> s.onNext(status));
			}

			@Override
			public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
				//...
			}

			@Override
			public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
				//...
			}

			@Override
			public void onScrubGeo(long userId, long upToStatusId) {
				//...
			}

			@Override
			public void onStallWarning(StallWarning warning) {
				//...
			}

			@Override
			public void onException(Exception ex) {
				subscribers.forEach(s -> s.onError(ex));
			}
		});
	}

	private final Observable<Status> observable = Observable.create(
			subscriber -> {
				register(subscriber);
				subscriber.add(Subscriptions.create(() ->
						this.deregister(subscriber)));
			});

	Observable<Status> observe() {
		return observable;
	}

	private synchronized void register(Subscriber<? super Status> subscriber) {
		if (subscribers.isEmpty()) {
			subscribers.add(subscriber);
			twitterStream.sample();
		} else {
			subscribers.add(subscriber);
		}
	}

	private synchronized void deregister(Subscriber<? super Status> subscriber) {
		subscribers.remove(subscriber);
		if (subscribers.isEmpty()) {
			twitterStream.shutdown();
		}
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/NaturalNumbersIterator.java
================================================
package com.oreilly.rxjava.ch2;

import java.math.BigInteger;
import java.util.Iterator;

class NaturalNumbersIterator implements Iterator<BigInteger> {

	private BigInteger current = BigInteger.ZERO;

	public boolean hasNext() {
		return true;
	}

	@Override
	public BigInteger next() {
		current = current.add(BigInteger.ONE);
		return current;
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/Tweet.java
================================================
package com.oreilly.rxjava.ch2;

class Tweet {

	private final String text;

	Tweet(String text) {
		this.text = text;
	}

	String getText() {
		return text;
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/TwitterSample.java
================================================
package com.oreilly.rxjava.ch2;

import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Subscription;
import rx.observables.ConnectableObservable;
import rx.subscriptions.Subscriptions;
import twitter4j.*;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

@Ignore
public class TwitterSample {

	private static final Logger log = LoggerFactory.getLogger(TwitterSample.class);

	@Test
	public void sample_18() throws Exception {
		TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
		twitterStream.addListener(new twitter4j.StatusListener() {
			@Override
			public void onStatus(Status status) {
				log.info("Status: {}", status);
			}

			@Override
			public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
				//...
			}

			@Override
			public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
				//...
			}

			@Override
			public void onScrubGeo(long userId, long upToStatusId) {
				//...
			}

			@Override
			public void onStallWarning(StallWarning warning) {
				//...
			}

			@Override
			public void onException(Exception ex) {
				log.error("Error callback", ex);
			}

			//other callbacks
		});
		twitterStream.sample();
		TimeUnit.SECONDS.sleep(10);
		twitterStream.shutdown();
	}

	void consume(
			Consumer<Status> onStatus,
			Consumer<Exception> onException) {
		TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
		twitterStream.addListener(new StatusListener() {
			@Override
			public void onStatus(Status status) {
				onStatus.accept(status);
			}

			@Override
			public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
				//...
			}

			@Override
			public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
				//...
			}

			@Override
			public void onScrubGeo(long userId, long upToStatusId) {
				//...
			}

			@Override
			public void onStallWarning(StallWarning warning) {
				//...
			}

			@Override
			public void onException(Exception ex) {
				onException.accept(ex);
			}
		});
		twitterStream.sample();
	}

	@Test
	public void sample_99() throws Exception {
		consume(
				status -> log.info("Status: {}", status),
				ex -> log.error("Error callback", ex)
		);
	}

	Observable<Status> observe() {
		return Observable.create(subscriber -> {
			TwitterStream twitterStream =
					new TwitterStreamFactory().getInstance();
			twitterStream.addListener(new StatusListener() {
				@Override
				public void onStatus(Status status) {
					if (subscriber.isUnsubscribed()) {
						twitterStream.shutdown();
					} else {
						subscriber.onNext(status);
					}
				}

				@Override
				public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
					//...
				}

				@Override
				public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
					//...
				}

				@Override
				public void onScrubGeo(long userId, long upToStatusId) {
					//...
				}

				@Override
				public void onStallWarning(StallWarning warning) {
					//...
				}

				@Override
				public void onException(Exception ex) {
					if (subscriber.isUnsubscribed()) {
						twitterStream.shutdown();
					} else {
						subscriber.onError(ex);
					}
				}
			});
			subscriber.add(Subscriptions.create(twitterStream::shutdown));
		});
	}

	@Test
	public void sample_150() throws Exception {
		observe().subscribe(
				status -> log.info("Status: {}", status),
				ex -> log.error("Error callback", ex)
		);
	}

	@Test
	public void sample_162() throws Exception {
		Observable<Status> observable = status();

		Subscription sub1 = observable.subscribe();
		System.out.println("Subscribed 1");
		Subscription sub2 = observable.subscribe();
		System.out.println("Subscribed 2");
		sub1.unsubscribe();
		System.out.println("Unsubscribed 1");
		sub2.unsubscribe();
		System.out.println("Unsubscribed 2");
	}

	private Observable<Status> status() {
		return Observable.create(subscriber -> {
			System.out.println("Establishing connection");
			TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
			//...
			subscriber.add(Subscriptions.create(() -> {
				System.out.println("Disconnecting");
				twitterStream.shutdown();
			}));
			twitterStream.sample();
		});
	}

	@Test
	public void sample_186() throws Exception {
		Observable<Status> observable = status();
		Observable<Status> lazy = observable.publish().refCount();
		//...
		System.out.println("Before subscribers");
		Subscription sub1 = lazy.subscribe();
		System.out.println("Subscribed 1");
		Subscription sub2 = lazy.subscribe();
		System.out.println("Subscribed 2");
		sub1.unsubscribe();
		System.out.println("Unsubscribed 1");
		sub2.unsubscribe();
		System.out.println("Unsubscribed 2");
	}

	@Test
	public void sample_206() throws Exception {
		final Observable<Status> tweets = status();
		ConnectableObservable<Status> published = tweets.publish();
		published.connect();
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch2/TwitterSubject.java
================================================
package com.oreilly.rxjava.ch2;

import rx.Observable;
import rx.subjects.PublishSubject;
import twitter4j.*;

class TwitterSubject {

	private final PublishSubject<Status> subject = PublishSubject.create();

	public TwitterSubject() {
		TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
		twitterStream.addListener(new StatusListener() {
			@Override
			public void onStatus(Status status) {
				subject.onNext(status);
			}

			@Override
			public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
				//...
			}

			@Override
			public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
				//...
			}

			@Override
			public void onScrubGeo(long userId, long upToStatusId) {
				//...
			}

			@Override
			public void onStallWarning(StallWarning warning) {
				//...
			}

			@Override
			public void onException(Exception ex) {
				subject.onError(ex);
			}

		});
		twitterStream.sample();
	}

	public Observable<Status> observe() {
		return subject;
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Car.java
================================================
package com.oreilly.rxjava.ch3;

class Car {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/CarPhoto.java
================================================
package com.oreilly.rxjava.ch3;

class CarPhoto {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/CashTransfer.java
================================================
package com.oreilly.rxjava.ch3;

import java.math.BigDecimal;

class CashTransfer {

	BigDecimal getAmount() {
		return BigDecimal.ONE;
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/CassandraFactStore.java
================================================
package com.oreilly.rxjava.ch3;

import rx.Observable;

class CassandraFactStore implements FactStore {
	@Override
	public Observable<ReservationEvent> observe() {
		return Observable.just(new ReservationEvent());
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Chapter3.java
================================================
package com.oreilly.rxjava.ch3;

import com.oreilly.rxjava.util.Sleeper;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.functions.Func1;
import twitter4j.Status;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;

import static com.oreilly.rxjava.ch3.Sound.DAH;
import static com.oreilly.rxjava.ch3.Sound.DI;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static rx.Observable.*;

@Ignore
public class Chapter3 {

	private static final Logger log = LoggerFactory.getLogger(Chapter3.class);

	@Test
	public void sample_6() throws Exception {
		Observable<String> strings = empty();
		Observable<String> filtered = strings.filter(s -> s.startsWith("#"));
	}

	@Test
	public void sample_15() throws Exception {
		Observable<String> strings = empty();
		Observable<String> comments = strings.filter(s -> s.startsWith("#"));
		Observable<String> instructions = strings.filter(s -> s.startsWith(">"));
		Observable<String> empty = strings.filter(String::isEmpty);
	}

	@Test
	public void sample_26() throws Exception {
		Observable<Status> tweets = empty();
		Observable<Date> dates = tweets.map(new Func1<Status, Date>() {
			@Override
			public Date call(Status status) {
				return status.getCreatedAt();
			}
		});

		Observable<Date> dates2 =
				tweets.map((Status status) -> status.getCreatedAt());

		Observable<Date> dates3 =
				tweets.map((status) -> status.getCreatedAt());

		Observable<Date> dates4 =
				tweets.map(Status::getCreatedAt);
	}

	@Test
	public void sample_49() throws Exception {
		Observable<Status> tweets = empty();

		Observable<Instant> instants = tweets
				.map(Status::getCreatedAt)
				.map((Date d) -> d.toInstant());
	}

	@Test
	public void sample_57() throws Exception {
		just(8, 9, 10)
				.filter(i -> i % 3 > 0)
				.map(i -> "#" + i * 10)
				.filter(s -> s.length() < 4);
	}

	@Test
	public void sample_66() throws Exception {
		just(8, 9, 10)
				.doOnNext(i -> System.out.println("A: " + i))
				.filter(i -> i % 3 > 0)
				.doOnNext(i -> System.out.println("B: " + i))
				.map(i -> "#" + i * 10)
				.doOnNext(s -> System.out.println("C: " + s))
				.filter(s -> s.length() < 4)
				.subscribe(s -> System.out.println("D: " + s));
	}

	@Test
	public void sample_79() throws Exception {
		Observable<Integer> numbers = just(1, 2, 3, 4);

		numbers.map(x -> x * 2);
		numbers.filter(x -> x != 10);

		//equivalent
		numbers.flatMap(x -> just(x * 2));
		numbers.flatMap(x -> (x != 10) ? just(x) : empty());
	}

	@Test
	public void sample_111() throws Exception {
		Observable<Customer> customers = Observable.just(new Customer());
		Observable<Order> orders = customers
				.flatMap(customer ->
						Observable.from(customer.getOrders()));
	}

	@Test
	public void sample_119() throws Exception {
		Observable<Customer> customers = Observable.just(new Customer());
		Observable<Order> orders = customers
				.map(Customer::getOrders)
				.flatMap(Observable::from);
	}

	@Test
	public void sample_127() throws Exception {
		Observable<Customer> customers = Observable.just(new Customer());
		Observable<Order> orders = customers
				.flatMapIterable(Customer::getOrders);
	}

	void store(UUID id) {
		upload(id).subscribe(
				bytes -> {
				}, //ignore
				e -> log.error("Error", e),
				() -> rate(id)
		);
	}

	Observable<Long> upload(UUID id) {
		return Observable.just(42L);
	}

	Observable<Rating> rate(UUID id) {
		return Observable.just(new Rating());
	}

	@Test
	public void sample_155() throws Exception {
		UUID id = UUID.randomUUID();
		upload(id)
				.flatMap(
						bytes -> Observable.empty(),
						e -> Observable.error(e),
						() -> rate(id)
				);
	}

	Observable<Sound> toMorseCode(char ch) {
		switch (ch) {
			case 'a':
				return just(DI, DAH);
			case 'b':
				return just(DAH, DI, DI, DI);
			case 'c':
				return just(DAH, DI, DAH, DI);
			case 'd':
				return just(DAH, DI, DI);
			case 'e':
				return just(DI);
			case 'f':
				return just(DI, DI, DAH, DI);
			case 'g':
				return just(DAH, DAH, DI);
			case 'h':
				return just(DI, DI, DI, DI);
			case 'i':
				return just(DI, DI);
			case 'j':
				return just(DI, DAH, DAH, DAH);
			case 'k':
				return just(DAH, DI, DAH);
			case 'l':
				return just(DI, DAH, DI, DI);
			case 'm':
				return just(DAH, DAH);
			case 'n':
				return just(DAH, DI);
			case 'o':
				return just(DAH, DAH, DAH);
			case 'p':
				return just(DI, DAH, DAH, DI);
			case 'q':
				return just(DAH, DAH, DI, DAH);
			case 'r':
				return just(DI, DAH, DI);
			case 's':
				return just(DI, DI, DI);
			case 't':
				return just(DAH);
			case 'u':
				return just(DI, DI, DAH);
			case 'v':
				return just(DI, DI, DI, DAH);
			case 'w':
				return just(DI, DAH, DAH);
			case 'x':
				return just(DAH, DI, DI, DAH);
			case 'y':
				return just(DAH, DI, DAH, DAH);
			case 'z':
				return just(DAH, DAH, DI, DI);
			case '0':
				return just(DAH, DAH, DAH, DAH, DAH);
			case '1':
				return just(DI, DAH, DAH, DAH, DAH);
			case '2':
				return just(DI, DI, DAH, DAH, DAH);
			case '3':
				return just(DI, DI, DI, DAH, DAH);
			case '4':
				return just(DI, DI, DI, DI, DAH);
			case '5':
				return just(DI, DI, DI, DI, DI);
			case '6':
				return just(DAH, DI, DI, DI, DI);
			case '7':
				return just(DAH, DAH, DI, DI, DI);
			case '8':
				return just(DAH, DAH, DAH, DI, DI);
			case '9':
				return just(DAH, DAH, DAH, DAH, DI);
			default:
				return empty();
		}
	}

	@Test
	public void sample_213() throws Exception {
		just('S', 'p', 'a', 'r', 't', 'a')
				.map(Character::toLowerCase)
				.flatMap(this::toMorseCode);
	}

	@Test
	public void sample_218() throws Exception {
		Observable
				.just("Lorem", "ipsum", "dolor", "sit", "amet",
						"consectetur", "adipiscing", "elit")
				.delay(word -> timer(word.length(), SECONDS))
				.subscribe(System.out::println);

		SECONDS.sleep(15);
	}

	Observable<String> loadRecordsFor(DayOfWeek dow) {
		switch (dow) {
			case SUNDAY:
				return
						interval(90, MILLISECONDS)
								.take(5)
								.map(i -> "Sun-" + i);
			case MONDAY:
				return
						interval(65, MILLISECONDS)
								.take(5)
								.map(i -> "Mon-" + i);
			default:
				throw new IllegalArgumentException("Illegal: " + dow);
		}
	}

	@Test
	public void sample_249() throws Exception {
		Observable
				.just(DayOfWeek.SUNDAY, DayOfWeek.MONDAY)
				.concatMap(this::loadRecordsFor);

	}

	@Test
	public void sample_258() throws Exception {
		List<User> veryLargeList = Arrays.asList(new User(), new User(), new User(), new User());
		Observable<Profile> profiles = Observable
				.from(veryLargeList)
				.flatMap(User::loadProfile);
	}

	@Test
	public void sample_286() throws Exception {
		final WeatherStation station = new BasicWeatherStation();

		Observable<Temperature> temperatureMeasurements = station.temperature();
		Observable<Wind> windMeasurements = station.wind();

		temperatureMeasurements
				.zipWith(windMeasurements,
						(temperature, wind) -> new Weather(temperature, wind));
	}

	@Test
	public void sample_298() throws Exception {
		Observable<Integer> oneToEight = Observable.range(1, 8);
		Observable<String> ranks = oneToEight
				.map(Object::toString);
		Observable<String> files = oneToEight
				.map(x -> 'a' + x - 1)
				.map(ascii -> (char) ascii.intValue())
				.map(ch -> Character.toString(ch));

		Observable<String> squares = files
				.flatMap(file -> ranks.map(rank -> file + rank));
	}

	@Test
	public void sample_312() throws Exception {
		Observable<LocalDate> nextTenDays =
				Observable
						.range(1, 10)
						.map(i -> LocalDate.now().plusDays(i));

		Observable<Vacation> possibleVacations = Observable
				.just(City.Warsaw, City.London, City.Paris)
				.flatMap(city -> nextTenDays.map(date -> new Vacation(city, date))
						.flatMap(vacation ->
								Observable.zip(
										vacation.weather().filter(Weather::isSunny),
										vacation.cheapFlightFrom(City.NewYork),
										vacation.cheapHotel(),
										(w, f, h) -> vacation
								)));
	}

	@Test
	public void sample_332() throws Exception {
		Observable<Long> red = interval(10, TimeUnit.MILLISECONDS);
		Observable<Long> green = interval(10, TimeUnit.MILLISECONDS);

		Observable.zip(
				red.timestamp(),
				green.timestamp(),
				(r, g) -> r.getTimestampMillis() - g.getTimestampMillis()
		).forEach(System.out::println);
	}

	@Test
	public void sample_345() throws Exception {
		Observable.combineLatest(
				interval(17, MILLISECONDS).map(x -> "S" + x),
				interval(10, MILLISECONDS).map(x -> "F" + x),
				(s, f) -> f + ":" + s
		).forEach(System.out::println);
		Sleeper.sleep(Duration.ofSeconds(2));
	}

	@Test
	public void sample_355() throws Exception {
		Observable<String> fast = interval(10, MILLISECONDS)
				.map(x -> "F" + x)
				.delay(100, MILLISECONDS)
				.startWith("FX");
		Observable<String> slow = interval(17, MILLISECONDS).map(x -> "S" + x);
		slow
				.withLatestFrom(fast, (s, f) -> s + ":" + f)
				.forEach(System.out::println);
	}

	@Test
	public void sample_367() throws Exception {
		Observable
				.just(1, 2)
				.startWith(0)
				.subscribe(System.out::println);
	}

	Observable<String> stream(int initialDelay, int interval, String name) {
		return Observable
				.interval(initialDelay, interval, MILLISECONDS)
				.map(x -> name + x)
				.doOnSubscribe(() ->
						log.info("Subscribe to " + name))
				.doOnUnsubscribe(() ->
						log.info("Unsubscribe from " + name));
	}

	@Test
	public void sample_375() throws Exception {
		Observable.amb(
				stream(100, 17, "S"),
				stream(200, 10, "F")
		).subscribe(log::info);
	}

	@Test
	public void sample_393() throws Exception {
		stream(100, 17, "S")
				.ambWith(stream(200, 10, "F"))
				.subscribe(log::info);
	}

	@Test
	public void sample_400() throws Exception {
		//BROKEN!
		Observable<Long> progress = transferFile();

		LongAdder total = new LongAdder();
		progress.subscribe(total::add);
		Sleeper.sleep(Duration.ofSeconds(10));
	}

	private Observable<Long> transferFile() {
		return Observable
				.interval(500, MILLISECONDS)
				.map(x -> RandomUtils.nextLong(10, 30))
				.take(100);
	}

	@Test
	public void sample_419() throws Exception {
		Observable<Long> progress = transferFile();

		Observable<Long> totalProgress = progress
				.scan((total, chunk) -> total + chunk);

		totalProgress
				.toBlocking()
				.subscribe(System.out::println);
	}

	@Test
	public void sample_431() throws Exception {
		Observable<BigInteger> factorials = Observable
				.range(2, 100)
				.scan(BigInteger.ONE, (big, cur) ->
						big.multiply(BigInteger.valueOf(cur)));
	}

	@Test
	public void sample_440() throws Exception {
		Observable<CashTransfer> transfers = Observable.just(new CashTransfer());


		Observable<BigDecimal> total1 = transfers
				.reduce(BigDecimal.ZERO,
						(totalSoFar, transfer) ->
								totalSoFar.add(transfer.getAmount()));

		Observable<BigDecimal> total2 = transfers
				.map(CashTransfer::getAmount)
				.reduce(BigDecimal.ZERO, BigDecimal::add);
	}

	@Test
	public void sample_456() throws Exception {
		Observable<List<Integer>> all = Observable
				.range(10, 20)
				.reduce(new ArrayList<>(), (list, item) -> {
					list.add(item);
					return list;
				});
	}

	@Test
	public void sample_463() throws Exception {
		Observable<List<Integer>> all = Observable
				.range(10, 20)
				.collect(ArrayList::new, List::add);
	}

	@Test
	public void sample_470() throws Exception {
		Observable<String> str = Observable
				.range(1, 10)
				.collect(
						StringBuilder::new,
						(sb, x) -> sb.append(x).append(", "))
				.map(StringBuilder::toString);
	}


	private Observable<Integer> randomInts() {
		Observable<Integer> randomInts = Observable.create(subscriber -> {
			Random random = new Random();
			while (!subscriber.isUnsubscribed()) {
				subscriber.onNext(random.nextInt(1000));
			}
		});
		return randomInts;
	}

	@Test
	public void sample_490() throws Exception {
		final Observable<Integer> randomInts = randomInts();
		Observable<Integer> uniqueRandomInts = randomInts
				.distinct()
				.take(10);
	}

	@Test
	public void sample_499() throws Exception {
		Observable<Status> tweets = Observable.empty();

		Observable<Long> distinctUserIds = tweets
				.map(status -> status.getUser().getId())
				.distinct();
	}

	@Test
	public void sample_508() throws Exception {
		Observable<Status> tweets = Observable.empty();

		Observable<Status> distinctUserIds = tweets
				.distinct(status -> status.getUser().getId());
	}

	@Test
	public void sample_516() throws Exception {
		Observable<Weather> measurements = Observable.empty();

		Observable<Weather> tempChanges = measurements
				.distinctUntilChanged(Weather::getTemperature);
	}

	@Test
	public void sample_524() throws Exception {
		Observable.range(1, 5).take(3);  // [1, 2, 3]
		Observable.range(1, 5).skip(3);  // [4, 5]
		Observable.range(1, 5).skip(5);  // []
	}

	@Test
	public void sample_531() throws Exception {
		Observable.range(1, 5).takeLast(2);  // [4, 5]
		Observable.range(1, 5).skipLast(2);  // [1, 2, 3]
	}

	@Test
	public void sample_537() throws Exception {
		Observable.range(1, 5).takeUntil(x -> x == 3);  // [1, 2, 3]
		Observable.range(1, 5).takeWhile(x -> x != 3);  // [1, 2]
	}

	@Test
	public void sample_543() throws Exception {
		Observable<Integer> size = Observable
				.just('A', 'B', 'C', 'D')
				.reduce(0, (sizeSoFar, ch) -> sizeSoFar + 1);
	}

	@Test
	public void sample_550() throws Exception {
		Observable<Integer> numbers = Observable.range(1, 5);

		numbers.all(x -> x != 4);    // [false]
		numbers.exists(x -> x == 4); // [true]
		numbers.contains(4);         // [true]
	}

	@Test
	public void sample_559() throws Exception {
		Observable<Data> veryLong = Observable
				.range(0, 1_000)
				.map(x -> new Data());
		final Observable<Data> ends = Observable.concat(
				veryLong.take(5),
				veryLong.takeLast(5)
		);
	}

	@Test
	public void sample_570() throws Exception {
		Observable<Car> fromCache = loadFromCache();
		Observable<Car> fromDb = loadFromDb();

		Observable<Car> found = Observable
				.concat(fromCache, fromDb)
				.first();

	}

	private Observable<Car> loadFromDb() {
		return Observable.just(new Car());
	}

	private Observable<Car> loadFromCache() {
		return Observable.just(new Car());
	}

	@Test
	public void sample_589() throws Exception {
		Observable<Boolean> trueFalse = Observable.just(true, false).repeat();
		Observable<Integer> upstream = Observable.range(30, 8);
		Observable<Integer> downstream = upstream
				.zipWith(trueFalse, Pair::of)
				.filter(Pair::getRight)
				.map(Pair::getLeft);
	}

	@Test
	public void sample_600() throws Exception {
		Observable<Boolean> trueFalse = Observable.just(true, false).repeat();
		Observable<Integer> upstream = Observable.range(30, 8);

		upstream.zipWith(trueFalse, (t, bool) ->
				bool ? just(t) : empty())
				.flatMap(obs -> obs);
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/City.java
================================================
package com.oreilly.rxjava.ch3;

enum City {

	Warsaw, London, Paris, NewYork

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/CustomOperators.java
================================================
package com.oreilly.rxjava.ch3;

import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;
import rx.Subscriber;

import static rx.Observable.just;

@Ignore
public class CustomOperators {

	static <T> Observable<T> odd(Observable<T> upstream) {
		Observable<Boolean> trueFalse = just(true, false).repeat();
		return upstream
				.zipWith(trueFalse, Pair::of)
				.filter(Pair::getRight)
				.map(Pair::getLeft);
	}

	private <T> Observable.Transformer<T, T> odd() {
		Observable<Boolean> trueFalse = just(true, false).repeat();
		return upstream -> upstream
				.zipWith(trueFalse, Pair::of)
				.filter(Pair::getRight)
				.map(Pair::getLeft);
	}
	
	@Test
	public void sample_618() throws Exception {
		//[A, B, C, D, E...]
		Observable<Character> alphabet =
				Observable
						.range(0, 'Z' - 'A' + 1)
						.map(c -> (char) ('A' + c));

		//[A, C, E, G, I...]
		alphabet
				.compose(odd())
				.forEach(System.out::println);

	}

	@Test
	public void sample_9() throws Exception {
		Observable
				.range(1, 1000)
				.filter(x -> x % 3 == 0)
				.distinct()
				.reduce((a, x) -> a + x)
				.map(Integer::toHexString)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_59() throws Exception {
		Observable<String> odd = Observable
				.range(1, 9)
				.lift(toStringOfOdd());
		//Will emit: "1", "3", "5", "7" and "9" strings

		odd.subscribe(System.out::println);
	}

	<T> Observable.Operator<String, T> toStringOfOdd() {
		return new Observable.Operator<String, T>() {

			private boolean odd = true;

			@Override
			public Subscriber<? super T> call(Subscriber<? super String> child) {
				return new Subscriber<T>(child) {
					@Override
					public void onCompleted() {
						child.onCompleted();
					}

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

					@Override
					public void onNext(T t) {
						if(odd) {
							child.onNext(t.toString());
						} else {
							request(1);
						}
						odd = !odd;
					}
				};
			}
		};
	}


	@Test
	public void sample_67() throws Exception {
		Observable
				.range(1, 9)
				.buffer(1, 2)
				.concatMapIterable(x -> x)
				.map(Object::toString);
	}

	@Test
	public void sample_112() throws Exception {
		Observable
				.range(1, 4)
				.repeat()
				.lift(toStringOfOdd())
				.take(3)
				.subscribe(
						System.out::println,
						Throwable::printStackTrace,
						() -> System.out.println("Completed")
				);
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Customer.java
================================================
package com.oreilly.rxjava.ch3;

import java.util.Arrays;
import java.util.List;

class Customer {

	List<Order> getOrders() {
		return Arrays.asList(new Order(), new Order());
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Data.java
================================================
package com.oreilly.rxjava.ch3;

class Data {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/FactStore.java
================================================
package com.oreilly.rxjava.ch3;

import rx.Observable;

interface FactStore {
	Observable<ReservationEvent> observe();
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Flight.java
================================================
package com.oreilly.rxjava.ch3;

class Flight {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Hotel.java
================================================
package com.oreilly.rxjava.ch3;

class Hotel {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/LicensePlate.java
================================================
package com.oreilly.rxjava.ch3;

class LicensePlate {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Licenses.java
================================================
package com.oreilly.rxjava.ch3;

import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;

@Ignore
public class Licenses {

	Observable<CarPhoto> cars() {
		return Observable.just(new CarPhoto());
	}

	Observable<LicensePlate> recognize(CarPhoto photo) {
		return Observable.just(new LicensePlate());
	}

	@Test
	public void sample_100() throws Exception {
		Observable<CarPhoto> cars = cars();

		Observable<Observable<LicensePlate>> plates =
				cars.map(this::recognize);

		Observable<LicensePlate> plates2 =
				cars.flatMap(this::recognize);
	}


	Observable<LicensePlate> fastAlgo(CarPhoto photo) {
		//Fast but poor quality
		return Observable.just(new LicensePlate());
	}

	Observable<LicensePlate> preciseAlgo(CarPhoto photo) {
		//Precise but can be expensive
		return Observable.just(new LicensePlate());
	}

	Observable<LicensePlate> experimentalAlgo(CarPhoto photo) {
		//Unpredictable, running anyway
		return Observable.just(new LicensePlate());
	}

	@Test
	public void sample_317() throws Exception {
		CarPhoto photo = new CarPhoto();
		Observable<LicensePlate> all = Observable.merge(
				preciseAlgo(photo),
				fastAlgo(photo),
				experimentalAlgo(photo)
		);
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/OperatorMap.java
================================================
package com.oreilly.rxjava.ch3;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;

final class OperatorMap<T, R> implements Observable.Operator<R, T> {

    private final Func1<T, R> transformer;

    public OperatorMap(Func1<T, R> transformer) {
        this.transformer = transformer;
    }

    @Override
    public Subscriber<? super T> call(Subscriber<? super R> child) {
        return new Subscriber<T>(child) {

            @Override
            public void onCompleted() {
                child.onCompleted();
            }

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

            @Override
            public void onNext(T t) {
                try {
                    child.onNext(transformer.call(t));
                } catch (Exception e) {
                    onError(e);
                }
            }
        };
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Order.java
================================================
package com.oreilly.rxjava.ch3;

class Order {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Profile.java
================================================
package com.oreilly.rxjava.ch3;

class Profile {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Rating.java
================================================
package com.oreilly.rxjava.ch3;

class Rating {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Reservation.java
================================================
package com.oreilly.rxjava.ch3;

class Reservation {

    Reservation consume(ReservationEvent event) {
        //mutate myself
        return this;
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/ReservationEvent.java
================================================
package com.oreilly.rxjava.ch3;

import java.util.UUID;

class ReservationEvent {
	private final UUID uuid = UUID.randomUUID();
	public UUID getReservationUuid() {
		return uuid;
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Reservations.java
================================================
package com.oreilly.rxjava.ch3;

import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;
import rx.observables.GroupedObservable;

import java.util.Optional;
import java.util.UUID;

@Ignore
public class Reservations {

	@Test
	public void sample_9() throws Exception {
		FactStore factStore = new CassandraFactStore();
		Observable<ReservationEvent> facts = factStore.observe();
		facts.subscribe(this::updateProjection);
	}

	void updateProjection(ReservationEvent event) {

	}

	private void store(UUID id, Reservation modified) {
		//...
	}

	Optional<Reservation> loadBy(UUID uuid) {
		//...
		return Optional.of(new Reservation());
	}

	@Test
	public void sample_34() throws Exception {
		FactStore factStore = new CassandraFactStore();

		Observable<ReservationEvent> facts = factStore.observe();

		facts
				.flatMap(this::updateProjectionAsync)
				.subscribe();

		//...
	}

	Observable<ReservationEvent> updateProjectionAsync(ReservationEvent event) {
		//possibly asynchronous
		return Observable.just(new ReservationEvent());
	}

	@Test
	public void sample_52() throws Exception {
		FactStore factStore = new CassandraFactStore();

		Observable<ReservationEvent> facts = factStore.observe();

		Observable<GroupedObservable<UUID, ReservationEvent>> grouped =
				facts.groupBy(ReservationEvent::getReservationUuid);

		grouped.subscribe(byUuid -> {
			byUuid.subscribe(this::updateProjection);
		});
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Shakespeare.java
================================================
package com.oreilly.rxjava.ch3;

import com.oreilly.rxjava.util.Sleeper;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;

import java.time.Duration;
import java.util.Random;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static rx.Observable.just;

@Ignore
public class Shakespeare {

	Observable<String> speak(String quote, long millisPerChar) {
		String[] tokens = quote.replaceAll("[:,]", "").split(" ");
		Observable<String> words = Observable.from(tokens);
		Observable<Long> absoluteDelay = words
				.map(String::length)
				.map(len -> len * millisPerChar)
				.scan((total, current) -> total + current);
		return words
				.zipWith(absoluteDelay.startWith(0L), Pair::of)
				.flatMap(pair -> just(pair.getLeft())
						.delay(pair.getRight(), MILLISECONDS));
	}

	@Test
	public void sample_28() throws Exception {
		Observable<String> alice = speak(
				"To be, or not to be: that is the question", 110);
		Observable<String> bob = speak(
				"Though this be madness, yet there is method in't", 90);
		Observable<String> jane = speak(
				"There are more things in Heaven and Earth, " +
						"Horatio, than are dreamt of in your philosophy", 100);

		Observable
				.merge(
						alice.map(w -> "Alice: " + w),
						bob.map(w   -> "Bob:   " + w),
						jane.map(w  -> "Jane:  " + w)
				)
				.subscribe(System.out::println);

		Sleeper.sleep(Duration.ofSeconds(10));
	}

	@Test
	public void sample_52() throws Exception {
		Observable<String> alice = speak(
				"To be, or not to be: that is the question", 110);
		Observable<String> bob = speak(
				"Though this be madness, yet there is method in't", 90);
		Observable<String> jane = speak(
				"There are more things in Heaven and Earth, " +
						"Horatio, than are dreamt of in your philosophy", 100);

		Random rnd = new Random();
		Observable<Observable<String>> quotes = just(
				alice.map(w -> "Alice: " + w),
				bob.map(w   -> "Bob:   " + w),
				jane.map(w  -> "Jane:  " + w))
				.flatMap(innerObs -> just(innerObs)
						.delay(rnd.nextInt(5), SECONDS));

		Observable
				.switchOnNext(quotes)
				.subscribe(System.out::println);
		Sleeper.sleep(Duration.ofSeconds(10));
	}


}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Sound.java
================================================
package com.oreilly.rxjava.ch3;

enum Sound { DI, DAH }


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/User.java
================================================
package com.oreilly.rxjava.ch3;

import rx.Observable;

class User {
    Observable<Profile> loadProfile() {
        //Make HTTP request...
        return Observable.just(new Profile());
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Vacation.java
================================================
package com.oreilly.rxjava.ch3;

import rx.Observable;

import java.time.LocalDate;

class Vacation {
	private final City where;
	private final LocalDate when;

	Vacation(City where, LocalDate when) {
		this.where = where;
		this.when = when;
	}

	public Observable<Weather> weather() {
		//...
		return Observable.just(new Weather(new Temperature(), new Wind()));
	}

	public Observable<Flight> cheapFlightFrom(City from) {
		//...
		return Observable.just(new Flight());
	}

	public Observable<Hotel> cheapHotel() {
		//...
		return Observable.just(new Hotel());
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/Weather.java
================================================
package com.oreilly.rxjava.ch3;

class Weather {
    private final Temperature temperature;

    public Weather(Temperature temperature, Wind wind) {
        //...
        this.temperature = temperature;
    }

    public boolean isSunny() {
        return true;
    }

    Temperature getTemperature() {
        return temperature;
    }
}

================================================
FILE: src/test/java/com/oreilly/rxjava/ch3/WeatherStation.java
================================================
package com.oreilly.rxjava.ch3;

import rx.Observable;

interface WeatherStation {
    Observable<Temperature> temperature();
    Observable<Wind> wind();
}

class BasicWeatherStation implements WeatherStation {

    @Override
    public Observable<Temperature> temperature() {
        return Observable.just(new Temperature());
    }

    @Override
    public Observable<Wind> wind() {
        return Observable.just(new Wind());
    }
}

class Temperature {}

class Wind {}



================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Book.java
================================================
package com.oreilly.rxjava.ch4;

class Book {
	public String getTitle() {
		return "Title";
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Chapter4.java
================================================
package com.oreilly.rxjava.ch4;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.oreilly.rxjava.util.Sleeper;
import org.apache.commons.lang3.RandomUtils;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Scheduler;
import rx.observables.BlockingObservable;
import rx.schedulers.Schedulers;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;


@Ignore
public class Chapter4 {

	private static final Logger log = LoggerFactory.getLogger(Chapter4.class);

	private final PersonDao personDao = new PersonDao();
	private int orderBookLength;

	@Test
	public void sample_9() throws Exception {
		List<Person> people = personDao.listPeople();
		String json = marshal(people);
	}

	@Test
	public void sample_20() throws Exception {
		Observable<Person> peopleStream = personDao.listPeople2();
		Observable<List<Person>> peopleList = peopleStream.toList();
		BlockingObservable<List<Person>> peopleBlocking = peopleList.toBlocking();
		List<Person> people = peopleBlocking.single();
	}

	private String marshal(List<Person> people) {
		return people.toString();
	}

	@Test
	public void sample_34() throws Exception {
		List<Person> people = personDao
				.listPeople2()
				.toList()
				.toBlocking()
				.single();
	}

	void bestBookFor(Person person) {
		Book book;
		try {
			book = recommend(person);
		} catch (Exception e) {
			book = bestSeller();
		}
		display(book.getTitle());
	}

	private Book bestSeller() {
		return new Book();
	}

	private Book recommend(Person person) {
		return new Book();
	}

	void display(String title) {
		//...
	}

	void bestBookFor2(Person person) {
		Observable<Book> recommended = recommend2(person);
		Observable<Book> bestSeller = bestSeller2();
		Observable<Book> book = recommended.onErrorResumeNext(bestSeller);
		Observable<String> title = book.map(Book::getTitle);
		title.subscribe(this::display);
	}

	void bestBookFor3(Person person) {
		recommend2(person)
				.onErrorResumeNext(bestSeller2())
				.map(Book::getTitle)
				.subscribe(this::display);
	}

	private Observable<Book> bestSeller2() {
		return Observable.fromCallable(Book::new);
	}

	private Observable<Book> recommend2(Person person) {
		return Observable.fromCallable(Book::new);
	}

	@Test
	public void sample_89() throws Exception {
		Observable
				.interval(10, TimeUnit.MILLISECONDS)
				.map(x -> getOrderBookLength())
				.distinctUntilChanged();
	}

	private int getOrderBookLength() {
		return RandomUtils.nextInt(5, 10);
	}

	Observable<Item> observeNewItems() {
		return Observable
				.interval(1, TimeUnit.SECONDS)
				.flatMapIterable(x -> query())
				.distinct();
	}

	List<Item> query() {
		//take snapshot of file system directory
		//or database table
		return Collections.emptyList();
	}

	@Test
	public void sample_118() throws Exception {
		ThreadFactory threadFactory = new ThreadFactoryBuilder()
				.setNameFormat("MyPool-%d")
				.build();
		Executor executor = new ThreadPoolExecutor(
				10,  //corePoolSize
				10,  //maximumPoolSize
				0L, TimeUnit.MILLISECONDS, //keepAliveTime, unit
				new LinkedBlockingQueue<>(1000),  //workQueue
				threadFactory
		);
		Scheduler scheduler = Schedulers.from(executor);
	}

	@Test
	public void sample_136() throws Exception {
		ExecutorService executor = Executors.newFixedThreadPool(10);
	}

	private final long start = System.currentTimeMillis();

	void log(Object label) {
		System.out.println(
				System.currentTimeMillis() - start + "\t| " +
						Thread.currentThread().getName()   + "\t| " +
						label);
	}

	@Test
	public void sample_141() throws Exception {
		Scheduler scheduler = Schedulers.immediate();
		Scheduler.Worker worker = scheduler.createWorker();

		log("Main start");
		worker.schedule(() -> {
			log(" Outer start");
			sleepOneSecond();
			worker.schedule(() -> {
				log("  Inner start");
				sleepOneSecond();
				log("  Inner end");
			});
			log(" Outer end");
		});
		log("Main end");
		worker.unsubscribe();
	}

	@Test
	public void sample_175() throws Exception {
		Scheduler scheduler = Schedulers.immediate();
		Scheduler.Worker worker = scheduler.createWorker();

		log("Main start");
		worker.schedule(() -> {
			log(" Outer start");
			sleepOneSecond();
			worker.schedule(() -> {
				log("  Middle start");
				sleepOneSecond();
				worker.schedule(() -> {
					log("   Inner start");
					sleepOneSecond();
					log("   Inner end");
				});
				log("  Middle end");
			});
			log(" Outer end");
		});
		log("Main end");
	}

	private void sleepOneSecond() {
		Sleeper.sleep(Duration.ofSeconds(1));
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Flight.java
================================================
package com.oreilly.rxjava.ch4;

class Flight {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Flights.java
================================================
package com.oreilly.rxjava.ch4;

import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.schedulers.Schedulers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static rx.Observable.fromCallable;

@Ignore
public class Flights {

	private static final Logger log = LoggerFactory.getLogger(Flights.class);

	Flight lookupFlight(String flightNo) {
		//...
		return new Flight();
	}

	Passenger findPassenger(long id) {
		//...
		return new Passenger();
	}

	Ticket bookTicket(Flight flight, Passenger passenger) {
		//...
		return new Ticket();
	}

	SmtpResponse sendEmail(Ticket ticket) {
		//...
		return new SmtpResponse();
	}

	@Test
	public void sample_29() throws Exception {
		Flight flight = lookupFlight("LOT 783");
		Passenger passenger = findPassenger(42);
		Ticket ticket = bookTicket(flight, passenger);
		sendEmail(ticket);
	}

	Observable<Flight> rxLookupFlight(String flightNo) {
		return Observable.defer(() ->
				Observable.just(lookupFlight(flightNo)));
	}

	Observable<Passenger> rxFindPassenger(long id) {
		return Observable.defer(() ->
				Observable.just(findPassenger(id)));
	}

	@Test
	public void sample_49() throws Exception {
		Observable<Flight> flight = rxLookupFlight("LOT 783");
		Observable<Passenger> passenger = rxFindPassenger(42);
		Observable<Ticket> ticket =
				flight.zipWith(passenger, (f, p) -> bookTicket(f, p));
		ticket.subscribe(this::sendEmail);
	}

	@Test
	public void sample_67() throws Exception {
		rxLookupFlight("LOT 783")
				.subscribeOn(Schedulers.io())
				.timeout(100, TimeUnit.MILLISECONDS);
	}

	@Test
	public void sample_76() throws Exception {
		Observable<Flight> flight =
				rxLookupFlight("LOT 783").subscribeOn(Schedulers.io());
		Observable<Passenger> passenger =
				rxFindPassenger(42).subscribeOn(Schedulers.io());

		Observable<Ticket> ticket = flight
				.zipWith(passenger, (Flight f, Passenger p) -> Pair.of(f, p))
				.flatMap(pair -> rxBookTicket(pair.getLeft(), pair.getRight()));
	}

	private Observable<Ticket> rxBookTicket(Flight left, Passenger right) {
		return Observable.just(new Ticket());
	}

	@Test
	public void sample_85() throws Exception {
		Observable<Flight> flight =
				rxLookupFlight("LOT 783").subscribeOn(Schedulers.io());
		Observable<Passenger> passenger =
				rxFindPassenger(42).subscribeOn(Schedulers.io());

		Observable<Ticket> ticket = flight
				.zipWith(passenger, this::rxBookTicket)
				.flatMap(obs -> obs);
	}

	@Test
	public void sample_97() throws Exception {
		List<Ticket> tickets = Arrays.asList(new Ticket(), new Ticket(), new Ticket());
		List<Ticket> failures = new ArrayList<>();
		for (Ticket ticket : tickets) {
			try {
				sendEmail(ticket);
			} catch (Exception e) {
				log.warn("Failed to send {}", ticket, e);
				failures.add(ticket);
			}
		}
	}

	@Test
	public void sample_120() throws Exception {
		List<Ticket> tickets = Arrays.asList(new Ticket(), new Ticket(), new Ticket());

		List<Pair<Ticket, Future<SmtpResponse>>> tasks = tickets
				.stream()
				.map(ticket -> Pair.of(ticket, sendEmailAsync(ticket)))
				.collect(toList());

		List<Ticket> failures = tasks.stream()
				.flatMap(pair -> {
					try {
						Future<SmtpResponse> future = pair.getRight();
						future.get(1, TimeUnit.SECONDS);
						return Stream.empty();
					} catch (Exception e) {
						Ticket ticket = pair.getLeft();
						log.warn("Failed to send {}", ticket, e);
						return Stream.of(ticket);
					}
				})
				.collect(toList());
	}

	private Future<SmtpResponse> sendEmailAsync(Ticket ticket) {
		return CompletableFuture.supplyAsync(() -> sendEmail(ticket));
	}

	@Test
	public void sample_152() throws Exception {
		List<Ticket> tickets = Arrays.asList(new Ticket(), new Ticket(), new Ticket());

		//WARNING: code is sequential despite utilizing thread pool
		tickets
				.stream()
				.map(ticket -> Pair.of(ticket, sendEmailAsync(ticket)))
				.map(pair -> {
					try {
						return pair.getRight().get();
					} catch (InterruptedException | ExecutionException e) {
						throw new RuntimeException(e);
					}
				})
				.collect(toList());
	}

	Observable<SmtpResponse> rxSendEmail(Ticket ticket) {
		//unusual synchronous Observable
		return fromCallable(() -> sendEmail(ticket));
	}

	@Test
	public void sample_177() throws Exception {
		List<Ticket> tickets = Arrays.asList(new Ticket(), new Ticket(), new Ticket());
		List<Ticket> failures = Observable.from(tickets)
				.flatMap(ticket ->
						rxSendEmail(ticket)
								.flatMap(response -> Observable.<Ticket>empty())
								.doOnError(e -> log.warn("Failed to send {}", ticket, e))
								.onErrorReturn(err -> ticket))
				.toList()
				.toBlocking()
				.single();
	}

	@Test
	public void sample_191() throws Exception {
		List<Ticket> tickets = Arrays.asList(new Ticket(), new Ticket(), new Ticket());

		Observable
				.from(tickets)
				.flatMap(ticket ->
						rxSendEmail(ticket)
								.ignoreElements()
								.doOnError(e -> log.warn("Failed to send {}", ticket, e))
								.subscribeOn(Schedulers.io()));
	}



}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Item.java
================================================
package com.oreilly.rxjava.ch4;

class Item {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/JmsConsumer.java
================================================
package com.oreilly.rxjava.ch4;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import rx.Observable;
import rx.subjects.PublishSubject;

@Component
class JmsConsumer {

    private final PublishSubject<Message> subject = PublishSubject.create();

    @JmsListener(destination = "orders", concurrency="1")
    public void newOrder(Message msg) {
        subject.onNext(msg);
    }

    Observable<Message> observe() {
        return subject;
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Messaging.java
================================================
package com.oreilly.rxjava.ch4;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQTopic;
import org.junit.Ignore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.subscriptions.Subscriptions;

import javax.jms.*;

import static javax.jms.Session.AUTO_ACKNOWLEDGE;

@Ignore
public class Messaging {

	private static final Logger log = LoggerFactory.getLogger(Messaging.class);

	void connect() {
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
		Observable<String> txtMessages = observe(connectionFactory, new ActiveMQTopic("orders"))
				.cast(TextMessage.class)
				.flatMap(m -> {
					try {
						return Observable.just(m.getText());
					} catch (JMSException e) {
						return Observable.error(e);
					}
				});
	}

	public Observable<Message> observe(ConnectionFactory connectionFactory, Topic topic) {
		return Observable.create(subscriber -> {
			try {
				subscribeThrowing(subscriber, connectionFactory, topic);
			} catch (JMSException e) {
				subscriber.onError(e);
			}
		});
	}

	private void subscribeThrowing(Subscriber<? super Message> subscriber, ConnectionFactory connectionFactory, Topic orders) throws JMSException {
		Connection connection = connectionFactory.createConnection();
		Session session = connection.createSession(true, AUTO_ACKNOWLEDGE);
		MessageConsumer consumer = session.createConsumer(orders);
		consumer.setMessageListener(subscriber::onNext);
		subscriber.add(onUnsubscribe(connection));
		connection.start();
	}

	private Subscription onUnsubscribe(Connection connection) {
		return Subscriptions.create(() -> {
			try {
				connection.close();
			} catch (Exception e) {
				log.error("Can't close", e);
			}
		});
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Passenger.java
================================================
package com.oreilly.rxjava.ch4;

class Passenger {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Person.java
================================================
package com.oreilly.rxjava.ch4;

class Person {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/PersonDao.java
================================================
package com.oreilly.rxjava.ch4;

import rx.Observable;

import java.util.Arrays;
import java.util.List;

import static rx.Observable.defer;
import static rx.Observable.from;

class PersonDao {

    private static final int PAGE_SIZE = 10;

    Observable<Person> allPeople(int initialPage) {
        return defer(() -> from(listPeople(initialPage)))
                .concatWith(defer(() ->
                        allPeople(initialPage + 1)));
    }

    void allPeople() {
        Observable<Person> allPages = Observable
                .range(0, Integer.MAX_VALUE)
                .map(this::listPeople)
                .takeWhile(list -> !list.isEmpty())
                .concatMap(Observable::from);
    }

    List<Person> listPeople() {
        return query("SELECT * FROM PEOPLE");
    }

    List<Person> listPeople(int initialPage) {
        return query("SELECT * FROM PEOPLE OFFSET ? MAX ?", initialPage * 10, PAGE_SIZE);
    }

    Observable<Person> listPeople2() {
        final List<Person> people = query("SELECT * FROM PEOPLE");
        return Observable.from(people);
    }

    public Observable<Person> listPeople3() {
        return defer(() ->
                Observable.from(query("SELECT * FROM PEOPLE")));
    }

    private List<Person> query(String sql, Object... args) {
        //...
        return Arrays.asList(new Person(), new Person());
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/RxGroceries.java
================================================
package com.oreilly.rxjava.ch4;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;

import java.math.BigDecimal;

class RxGroceries {

    private static final Logger log = LoggerFactory.getLogger(RxGroceries.class);

    private final long start = System.currentTimeMillis();

    void log(Object label) {
        System.out.println(
                System.currentTimeMillis() - start + "\t| " +
                        Thread.currentThread().getName()   + "\t| " +
                        label);
    }


    Observable<BigDecimal> purchase(String productName, int quantity) {
        return Observable.fromCallable(() ->
            doPurchase(productName, quantity));
    }

    BigDecimal doPurchase(String productName, int quantity) {
        log("Purchasing " + quantity + " " + productName);
        //real logic here
        log("Done " + quantity + " " + productName);
        BigDecimal priceForProduct = BigDecimal.ONE;
        return priceForProduct;
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Schedulers.java
================================================
package com.oreilly.rxjava.ch4;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Scheduler;

import java.math.BigDecimal;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

import static java.util.concurrent.Executors.newFixedThreadPool;
import static java.util.concurrent.TimeUnit.SECONDS;

@Ignore
public class Schedulers {

	private static final Logger log = LoggerFactory.getLogger(Schedulers.class);

	ExecutorService poolA = newFixedThreadPool(10, threadFactory("Sched-A-%d"));
	Scheduler schedulerA = rx.schedulers.Schedulers.from(poolA);

	ExecutorService poolB = newFixedThreadPool(10, threadFactory("Sched-B-%d"));
	Scheduler schedulerB = rx.schedulers.Schedulers.from(poolB);

	ExecutorService poolC = newFixedThreadPool(10, threadFactory("Sched-C-%d"));
	Scheduler schedulerC = rx.schedulers.Schedulers.from(poolC);

	private final long start = System.currentTimeMillis();

	void log(Object label) {
		System.out.println(
				System.currentTimeMillis() - start + "\t| " +
						Thread.currentThread().getName()   + "\t| " +
						label);
	}

	private ThreadFactory threadFactory(String pattern) {
		return new ThreadFactoryBuilder()
				.setNameFormat(pattern)
				.build();
	}

	Observable<String> simple() {
		return Observable.create(subscriber -> {
			log("Subscribed");
			subscriber.onNext("A");
			subscriber.onNext("B");
			subscriber.onCompleted();
		});
	}

	@Test
	public void sample_215() throws Exception {
		log("Starting");
		final Observable<String> obs = simple();
		log("Created");
		obs
				.subscribeOn(schedulerA)
				.subscribe(
						x -> log("Got " + x),
						Throwable::printStackTrace,
						() -> log("Completed")
				);
		log("Exiting");
	}


	@Test
	public void sample_33() throws Exception {
		//Don't do this
		Observable<String> obs = Observable.create(subscriber -> {
			log("Subscribed");
			Runnable code = () -> {
				subscriber.onNext("A");
				subscriber.onNext("B");
				subscriber.onCompleted();
			};
			new Thread(code, "Async").start();
		});
	}

	@Test
	public void sample_77() throws Exception {
		log("Starting");
		Observable<String> obs = simple();
		log("Created");
		obs
				.subscribeOn(schedulerA)
				//many other operators
				.subscribeOn(schedulerB)
				.subscribe(
						x -> log("Got " + x),
						Throwable::printStackTrace,
						() -> log("Completed")
				);
		log("Exiting");
	}

	@Test
	public void sample_103() throws Exception {
		log("Starting");
		final Observable<String> obs = simple();
		log("Created");
		obs
				.doOnNext(this::log)
				.map(x -> x + '1')
				.doOnNext(this::log)
				.map(x -> x + '2')
				.subscribeOn(schedulerA)
				.doOnNext(this::log)
				.subscribe(
						x -> log("Got " + x),
						Throwable::printStackTrace,
						() -> log("Completed")
				);
		log("Exiting");
	}

	private final RxGroceries rxGroceries = new RxGroceries();

	@Test
	public void sample_122() throws Exception {
		Observable<BigDecimal> totalPrice = Observable
				.just("bread", "butter", "milk", "tomato", "cheese")
				.subscribeOn(schedulerA)  //BROKEN!!!
				.map(prod -> rxGroceries.doPurchase(prod, 1))
				.reduce(BigDecimal::add)
				.single();
	}

	@Test
	public void sample_135() throws Exception {
		final Observable<BigDecimal> totalPrice = Observable
				.just("bread", "butter", "milk", "tomato", "cheese")
				.subscribeOn(schedulerA)
				.flatMap(prod -> rxGroceries.purchase(prod, 1))
				.reduce(BigDecimal::add)
				.single();
	}

	@Test
	public void sample_145() throws Exception {
		Observable<BigDecimal> totalPrice = Observable
				.just("bread", "butter", "milk", "tomato", "cheese")
				.flatMap(prod ->
						rxGroceries
								.purchase(prod, 1)
								.subscribeOn(schedulerA))
				.reduce(BigDecimal::add)
				.single();
	}

	@Test
	public void sample_157() throws Exception {
		Observable<BigDecimal> totalPrice = Observable
				.just("bread", "butter", "egg", "milk", "tomato",
						"cheese", "tomato", "egg", "egg")
				.groupBy(prod -> prod)
				.flatMap(grouped -> grouped
						.count()
						.map(quantity -> {
							String productName = grouped.getKey();
							return Pair.of(productName, quantity);
						}))
				.flatMap(order -> rxGroceries
						.purchase(order.getKey(), order.getValue())
						.subscribeOn(schedulerA))
				.reduce(BigDecimal::add)
				.single();
	}

	@Test
	public void sample_177() throws Exception {
		log("Starting");
		final Observable<String> obs = simple();
		log("Created");
		obs
				.doOnNext(x -> log("Found 1: " + x))
				.observeOn(schedulerA)
				.doOnNext(x -> log("Found 2: " + x))
				.subscribe(
						x -> log("Got 1: " + x),
						Throwable::printStackTrace,
						() -> log("Completed")
				);
		log("Exiting");
	}

	@Test
	public void sample_194() throws Exception {
		log("Starting");
		final Observable<String> obs = simple();
		log("Created");
		obs
				.doOnNext(x -> log("Found 1: " + x))
				.observeOn(schedulerB)
				.doOnNext(x -> log("Found 2: " + x))
				.observeOn(schedulerC)
				.doOnNext(x -> log("Found 3: " + x))
				.subscribeOn(schedulerA)
				.subscribe(
						x -> log("Got 1: " + x),
						Throwable::printStackTrace,
						() -> log("Completed")
				);
		log("Exiting");
	}

	@Test
	public void sample_214() throws Exception {
		log("Starting");
		Observable<String> obs = Observable.create(subscriber -> {
			log("Subscribed");
			subscriber.onNext("A");
			subscriber.onNext("B");
			subscriber.onNext("C");
			subscriber.onNext("D");
			subscriber.onCompleted();
		});
		log("Created");
		obs
				.subscribeOn(schedulerA)
				.flatMap(record -> store(record).subscribeOn(schedulerB))
				.observeOn(schedulerC)
				.subscribe(
						x -> log("Got: " + x),
						Throwable::printStackTrace,
						() -> log("Completed")
				);
		log("Exiting");
	}

	Observable<UUID> store(String s) {
		return Observable.create(subscriber -> {
			log("Storing " + s);
			//hard work
			subscriber.onNext(UUID.randomUUID());
			subscriber.onCompleted();
		});
	}

	@Test
	public void sample_248() throws Exception {
		Observable
				.just('A', 'B')
				.delay(1, SECONDS, schedulerA)
				.subscribe(this::log);
	}


}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/SimplifiedHandlerScheduler.java
================================================
package com.oreilly.rxjava.ch4;

import android.os.Handler;
import android.os.Looper;
import rx.Scheduler;
import rx.Subscription;
import rx.functions.Action0;
import rx.internal.schedulers.ScheduledAction;
import rx.subscriptions.CompositeSubscription;
import rx.subscriptions.Subscriptions;

import java.util.concurrent.TimeUnit;

public final class SimplifiedHandlerScheduler extends Scheduler {

    @Override
    public Worker createWorker() {
        return new HandlerWorker();
    }

    static class HandlerWorker extends Worker {

        private final Handler handler = new Handler(Looper.getMainLooper());

        @Override
        public Subscription schedule(final Action0 action) {
            return schedule(action, 0, TimeUnit.MILLISECONDS);
        }

        private final CompositeSubscription compositeSubscription = new CompositeSubscription();

        @Override
        public void unsubscribe() {
            compositeSubscription.unsubscribe();
        }

        @Override
        public boolean isUnsubscribed() {
            return compositeSubscription.isUnsubscribed();
        }

        @Override
        public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) {
            if (compositeSubscription.isUnsubscribed()) {
                return Subscriptions.unsubscribed();
            }

            final ScheduledAction scheduledAction = new ScheduledAction(action);
            scheduledAction.addParent(compositeSubscription);
            compositeSubscription.add(scheduledAction);

            handler.postDelayed(scheduledAction, unit.toMillis(delayTime));

            scheduledAction.add(Subscriptions.create(() ->
                    handler.removeCallbacks(scheduledAction)));

            return scheduledAction;
        }
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/SmtpResponse.java
================================================
package com.oreilly.rxjava.ch4;

class SmtpResponse {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch4/Ticket.java
================================================
package com.oreilly.rxjava.ch4;

class Ticket {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/Chapter5.java
================================================
package com.oreilly.rxjava.ch5;

import io.netty.buffer.ByteBuf;
import io.reactivex.netty.protocol.http.client.HttpClient;
import io.reactivex.netty.protocol.http.client.HttpClientResponse;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;

import java.net.URL;

import static java.nio.charset.StandardCharsets.UTF_8;

@Ignore
public class Chapter5 {

	@Test
	public void sample_9() throws Exception {
		Observable<ByteBuf> response = HttpClient
				.newClient("example.com", 80)
				.createGet("/")
				.flatMap(HttpClientResponse::getContent);
		response
				.map(bb -> bb.toString(UTF_8))
				.subscribe(System.out::println);
	}

	@Test
	public void sample_22() throws Exception {
		Observable<URL> sources = Observable.just(new URL("http://www.google.com"));

		Observable<ByteBuf> packets =
				sources
						.flatMap(url -> HttpClient
								.newClient(url.getHost(), url.getPort())
								.createGet(url.getPath()))
						.flatMap(HttpClientResponse::getContent);
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/CompletableFutures.java
================================================
package com.oreilly.rxjava.ch5;

import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.function.UnaryOperator.identity;

@Ignore
public class CompletableFutures {

	User findById(long id) {
		return new User();
	}

	GeoLocation locate() {
		return new GeoLocation();
	}

	Ticket book(Flight flight) {
		return new Ticket();
	}

	@Test
	public void sample_21() throws Exception {
		long id = 42;

		ExecutorService pool = Executors.newFixedThreadPool(10);
		List<TravelAgency> agencies = Collections.singletonList(new SomeTravelAgency());

		User user = findById(id);
		GeoLocation location = locate();
		ExecutorCompletionService<Flight> ecs = new ExecutorCompletionService<>(pool);
		agencies.forEach(agency ->
				ecs.submit(() ->
						agency.search(user, location)));
		Future<Flight> firstFlight = ecs.poll(5, SECONDS);
		Flight flight = firstFlight.get();
		book(flight);
	}

	CompletableFuture<User> findByIdAsync(long id) {
		return CompletableFuture.supplyAsync(() -> findById(id));
	}

	CompletableFuture<GeoLocation> locateAsync() {
		return CompletableFuture.supplyAsync(this::locate);
	}

	CompletableFuture<Ticket> bookAsync(Flight flight) {
		return CompletableFuture.supplyAsync(() -> book(flight));
	}

	Observable<User> rxFindById(long id) {
		return Util.observe(findByIdAsync(id));
	}

	Observable<GeoLocation> rxLocate() {
		return Util.observe(locateAsync());
	}

	Observable<Ticket> rxBook(Flight flight) {
		return Util.observe(bookAsync(flight));
	}

	@Test
	public void sample_63() throws Exception {
		long id = 42;
		List<TravelAgency> agencies = Collections.singletonList(new SomeTravelAgency());
		CompletableFuture<User> user = findByIdAsync(id);
		CompletableFuture<GeoLocation> location = locateAsync();

		CompletableFuture<Ticket> ticketFuture = user
				.thenCombine(location, (User us, GeoLocation loc) -> agencies
						.stream()
						.map(agency -> agency.searchAsync(us, loc))
						.reduce((f1, f2) ->
								f1.applyToEither(f2, identity())
						)
						.get()
				)
				.thenCompose(identity())
				.thenCompose(this::bookAsync);
	}

	@Test
	public void sample_80() throws Exception {
		CompletableFuture<Long> timeFuture = CompletableFuture.completedFuture(System.currentTimeMillis());
		CompletableFuture<ZoneId> zoneFuture = CompletableFuture.completedFuture(ZoneId.of("GMT"));

		CompletableFuture<Instant> instantFuture = timeFuture
				.thenApply(time -> Instant.ofEpochMilli(time));

		CompletableFuture<ZonedDateTime> zdtFuture = instantFuture
				.thenCombine(zoneFuture, (instant, zoneId) ->
						ZonedDateTime.ofInstant(instant, zoneId));
	}

	@Test
	public void sample_96() throws Exception {
		List<TravelAgency> agencies = Collections.singletonList(new SomeTravelAgency());

		User us = new User();
		GeoLocation loc = new GeoLocation();
		agencies
				.stream()
				.map(agency -> agency.searchAsync(us, loc))
				.reduce((f1, f2) ->
						f1.applyToEither(f2, identity())
				)
				.get();

	}

	@Test
	public void sample_111() throws Exception {
		CompletableFuture<User> primaryFuture = CompletableFuture.completedFuture(new User());
		CompletableFuture<User> secondaryFuture = CompletableFuture.completedFuture(new User());

		CompletableFuture<LocalDate> ageFuture =
				primaryFuture
						.applyToEither(secondaryFuture,
								user -> user.getBirth());
	}

	@Test
	public void sample_123() throws Exception {
		CompletableFuture<Flight> flightFuture = CompletableFuture.completedFuture(new Flight());

		CompletableFuture<Ticket> ticketFuture = flightFuture
				.thenCompose(flight -> bookAsync(flight));

	}

	@Test
	public void sample_145() throws Exception {
		long id = 42;

		Observable<TravelAgency> agencies = agencies();
		Observable<User> user = rxFindById(id);
		Observable<GeoLocation> location = rxLocate();

		Observable<Ticket> ticket = user
				.zipWith(location, (us, loc) ->
						agencies
								.flatMap(agency -> agency.rxSearch(us, loc))
								.first()
				)
				.flatMap(x -> x)
				.flatMap(this::rxBook);

	}

	private Observable<TravelAgency> agencies() {
		return Observable.just(new SomeTravelAgency());
	}

	@Test
	public void sample_168() throws Exception {
		Observable<User> user = Observable.just(new User());
		Observable<GeoLocation> location = Observable.just(new GeoLocation());
		Observable<TravelAgency> agencies = agencies();

		Observable<Ticket> ticket = user
				.zipWith(location, (usr, loc) -> Pair.of(usr, loc))
				.flatMap(pair -> agencies
						.flatMap(agency -> {
							User usr = pair.getLeft();
							GeoLocation loc = pair.getRight();
							return agency.rxSearch(usr, loc);
						}))
				.first()
				.flatMap(this::rxBook);

	}

}




================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/EurUsdCurrencyTcpServer.java
================================================
package com.oreilly.rxjava.ch5;

import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.reactivex.netty.protocol.tcp.server.TcpServer;
import rx.Observable;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;

class EurUsdCurrencyTcpServer {

    private static final BigDecimal RATE = new BigDecimal("1.06448");
    
    public static void main(final String[] args) {
        TcpServer
            .newServer(8080)
            .<String, String>pipelineConfigurator(pipeline -> {
                pipeline.addLast(new LineBasedFrameDecoder(1024));
                pipeline.addLast(new StringDecoder(UTF_8));
            })
            .start(connection -> {
                Observable<String> output = connection
                    .getInput()
                    .map(BigDecimal::new)
                    .flatMap(eur -> eurToUsd(eur));
                return connection.writeAndFlushOnEach(output);
            })
            .awaitShutdown();
    }

    static Observable<String> eurToUsd(BigDecimal eur) {
        return Observable
            .just(eur.multiply(RATE))
            .map(amount -> eur + " EUR is " + amount + " USD\n")
            .delay(1, TimeUnit.SECONDS);
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/Flight.java
================================================
package com.oreilly.rxjava.ch5;

class Flight {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/GeoLocation.java
================================================
package com.oreilly.rxjava.ch5;

class GeoLocation {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/HttpHandler.java
================================================
package com.oreilly.rxjava.ch5;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import static java.nio.charset.StandardCharsets.UTF_8;

@ChannelHandler.Sharable
class HttpHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(HttpHandler.class);

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof HttpRequest) {
            sendResponse(ctx);
        }
    }

    private void sendResponse(ChannelHandlerContext ctx) {
        final DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                HTTP_1_1,
                HttpResponseStatus.OK,
                Unpooled.wrappedBuffer("OK".getBytes(UTF_8)));
        response.headers().add("Content-length", 2);
        ctx.writeAndFlush(response);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("Error", cause);
        ctx.close();
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/HttpInitializer.java
================================================
package com.oreilly.rxjava.ch5;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;


class HttpInitializer extends ChannelInitializer<SocketChannel> {

    private final HttpHandler httpHandler = new HttpHandler();

    @Override
    public void initChannel(SocketChannel ch) {
        ch
                .pipeline()
                .addLast(new HttpServerCodec())
                .addLast(httpHandler);
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/HttpTcpNettyServer.java
================================================
package com.oreilly.rxjava.ch5;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

class HttpTcpNettyServer {

    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            new ServerBootstrap()
                    .option(ChannelOption.SO_BACKLOG, 50_000)
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new HttpInitializer())
                    .bind(8080)
                    .sync()
                    .channel()
                    .closeFuture()
                    .sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/HttpTcpRxNettyServer.java
================================================
package com.oreilly.rxjava.ch5;

import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.reactivex.netty.protocol.tcp.server.TcpServer;
import rx.Observable;

import static java.nio.charset.StandardCharsets.UTF_8;

class HttpTcpRxNettyServer {

    public static final Observable<String> RESPONSE = Observable.just(
            "HTTP/1.1 200 OK\r\n" +
            "Content-length: 2\r\n" +
            "\r\n" +
            "OK");

    public static void main(final String[] args) {
        TcpServer
            .newServer(8080)
            .<String, String>pipelineConfigurator(pipeline -> {
                pipeline.addLast(new LineBasedFrameDecoder(128));
                pipeline.addLast(new StringDecoder(UTF_8));
            })
            .start(connection -> {
                Observable<String> output = connection
                    .getInput()
                    .flatMap(line -> {
                        if (line.isEmpty()) {
                            return RESPONSE;
                        } else {
                            return Observable.empty();
                        }
                    });
                return connection.writeAndFlushOnEach(output);
            })
            .awaitShutdown();
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/Postgres.java
================================================
package com.oreilly.rxjava.ch5;

import org.junit.Ignore;
import org.junit.Test;
import org.postgresql.PGNotification;
import org.postgresql.jdbc2.AbstractJdbc2Connection;
import org.postgresql.jdbc42.Jdbc42Connection;
import rx.Observable;
import rx.observers.Subscribers;
import rx.subscriptions.Subscriptions;

import java.sql.*;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

@Ignore
public class Postgres {


	@Test
	public void sample_37() throws Exception {
		try (
				Connection conn = DriverManager.getConnection("jdbc:h2:mem:");
				Statement stat = conn.createStatement();
				ResultSet rs = stat.executeQuery("SELECT 2 + 2 AS total")
		) {
			if (rs.next()) {
				System.out.println(rs.getInt("total"));
				assert rs.getInt("total") == 4;
			}
		}
	}

	@Test
	public void sample_55() throws Exception {
		try (Connection connection =
				     DriverManager.getConnection("jdbc:postgresql:db")) {
			try (Statement statement = connection.createStatement()) {
				statement.execute("LISTEN my_channel");
			}
			Jdbc42Connection pgConn = (Jdbc42Connection) connection;
			pollForNotifications(pgConn);
		}
	}

	void pollForNotifications(Jdbc42Connection pgConn) throws Exception {
		while (!Thread.currentThread().isInterrupted()) {
			final PGNotification[] notifications = pgConn.getNotifications();
			if (notifications != null) {
				for (final PGNotification notification : notifications) {
					System.out.println(
							notification.getName() + ": " +
									notification.getParameter());
				}
			}
			TimeUnit.MILLISECONDS.sleep(100);
		}
	}

	Observable<PGNotification> observe(String channel, long pollingPeriod) {
		return Observable.<PGNotification>create(subscriber -> {
			try {
				Connection connection = DriverManager
						.getConnection("jdbc:postgresql:db");
				subscriber.add(Subscriptions.create(() ->
						closeQuietly(connection)));
				listenOn(connection, channel);
				Jdbc42Connection pgConn = (Jdbc42Connection) connection;
				pollForNotifications(pollingPeriod, pgConn)
						.subscribe(Subscribers.wrap(subscriber));
			} catch (Exception e) {
				subscriber.onError(e);
			}
		}).share();
	}

	void listenOn(Connection connection, String channel) throws SQLException {
		try (Statement statement = connection.createStatement()) {
			statement.execute("LISTEN " + channel);
		}
	}

	void closeQuietly(Connection connection) {
		try {
			connection.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	Observable<PGNotification> pollForNotifications(
			long pollingPeriod,
			AbstractJdbc2Connection pgConn) {
		return Observable
				.interval(0, pollingPeriod, TimeUnit.MILLISECONDS)
				.flatMap(x -> tryGetNotification(pgConn))
				.filter(arr -> arr != null)
				.flatMapIterable(Arrays::asList);
	}

	Observable<PGNotification[]> tryGetNotification(
			AbstractJdbc2Connection pgConn) {
		try {
			return Observable.just(pgConn.getNotifications());
		} catch (SQLException e) {
			return Observable.error(e);
		}
	}


}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/RestCurrencyServer.java
================================================
package com.oreilly.rxjava.ch5;

import io.reactivex.netty.protocol.http.server.HttpServer;
import rx.Observable;

import java.math.BigDecimal;

class RestCurrencyServer {

    private static final BigDecimal RATE = new BigDecimal("1.06448");

    public static void main(final String[] args) {
        HttpServer
                .newServer(8080)
                .start((req, resp) -> {
                    String amountStr = req.getDecodedPath().substring(1);
                    BigDecimal amount = new BigDecimal(amountStr);
                    Observable<String> response = Observable
                            .just(amount)
                            .map(eur -> eur.multiply(RATE))
                            .map(usd -> 
                                    "{\"EUR\": " + amount + ", " +
                                     "\"USD\": " + usd + "}");
                    return resp.writeString(response);
                })
                .awaitShutdown();
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/RxNettyHttpServer.java
================================================
package com.oreilly.rxjava.ch5;

import io.reactivex.netty.protocol.http.server.HttpServer;
import rx.Observable;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;

class RxNettyHttpServer {

    private static final Observable<String> RESPONSE_OK =
        Observable.just("OK");

    public static void main(String[] args) {
        HttpServer
            .newServer(8086)
            .start((req, resp) ->
                resp
                    .setHeader(CONTENT_LENGTH, 2)
                    .writeStringAndFlushOnEach(RESPONSE_OK)
            ).awaitShutdown();
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/SingleThread.java
================================================
package com.oreilly.rxjava.ch5;

import org.apache.commons.io.IOUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

class SingleThread {

    public static final byte[] RESPONSE = (
            "HTTP/1.1 200 OK\r\n" +
                    "Content-length: 2\r\n" +
                    "\r\n" +
                    "OK").getBytes();

    public static void main(String[] args) throws IOException {
        final ServerSocket serverSocket = new ServerSocket(8080, 100);
        while (!Thread.currentThread().isInterrupted()) {
            final Socket client = serverSocket.accept();
            handle(client);
        }
    }

    private static void handle(Socket client) {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                readFullRequest(client);
                client.getOutputStream().write(RESPONSE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            IOUtils.closeQuietly(client);
        }
    }

    private static void readFullRequest(Socket client) throws IOException {
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
        String line = reader.readLine();
        while (line != null && !line.isEmpty()) {
            line = reader.readLine();
        }
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/Singles.java
================================================
package com.oreilly.rxjava.ch5;

import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.Response;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.w3c.dom.Document;
import rx.Observable;
import rx.Single;
import rx.SingleSubscriber;
import rx.schedulers.Schedulers;

import java.io.IOException;
import java.time.Instant;

@Ignore
public class Singles {

	@Test
	public void sample_6() throws Exception {
		Single<String> single = Single.just("Hello, world!");
		single.subscribe(System.out::println);

		Single<Instant> error =
				Single.error(new RuntimeException("Opps!"));
		error
				.observeOn(Schedulers.io())
				.subscribe(
						System.out::println,
						Throwable::printStackTrace
				);
	}

	AsyncHttpClient asyncHttpClient = new AsyncHttpClient();

	Single<Response> fetch(String address) {
		return Single.create(subscriber ->
				asyncHttpClient
						.prepareGet(address)
						.execute(handler(subscriber)));
	}

	AsyncCompletionHandler handler(SingleSubscriber<? super Response> subscriber) {
		return new AsyncCompletionHandler() {
			public Response onCompleted(Response response) {
				subscriber.onSuccess(response);
				return response;
			}

			public void onThrowable(Throwable t) {
				subscriber.onError(t);
			}
		};
	}

	@Test
	public void sample_55() throws Exception {
		Single<String> example =
				fetch("http://www.example.com")
						.flatMap(this::body);

		String b = example.toBlocking().value();
	}

	Single<String> body(Response response) {
		return Single.create(subscriber -> {
			try {
				subscriber.onSuccess(response.getResponseBody());
			} catch (IOException e) {
				subscriber.onError(e);
			}
		});
	}

	//Same functionality as body():
	Single<String> body2(Response response) {
		return Single.fromCallable(() ->
				response.getResponseBody());
	}

	private final JdbcTemplate jdbcTemplate = new JdbcTemplate();

	Single<String> content(int id) {
		return Single.fromCallable(() -> jdbcTemplate
				.queryForObject(
						"SELECT content FROM articles WHERE id = ?",
						String.class, id))
				.subscribeOn(Schedulers.io());
	}

	Single<Integer> likes(int id) {
		//asynchronous HTTP request to social media website
		return Single.just(7);
	}

	Single<Void> updateReadCount() {
		//only side effect, no return value in Single
		return Single.just(null);
	}

	@Test
	public void sample_98() throws Exception {
		Single<Document> doc = Single.zip(
				content(123),
				likes(123),
				updateReadCount(),
				(con, lks, vod) -> buildHtml(con, lks)
		);
	}

	Document buildHtml(String content, int likes) {
		//...
		return null;
	}

	@Test
	public void sample_113() throws Exception {
		Single<String> single = Single.create(subscriber -> {
			System.out.println("Subscribing");
			subscriber.onSuccess("42");
		});

		Single<String> cachedSingle = single
				.toObservable()
				.cache()
				.toSingle();

		cachedSingle.subscribe(System.out::println);
		cachedSingle.subscribe(System.out::println);
	}

	@Test
	public void sample_129() throws Exception {
		Single<Integer> emptySingle =
				Observable.<Integer>empty().toSingle();
		Single<Integer> doubleSingle =
				Observable.just(1, 2).toSingle();
	}

	@Test
	public void sample_138() throws Exception {
		Single<Integer> ignored = Single
				.just(1)
				.toObservable()
				.ignoreElements()   //PROBLEM
				.toSingle();
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/Ticket.java
================================================
package com.oreilly.rxjava.ch5;

class Ticket {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/TravelAgency.java
================================================
package com.oreilly.rxjava.ch5;

import rx.Observable;

import java.util.concurrent.CompletableFuture;

interface TravelAgency {
	Flight search(User user, GeoLocation location);

	default CompletableFuture<Flight> searchAsync(User user, GeoLocation location) {
		return CompletableFuture.supplyAsync(() -> search(user, location));
	}

	default Observable<Flight> rxSearch(User user, GeoLocation location) {
		return Observable.fromCallable(() -> search(user, location));
	}

}


class SomeTravelAgency implements TravelAgency {

	@Override
	public Flight search(User user, GeoLocation location) {
		return new Flight();
	}
}

================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/User.java
================================================
package com.oreilly.rxjava.ch5;

import java.time.LocalDate;

class User {

	LocalDate getBirth() {
		return LocalDate.now().minusYears(30);
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch5/Util.java
================================================
package com.oreilly.rxjava.ch5;

import rx.Observable;

import java.util.List;
import java.util.concurrent.CompletableFuture;

class Util {
    static <T> Observable<T> observe(CompletableFuture<T> future) {
        return Observable.create(subscriber -> {
            future.whenComplete((value, exception) -> {
                if (exception != null) {
                    subscriber.onError(exception);
                } else {
                    subscriber.onNext(value);
                    subscriber.onCompleted();
                }
            });
        });
    }

    static <T> CompletableFuture<T> toFuture(Observable<T> observable) {
        CompletableFuture<T> promise = new CompletableFuture<>();
        observable
                .single()
                .subscribe(
                        promise::complete,
                        promise::completeExceptionally
                );
        return promise;
    }

    static <T> CompletableFuture<List<T>> toFutureList(Observable<T> observable) {
        return toFuture(observable.toList());
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/Backpressure.java
================================================
package com.oreilly.rxjava.ch6;

import com.oreilly.rxjava.util.Sleeper;
import org.apache.commons.dbutils.ResultSetIterator;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Subscriber;
import rx.observables.SyncOnSubscribe;
import rx.schedulers.Schedulers;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Duration;

@Ignore
public class Backpressure {

	private static final Logger log = LoggerFactory.getLogger(Backpressure.class);


	private Observable<Dish> dishes() {
		Observable<Dish> dishes = Observable
				.range(1, 1_000_000_000)
				.map(Dish::new);
		return dishes;
	}

	@Test
	public void sample_18() throws Exception {
		Observable
				.range(1, 1_000_000_000)
				.map(Dish::new)
				.subscribe(x -> {
					System.out.println("Washing: " + x);
					sleepMillis(50);
				});
	}

	@Test
	public void sample_32() throws Exception {
		final Observable<Dish> dishes = dishes();

		dishes
				.observeOn(Schedulers.io())
				.subscribe(x -> {
					System.out.println("Washing: " + x);
					sleepMillis(50);
				});

	}

	private void sleepMillis(int millis) {
		Sleeper.sleep(Duration.ofMillis(millis));
	}

	Observable<Integer> myRange(int from, int count) {
		return Observable.create(subscriber -> {
			int i = from;
			while (i < from + count) {
				if (!subscriber.isUnsubscribed()) {
					subscriber.onNext(i++);
				} else {
					return;
				}
			}
			subscriber.onCompleted();
		});
	}

	@Test
	public void sample_65() throws Exception {
		myRange(1, 1_000_000_000)
				.map(Dish::new)
				.observeOn(Schedulers.io())
				.subscribe(x -> {
							System.out.println("Washing: " + x);
							sleepMillis(50);
						},
						Throwable::printStackTrace
				);
	}

	@Test
	public void sample_78() throws Exception {
		Observable
				.range(1, 10)
				.subscribe(new Subscriber<Integer>() {

					@Override
					public void onStart() {
						request(3);
					}

					@Override
					public void onCompleted() {

					}

					@Override
					public void onError(Throwable e) {

					}

					@Override
					public void onNext(Integer integer) {

					}

				});
	}

	@Test
	public void sample_94() throws Exception {
		Observable
				.range(1, 10)
				.subscribe(new Subscriber<Integer>() {

					{
						{
							request(3);
						}
					}

					@Override
					public void onCompleted() {

					}

					@Override
					public void onError(Throwable e) {

					}

					@Override
					public void onNext(Integer integer) {

					}

				});
	}

	@Test
	public void sample_136() throws Exception {
		Observable
				.range(1, 10)
				.subscribe(new Subscriber<Integer>() {

					@Override
					public void onStart() {
						request(1);
					}

					@Override
					public void onCompleted() {

					}

					@Override
					public void onError(Throwable e) {

					}

					@Override
					public void onNext(Integer integer) {
						request(1);
						log.info("Next {}", integer);
					}

					//onCompleted, onError...
				});
	}

	@Test
	public void sample_173() throws Exception {
		myRange(1, 1_000_000_000)
				.map(Dish::new)
				.onBackpressureBuffer()
				//.onBackpressureBuffer(1000, () -> log.warn("Buffer full"))
				//.onBackpressureDrop(dish -> log.warn("Throw away {}", dish))
				.observeOn(Schedulers.io())
				.subscribe(x -> {
					System.out.println("Washing: " + x);
					sleepMillis(50);
				});
	}

	@Test
	public void sample_189() throws Exception {
		Connection connection = null;
		PreparedStatement statement =
				connection.prepareStatement("SELECT ...");
		statement.setFetchSize(1000);
		ResultSet rs = statement.executeQuery();
		Observable<Object[]> result =
				Observable
						.from(ResultSetIterator.iterable(rs))
						.doAfterTerminate(() -> {
							try {
								rs.close();
								statement.close();
								connection.close();
							} catch (SQLException e) {
								log.warn("Unable to close", e);
							}
						});
	}

	@Test
	public void sample_213() throws Exception {
		Observable.OnSubscribe<Double> onSubscribe =
				SyncOnSubscribe.createStateless(
						observer -> observer.onNext(Math.random())
				);

		Observable<Double> rand = Observable.create(onSubscribe);
	}

	@Test
	public void sample_224() throws Exception {
		Observable.OnSubscribe<Long> onSubscribe =
				SyncOnSubscribe.createStateful(
						() -> 0L,
						(cur, observer) -> {
							observer.onNext(cur);
							return cur + 1;
						}
				);

		Observable<Long> naturals = Observable.create(onSubscribe);
	}

	@Test
	public void sample_238() throws Exception {
		Observable<Long> naturals = Observable.create(subscriber -> {
			long cur = 0;
			while (!subscriber.isUnsubscribed()) {
				System.out.println("Produced: " + cur);
				subscriber.onNext(cur++);
			}
		});
	}

	@Test
	public void sample_249() throws Exception {
		ResultSet resultSet = null; //...

		Observable.OnSubscribe<Object[]> onSubscribe = SyncOnSubscribe.createSingleState(
				() -> resultSet,
				(rs, observer) -> {
					try {
						rs.next();
						observer.onNext(toArray(rs));
					} catch (SQLException e) {
						observer.onError(e);
					}
				},
				rs -> {
					try {
						//Also close Statement, Connection, etc.
						rs.close();
					} catch (SQLException e) {
						log.warn("Unable to close", e);
					}
				}
		);

		Observable<Object[]> records = Observable.create(onSubscribe);

	}

	private Object[] toArray(ResultSet rs) {
		//TODO
		return new Object[] {};
	}

	@Test
	public void sample_284() throws Exception {
		Observable<Integer> source = Observable.range(1, 1_000);

		source.subscribe(this::store);

		source
				.flatMap(this::store)
				.subscribe(uuid -> log.debug("Stored: {}", uuid));

		source
				.flatMap(this::store)
				.buffer(100)
				.subscribe(
						hundredUuids -> log.debug("Stored: {}", hundredUuids));
	}

	Observable<Void> store(int x) {
		return Observable.empty();
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/Chapter6.java
================================================
package com.oreilly.rxjava.ch6;

import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;

import java.time.Duration;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static rx.Observable.empty;
import static rx.Observable.just;

@Ignore
public class Chapter6 {

	@Test
	public void sample_9() throws Exception {
		long startTime = System.currentTimeMillis();
		Observable
				.interval(7, MILLISECONDS)
				.timestamp()
				.sample(1, SECONDS)
				.map(ts -> ts.getTimestampMillis() - startTime + "ms: " + ts.getValue())
				.take(5)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_25() throws Exception {
		Observable<String> delayedNames = delayedNames();

		delayedNames
				.sample(1, SECONDS)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_37() throws Exception {
		Observable<String> delayedNames = delayedNames();

		delayedNames
				.concatWith(delayedCompletion())
				.sample(1, SECONDS)
				.subscribe(System.out::println);

	}

	private Observable<String> delayedNames() {
		Observable<String> names =
				just("Mary", "Patricia", "Linda",
						"Barbara",
						"Elizabeth", "Jennifer", "Maria", "Susan",
						"Margaret", "Dorothy");

		Observable<Long> absoluteDelayMillis =
				just(0.1, 0.6, 0.9,
						1.1,
						3.3, 3.4, 3.5, 3.6,
						4.4, 4.8)
						.map(d -> (long) (d * 1_000));

		final Observable<String> delayedNames = names
				.zipWith(absoluteDelayMillis,
						(n, d) ->
								just(n)
										.delay(d, MILLISECONDS))
				.flatMap(o -> o);
		return delayedNames;
	}

	static <T> Observable<T> delayedCompletion() {
		return Observable.<T>empty().delay(1, SECONDS);
	}

	@Test
	public void sample_64() throws Exception {
		Observable<Long> obs = Observable.interval(20, MILLISECONDS);

		//equivalent:
		obs.sample(1, SECONDS);
		obs.sample(Observable.interval(1, SECONDS));
	}

	@Test
	public void sample_73() throws Exception {
		Observable<String> delayedNames = delayedNames();

		delayedNames
				.throttleFirst(1, SECONDS)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_93() throws Exception {
		Observable
				.range(1, 7)  //1, 2, 3, ... 7
				.buffer(3)
				.subscribe((List<Integer> list) -> {
							System.out.println(list);
						}
				);
	}

	Repository repository = new SomeRepository();

	@Test
	public void sample_105() throws Exception {
		Observable<Record> events = Observable.range(1, 100).map(x -> new Record());

		events
				.subscribe(repository::store);
//vs.
		events
				.buffer(10)
				.subscribe(repository::storeAll);

	}

	@Test
	public void sample_120() throws Exception {
		Random random = new Random();
		Observable
				.defer(() -> just(random.nextGaussian()))
				.repeat(1000)
				.buffer(100, 1)
				.map(this::averageOfList)
				.subscribe(System.out::println);
	}

	private double averageOfList(List<Double> list) {
		return list
				.stream()
				.collect(Collectors.averagingDouble(x -> x));
	}

	@Test
	public void sample_139() throws Exception {
		Observable<List<Integer>> odd = Observable
				.range(1, 7)
				.buffer(1, 2);
		odd.subscribe(System.out::println);
	}

	@Test
	public void sample_147() throws Exception {
		Observable<Integer> odd = Observable
				.range(1, 7)
				.buffer(1, 2)
				.flatMapIterable(list -> list);
	}

	@Test
	public void sample_155() throws Exception {
		Observable<String> delayedNames = delayedNames();

		delayedNames
				.buffer(1, SECONDS)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_164() throws Exception {
		Observable<KeyEvent> keyEvents = empty();

		Observable<Integer> eventPerSecond = keyEvents
				.buffer(1, SECONDS)
				.map(List::size);
	}

	@Test
	public void sample_173() throws Exception {
		Observable<Duration> insideBusinessHours = Observable
				.interval(1, SECONDS)
				.filter(x -> isBusinessHour())
				.map(x -> Duration.ofMillis(100));
		Observable<Duration> outsideBusinessHours = Observable
				.interval(5, SECONDS)
				.filter(x -> !isBusinessHour())
				.map(x -> Duration.ofMillis(200));

		Observable<Duration> openings = Observable.merge(
				insideBusinessHours, outsideBusinessHours);

		Observable<TeleData> upstream = empty();

		Observable<List<TeleData>> samples = upstream
				.buffer(openings);

		Observable<List<TeleData>> samples2 = upstream
				.buffer(
						openings,
						duration -> empty()
								.delay(duration.toMillis(), MILLISECONDS));

	}

	private static final LocalTime BUSINESS_START = LocalTime.of(9, 0);
	private static final LocalTime BUSINESS_END = LocalTime.of(17, 0);

	private boolean isBusinessHour() {
		ZoneId zone = ZoneId.of("Europe/Warsaw");
		ZonedDateTime zdt = ZonedDateTime.now(zone);
		LocalTime localTime = zdt.toLocalTime();
		return !localTime.isBefore(BUSINESS_START)
				&& !localTime.isAfter(BUSINESS_END);
	}

	@Test
	public void sample_216() throws Exception {
		Observable<KeyEvent> keyEvents = empty();

		Observable<Observable<KeyEvent>> windows = keyEvents.window(1, SECONDS);
		Observable<Integer> eventPerSecond = windows
				.flatMap(eventsInSecond -> eventsInSecond.count());
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/Debounce.java
================================================
package com.oreilly.rxjava.ch6;

import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;
import rx.observables.ConnectableObservable;

import java.math.BigDecimal;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static rx.Observable.defer;

@Ignore
public class Debounce {


	private final TradingPlatform tradingPlatform = new TradingPlatform();

	@Test
	public void sample_225() throws Exception {
		Observable<BigDecimal> prices = tradingPlatform.pricesOf("NFLX");
		Observable<BigDecimal> debounced = prices.debounce(100, MILLISECONDS);

		prices
				.debounce(x -> {
					boolean goodPrice = x.compareTo(BigDecimal.valueOf(150)) > 0;
					return Observable
							.empty()
							.delay(goodPrice? 10 : 100, MILLISECONDS);
				});
	}

	@Test
	public void sample_242() throws Exception {
		Observable
				.interval(99, MILLISECONDS)
				.debounce(100, MILLISECONDS);
	}

	@Test
	public void sample_249() throws Exception {
		Observable
				.interval(99, MILLISECONDS)
				.debounce(100, MILLISECONDS)
				.timeout(1, SECONDS);
	}

	@Test
	public void sample_48() throws Exception {
		ConnectableObservable<Long> upstream = Observable
				.interval(99, MILLISECONDS)
				.publish();
		upstream
				.debounce(100, MILLISECONDS)
				.timeout(1, SECONDS, upstream.take(1));
		upstream.connect();
	}

	@Test
	public void sample_60() throws Exception {
		final Observable<Long> upstream = Observable.interval(99, MILLISECONDS);

		upstream
				.debounce(100, MILLISECONDS)
				.timeout(1, SECONDS, upstream
						.take(1)
						.concatWith(
								upstream.debounce(100, MILLISECONDS)));
	}

	@Test
	public void sample_72() throws Exception {
		final Observable<Long> upstream = Observable.interval(99, MILLISECONDS);

		upstream
				.debounce(100, MILLISECONDS)
				.timeout(1, SECONDS, upstream
						.take(1)
						.concatWith(
								upstream
										.debounce(100, MILLISECONDS)
										.timeout(1, SECONDS, upstream)));
	}

	Observable<Long> timedDebounce(Observable<Long> upstream) {
		Observable<Long> onTimeout = upstream
				.take(1)
				.concatWith(defer(() -> timedDebounce(upstream)));
		return upstream
				.debounce(100, MILLISECONDS)
				.timeout(1, SECONDS, onTimeout);
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/Dish.java
================================================
package com.oreilly.rxjava.ch6;

class Dish {
    private final byte[] oneKb = new byte[1_024];
    private final int id;

    Dish(int id) {
        this.id = id;
        System.out.println("Created: " + id);
    }

    public String toString() {
        return String.valueOf(id);
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/KeyEvent.java
================================================
package com.oreilly.rxjava.ch6;

class KeyEvent {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/Record.java
================================================
package com.oreilly.rxjava.ch6;

class Record {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/Repository.java
================================================
package com.oreilly.rxjava.ch6;

import java.util.List;

interface Repository {
    void store(Record record);
    void storeAll(List<Record> records);
}

class SomeRepository implements Repository {
    @Override
    public void store(Record record) {
    }

    @Override
    public void storeAll(List<Record> records) {
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/TeleData.java
================================================
package com.oreilly.rxjava.ch6;

class TeleData {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch6/TradingPlatform.java
================================================
package com.oreilly.rxjava.ch6;

import rx.Observable;

import java.math.BigDecimal;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

class TradingPlatform {

	Observable<BigDecimal> pricesOf(String ticker) {
		return Observable
				.interval(50, MILLISECONDS)
				.flatMap(this::randomDelay)
				.map(this::randomStockPrice)
				.map(BigDecimal::valueOf);
	}

	Observable<Long> randomDelay(long x) {
		return Observable
				.just(x)
				.delay((long) (Math.random() * 100), MILLISECONDS);
	}

	double randomStockPrice(long x) {
		return 100 + Math.random() * 10 +
				(Math.sin(x / 100.0)) * 60.0;
	}


}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/Agreement.java
================================================
package com.oreilly.rxjava.ch7;

class Agreement {
	boolean postalMailRequired() {
		return true;
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/Chapter7.java
================================================
package com.oreilly.rxjava.ch7;

import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.schedulers.TimeInterval;

import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static java.time.Month.*;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

@Ignore
public class Chapter7 {

	private static final Logger log = LoggerFactory.getLogger(Chapter7.class);

	@Test
	public void sample_9() throws Exception {
		Observable
				.create(subscriber -> {
					try {
						subscriber.onNext(1 / 0);
					} catch (Exception e) {
						subscriber.onError(e);
					}
				})
				//BROKEN, missing onError() callback
				.subscribe(System.out::println);
	}

	@Test
	public void sample_29() throws Exception {
		Observable
				.create(subscriber -> {
					try {
						subscriber.onNext(1 / 0);
					} catch (Exception e) {
						subscriber.onError(e);
					}
				})
				.subscribe(
						System.out::println,
						throwable -> log.error("That escalated quickly", throwable));

	}

	@Test
	public void sample_45() throws Exception {
		Observable.create(subscriber -> {
			try {
				subscriber.onNext(1 / 0);
			} catch (Exception e) {
				subscriber.onError(e);
			}
		});

		Observable.create(subscriber -> subscriber.onNext(1 / 0));

		Observable.fromCallable(() -> 1 / 0);
	}

	@Test
	public void sample_60() throws Exception {
		Observable
				.just(1, 0)
				.map(x -> 10 / x);

		Observable
				.just("Lorem", null, "ipsum")
				.filter(String::isEmpty);
	}

	@Test
	public void sample_71() throws Exception {
		Observable
				.just(1, 0)
				.flatMap(x -> (x == 0) ?
						Observable.error(new ArithmeticException("Zero :-(")) :
						Observable.just(10 / x)
				);
	}


	private final PrintHouse printHouse = new PrintHouse();

	@Test
	public void sample_81() throws Exception {
		Observable<Person> person = Observable.just(new Person());
		Observable<InsuranceContract> insurance = Observable.just(new InsuranceContract());
		Observable<Health> health = person.flatMap(this::checkHealth);
		Observable<Income> income = person.flatMap(this::determineIncome);
		Observable<Score> score = Observable
				.zip(health, income, (h, i) -> asses(h, i))
				.map(this::translate);
		Observable<Agreement> agreement = Observable.zip(
				insurance,
				score.filter(Score::isHigh),
				this::prepare);
		Observable<TrackingId> mail = agreement
				.filter(Agreement::postalMailRequired)
				.flatMap(this::print)
				.flatMap(printHouse::deliver);
	}

	private Observable<Agreement> print(Agreement agreement) {
		return Observable.just(agreement);
	}

	private Agreement prepare(InsuranceContract contract, Score score) {
		return new Agreement();
	}

	private Score translate(BigInteger score) {
		return new Score();
	}

	private BigInteger asses(Health h, Income i) {
		return BigInteger.ONE;
	}

	private Observable<Income> determineIncome(Person person) {
		return Observable.error(new RuntimeException("Foo"));
	}

	private Observable<Health> checkHealth(Person person) {
		return Observable.just(new Health());
	}

	@Test
	public void sample_129() throws Exception {
		Observable<Person> person = Observable.just(new Person());
		Observable<Income> income = person
				.flatMap(this::determineIncome)
				.onErrorReturn(error -> Income.no());
	}

	public Observable<Income> sample_137() throws Exception {
		Person person = new Person();
		try {
			return determineIncome(person);
		} catch (Exception e) {
			return Observable.just(Income.no());
		}
	}

	@Test
	public void sample_147() throws Exception {
		Observable<Person> person = Observable.just(new Person());
		Observable<Income> income = person
				.flatMap(this::determineIncome)
				.onErrorResumeNext(person.flatMap(this::guessIncome));

	}

	private Observable<Income> guessIncome(Person person) {
		//...
		return Observable.just(new Income(1));
	}

	@Test
	public void sample_161() throws Exception {
		Observable<Person> person = Observable.just(new Person());

		Observable<Income> income = person
				.flatMap(this::determineIncome)
				.flatMap(
						Observable::just,
						th -> Observable.empty(),
						Observable::empty)
				.concatWith(person.flatMap(this::guessIncome))
				.first();
	}

	@Test
	public void sample_175() throws Exception {
		Observable<Person> person = Observable.just(new Person());

		Observable<Income> income = person
				.flatMap(this::determineIncome)
				.flatMap(
						Observable::just,
						th -> person.flatMap(this::guessIncome),
						Observable::empty);
	}

	@Test
	public void sample_187() throws Exception {
		Observable<Person> person = Observable.just(new Person());

		Observable<Income> income = person
				.flatMap(this::determineIncome)
				.onErrorResumeNext(th -> {
					if (th instanceof NullPointerException) {
						return Observable.error(th);
					} else {
						return person.flatMap(this::guessIncome);
					}
				});
	}

	Observable<Confirmation> confirmation() {
		Observable<Confirmation> delayBeforeCompletion =
				Observable
						.<Confirmation>empty()
						.delay(200, MILLISECONDS);
		return Observable
				.just(new Confirmation())
				.delay(100, MILLISECONDS)
				.concatWith(delayBeforeCompletion);
	}

	@Test
	public void sample_215() throws Exception {
		confirmation()
				.timeout(210, MILLISECONDS)
				.forEach(
						System.out::println,
						th -> {
							if ((th instanceof TimeoutException)) {
								System.out.println("Too long");
							} else {
								th.printStackTrace();
							}
						}
				);
	}

	Observable<LocalDate> nextSolarEclipse(LocalDate after) {
		return Observable
				.just(
						LocalDate.of(2016, MARCH, 9),
						LocalDate.of(2016, SEPTEMBER, 1),
						LocalDate.of(2017, FEBRUARY, 26),
						LocalDate.of(2017, AUGUST, 21),
						LocalDate.of(2018, FEBRUARY, 15),
						LocalDate.of(2018, JULY, 13),
						LocalDate.of(2018, AUGUST, 11),
						LocalDate.of(2019, JANUARY, 6),
						LocalDate.of(2019, JULY, 2),
						LocalDate.of(2019, DECEMBER, 26))
				.skipWhile(date -> !date.isAfter(after))
				.zipWith(
						Observable.interval(500, 50, MILLISECONDS),
						(date, x) -> date);
	}

	@Test
	public void sample_253() throws Exception {
		nextSolarEclipse(LocalDate.of(2016, SEPTEMBER, 1))
				.timeout(
						() -> Observable.timer(1000, TimeUnit.MILLISECONDS),
						date -> Observable.timer(100, MILLISECONDS));
	}

	@Test
	public void sample_262() throws Exception {
		Observable<TimeInterval<LocalDate>> intervals =
				nextSolarEclipse(LocalDate.of(2016, JANUARY, 1))
						.timeInterval();
	}

	@Test
	public void sample_271() throws Exception {
		Observable<Instant> timestamps = Observable
				.fromCallable(() -> dbQuery())
				.doOnSubscribe(() -> log.info("subscribe()"))
				.doOnRequest(c -> log.info("Requested {}", c))
				.doOnNext(instant -> log.info("Got: {}", instant));

		timestamps
				.zipWith(timestamps.skip(1), Duration::between)
				.map(Object::toString)
				.subscribe(log::info);
	}

	private Instant dbQuery() {
		return Instant.now();
	}

	@Test
	public void sample_291() throws Exception {
		Observable<String> obs = Observable
				.<String>error(new RuntimeException("Swallowed"))
				.doOnError(th -> log.warn("onError", th))
				.onErrorReturn(th -> "Fallback");
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/Confirmation.java
================================================
package com.oreilly.rxjava.ch7;

class Confirmation {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/Monitoring.java
================================================
package com.oreilly.rxjava.ch7;

import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Slf4jReporter;
import com.codahale.metrics.Timer;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import rx.Observable;

import java.util.concurrent.TimeUnit;

@Ignore
public class Monitoring {

	private MetricRegistry metricRegistry;

	@Test
	public void sample_9() throws Exception {
		metricRegistry = new MetricRegistry();
		Slf4jReporter reporter = Slf4jReporter
				.forRegistry(metricRegistry)
				.outputTo(LoggerFactory.getLogger(Monitoring.class))
				.build();
		reporter.start(1, TimeUnit.SECONDS);
	}

	@Test
	public void sample_26() throws Exception {
		final Observable<Integer> observable = Observable.range(1, 100);
		final Counter items = metricRegistry.counter("items");
		observable
				.doOnNext(x -> items.inc())
				.subscribe(/* ... */);
	}

	Observable<Long> makeNetworkCall(long x) {
		//...
		return Observable.just(10L);
	}

	@Test
	public void sample_38() throws Exception {
		final Observable<Integer> observable = Observable.range(1, 100);

		Counter counter = metricRegistry.counter("counter");
		observable
				.doOnNext(x -> counter.inc())
				.flatMap(this::makeNetworkCall)
				.doOnNext(x -> counter.dec())
				.subscribe(/* ... */);
	}

	@Test
	public void sample_55() throws Exception {
		final Observable<Integer> observable = Observable.range(1, 100);
		Counter counter = metricRegistry.counter("counter");

		observable
				.flatMap(x ->
						makeNetworkCall(x)
								.doOnSubscribe(counter::inc)
								.doOnTerminate(counter::dec)
				)
				.subscribe(/* ... */);
	}

	@Test
	public void sample_69() throws Exception {
		Timer timer = metricRegistry.timer("timer");
		Timer.Context ctx = timer.time();
		//some lengthy operation...
		ctx.stop();
	}

	@Test
	public void sample_78() throws Exception {
		Observable<Long> external = Observable.just(42L);

		Timer timer = metricRegistry.timer("timer");

		Observable<Long> externalWithTimer = Observable
				.defer(() -> Observable.just(timer.time()))
				.flatMap(timerCtx ->
						external.doOnCompleted(timerCtx::stop));
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/MyService.java
================================================
package com.oreilly.rxjava.ch7;

import rx.Observable;

import java.time.LocalDate;

interface MyService {
    Observable<LocalDate> externalCall();
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/MyServiceWithTimeout.java
================================================
package com.oreilly.rxjava.ch7;

import rx.Observable;
import rx.Scheduler;

import java.time.LocalDate;
import java.util.concurrent.TimeUnit;

class MyServiceWithTimeout implements MyService {

    private final MyService delegate;
    private final Scheduler scheduler;

    MyServiceWithTimeout(MyService d, Scheduler s) {
        this.delegate = d;
        this.scheduler = s;
    }

    @Override
    public Observable<LocalDate> externalCall() {
        return delegate
                .externalCall()
                .timeout(1, TimeUnit.SECONDS,
                     Observable.empty(),
                     scheduler);
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/Person.java
================================================
package com.oreilly.rxjava.ch7;

class Person {
}

class Health {
}

class Score {
	boolean isHigh() {
		return true;
	}
}

class InsuranceContract {
}

class Income {


	public Income(int i) {
	}

	static Income no() {
		return new Income(0);
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/PrintHouse.java
================================================
package com.oreilly.rxjava.ch7;

import rx.Observable;

class PrintHouse {

	Observable<TrackingId> deliver(Agreement agreement) {
		return Observable.just(new TrackingId());
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/RetryTimeouts.java
================================================
package com.oreilly.rxjava.ch7;

import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;

import java.util.concurrent.TimeoutException;

import static java.util.concurrent.TimeUnit.SECONDS;

@Ignore
public class RetryTimeouts {

	private static final Logger log = LoggerFactory.getLogger(RetryTimeouts.class);

	Observable<String> risky() {
		return Observable.fromCallable(() -> {
			if (Math.random() < 0.1) {
				Thread.sleep((long) (Math.random() * 2000));
				return "OK";
			} else {
				throw new RuntimeException("Transient");
			}
		});
	}

	@Test
	public void sample_281() throws Exception {
		risky()
				.timeout(1, SECONDS)
				.doOnError(th -> log.warn("Will retry", th))
				.retry()
				.subscribe(log::info);
	}

	@Test
	public void sample_291() throws Exception {
		risky().cache().retry();  //BROKEN
	}

	@Test
	public void sample_296() throws Exception {
		Observable
				.defer(() -> risky())
				.retry();
	}

	@Test
	public void sample_303() throws Exception {
		risky()
				.timeout(1, SECONDS)
				.retry(10);
	}

	@Test
	public void sample_310() throws Exception {
		risky()
				.timeout(1, SECONDS)
				.retry((attempt, e) ->
						attempt <= 10 && !(e instanceof TimeoutException));
	}

	@Test
	public void sample_66() throws Exception {
		risky()
				.timeout(1, SECONDS)
//				.retryWhen(failures -> failures.take(10))
				.retryWhen(failures -> failures.delay(1, SECONDS));
	}

	private static final int ATTEMPTS = 11;

	@Test
	public void sample_74() throws Exception {
		risky()
				.timeout(1, SECONDS)
				.retryWhen(failures -> failures
						.zipWith(Observable.range(1, ATTEMPTS), (err, attempt) ->
								attempt < ATTEMPTS ?
										Observable.timer(1, SECONDS) :
										Observable.error(err))
						.flatMap(x -> x)
				);
	}

	@Test
	public void sample_89() throws Exception {
		risky()
				.timeout(1, SECONDS)
				.retryWhen(failures -> failures
						.zipWith(Observable.range(1, ATTEMPTS),
								this::handleRetryAttempt)
						.flatMap(x -> x)
				);
	}

	Observable<Long> handleRetryAttempt(Throwable err, int attempt) {
		switch (attempt) {
			case 1:
				return Observable.just(42L);
			case ATTEMPTS:
				return Observable.error(err);
			default:
				long expDelay = (long) Math.pow(2, attempt - 2);
				return Observable.timer(expDelay, SECONDS);
		}
	}



}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/Testing.java
================================================
package com.oreilly.rxjava.ch7;

import com.google.common.io.Files;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import rx.Notification;
import rx.Observable;
import rx.Scheduler;
import rx.observables.BlockingObservable;
import rx.observables.SyncOnSubscribe;
import rx.observers.TestSubscriber;
import rx.plugins.RxJavaPlugins;
import rx.plugins.RxJavaSchedulersHook;
import rx.schedulers.Schedulers;
import rx.schedulers.TestScheduler;

import java.io.File;
import java.io.FileNotFoundException;
import java.time.LocalDate;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.assertj.core.api.AssertionsForClassTypes.failBecauseExceptionWasNotThrown;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static rx.Notification.Kind.OnError;
import static rx.Notification.Kind.OnNext;
import static rx.Observable.fromCallable;

@Ignore
public class Testing {

	@Test
	public void sample_9() throws Exception {
		TestScheduler sched = Schedulers.test();
		Observable<String> fast = Observable
				.interval(10, MILLISECONDS, sched)
				.map(x -> "F" + x)
				.take(3);
		Observable<String> slow = Observable
				.interval(50, MILLISECONDS, sched)
				.map(x -> "S" + x);

		Observable<String> stream = Observable.concat(fast, slow);
		stream.subscribe(System.out::println);
		System.out.println("Subscribed");
	}

	@Test
	public void sample_31() throws Exception {
		TestScheduler sched = Schedulers.test();

		TimeUnit.SECONDS.sleep(1);
		System.out.println("After one second");
		sched.advanceTimeBy(25, MILLISECONDS);

		TimeUnit.SECONDS.sleep(1);
		System.out.println("After one more second");
		sched.advanceTimeBy(75, MILLISECONDS);

		TimeUnit.SECONDS.sleep(1);
		System.out.println("...and one more");
		sched.advanceTimeTo(200, MILLISECONDS);
	}

	@Test
	public void shouldApplyConcatMapInOrder() throws Exception {
		List<String> list = Observable
				.range(1, 3)
				.concatMap(x -> Observable.just(x, -x))
				.map(Object::toString)
				.toList()
				.toBlocking()
				.single();

		assertThat(list).containsExactly("1", "-1", "2", "-2", "3", "-3");
	}

	@Test
	public void sample_65() throws Exception {
		File file = new File("404.txt");
		BlockingObservable<String> fileContents =
				fromCallable(() -> Files.toString(file, UTF_8))
				.toBlocking();

		try {
			fileContents.single();
			failBecauseExceptionWasNotThrown(FileNotFoundException.class);
		} catch (RuntimeException expected) {
			assertThat(expected)
					.hasCauseInstanceOf(FileNotFoundException.class);
		}
	}

	@Test
	public void sample_87() throws Exception {
		Observable<Notification<Integer>> notifications = Observable
				.just(3, 0, 2, 0, 1, 0)
				.concatMapDelayError(x -> fromCallable(() -> 100 / x))
				.materialize();

		List<Notification.Kind> kinds = notifications
				.map(Notification::getKind)
				.toList()
				.toBlocking()
				.single();

		assertThat(kinds).containsExactly(OnNext, OnNext, OnNext, OnError);
	}

	@Test
	public void sample_107() throws Exception {
		Observable<Integer> obs = Observable
				.just(3, 0, 2, 0, 1, 0)
				.concatMapDelayError(x -> Observable.fromCallable(() -> 100 / x));

		TestSubscriber<Integer> ts = new TestSubscriber<>();
		obs.subscribe(ts);

		ts.assertValues(33, 50, 100);
		ts.assertError(ArithmeticException.class);  //Fails (!)
	}

	private MyServiceWithTimeout mockReturning(
			Observable<LocalDate> result,
			TestScheduler testScheduler) {
		MyService mock = mock(MyService.class);
		given(mock.externalCall()).willReturn(result);
		return new MyServiceWithTimeout(mock, testScheduler);
	}

	@Test
	public void timeoutWhenServiceNeverCompletes() throws Exception {
		//given
		TestScheduler testScheduler = Schedulers.test();
		MyService mock = mockReturning(
				Observable.never(), testScheduler);
		TestSubscriber<LocalDate> ts = new TestSubscriber<>();

		//when
		mock.externalCall().subscribe(ts);

		//then
		testScheduler.advanceTimeBy(950, MILLISECONDS);
		ts.assertNoTerminalEvent();
		testScheduler.advanceTimeBy(100, MILLISECONDS);
		ts.assertCompleted();
		ts.assertNoValues();
	}

	@Test
	public void valueIsReturnedJustBeforeTimeout() throws Exception {
		//given
		TestScheduler testScheduler = Schedulers.test();
		Observable<LocalDate> slow = Observable
				.timer(950, MILLISECONDS, testScheduler)
				.map(x -> LocalDate.now());
		MyService myService = mockReturning(slow, testScheduler);
		TestSubscriber<LocalDate> ts = new TestSubscriber<>();

		//when
		myService.externalCall().subscribe(ts);

		//then
		testScheduler.advanceTimeBy(930, MILLISECONDS);
		ts.assertNotCompleted();
		ts.assertNoValues();
		testScheduler.advanceTimeBy(50, MILLISECONDS);
		ts.assertCompleted();
		ts.assertValueCount(1);
	}

	private final TestScheduler testScheduler = new TestScheduler();

	@Before
	public void alwaysUseTestScheduler() {
		RxJavaPlugins
				.getInstance()
				.registerSchedulersHook(new RxJavaSchedulersHook() {
					@Override
					public Scheduler getComputationScheduler() {
						return testScheduler;
					}

					@Override
					public Scheduler getIOScheduler() {
						return testScheduler;
					}

					@Override
					public Scheduler getNewThreadScheduler() {
						return testScheduler;
					}
				});
	}

	Observable<Long> naturals1() {
		return Observable.create(subscriber -> {
			long i = 0;
			while (!subscriber.isUnsubscribed()) {
				subscriber.onNext(i++);
			}
		});
	}

	Observable<Long> naturals2() {
		return Observable.create(
				SyncOnSubscribe.createStateful(
						() -> 0L,
						(cur, observer) -> {
							observer.onNext(cur);
							return cur + 1;
						}
				));
	}

	@Test
	public void sample_222() throws Exception {
		TestSubscriber<Long> ts = new TestSubscriber<>(0);

		naturals1()
				.take(10)
				.subscribe(ts);

		ts.assertNoValues();
		ts.requestMore(100);
		ts.assertValueCount(10);
		ts.assertCompleted();
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch7/TrackingId.java
================================================
package com.oreilly.rxjava.ch7;

class TrackingId {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Android.java
================================================
package com.oreilly.rxjava.ch8;

import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.*;
import com.oreilly.rxjava.ch8.rxandroid.AndroidSchedulers;
import com.oreilly.rxjava.ch8.rxbinding.RxTextView;
import com.oreilly.rxjava.ch8.rxbinding.RxView;
import com.oreilly.rxjava.ch8.rxbinding.TextViewAfterTextChangeEvent;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.functions.Func2;
import rx.schedulers.Schedulers;

import java.util.List;
import java.util.concurrent.TimeUnit;

import static android.content.ContentValues.TAG;

@Ignore
public class Android extends Activity {

	private final MeetupApi meetup = new ApiFactory().meetup();

	@Test
	public void sample_9() throws Exception {
		Button button = null;  //...
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				meetup
						.listCities(52.229841, 21.011736)
						.concatMapIterable(extractCities())
						.map(toCityName())
						.toList()
						.subscribeOn(Schedulers.io())
						.observeOn(AndroidSchedulers.mainThread())
						.subscribe(
								putOnListView(),
								displayError());
			}

			//...

		});
	}

	//Cities::getResults
	Func1<Cities, Iterable<City>> extractCities() {
		return new Func1<Cities, Iterable<City>>() {
			@Override
			public Iterable<City> call(Cities cities) {
				return cities.getResults();
			}
		};
	}

	//City::getCity
	Func1<City, String> toCityName() {
		return new Func1<City, String>() {
			@Override
			public String call(City city) {
				return city.getCity();
			}
		};
	}

	//cities -> listView.setAdapter(...)
	Action1<List<String>> putOnListView() {
		ListView listView = null; //...
		return new Action1<List<String>>() {
			@Override
			public void call(List<String> cities) {
				listView.setAdapter(new ArrayAdapter(Android.this, -1 /*R.layout.list*/, cities));
			}
		};
	}

	//throwable -> {...}
	Action1<Throwable> displayError() {
		return new Action1<Throwable>() {
			@Override
			public void call(Throwable throwable) {
				Log.e(TAG, "Error", throwable);
				Toast.makeText(Android.this, "Unable to load cities", Toast.LENGTH_SHORT).show();
			}
		};
	}

	@Test
	public void sample_98() throws Exception {
		Button button = new Button(null);
		RxView
				.clicks(button)
				.flatMap(c -> meetup.listCities(52.229841, 21.011736))
				.delay(2, TimeUnit.SECONDS)
				.concatMapIterable(extractCities())
				.map(toCityName())
				.toList()
				.subscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread())
				.subscribe(
						putOnListView(),
						displayError());
	}

	Func1<Void, Observable<Cities>> listCities(final double lat, final double lon) {
		return new Func1<Void, Observable<Cities>>() {
			@Override
			public Observable<Cities> call(Void aVoid) {
				return meetup.listCities(lat, lon);
			}
		};
	}

	@Test
	public void sample_121() throws Exception {
		EditText latText = null;//...
		EditText lonText = null;//...

		Observable<Double> latChanges = RxTextView
				.afterTextChangeEvents(latText)
				.flatMap(toDouble());
		Observable<Double> lonChanges = RxTextView
				.afterTextChangeEvents(lonText)
				.flatMap(toDouble());

		Observable<Cities> cities = Observable
				.combineLatest(latChanges, lonChanges, toPair())
				.debounce(1, TimeUnit.SECONDS)
				.flatMap(listCitiesNear());
	}

	Func1<TextViewAfterTextChangeEvent, Observable<Double>> toDouble() {
		return new Func1<TextViewAfterTextChangeEvent, Observable<Double>>() {
			@Override
			public Observable<Double> call(TextViewAfterTextChangeEvent e) {
				String s = e.editable().toString();
				try {
					return Observable.just(Double.parseDouble(s));
				} catch (NumberFormatException ex) {
					return Observable.empty();
				}
			}
		};
	}

	//return Pair::new
	Func2<Double, Double, Pair<Double, Double>> toPair() {
		return new Func2<Double, Double, Pair<Double, Double>>() {
			@Override
			public Pair<Double, Double> call(Double lat, Double lon) {
				return Pair.of(lat, lon);
			}
		};
	}

	//return latLon -> meetup.listCities(latLon.first, latLon.second)
	Func1<Pair<Double, Double>, Observable<Cities>> listCitiesNear() {
		return new Func1<Pair<Double, Double>, Observable<Cities>>() {
			@Override
			public Observable<Cities> call(Pair<Double, Double> latLon) {
				return meetup.listCities(latLon.getLeft(), latLon.getRight());
			}
		};
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/ApiFactory.java
================================================
package com.oreilly.rxjava.ch8;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;

class ApiFactory {

	GeoNames geoNames() {
		return new Retrofit.Builder()
				.baseUrl("http://api.geonames.org")
				.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
				.addConverterFactory(JacksonConverterFactory.create(objectMapper()))
				.build()
				.create(GeoNames.class);
	}

	MeetupApi meetup() {
		Retrofit retrofit = new Retrofit.Builder()
				.baseUrl("https://api.meetup.com/")
				.addCallAdapterFactory(
						RxJavaCallAdapterFactory.create())
				.addConverterFactory(
						JacksonConverterFactory.create(objectMapper()))
				.build();
		return retrofit.create(MeetupApi.class);
	}

	private ObjectMapper objectMapper() {
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setPropertyNamingStrategy(
				PropertyNamingStrategy.SNAKE_CASE);
		objectMapper.configure(
				DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		return objectMapper;
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Chapter8.java
================================================
package com.oreilly.rxjava.ch8;

import com.couchbase.client.java.CouchbaseAsyncCluster;
import com.couchbase.client.java.document.AbstractDocument;
import com.couchbase.client.java.document.json.JsonArray;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.rx.client.MongoClients;
import com.mongodb.rx.client.MongoCollection;
import com.mongodb.rx.client.MongoDatabase;
import org.apache.camel.CamelContext;
import org.apache.camel.Message;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.rx.ReactiveCamel;
import org.bson.Document;
import org.junit.Ignore;
import org.junit.Test;
import rx.Observable;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Month;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.oreilly.rxjava.ch8.GeoNames.log;
import static java.time.Month.APRIL;
import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.stream.Collectors.toList;


@Ignore
public class Chapter8 {

	@Test
	public void sample_9() throws Exception {
		final ApiFactory api = new ApiFactory();
		MeetupApi meetup = api.meetup();
		GeoNames geoNames = api.geoNames();

		double warsawLat = 52.229841;
		double warsawLon = 21.011736;
		Observable<Cities> cities = meetup.listCities(warsawLat, warsawLon);
		Observable<City> cityObs = cities.concatMapIterable(Cities::getResults);

		Observable<String> map = cityObs
				.filter(city -> city.distanceTo(warsawLat, warsawLon) < 50)
				.map(City::getCity);

		Observable<Long> totalPopulation = meetup
				.listCities(warsawLat, warsawLon)
				.concatMapIterable(Cities::getResults)
				.filter(city -> city.distanceTo(warsawLat, warsawLon) < 50)
				.map(City::getCity)
				.flatMap(geoNames::populationOf)
				.reduce(0L, (x, y) -> x + y);
	}

	@Test
	public void sample_35() throws Exception {
		CouchbaseAsyncCluster cluster = CouchbaseAsyncCluster.create();
		cluster
				.openBucket("travel-sample")
				.flatMap(cl -> cl.get("route_14197")
						.map(AbstractDocument::content)
						.map(jsonObject -> jsonObject.getArray("schedule")))
				.concatMapIterable(JsonArray::toList)
				.cast(Map.class)
				.filter(m -> ((Number) m.get("day")).intValue() == 0)
				.map(m -> m.get("flight").toString())
				.subscribe(flight -> System.out.println(flight));
	}

	@Test
	public void sample_55() throws Exception {
		MongoCollection<Document> monthsColl = com.mongodb.rx.client.MongoClients
				.create()
				.getDatabase("rx")
				.getCollection("months");

		Observable
				.from(Month.values())
				.map(month -> new Document()
						.append("name", month.name())
						.append("days_not_leap", month.length(false))
						.append("days_leap", month.length(true))
				)
				.toList()
				.flatMap(monthsColl::insertMany)
				.flatMap(s -> monthsColl.find().toObservable())
				.toBlocking()
				.subscribe(System.out::println);

	}

	@Test
	public void sample_105() throws Exception {
		final MongoDatabase db = MongoClients
				.create()
				.getDatabase("rx");

		Observable<Integer> days = db.getCollection("months")
				.find(Filters.eq("name", APRIL.name()))
				.projection(Projections.include("days_not_leap"))
				.first()
				.map(doc -> doc.getInteger("days_not_leap"));
		Observable<Instant> carManufactured = db.getCollection("cars")
				.find(Filters.eq("owner.name", "Smith"))
				.first()
				.map(doc -> doc.getDate("manufactured"))
				.map(Date::toInstant);

		Observable<BigDecimal> pricePerDay = dailyPrice(LocalDateTime.now());
		Observable<Insurance> insurance = Observable
				.zip(days, carManufactured, pricePerDay,
						(d, man, price) -> {
							//Create insurance
							return new Insurance();
						});
	}

	private Observable<BigDecimal> dailyPrice(LocalDateTime date) {
		return Observable.just(BigDecimal.TEN);
	}

	@Test
	public void sample_121() throws Exception {
		CamelContext camel = new DefaultCamelContext();
		ReactiveCamel reactiveCamel = new ReactiveCamel(camel);

		reactiveCamel
				.toObservable("file:/home/user/tmp")
				.subscribe(e ->
						log.info("New file: {}", e));
	}

	@Test
	public void sample_136() throws Exception {
		CamelContext camel = new DefaultCamelContext();
		ReactiveCamel reactiveCamel = new ReactiveCamel(camel);
		reactiveCamel
				.toObservable("kafka:localhost:9092?topic=demo&groupId=rx")
				.map(Message::getBody)
				.subscribe(e ->
						log.info("Message: {}", e));
	}

	@Test
	public void sample_148() throws Exception {
		List<Person> people = Collections.emptyList(); //...

		List<String> sorted = people
				.parallelStream()
				.filter(p -> p.getAge() >= 18)
				.map(Person::getFirstName)
				.sorted(Comparator.comparing(String::toLowerCase))
				.collect(toList());

		//DON'T DO THIS
		people
				.parallelStream()
				.forEach(this::publishOverJms);
	}

	private void publishOverJms(Person person) {
		//...
	}

	@Test
	public void sample_170() throws Exception {
		Observable
				.range(0, Integer.MAX_VALUE)
				.map(Picture::new)
				.distinct()
				.distinct(Picture::getTag)
				.sample(1, TimeUnit.SECONDS)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_182() throws Exception {
		Observable
				.range(0, Integer.MAX_VALUE)
				.map(Picture::new)
				.window(1, TimeUnit.SECONDS)
				.flatMap(Observable::count)
				.subscribe(System.out::println);
	}

	@Test
	public void sample_192() throws Exception {
		Observable
				.range(0, Integer.MAX_VALUE)
				.map(Picture::new)
				.window(10, TimeUnit.SECONDS)
				.flatMap(Observable::distinct);
	}

	@Test
	public void sample_201() throws Exception {
		Observable<Incident> incidents = Observable.empty(); //...

		Observable<Boolean> danger = incidents
				.buffer(1, TimeUnit.SECONDS)
				.map((List<Incident> oneSecond) -> oneSecond
						.stream()
						.filter(Incident::isHIghPriority)
						.count() > 5);
	}

	@Test
	public void sample_213() throws Exception {
		Observable<Picture> fast = Observable
				.interval(10, MICROSECONDS)
				.map(Picture::new);
		Observable<Picture> slow = Observable
				.interval(11, MICROSECONDS)
				.map(Picture::new);

		Observable
				.zip(fast, slow, (f, s) -> f + " : " + s);

		Observable
				.zip(
						fast.onBackpressureDrop(),
						slow.onBackpressureDrop(),
						(f, s) -> f + " : " + s);
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Cities.java
================================================
package com.oreilly.rxjava.ch8;

import java.util.List;

public class Cities {
    private List<City> results;

    public List<City> getResults() {
        return results;
    }

    public void setResults(List<City> results) {
        this.results = results;
    }
}



================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/City.java
================================================
package com.oreilly.rxjava.ch8;

public class City {
    private String city;
    private String country;
    private Double distance;
    private Integer id;
    private Double lat;
    private String localizedCountryName;
    private Double lon;
    private Integer memberCount;
    private Integer ranking;
    private String zip;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public Double getDistance() {
        return distance;
    }

    public void setDistance(Double distance) {
        this.distance = distance;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Double getLat() {
        return lat;
    }

    public void setLat(Double lat) {
        this.lat = lat;
    }

    public String getLocalizedCountryName() {
        return localizedCountryName;
    }

    public void setLocalizedCountryName(String localizedCountryName) {
        this.localizedCountryName = localizedCountryName;
    }

    public Double getLon() {
        return lon;
    }

    public void setLon(Double lon) {
        this.lon = lon;
    }

    public Integer getMemberCount() {
        return memberCount;
    }

    public void setMemberCount(Integer memberCount) {
        this.memberCount = memberCount;
    }

    public Integer getRanking() {
        return ranking;
    }

    public void setRanking(Integer ranking) {
        this.ranking = ranking;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(String zip) {
        this.zip = zip;
    }

    public double distanceTo(double lat, double lon) {
        //TODO Use correct formula
        return 0.0;
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/GeoNames.java
================================================
package com.oreilly.rxjava.ch8;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.http.GET;
import retrofit2.http.Query;
import rx.Observable;
import rx.schedulers.Schedulers;

public interface GeoNames {

    Logger log = LoggerFactory.getLogger(GeoNames.class);

    default Observable<Integer> populationOf(String query) {
        return search(query)
                .concatMapIterable(SearchResult::getGeonames)
                .map(Geoname::getPopulation)
                .filter(p -> p != null)
                .singleOrDefault(0)
                .doOnError(th ->
                        log.warn("Falling back to 0 for {}", query, th))
                .onErrorReturn(th -> 0)
                .subscribeOn(Schedulers.io());
    }

    default Observable<SearchResult> search(String query) {
        return search(query, 1, "LONG", "some_user");
    }

    @GET("/searchJSON")
    Observable<SearchResult> search(
            @Query("q") String query,
            @Query("maxRows") int maxRows,
            @Query("style") String style,
            @Query("username") String username
    );

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Geoname.java
================================================
package com.oreilly.rxjava.ch8;

public class Geoname {
    private String lat;
    private String lng;
    private Integer geonameId;
    private Integer population;
    private String countryCode;
    private String name;

    public String getLat() {
        return lat;
    }

    public void setLat(String lat) {
        this.lat = lat;
    }

    public String getLng() {
        return lng;
    }

    public void setLng(String lng) {
        this.lng = lng;
    }

    public Integer getGeonameId() {
        return geonameId;
    }

    public void setGeonameId(Integer geonameId) {
        this.geonameId = geonameId;
    }

    public Integer getPopulation() {
        return population;
    }

    public void setPopulation(Integer population) {
        this.population = population;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Incident.java
================================================
package com.oreilly.rxjava.ch8;

class Incident {
	boolean isHIghPriority() {
		return true;
	}
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Insurance.java
================================================
package com.oreilly.rxjava.ch8;

class Insurance {
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/MeetupApi.java
================================================
package com.oreilly.rxjava.ch8;

import retrofit2.http.GET;
import retrofit2.http.Query;
import rx.Observable;


public interface MeetupApi {

    @GET("/2/cities")
    Observable<Cities> listCities(
		@Query("lat") double lat,
		@Query("lon") double lon
    );

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Person.java
================================================
package com.oreilly.rxjava.ch8;

class Person {

	int getAge() {
		return 42;
	}

	String getFirstName() {
		return "Smith";
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/Picture.java
================================================
package com.oreilly.rxjava.ch8;

class Picture {
    private final byte[] blob = new byte[128 * 1024];
    private final long tag;

    Picture(long tag) { this.tag = tag; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Picture)) return false;
        Picture picture = (Picture) o;
        return tag == picture.tag;
    }

    long getTag() {
        return tag;
    }

    @Override
    public int hashCode() {
        return (int) (tag ^ (tag >>> 32));
    }

    @Override
    public String toString() {
        return Long.toString(tag);
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/SearchResult.java
================================================
package com.oreilly.rxjava.ch8;

import java.util.ArrayList;
import java.util.List;

class SearchResult {
    private List<Geoname> geonames = new ArrayList<>();

    public List<Geoname> getGeonames() {
        return geonames;
    }

    public void setGeonames(List<Geoname> geonames) {
        this.geonames = geonames;
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/BlockingCmd.java
================================================
package com.oreilly.rxjava.ch8.hystrix;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;

class BlockingCmd extends HystrixCommand<String> {

	public BlockingCmd() {
		super(HystrixCommandGroupKey.Factory.asKey("SomeGroup"));
	}

	@Override
	protected String run() throws IOException {
		final URL url = new URL("http://www.example.com");
		try (InputStream input = url.openStream()) {
			return IOUtils.toString(input, StandardCharsets.UTF_8);
		}
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/Book.java
================================================
package com.oreilly.rxjava.ch8.hystrix;

class Book {
}

class Rating {

	private final Book book;

	Rating(Book book) {
		this.book = book;
	}

	public Book getBook() {
		return book;
	}
}

================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/CitiesCmd.java
================================================
package com.oreilly.rxjava.ch8.hystrix;

import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixObservableCommand;
import com.oreilly.rxjava.ch8.Cities;
import com.oreilly.rxjava.ch8.MeetupApi;
import rx.Observable;

class CitiesCmd extends HystrixObservableCommand<Cities> {

    private final MeetupApi api;
    private final double lat;
    private final double lon;

    protected CitiesCmd(MeetupApi api, double lat, double lon) {
        super(HystrixCommandGroupKey.Factory.asKey("Meetup"));
        this.api = api;
        this.lat = lat;
        this.lon = lon;
    }

    @Override
    protected Observable<Cities> construct() {
        return api.listCities(lat, lon);
    }
}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/FetchManyRatings.java
================================================
package com.oreilly.rxjava.ch8.hystrix;

import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixObservableCommand;
import rx.Observable;

import java.util.Collection;

class FetchManyRatings extends HystrixObservableCommand<Rating> {

    private final Collection<Book> books;

    protected FetchManyRatings(Collection<Book> books) {
        super(HystrixCommandGroupKey.Factory.asKey("Books"));
        this.books = books;
    }

    @Override
    protected Observable<Rating> construct() {
        return fetchManyRatings(books);
    }

    private Observable<Rating> fetchManyRatings(Collection<Book> books) {
        return Observable
                .from(books)
                .map(Rating::new);
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/FetchRatingsCollapser.java
================================================
package com.oreilly.rxjava.ch8.hystrix;

import com.netflix.hystrix.*;
import rx.functions.Func1;

import java.util.Collection;
import java.util.List;

import static com.netflix.hystrix.HystrixObservableCollapser.Setter.withCollapserKey;
import static java.util.stream.Collectors.toList;

public class FetchRatingsCollapser
	extends HystrixObservableCollapser<Book, Rating, Rating, Book> {

    private final Book book;

    public FetchRatingsCollapser(Book book) {
        super(withCollapserKey(HystrixCollapserKey.Factory.asKey("Books"))
                .andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter()
                        .withTimerDelayInMilliseconds(20)
                        .withMaxRequestsInBatch(50)
                )
                .andScope(Scope.GLOBAL));
        this.book = book;
    }

    public Book getRequestArgument() {
        return book;
    }

    protected HystrixObservableCommand<Rating> createCommand(
    		Collection<HystrixCollapser.CollapsedRequest<Rating, Book>> requests) {
        List<Book> books = requests.stream()
                .map(c -> c.getArgument())
                .collect(toList());
        return new FetchManyRatings(books);
    }

    protected void onMissingResponse(HystrixCollapser.CollapsedRequest<Rating, Book> r) {
        r.setException(new RuntimeException("Not found for: " + r.getArgument()));
    }

    protected Func1<Book, Book> getRequestArgumentKeySelector() {
        return x -> x;
    }

    protected Func1<Rating, Rating> getBatchReturnTypeToResponseTypeMapper() {
        return x -> x;
    }

    protected Func1<Rating, Book> getBatchReturnTypeKeySelector() {
        return Rating::getBook;
    }

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/Hystrix.java
================================================
package com.oreilly.rxjava.ch8.hystrix;

import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import com.netflix.hystrix.metric.HystrixCommandCompletionStream;
import com.oreilly.rxjava.ch8.Cities;
import com.oreilly.rxjava.ch8.MeetupApi;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static com.netflix.hystrix.HystrixEventType.FAILURE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.eclipse.jetty.servlet.ServletContextHandler.NO_SESSIONS;
import static org.mockito.ArgumentMatchers.anyDouble;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

@Ignore
public class Hystrix {

	private static final Logger log = LoggerFactory.getLogger(Hystrix.class);

	@Test
	public void sample_17() throws Exception {
		String string = new BlockingCmd().execute();
		Future<String> future = new BlockingCmd().queue();
		Observable<String> eager = new BlockingCmd().observe();
		Observable<String> lazy = new BlockingCmd().toObservable();
	}

	@Test
	public void sample_28() throws Exception {
		Observable<String> retried = new BlockingCmd()
				.toObservable()
				.doOnError(ex -> log.warn("Error ", ex))
				.retryWhen(ex -> ex.delay(500, MILLISECONDS))
				.timeout(3, SECONDS);
	}

	@Test
	public void sample_44() throws Exception {
		MeetupApi api = mock(MeetupApi.class);
		given(api.listCities(anyDouble(), anyDouble())).willReturn(
				Observable
						.<Cities>error(new RuntimeException("Broken"))
						.doOnSubscribe(() -> log.debug("Invoking"))
						.delay(2, SECONDS)
		);

		Observable
				.interval(50, MILLISECONDS)
				.doOnNext(x -> log.debug("Requesting"))
				.flatMap(x ->
								new CitiesCmd(api, 52.229841, 21.011736)
										.toObservable()
										.onErrorResumeNext(ex -> Observable.empty()),
						5);
	}

	Observable<Book> allBooks() {
		return Observable.just(new Book());
	}
	Observable<Rating> fetchRating(Book book) {
		return Observable.just(new Rating(book));
	}

	@Test
	public void sample_69() throws Exception {
		Observable<Rating> ratings = allBooks()
				.flatMap(this::fetchRating);
	}

	@Test
	public void sample_83() throws Exception {
		final Book book = new Book();
		Observable<Rating> ratingObservable =
				new FetchRatingsCollapser(book).toObservable();
	}

	@Test
	public void sample_82() throws Exception {
		HystrixCommandCompletionStream
				.getInstance(HystrixCommandKey.Factory.asKey("FetchRating"))
				.observe()
				.filter(e -> e.getEventCounts().getCount(FAILURE) > 0)
				.window(1, TimeUnit.SECONDS)
				.flatMap(Observable::count)
				.subscribe(x -> log.info("{} failures/s", x));
	}

	@Test
	public void sample_98() throws Exception {
		ServletContextHandler context = new ServletContextHandler(NO_SESSIONS);
		HystrixMetricsStreamServlet servlet = new HystrixMetricsStreamServlet();
		context.addServlet(new ServletHolder(servlet), "/hystrix.stream");
		Server server = new Server(8080);
		server.setHandler(context);
		server.start();
		server.join();
	}

}


================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/AndroidSchedulers.java
================================================
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * 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.
 */
package com.oreilly.rxjava.ch8.rxandroid;

import android.os.Looper;
import rx.Scheduler;
import rx.annotations.Experimental;

import java.util.concurrent.atomic.AtomicReference;

/** Android-specific Schedulers. */
public final class AndroidSchedulers {
    private static final AtomicReference<AndroidSchedulers> INSTANCE = new AtomicReference<>();

    private final Scheduler mainThreadScheduler;

    private static AndroidSchedulers getInstance() {
        for (;;) {
            AndroidSchedulers current = INSTANCE.get();
            if (current != null) {
                return current;
            }
            current = new AndroidSchedulers();
            if (INSTANCE.compareAndSet(null, current)) {
                return current;
            }
        }
    }

    private AndroidSchedulers() {
        RxAndroidSchedulersHook hook = RxAndroidPlugins.getInstance().getSchedulersHook();

        Scheduler main = hook.getMainThreadScheduler();
        if (main != null) {
            mainThreadScheduler = main;
        } else {
            mainThreadScheduler = new LooperScheduler(Looper.getMainLooper());
        }
    }

    /** A {@link Scheduler} which executes actions on the Android UI thread. */
    public static Scheduler mainThread() {
        return getInstance().mainThreadScheduler;
    }

    /** A {@link Scheduler} which executes actions on {@code looper}. */
    public static Scheduler from(Looper looper) {
        if (looper == null) throw new NullPointerException("looper == null");
        return new LooperScheduler(looper);
    }

    /**
     * Resets the current {@link AndroidSchedulers} instance.
     * This will re-init the cached schedulers on the next usage,
     * which can be useful in testing.
     */
    @Experimental
    public static void reset() {
        INSTANCE.set(null);
    }
}

================================================
FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/LooperScheduler.java
================================================
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * 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.
 */
package com.oreilly.rxjava.ch8.rxandroid;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import rx.Scheduler;
import rx.Subscription;
import rx.exceptions.OnErrorNotImplementedException;
import rx.functions.Action0;
import rx.plugins.RxJavaPlugins;
import rx.subscriptions.Subscriptions;

import java.util.concurrent.TimeUnit;

class LooperScheduler extends Scheduler {
    private final Handler handler;

    LooperScheduler(Looper looper) {
        handler = new Handler(looper);
    }

    LooperScheduler(Handler handler) {
        this.handler = handler;
    }

    @Override
    public Worker createWorker() {
        return new HandlerWorker(handler);
    }

    static class HandlerWorker extends Worker {
        private final Handler handler;
        private final RxAndroidSchedulersHook hook;
        private volatile boolean unsubscribed;

        HandlerWorker(Handler handler) {
            this.handler = handler;
            this.hook = RxAndroidPlugins.getInstance().getSchedulersHook();
        }

        @Override
        public void unsubscribe() {
            unsubscribed = true;
            handler.removeCallbacksAndMessages(this /* token */);
        }

        @Override
        public boolean isUnsubscribed() {
            return unsubscribed;
        }

        @Override
        public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) {
            if (unsubscribed) {
                return Subscriptions.unsubscribed();
            }

            action = hook.onSchedule(action);

            ScheduledAction scheduledAction = new ScheduledAction(action, handler);

            Message message = Message.obtain(handler, scheduledAction);
            message.obj = this; // Used as token for unsubscription operation.

            handler.sendMessageDelayed(message, unit.toMillis(delayTime));

            if (unsubscribed) {
                handler.removeCallbacks(scheduledAction);
                return Subscriptions.unsubscribed();
            }

            return scheduledAction;
        }

        @Override
        public Subscription schedule(final Action0 action) {
            return schedule(action, 0, TimeUnit.MILLISECONDS);
        }
    
Download .txt
gitextract_yjbw__u9/

├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src/
    └── test/
        └── java/
            └── com/
                └── oreilly/
                    └── rxjava/
                        ├── appendix1/
                        │   ├── ClientConnection.java
                        │   ├── HttpServer.java
                        │   ├── SingleThread.java
                        │   ├── ThreadPerConnection.java
                        │   └── ThreadPool.java
                        ├── ch1/
                        │   ├── Callback.java
                        │   └── Chapter1.java
                        ├── ch2/
                        │   ├── Chapter2.java
                        │   ├── Config.java
                        │   ├── Data.java
                        │   ├── LazyTwitterObservable.java
                        │   ├── NaturalNumbersIterator.java
                        │   ├── Tweet.java
                        │   ├── TwitterSample.java
                        │   └── TwitterSubject.java
                        ├── ch3/
                        │   ├── Car.java
                        │   ├── CarPhoto.java
                        │   ├── CashTransfer.java
                        │   ├── CassandraFactStore.java
                        │   ├── Chapter3.java
                        │   ├── City.java
                        │   ├── CustomOperators.java
                        │   ├── Customer.java
                        │   ├── Data.java
                        │   ├── FactStore.java
                        │   ├── Flight.java
                        │   ├── Hotel.java
                        │   ├── LicensePlate.java
                        │   ├── Licenses.java
                        │   ├── OperatorMap.java
                        │   ├── Order.java
                        │   ├── Profile.java
                        │   ├── Rating.java
                        │   ├── Reservation.java
                        │   ├── ReservationEvent.java
                        │   ├── Reservations.java
                        │   ├── Shakespeare.java
                        │   ├── Sound.java
                        │   ├── User.java
                        │   ├── Vacation.java
                        │   ├── Weather.java
                        │   └── WeatherStation.java
                        ├── ch4/
                        │   ├── Book.java
                        │   ├── Chapter4.java
                        │   ├── Flight.java
                        │   ├── Flights.java
                        │   ├── Item.java
                        │   ├── JmsConsumer.java
                        │   ├── Messaging.java
                        │   ├── Passenger.java
                        │   ├── Person.java
                        │   ├── PersonDao.java
                        │   ├── RxGroceries.java
                        │   ├── Schedulers.java
                        │   ├── SimplifiedHandlerScheduler.java
                        │   ├── SmtpResponse.java
                        │   └── Ticket.java
                        ├── ch5/
                        │   ├── Chapter5.java
                        │   ├── CompletableFutures.java
                        │   ├── EurUsdCurrencyTcpServer.java
                        │   ├── Flight.java
                        │   ├── GeoLocation.java
                        │   ├── HttpHandler.java
                        │   ├── HttpInitializer.java
                        │   ├── HttpTcpNettyServer.java
                        │   ├── HttpTcpRxNettyServer.java
                        │   ├── Postgres.java
                        │   ├── RestCurrencyServer.java
                        │   ├── RxNettyHttpServer.java
                        │   ├── SingleThread.java
                        │   ├── Singles.java
                        │   ├── Ticket.java
                        │   ├── TravelAgency.java
                        │   ├── User.java
                        │   └── Util.java
                        ├── ch6/
                        │   ├── Backpressure.java
                        │   ├── Chapter6.java
                        │   ├── Debounce.java
                        │   ├── Dish.java
                        │   ├── KeyEvent.java
                        │   ├── Record.java
                        │   ├── Repository.java
                        │   ├── TeleData.java
                        │   └── TradingPlatform.java
                        ├── ch7/
                        │   ├── Agreement.java
                        │   ├── Chapter7.java
                        │   ├── Confirmation.java
                        │   ├── Monitoring.java
                        │   ├── MyService.java
                        │   ├── MyServiceWithTimeout.java
                        │   ├── Person.java
                        │   ├── PrintHouse.java
                        │   ├── RetryTimeouts.java
                        │   ├── Testing.java
                        │   └── TrackingId.java
                        ├── ch8/
                        │   ├── Android.java
                        │   ├── ApiFactory.java
                        │   ├── Chapter8.java
                        │   ├── Cities.java
                        │   ├── City.java
                        │   ├── GeoNames.java
                        │   ├── Geoname.java
                        │   ├── Incident.java
                        │   ├── Insurance.java
                        │   ├── MeetupApi.java
                        │   ├── Person.java
                        │   ├── Picture.java
                        │   ├── SearchResult.java
                        │   ├── hystrix/
                        │   │   ├── BlockingCmd.java
                        │   │   ├── Book.java
                        │   │   ├── CitiesCmd.java
                        │   │   ├── FetchManyRatings.java
                        │   │   ├── FetchRatingsCollapser.java
                        │   │   └── Hystrix.java
                        │   ├── rxandroid/
                        │   │   ├── AndroidSchedulers.java
                        │   │   ├── LooperScheduler.java
                        │   │   ├── MainActivity.java
                        │   │   ├── MainThreadSubscription.java
                        │   │   ├── RxAndroidPlugins.java
                        │   │   └── RxAndroidSchedulersHook.java
                        │   └── rxbinding/
                        │       ├── RxTextView.java
                        │       ├── RxView.java
                        │       ├── TextViewAfterTextChangeEvent.java
                        │       ├── TextViewAfterTextChangeEventOnSubscribe.java
                        │       ├── TextViewBeforeTextChangeEvent.java
                        │       ├── TextViewBeforeTextChangeEventOnSubscribe.java
                        │       ├── TextViewEditorActionEvent.java
                        │       ├── TextViewEditorActionEventOnSubscribe.java
                        │       ├── TextViewEditorActionOnSubscribe.java
                        │       ├── TextViewTextChangeEvent.java
                        │       ├── TextViewTextChangeEventOnSubscribe.java
                        │       ├── TextViewTextOnSubscribe.java
                        │       ├── ViewClickOnSubscribe.java
                        │       ├── ViewEvent.java
                        │       └── internal/
                        │           ├── Functions.java
                        │           └── Preconditions.java
                        ├── ch9/
                        │   └── Chapter9.java
                        └── util/
                            └── Sleeper.java
Download .txt
SYMBOL INDEX (814 symbols across 138 files)

FILE: src/test/java/com/oreilly/rxjava/appendix1/ClientConnection.java
  class ClientConnection (line 10) | class ClientConnection implements Runnable {
    method ClientConnection (line 23) | ClientConnection(Socket client) {
    method run (line 27) | public void run() {
    method readFullRequest (line 39) | private void readFullRequest() throws IOException {
    method serviceUnavailable (line 48) | public void serviceUnavailable() {

FILE: src/test/java/com/oreilly/rxjava/appendix1/HttpServer.java
  class HttpServer (line 7) | abstract class HttpServer  {
    method run (line 9) | void run(int port) throws IOException {
    method handle (line 17) | abstract void handle(ClientConnection clientConnection);

FILE: src/test/java/com/oreilly/rxjava/appendix1/SingleThread.java
  class SingleThread (line 3) | public class SingleThread extends HttpServer {
    method main (line 5) | public static void main(String[] args) throws Exception {
    method handle (line 9) | @Override

FILE: src/test/java/com/oreilly/rxjava/appendix1/ThreadPerConnection.java
  class ThreadPerConnection (line 5) | public class ThreadPerConnection extends HttpServer {
    method main (line 7) | public static void main(String[] args) throws IOException {
    method handle (line 11) | @Override

FILE: src/test/java/com/oreilly/rxjava/appendix1/ThreadPool.java
  class ThreadPool (line 10) | class ThreadPool extends HttpServer {
    method main (line 14) | public static void main(String[] args) throws IOException {
    method ThreadPool (line 18) | public ThreadPool() {
    method handle (line 27) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch1/Callback.java
  class Callback (line 5) | class Callback {
    method onResponse (line 9) | Callback onResponse(Consumer<String> consumer) {
    method onFailure (line 14) | Callback onFailure(Consumer<Exception> consumer) {
    method getOnResponse (line 19) | public Consumer<String> getOnResponse() {
    method getOnFailure (line 23) | public Consumer<Exception> getOnFailure() {

FILE: src/test/java/com/oreilly/rxjava/ch1/Chapter1.java
  class Chapter1 (line 19) | @Ignore
    method sample_6 (line 24) | @Test
    method sample_17 (line 32) | @Test
    method sample_35 (line 43) | @Test
    method putInCache (line 69) | private void putInCache(String key, String value) {
    method getDataAsynchronously (line 73) | private Callback getDataAsynchronously(String key) {
    method getFromCache (line 82) | private String getFromCache(String key) {
    method sample_81 (line 87) | @Test
    method sample_94 (line 100) | @Test
    method sample_108 (line 114) | @Test
    method sample_121 (line 127) | @Test
    method sample_142 (line 148) | @Test
    method sample_164 (line 170) | @Test
    method getDataFromServerWithCallback (line 190) | private void getDataFromServerWithCallback(String args, Consumer<Strin...
    method sample_188 (line 194) | @Test
    method getDataFromLocalMemorySynchronously (line 205) | private Stream<String> getDataFromLocalMemorySynchronously() {
    method sample_205 (line 211) | @Test
    method getDataFromNetworkAsynchronously (line 222) | private Observable<String> getDataFromNetworkAsynchronously() {
    method sample_225 (line 228) | @Test
    method getDataAsFuture (line 238) | private CompletableFuture<String> getDataAsFuture(int i) {
    method sample_240 (line 242) | @Test
    method getDataAsObservable (line 252) | private Observable<String> getDataAsObservable(int i) {
    method sample_254 (line 256) | @Test
    method sample_265 (line 265) | @Test
    method getDataA (line 271) | public static Single<String> getDataA() {
    method sample_277 (line 277) | @Test
    method getDataAsSingle (line 289) | private Single<String> getDataAsSingle(int i) {
    method getDataB (line 293) | public static Single<String> getDataB() {
    method writeToDatabase (line 298) | static Completable writeToDatabase(Object data) {
    method doAsyncWrite (line 308) | static void doAsyncWrite(Object data, Runnable onSuccess, Consumer<Exc...

FILE: src/test/java/com/oreilly/rxjava/ch2/Chapter2.java
  class Chapter2 (line 25) | @Ignore
    method sample_6 (line 28) | @Test
    method sample_17 (line 36) | @Test
    method sample_27 (line 46) | @Test
    method sample_38 (line 57) | @Test
    method noMore (line 67) | private void noMore() {
    method sample_51 (line 70) | @Test
    method sample_78 (line 96) | @Test
    method sample_91 (line 108) | @Test
    method log (line 131) | private static void log(Object msg) {
    method sample_117 (line 137) | @Test
    method sample_135 (line 149) | @Test
    method just (line 168) | static <T> Observable<T> just(T x) {
    method sample_162 (line 176) | @Test
    method sample_177 (line 191) | @Test
    method sample_187 (line 201) | @Test
    method naturalNumbers (line 215) | private Observable<BigInteger> naturalNumbers() {
    method sample_221 (line 230) | @Test
    method delayed (line 238) | static <T> Observable<T> delayed(T x) {
    method sleep (line 252) | static void sleep(int timeout, TimeUnit unit) {
    method delayed2 (line 260) | static <T> Observable<T> delayed2(T x) {
    method loadAll (line 270) | Observable<Data> loadAll(Collection<Integer> ids) {
    method load (line 286) | private Data load(Integer id) {
    method rxLoad (line 290) | Observable<Data> rxLoad(int id) {
    method rxLoad2 (line 301) | Observable<Data> rxLoad2(int id) {
    method sample_304 (line 306) | @Test
    method sample_311 (line 314) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch2/Config.java
  class Config (line 15) | @Configuration
    method observable (line 26) | @Bean
    method onApplicationEvent (line 31) | @Override
  class Foo (line 38) | @Component
    method Foo (line 43) | @Autowired
  class Bar (line 52) | @Component
    method Bar (line 57) | @Autowired

FILE: src/test/java/com/oreilly/rxjava/ch2/Data.java
  class Data (line 3) | class Data {

FILE: src/test/java/com/oreilly/rxjava/ch2/LazyTwitterObservable.java
  class LazyTwitterObservable (line 12) | class LazyTwitterObservable {
    method LazyTwitterObservable (line 19) | public LazyTwitterObservable() {
    method observe (line 61) | Observable<Status> observe() {
    method register (line 65) | private synchronized void register(Subscriber<? super Status> subscrib...
    method deregister (line 74) | private synchronized void deregister(Subscriber<? super Status> subscr...

FILE: src/test/java/com/oreilly/rxjava/ch2/NaturalNumbersIterator.java
  class NaturalNumbersIterator (line 6) | class NaturalNumbersIterator implements Iterator<BigInteger> {
    method hasNext (line 10) | public boolean hasNext() {
    method next (line 14) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch2/Tweet.java
  class Tweet (line 3) | class Tweet {
    method Tweet (line 7) | Tweet(String text) {
    method getText (line 11) | String getText() {

FILE: src/test/java/com/oreilly/rxjava/ch2/TwitterSample.java
  class TwitterSample (line 16) | @Ignore
    method sample_18 (line 21) | @Test
    method consume (line 62) | void consume(
    method sample_99 (line 100) | @Test
    method observe (line 108) | Observable<Status> observe() {
    method sample_150 (line 155) | @Test
    method sample_162 (line 163) | @Test
    method status (line 177) | private Observable<Status> status() {
    method sample_186 (line 190) | @Test
    method sample_206 (line 206) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch2/TwitterSubject.java
  class TwitterSubject (line 7) | class TwitterSubject {
    method TwitterSubject (line 11) | public TwitterSubject() {
    method observe (line 48) | public Observable<Status> observe() {

FILE: src/test/java/com/oreilly/rxjava/ch3/Car.java
  class Car (line 3) | class Car {

FILE: src/test/java/com/oreilly/rxjava/ch3/CarPhoto.java
  class CarPhoto (line 3) | class CarPhoto {

FILE: src/test/java/com/oreilly/rxjava/ch3/CashTransfer.java
  class CashTransfer (line 5) | class CashTransfer {
    method getAmount (line 7) | BigDecimal getAmount() {

FILE: src/test/java/com/oreilly/rxjava/ch3/CassandraFactStore.java
  class CassandraFactStore (line 5) | class CassandraFactStore implements FactStore {
    method observe (line 6) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch3/Chapter3.java
  class Chapter3 (line 30) | @Ignore
    method sample_6 (line 35) | @Test
    method sample_15 (line 41) | @Test
    method sample_26 (line 49) | @Test
    method sample_49 (line 69) | @Test
    method sample_57 (line 78) | @Test
    method sample_66 (line 86) | @Test
    method sample_79 (line 98) | @Test
    method sample_111 (line 110) | @Test
    method sample_119 (line 118) | @Test
    method sample_127 (line 126) | @Test
    method store (line 133) | void store(UUID id) {
    method upload (line 142) | Observable<Long> upload(UUID id) {
    method rate (line 146) | Observable<Rating> rate(UUID id) {
    method sample_155 (line 150) | @Test
    method toMorseCode (line 161) | Observable<Sound> toMorseCode(char ch) {
    method sample_213 (line 240) | @Test
    method sample_218 (line 247) | @Test
    method loadRecordsFor (line 258) | Observable<String> loadRecordsFor(DayOfWeek dow) {
    method sample_249 (line 275) | @Test
    method sample_258 (line 283) | @Test
    method sample_286 (line 291) | @Test
    method sample_298 (line 303) | @Test
    method sample_312 (line 317) | @Test
    method sample_332 (line 336) | @Test
    method sample_345 (line 348) | @Test
    method sample_355 (line 358) | @Test
    method sample_367 (line 370) | @Test
    method stream (line 378) | Observable<String> stream(int initialDelay, int interval, String name) {
    method sample_375 (line 388) | @Test
    method sample_393 (line 396) | @Test
    method sample_400 (line 403) | @Test
    method transferFile (line 413) | private Observable<Long> transferFile() {
    method sample_419 (line 420) | @Test
    method sample_431 (line 432) | @Test
    method sample_440 (line 440) | @Test
    method sample_456 (line 455) | @Test
    method sample_463 (line 465) | @Test
    method sample_470 (line 472) | @Test
    method randomInts (line 483) | private Observable<Integer> randomInts() {
    method sample_490 (line 493) | @Test
    method sample_499 (line 501) | @Test
    method sample_508 (line 510) | @Test
    method sample_516 (line 518) | @Test
    method sample_524 (line 526) | @Test
    method sample_531 (line 533) | @Test
    method sample_537 (line 539) | @Test
    method sample_543 (line 545) | @Test
    method sample_550 (line 552) | @Test
    method sample_559 (line 561) | @Test
    method sample_570 (line 572) | @Test
    method loadFromDb (line 583) | private Observable<Car> loadFromDb() {
    method loadFromCache (line 587) | private Observable<Car> loadFromCache() {
    method sample_589 (line 591) | @Test
    method sample_600 (line 601) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch3/City.java
  type City (line 3) | enum City {

FILE: src/test/java/com/oreilly/rxjava/ch3/CustomOperators.java
  class CustomOperators (line 11) | @Ignore
    method odd (line 14) | static <T> Observable<T> odd(Observable<T> upstream) {
    method odd (line 22) | private <T> Observable.Transformer<T, T> odd() {
    method sample_618 (line 30) | @Test
    method sample_9 (line 45) | @Test
    method sample_59 (line 56) | @Test
    method toStringOfOdd (line 66) | <T> Observable.Operator<String, T> toStringOfOdd() {
    method sample_67 (line 99) | @Test
    method sample_112 (line 108) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch3/Customer.java
  class Customer (line 6) | class Customer {
    method getOrders (line 8) | List<Order> getOrders() {

FILE: src/test/java/com/oreilly/rxjava/ch3/Data.java
  class Data (line 3) | class Data {

FILE: src/test/java/com/oreilly/rxjava/ch3/FactStore.java
  type FactStore (line 5) | interface FactStore {
    method observe (line 6) | Observable<ReservationEvent> observe();

FILE: src/test/java/com/oreilly/rxjava/ch3/Flight.java
  class Flight (line 3) | class Flight {

FILE: src/test/java/com/oreilly/rxjava/ch3/Hotel.java
  class Hotel (line 3) | class Hotel {

FILE: src/test/java/com/oreilly/rxjava/ch3/LicensePlate.java
  class LicensePlate (line 3) | class LicensePlate {

FILE: src/test/java/com/oreilly/rxjava/ch3/Licenses.java
  class Licenses (line 7) | @Ignore
    method cars (line 10) | Observable<CarPhoto> cars() {
    method recognize (line 14) | Observable<LicensePlate> recognize(CarPhoto photo) {
    method sample_100 (line 18) | @Test
    method fastAlgo (line 30) | Observable<LicensePlate> fastAlgo(CarPhoto photo) {
    method preciseAlgo (line 35) | Observable<LicensePlate> preciseAlgo(CarPhoto photo) {
    method experimentalAlgo (line 40) | Observable<LicensePlate> experimentalAlgo(CarPhoto photo) {
    method sample_317 (line 45) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch3/OperatorMap.java
  class OperatorMap (line 7) | final class OperatorMap<T, R> implements Observable.Operator<R, T> {
    method OperatorMap (line 11) | public OperatorMap(Func1<T, R> transformer) {
    method call (line 15) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch3/Order.java
  class Order (line 3) | class Order {

FILE: src/test/java/com/oreilly/rxjava/ch3/Profile.java
  class Profile (line 3) | class Profile {

FILE: src/test/java/com/oreilly/rxjava/ch3/Rating.java
  class Rating (line 3) | class Rating {

FILE: src/test/java/com/oreilly/rxjava/ch3/Reservation.java
  class Reservation (line 3) | class Reservation {
    method consume (line 5) | Reservation consume(ReservationEvent event) {

FILE: src/test/java/com/oreilly/rxjava/ch3/ReservationEvent.java
  class ReservationEvent (line 5) | class ReservationEvent {
    method getReservationUuid (line 7) | public UUID getReservationUuid() {

FILE: src/test/java/com/oreilly/rxjava/ch3/Reservations.java
  class Reservations (line 11) | @Ignore
    method sample_9 (line 14) | @Test
    method updateProjection (line 21) | void updateProjection(ReservationEvent event) {
    method store (line 25) | private void store(UUID id, Reservation modified) {
    method loadBy (line 29) | Optional<Reservation> loadBy(UUID uuid) {
    method sample_34 (line 34) | @Test
    method updateProjectionAsync (line 47) | Observable<ReservationEvent> updateProjectionAsync(ReservationEvent ev...
    method sample_52 (line 52) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch3/Shakespeare.java
  class Shakespeare (line 16) | @Ignore
    method speak (line 19) | Observable<String> speak(String quote, long millisPerChar) {
    method sample_28 (line 32) | @Test
    method sample_52 (line 53) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch3/Sound.java
  type Sound (line 3) | enum Sound { DI, DAH }

FILE: src/test/java/com/oreilly/rxjava/ch3/User.java
  class User (line 5) | class User {
    method loadProfile (line 6) | Observable<Profile> loadProfile() {

FILE: src/test/java/com/oreilly/rxjava/ch3/Vacation.java
  class Vacation (line 7) | class Vacation {
    method Vacation (line 11) | Vacation(City where, LocalDate when) {
    method weather (line 16) | public Observable<Weather> weather() {
    method cheapFlightFrom (line 21) | public Observable<Flight> cheapFlightFrom(City from) {
    method cheapHotel (line 26) | public Observable<Hotel> cheapHotel() {

FILE: src/test/java/com/oreilly/rxjava/ch3/Weather.java
  class Weather (line 3) | class Weather {
    method Weather (line 6) | public Weather(Temperature temperature, Wind wind) {
    method isSunny (line 11) | public boolean isSunny() {
    method getTemperature (line 15) | Temperature getTemperature() {

FILE: src/test/java/com/oreilly/rxjava/ch3/WeatherStation.java
  type WeatherStation (line 5) | interface WeatherStation {
    method temperature (line 6) | Observable<Temperature> temperature();
    method wind (line 7) | Observable<Wind> wind();
  class BasicWeatherStation (line 10) | class BasicWeatherStation implements WeatherStation {
    method temperature (line 12) | @Override
    method wind (line 17) | @Override
  class Temperature (line 23) | class Temperature {}
  class Wind (line 25) | class Wind {}

FILE: src/test/java/com/oreilly/rxjava/ch4/Book.java
  class Book (line 3) | class Book {
    method getTitle (line 4) | public String getTitle() {

FILE: src/test/java/com/oreilly/rxjava/ch4/Chapter4.java
  class Chapter4 (line 21) | @Ignore
    method sample_9 (line 29) | @Test
    method sample_20 (line 35) | @Test
    method marshal (line 43) | private String marshal(List<Person> people) {
    method sample_34 (line 47) | @Test
    method bestBookFor (line 56) | void bestBookFor(Person person) {
    method bestSeller (line 66) | private Book bestSeller() {
    method recommend (line 70) | private Book recommend(Person person) {
    method display (line 74) | void display(String title) {
    method bestBookFor2 (line 78) | void bestBookFor2(Person person) {
    method bestBookFor3 (line 86) | void bestBookFor3(Person person) {
    method bestSeller2 (line 93) | private Observable<Book> bestSeller2() {
    method recommend2 (line 97) | private Observable<Book> recommend2(Person person) {
    method sample_89 (line 101) | @Test
    method getOrderBookLength (line 109) | private int getOrderBookLength() {
    method observeNewItems (line 113) | Observable<Item> observeNewItems() {
    method query (line 120) | List<Item> query() {
    method sample_118 (line 126) | @Test
    method sample_136 (line 141) | @Test
    method log (line 148) | void log(Object label) {
    method sample_141 (line 155) | @Test
    method sample_175 (line 175) | @Test
    method sleepOneSecond (line 199) | private void sleepOneSecond() {

FILE: src/test/java/com/oreilly/rxjava/ch4/Flight.java
  class Flight (line 3) | class Flight {

FILE: src/test/java/com/oreilly/rxjava/ch4/Flights.java
  class Flights (line 23) | @Ignore
    method lookupFlight (line 28) | Flight lookupFlight(String flightNo) {
    method findPassenger (line 33) | Passenger findPassenger(long id) {
    method bookTicket (line 38) | Ticket bookTicket(Flight flight, Passenger passenger) {
    method sendEmail (line 43) | SmtpResponse sendEmail(Ticket ticket) {
    method sample_29 (line 48) | @Test
    method rxLookupFlight (line 56) | Observable<Flight> rxLookupFlight(String flightNo) {
    method rxFindPassenger (line 61) | Observable<Passenger> rxFindPassenger(long id) {
    method sample_49 (line 66) | @Test
    method sample_67 (line 75) | @Test
    method sample_76 (line 82) | @Test
    method rxBookTicket (line 94) | private Observable<Ticket> rxBookTicket(Flight left, Passenger right) {
    method sample_85 (line 98) | @Test
    method sample_97 (line 110) | @Test
    method sample_120 (line 124) | @Test
    method sendEmailAsync (line 148) | private Future<SmtpResponse> sendEmailAsync(Ticket ticket) {
    method sample_152 (line 152) | @Test
    method rxSendEmail (line 170) | Observable<SmtpResponse> rxSendEmail(Ticket ticket) {
    method sample_177 (line 175) | @Test
    method sample_191 (line 189) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch4/Item.java
  class Item (line 3) | class Item {

FILE: src/test/java/com/oreilly/rxjava/ch4/JmsConsumer.java
  class JmsConsumer (line 9) | @Component
    method newOrder (line 14) | @JmsListener(destination = "orders", concurrency="1")
    method observe (line 19) | Observable<Message> observe() {

FILE: src/test/java/com/oreilly/rxjava/ch4/Messaging.java
  class Messaging (line 17) | @Ignore
    method connect (line 22) | void connect() {
    method observe (line 35) | public Observable<Message> observe(ConnectionFactory connectionFactory...
    method subscribeThrowing (line 45) | private void subscribeThrowing(Subscriber<? super Message> subscriber,...
    method onUnsubscribe (line 54) | private Subscription onUnsubscribe(Connection connection) {

FILE: src/test/java/com/oreilly/rxjava/ch4/Passenger.java
  class Passenger (line 3) | class Passenger {

FILE: src/test/java/com/oreilly/rxjava/ch4/Person.java
  class Person (line 3) | class Person {

FILE: src/test/java/com/oreilly/rxjava/ch4/PersonDao.java
  class PersonDao (line 11) | class PersonDao {
    method allPeople (line 15) | Observable<Person> allPeople(int initialPage) {
    method allPeople (line 21) | void allPeople() {
    method listPeople (line 29) | List<Person> listPeople() {
    method listPeople (line 33) | List<Person> listPeople(int initialPage) {
    method listPeople2 (line 37) | Observable<Person> listPeople2() {
    method listPeople3 (line 42) | public Observable<Person> listPeople3() {
    method query (line 47) | private List<Person> query(String sql, Object... args) {

FILE: src/test/java/com/oreilly/rxjava/ch4/RxGroceries.java
  class RxGroceries (line 9) | class RxGroceries {
    method log (line 15) | void log(Object label) {
    method purchase (line 23) | Observable<BigDecimal> purchase(String productName, int quantity) {
    method doPurchase (line 28) | BigDecimal doPurchase(String productName, int quantity) {

FILE: src/test/java/com/oreilly/rxjava/ch4/Schedulers.java
  class Schedulers (line 20) | @Ignore
    method log (line 36) | void log(Object label) {
    method threadFactory (line 43) | private ThreadFactory threadFactory(String pattern) {
    method simple (line 49) | Observable<String> simple() {
    method sample_215 (line 58) | @Test
    method sample_33 (line 74) | @Test
    method sample_77 (line 88) | @Test
    method sample_103 (line 105) | @Test
    method sample_122 (line 127) | @Test
    method sample_135 (line 137) | @Test
    method sample_145 (line 147) | @Test
    method sample_157 (line 159) | @Test
    method sample_177 (line 178) | @Test
    method sample_194 (line 195) | @Test
    method sample_214 (line 215) | @Test
    method store (line 239) | Observable<UUID> store(String s) {
    method sample_248 (line 248) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch4/SimplifiedHandlerScheduler.java
  class SimplifiedHandlerScheduler (line 14) | public final class SimplifiedHandlerScheduler extends Scheduler {
    method createWorker (line 16) | @Override
    class HandlerWorker (line 21) | static class HandlerWorker extends Worker {
      method schedule (line 25) | @Override
      method unsubscribe (line 32) | @Override
      method isUnsubscribed (line 37) | @Override
      method schedule (line 42) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch4/SmtpResponse.java
  class SmtpResponse (line 3) | class SmtpResponse {

FILE: src/test/java/com/oreilly/rxjava/ch4/Ticket.java
  class Ticket (line 3) | class Ticket {

FILE: src/test/java/com/oreilly/rxjava/ch5/Chapter5.java
  class Chapter5 (line 14) | @Ignore
    method sample_9 (line 17) | @Test
    method sample_22 (line 28) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch5/CompletableFutures.java
  class CompletableFutures (line 19) | @Ignore
    method findById (line 22) | User findById(long id) {
    method locate (line 26) | GeoLocation locate() {
    method book (line 30) | Ticket book(Flight flight) {
    method sample_21 (line 34) | @Test
    method findByIdAsync (line 52) | CompletableFuture<User> findByIdAsync(long id) {
    method locateAsync (line 56) | CompletableFuture<GeoLocation> locateAsync() {
    method bookAsync (line 60) | CompletableFuture<Ticket> bookAsync(Flight flight) {
    method rxFindById (line 64) | Observable<User> rxFindById(long id) {
    method rxLocate (line 68) | Observable<GeoLocation> rxLocate() {
    method rxBook (line 72) | Observable<Ticket> rxBook(Flight flight) {
    method sample_63 (line 76) | @Test
    method sample_80 (line 96) | @Test
    method sample_96 (line 109) | @Test
    method sample_111 (line 125) | @Test
    method sample_123 (line 136) | @Test
    method sample_145 (line 145) | @Test
    method agencies (line 164) | private Observable<TravelAgency> agencies() {
    method sample_168 (line 168) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch5/EurUsdCurrencyTcpServer.java
  class EurUsdCurrencyTcpServer (line 13) | class EurUsdCurrencyTcpServer {
    method main (line 17) | public static void main(final String[] args) {
    method eurToUsd (line 34) | static Observable<String> eurToUsd(BigDecimal eur) {

FILE: src/test/java/com/oreilly/rxjava/ch5/Flight.java
  class Flight (line 3) | class Flight {

FILE: src/test/java/com/oreilly/rxjava/ch5/GeoLocation.java
  class GeoLocation (line 3) | class GeoLocation {

FILE: src/test/java/com/oreilly/rxjava/ch5/HttpHandler.java
  class HttpHandler (line 16) | @ChannelHandler.Sharable
    method channelReadComplete (line 21) | @Override
    method channelRead (line 26) | @Override
    method sendResponse (line 33) | private void sendResponse(ChannelHandlerContext ctx) {
    method exceptionCaught (line 42) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch5/HttpInitializer.java
  class HttpInitializer (line 8) | class HttpInitializer extends ChannelInitializer<SocketChannel> {
    method initChannel (line 12) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch5/HttpTcpNettyServer.java
  class HttpTcpNettyServer (line 9) | class HttpTcpNettyServer {
    method main (line 11) | public static void main(String[] args) throws Exception {

FILE: src/test/java/com/oreilly/rxjava/ch5/HttpTcpRxNettyServer.java
  class HttpTcpRxNettyServer (line 10) | class HttpTcpRxNettyServer {
    method main (line 18) | public static void main(final String[] args) {

FILE: src/test/java/com/oreilly/rxjava/ch5/Postgres.java
  class Postgres (line 16) | @Ignore
    method sample_37 (line 20) | @Test
    method sample_55 (line 34) | @Test
    method pollForNotifications (line 46) | void pollForNotifications(Jdbc42Connection pgConn) throws Exception {
    method observe (line 60) | Observable<PGNotification> observe(String channel, long pollingPeriod) {
    method listenOn (line 77) | void listenOn(Connection connection, String channel) throws SQLExcepti...
    method closeQuietly (line 83) | void closeQuietly(Connection connection) {
    method pollForNotifications (line 91) | Observable<PGNotification> pollForNotifications(
    method tryGetNotification (line 101) | Observable<PGNotification[]> tryGetNotification(

FILE: src/test/java/com/oreilly/rxjava/ch5/RestCurrencyServer.java
  class RestCurrencyServer (line 8) | class RestCurrencyServer {
    method main (line 12) | public static void main(final String[] args) {

FILE: src/test/java/com/oreilly/rxjava/ch5/RxNettyHttpServer.java
  class RxNettyHttpServer (line 8) | class RxNettyHttpServer {
    method main (line 13) | public static void main(String[] args) {

FILE: src/test/java/com/oreilly/rxjava/ch5/SingleThread.java
  class SingleThread (line 11) | class SingleThread {
    method main (line 19) | public static void main(String[] args) throws IOException {
    method handle (line 27) | private static void handle(Socket client) {
    method readFullRequest (line 39) | private static void readFullRequest(Socket client) throws IOException {

FILE: src/test/java/com/oreilly/rxjava/ch5/Singles.java
  class Singles (line 18) | @Ignore
    method sample_6 (line 21) | @Test
    method fetch (line 38) | Single<Response> fetch(String address) {
    method handler (line 45) | AsyncCompletionHandler handler(SingleSubscriber<? super Response> subs...
    method sample_55 (line 58) | @Test
    method body (line 67) | Single<String> body(Response response) {
    method body2 (line 78) | Single<String> body2(Response response) {
    method content (line 85) | Single<String> content(int id) {
    method likes (line 93) | Single<Integer> likes(int id) {
    method updateReadCount (line 98) | Single<Void> updateReadCount() {
    method sample_98 (line 103) | @Test
    method buildHtml (line 113) | Document buildHtml(String content, int likes) {
    method sample_113 (line 118) | @Test
    method sample_129 (line 134) | @Test
    method sample_138 (line 142) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch5/Ticket.java
  class Ticket (line 3) | class Ticket {

FILE: src/test/java/com/oreilly/rxjava/ch5/TravelAgency.java
  type TravelAgency (line 7) | interface TravelAgency {
    method search (line 8) | Flight search(User user, GeoLocation location);
    method searchAsync (line 10) | default CompletableFuture<Flight> searchAsync(User user, GeoLocation l...
    method rxSearch (line 14) | default Observable<Flight> rxSearch(User user, GeoLocation location) {
  class SomeTravelAgency (line 21) | class SomeTravelAgency implements TravelAgency {
    method search (line 23) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch5/User.java
  class User (line 5) | class User {
    method getBirth (line 7) | LocalDate getBirth() {

FILE: src/test/java/com/oreilly/rxjava/ch5/Util.java
  class Util (line 8) | class Util {
    method observe (line 9) | static <T> Observable<T> observe(CompletableFuture<T> future) {
    method toFuture (line 22) | static <T> CompletableFuture<T> toFuture(Observable<T> observable) {
    method toFutureList (line 33) | static <T> CompletableFuture<List<T>> toFutureList(Observable<T> obser...

FILE: src/test/java/com/oreilly/rxjava/ch6/Backpressure.java
  class Backpressure (line 20) | @Ignore
    method dishes (line 26) | private Observable<Dish> dishes() {
    method sample_18 (line 33) | @Test
    method sample_32 (line 44) | @Test
    method sleepMillis (line 57) | private void sleepMillis(int millis) {
    method myRange (line 61) | Observable<Integer> myRange(int from, int count) {
    method sample_65 (line 75) | @Test
    method sample_78 (line 88) | @Test
    method sample_94 (line 117) | @Test
    method sample_136 (line 147) | @Test
    method sample_173 (line 178) | @Test
    method sample_189 (line 192) | @Test
    method sample_213 (line 213) | @Test
    method sample_224 (line 223) | @Test
    method sample_238 (line 237) | @Test
    method sample_249 (line 248) | @Test
    method toArray (line 276) | private Object[] toArray(ResultSet rs) {
    method sample_284 (line 281) | @Test
    method store (line 298) | Observable<Void> store(int x) {

FILE: src/test/java/com/oreilly/rxjava/ch6/Chapter6.java
  class Chapter6 (line 20) | @Ignore
    method sample_9 (line 23) | @Test
    method sample_25 (line 35) | @Test
    method sample_37 (line 44) | @Test
    method delayedNames (line 55) | private Observable<String> delayedNames() {
    method delayedCompletion (line 78) | static <T> Observable<T> delayedCompletion() {
    method sample_64 (line 82) | @Test
    method sample_73 (line 91) | @Test
    method sample_93 (line 100) | @Test
    method sample_105 (line 113) | @Test
    method sample_120 (line 126) | @Test
    method averageOfList (line 137) | private double averageOfList(List<Double> list) {
    method sample_139 (line 143) | @Test
    method sample_147 (line 151) | @Test
    method sample_155 (line 159) | @Test
    method sample_164 (line 168) | @Test
    method sample_173 (line 177) | @Test
    method isBusinessHour (line 207) | private boolean isBusinessHour() {
    method sample_216 (line 215) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch6/Debounce.java
  class Debounce (line 14) | @Ignore
    method sample_225 (line 20) | @Test
    method sample_242 (line 34) | @Test
    method sample_249 (line 41) | @Test
    method sample_48 (line 49) | @Test
    method sample_60 (line 60) | @Test
    method sample_72 (line 72) | @Test
    method timedDebounce (line 86) | Observable<Long> timedDebounce(Observable<Long> upstream) {

FILE: src/test/java/com/oreilly/rxjava/ch6/Dish.java
  class Dish (line 3) | class Dish {
    method Dish (line 7) | Dish(int id) {
    method toString (line 12) | public String toString() {

FILE: src/test/java/com/oreilly/rxjava/ch6/KeyEvent.java
  class KeyEvent (line 3) | class KeyEvent {

FILE: src/test/java/com/oreilly/rxjava/ch6/Record.java
  class Record (line 3) | class Record {

FILE: src/test/java/com/oreilly/rxjava/ch6/Repository.java
  type Repository (line 5) | interface Repository {
    method store (line 6) | void store(Record record);
    method storeAll (line 7) | void storeAll(List<Record> records);
  class SomeRepository (line 10) | class SomeRepository implements Repository {
    method store (line 11) | @Override
    method storeAll (line 15) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch6/TeleData.java
  class TeleData (line 3) | class TeleData {

FILE: src/test/java/com/oreilly/rxjava/ch6/TradingPlatform.java
  class TradingPlatform (line 9) | class TradingPlatform {
    method pricesOf (line 11) | Observable<BigDecimal> pricesOf(String ticker) {
    method randomDelay (line 19) | Observable<Long> randomDelay(long x) {
    method randomStockPrice (line 25) | double randomStockPrice(long x) {

FILE: src/test/java/com/oreilly/rxjava/ch7/Agreement.java
  class Agreement (line 3) | class Agreement {
    method postalMailRequired (line 4) | boolean postalMailRequired() {

FILE: src/test/java/com/oreilly/rxjava/ch7/Chapter7.java
  class Chapter7 (line 20) | @Ignore
    method sample_9 (line 25) | @Test
    method sample_29 (line 39) | @Test
    method sample_45 (line 55) | @Test
    method sample_60 (line 70) | @Test
    method sample_71 (line 81) | @Test
    method sample_81 (line 94) | @Test
    method print (line 113) | private Observable<Agreement> print(Agreement agreement) {
    method prepare (line 117) | private Agreement prepare(InsuranceContract contract, Score score) {
    method translate (line 121) | private Score translate(BigInteger score) {
    method asses (line 125) | private BigInteger asses(Health h, Income i) {
    method determineIncome (line 129) | private Observable<Income> determineIncome(Person person) {
    method checkHealth (line 133) | private Observable<Health> checkHealth(Person person) {
    method sample_129 (line 137) | @Test
    method sample_137 (line 145) | public Observable<Income> sample_137() throws Exception {
    method sample_147 (line 154) | @Test
    method guessIncome (line 163) | private Observable<Income> guessIncome(Person person) {
    method sample_161 (line 168) | @Test
    method sample_175 (line 182) | @Test
    method sample_187 (line 194) | @Test
    method confirmation (line 209) | Observable<Confirmation> confirmation() {
    method sample_215 (line 220) | @Test
    method nextSolarEclipse (line 236) | Observable<LocalDate> nextSolarEclipse(LocalDate after) {
    method sample_253 (line 255) | @Test
    method sample_262 (line 263) | @Test
    method sample_271 (line 270) | @Test
    method dbQuery (line 284) | private Instant dbQuery() {
    method sample_291 (line 288) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch7/Confirmation.java
  class Confirmation (line 3) | class Confirmation {

FILE: src/test/java/com/oreilly/rxjava/ch7/Monitoring.java
  class Monitoring (line 14) | @Ignore
    method sample_9 (line 19) | @Test
    method sample_26 (line 29) | @Test
    method makeNetworkCall (line 38) | Observable<Long> makeNetworkCall(long x) {
    method sample_38 (line 43) | @Test
    method sample_55 (line 55) | @Test
    method sample_69 (line 69) | @Test
    method sample_78 (line 77) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch7/MyService.java
  type MyService (line 7) | interface MyService {
    method externalCall (line 8) | Observable<LocalDate> externalCall();

FILE: src/test/java/com/oreilly/rxjava/ch7/MyServiceWithTimeout.java
  class MyServiceWithTimeout (line 9) | class MyServiceWithTimeout implements MyService {
    method MyServiceWithTimeout (line 14) | MyServiceWithTimeout(MyService d, Scheduler s) {
    method externalCall (line 19) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch7/Person.java
  class Person (line 3) | class Person {
  class Health (line 6) | class Health {
  class Score (line 9) | class Score {
    method isHigh (line 10) | boolean isHigh() {
  class InsuranceContract (line 15) | class InsuranceContract {
  class Income (line 18) | class Income {
    method Income (line 21) | public Income(int i) {
    method no (line 24) | static Income no() {

FILE: src/test/java/com/oreilly/rxjava/ch7/PrintHouse.java
  class PrintHouse (line 5) | class PrintHouse {
    method deliver (line 7) | Observable<TrackingId> deliver(Agreement agreement) {

FILE: src/test/java/com/oreilly/rxjava/ch7/RetryTimeouts.java
  class RetryTimeouts (line 13) | @Ignore
    method risky (line 18) | Observable<String> risky() {
    method sample_281 (line 29) | @Test
    method sample_291 (line 38) | @Test
    method sample_296 (line 43) | @Test
    method sample_303 (line 50) | @Test
    method sample_310 (line 57) | @Test
    method sample_66 (line 65) | @Test
    method sample_74 (line 75) | @Test
    method sample_89 (line 88) | @Test
    method handleRetryAttempt (line 99) | Observable<Long> handleRetryAttempt(Throwable err, int attempt) {

FILE: src/test/java/com/oreilly/rxjava/ch7/Testing.java
  class Testing (line 34) | @Ignore
    method sample_9 (line 37) | @Test
    method sample_31 (line 53) | @Test
    method shouldApplyConcatMapInOrder (line 70) | @Test
    method sample_65 (line 83) | @Test
    method sample_87 (line 99) | @Test
    method sample_107 (line 115) | @Test
    method mockReturning (line 128) | private MyServiceWithTimeout mockReturning(
    method timeoutWhenServiceNeverCompletes (line 136) | @Test
    method valueIsReturnedJustBeforeTimeout (line 155) | @Test
    method alwaysUseTestScheduler (line 179) | @Before
    method naturals1 (line 201) | Observable<Long> naturals1() {
    method naturals2 (line 210) | Observable<Long> naturals2() {
    method sample_222 (line 221) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch7/TrackingId.java
  class TrackingId (line 3) | class TrackingId {

FILE: src/test/java/com/oreilly/rxjava/ch8/Android.java
  class Android (line 25) | @Ignore
    method sample_9 (line 30) | @Test
    method extractCities (line 54) | Func1<Cities, Iterable<City>> extractCities() {
    method toCityName (line 64) | Func1<City, String> toCityName() {
    method putOnListView (line 74) | Action1<List<String>> putOnListView() {
    method displayError (line 85) | Action1<Throwable> displayError() {
    method sample_98 (line 95) | @Test
    method listCities (line 112) | Func1<Void, Observable<Cities>> listCities(final double lat, final dou...
    method sample_121 (line 121) | @Test
    method toDouble (line 139) | Func1<TextViewAfterTextChangeEvent, Observable<Double>> toDouble() {
    method toPair (line 154) | Func2<Double, Double, Pair<Double, Double>> toPair() {
    method listCitiesNear (line 164) | Func1<Pair<Double, Double>, Observable<Cities>> listCitiesNear() {

FILE: src/test/java/com/oreilly/rxjava/ch8/ApiFactory.java
  class ApiFactory (line 10) | class ApiFactory {
    method geoNames (line 12) | GeoNames geoNames() {
    method meetup (line 21) | MeetupApi meetup() {
    method objectMapper (line 32) | private ObjectMapper objectMapper() {

FILE: src/test/java/com/oreilly/rxjava/ch8/Chapter8.java
  class Chapter8 (line 33) | @Ignore
    method sample_9 (line 36) | @Test
    method sample_35 (line 60) | @Test
    method sample_55 (line 75) | @Test
    method sample_105 (line 97) | @Test
    method dailyPrice (line 123) | private Observable<BigDecimal> dailyPrice(LocalDateTime date) {
    method sample_121 (line 127) | @Test
    method sample_136 (line 138) | @Test
    method sample_148 (line 149) | @Test
    method publishOverJms (line 166) | private void publishOverJms(Person person) {
    method sample_170 (line 170) | @Test
    method sample_182 (line 181) | @Test
    method sample_192 (line 191) | @Test
    method sample_201 (line 200) | @Test
    method sample_213 (line 212) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch8/Cities.java
  class Cities (line 5) | public class Cities {
    method getResults (line 8) | public List<City> getResults() {
    method setResults (line 12) | public void setResults(List<City> results) {

FILE: src/test/java/com/oreilly/rxjava/ch8/City.java
  class City (line 3) | public class City {
    method getCity (line 15) | public String getCity() {
    method setCity (line 19) | public void setCity(String city) {
    method getCountry (line 23) | public String getCountry() {
    method setCountry (line 27) | public void setCountry(String country) {
    method getDistance (line 31) | public Double getDistance() {
    method setDistance (line 35) | public void setDistance(Double distance) {
    method getId (line 39) | public Integer getId() {
    method setId (line 43) | public void setId(Integer id) {
    method getLat (line 47) | public Double getLat() {
    method setLat (line 51) | public void setLat(Double lat) {
    method getLocalizedCountryName (line 55) | public String getLocalizedCountryName() {
    method setLocalizedCountryName (line 59) | public void setLocalizedCountryName(String localizedCountryName) {
    method getLon (line 63) | public Double getLon() {
    method setLon (line 67) | public void setLon(Double lon) {
    method getMemberCount (line 71) | public Integer getMemberCount() {
    method setMemberCount (line 75) | public void setMemberCount(Integer memberCount) {
    method getRanking (line 79) | public Integer getRanking() {
    method setRanking (line 83) | public void setRanking(Integer ranking) {
    method getZip (line 87) | public String getZip() {
    method setZip (line 91) | public void setZip(String zip) {
    method distanceTo (line 95) | public double distanceTo(double lat, double lon) {

FILE: src/test/java/com/oreilly/rxjava/ch8/GeoNames.java
  type GeoNames (line 10) | public interface GeoNames {
    method populationOf (line 14) | default Observable<Integer> populationOf(String query) {
    method search (line 26) | default Observable<SearchResult> search(String query) {
    method search (line 30) | @GET("/searchJSON")

FILE: src/test/java/com/oreilly/rxjava/ch8/Geoname.java
  class Geoname (line 3) | public class Geoname {
    method getLat (line 11) | public String getLat() {
    method setLat (line 15) | public void setLat(String lat) {
    method getLng (line 19) | public String getLng() {
    method setLng (line 23) | public void setLng(String lng) {
    method getGeonameId (line 27) | public Integer getGeonameId() {
    method setGeonameId (line 31) | public void setGeonameId(Integer geonameId) {
    method getPopulation (line 35) | public Integer getPopulation() {
    method setPopulation (line 39) | public void setPopulation(Integer population) {
    method getCountryCode (line 43) | public String getCountryCode() {
    method setCountryCode (line 47) | public void setCountryCode(String countryCode) {
    method getName (line 51) | public String getName() {
    method setName (line 55) | public void setName(String name) {

FILE: src/test/java/com/oreilly/rxjava/ch8/Incident.java
  class Incident (line 3) | class Incident {
    method isHIghPriority (line 4) | boolean isHIghPriority() {

FILE: src/test/java/com/oreilly/rxjava/ch8/Insurance.java
  class Insurance (line 3) | class Insurance {

FILE: src/test/java/com/oreilly/rxjava/ch8/MeetupApi.java
  type MeetupApi (line 8) | public interface MeetupApi {
    method listCities (line 10) | @GET("/2/cities")

FILE: src/test/java/com/oreilly/rxjava/ch8/Person.java
  class Person (line 3) | class Person {
    method getAge (line 5) | int getAge() {
    method getFirstName (line 9) | String getFirstName() {

FILE: src/test/java/com/oreilly/rxjava/ch8/Picture.java
  class Picture (line 3) | class Picture {
    method Picture (line 7) | Picture(long tag) { this.tag = tag; }
    method equals (line 9) | @Override
    method getTag (line 17) | long getTag() {
    method hashCode (line 21) | @Override
    method toString (line 26) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch8/SearchResult.java
  class SearchResult (line 6) | class SearchResult {
    method getGeonames (line 9) | public List<Geoname> getGeonames() {
    method setGeonames (line 13) | public void setGeonames(List<Geoname> geonames) {

FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/BlockingCmd.java
  class BlockingCmd (line 12) | class BlockingCmd extends HystrixCommand<String> {
    method BlockingCmd (line 14) | public BlockingCmd() {
    method run (line 18) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/Book.java
  class Book (line 3) | class Book {
  class Rating (line 6) | class Rating {
    method Rating (line 10) | Rating(Book book) {
    method getBook (line 14) | public Book getBook() {

FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/CitiesCmd.java
  class CitiesCmd (line 9) | class CitiesCmd extends HystrixObservableCommand<Cities> {
    method CitiesCmd (line 15) | protected CitiesCmd(MeetupApi api, double lat, double lon) {
    method construct (line 22) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/FetchManyRatings.java
  class FetchManyRatings (line 9) | class FetchManyRatings extends HystrixObservableCommand<Rating> {
    method FetchManyRatings (line 13) | protected FetchManyRatings(Collection<Book> books) {
    method construct (line 18) | @Override
    method fetchManyRatings (line 23) | private Observable<Rating> fetchManyRatings(Collection<Book> books) {

FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/FetchRatingsCollapser.java
  class FetchRatingsCollapser (line 12) | public class FetchRatingsCollapser
    method FetchRatingsCollapser (line 17) | public FetchRatingsCollapser(Book book) {
    method getRequestArgument (line 27) | public Book getRequestArgument() {
    method createCommand (line 31) | protected HystrixObservableCommand<Rating> createCommand(
    method onMissingResponse (line 39) | protected void onMissingResponse(HystrixCollapser.CollapsedRequest<Rat...
    method getRequestArgumentKeySelector (line 43) | protected Func1<Book, Book> getRequestArgumentKeySelector() {
    method getBatchReturnTypeToResponseTypeMapper (line 47) | protected Func1<Rating, Rating> getBatchReturnTypeToResponseTypeMapper...
    method getBatchReturnTypeKeySelector (line 51) | protected Func1<Rating, Book> getBatchReturnTypeKeySelector() {

FILE: src/test/java/com/oreilly/rxjava/ch8/hystrix/Hystrix.java
  class Hystrix (line 28) | @Ignore
    method sample_17 (line 33) | @Test
    method sample_28 (line 41) | @Test
    method sample_44 (line 50) | @Test
    method allBooks (line 70) | Observable<Book> allBooks() {
    method fetchRating (line 73) | Observable<Rating> fetchRating(Book book) {
    method sample_69 (line 77) | @Test
    method sample_83 (line 83) | @Test
    method sample_82 (line 90) | @Test
    method sample_98 (line 101) | @Test

FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/AndroidSchedulers.java
  class AndroidSchedulers (line 23) | public final class AndroidSchedulers {
    method getInstance (line 28) | private static AndroidSchedulers getInstance() {
    method AndroidSchedulers (line 41) | private AndroidSchedulers() {
    method mainThread (line 53) | public static Scheduler mainThread() {
    method from (line 58) | public static Scheduler from(Looper looper) {
    method reset (line 68) | @Experimental

FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/LooperScheduler.java
  class LooperScheduler (line 28) | class LooperScheduler extends Scheduler {
    method LooperScheduler (line 31) | LooperScheduler(Looper looper) {
    method LooperScheduler (line 35) | LooperScheduler(Handler handler) {
    method createWorker (line 39) | @Override
    class HandlerWorker (line 44) | static class HandlerWorker extends Worker {
      method HandlerWorker (line 49) | HandlerWorker(Handler handler) {
      method unsubscribe (line 54) | @Override
      method isUnsubscribed (line 60) | @Override
      method schedule (line 65) | @Override
      method schedule (line 88) | @Override
    class ScheduledAction (line 94) | static final class ScheduledAction implements Runnable, Subscription {
      method ScheduledAction (line 99) | ScheduledAction(Action0 action, Handler handler) {
      method run (line 104) | @Override public void run() {
      method unsubscribe (line 121) | @Override public void unsubscribe() {
      method isUnsubscribed (line 126) | @Override public boolean isUnsubscribed() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/MainActivity.java
  class MainActivity (line 11) | public class MainActivity extends Activity {
    method onCreate (line 17) | @Override
    method onDestroy (line 29) | @Override

FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/MainThreadSubscription.java
  class MainThreadSubscription (line 47) | public abstract class MainThreadSubscription implements Subscription {
    method verifyMainThread (line 56) | public static void verifyMainThread() {
    method isUnsubscribed (line 65) | @Override public final boolean isUnsubscribed() {
    method unsubscribe (line 69) | @Override public final void unsubscribe() {
    method onUnsubscribe (line 83) | protected abstract void onUnsubscribe();

FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/RxAndroidPlugins.java
  class RxAndroidPlugins (line 28) | public final class RxAndroidPlugins {
    method getInstance (line 31) | public static RxAndroidPlugins getInstance() {
    method RxAndroidPlugins (line 37) | RxAndroidPlugins() {
    method reset (line 45) | @Experimental
    method getSchedulersHook (line 58) | public RxAndroidSchedulersHook getSchedulersHook() {
    method registerSchedulersHook (line 74) | public void registerSchedulersHook(RxAndroidSchedulersHook impl) {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxandroid/RxAndroidSchedulersHook.java
  class RxAndroidSchedulersHook (line 19) | public class RxAndroidSchedulersHook {
    method getDefaultInstance (line 22) | public static RxAndroidSchedulersHook getDefaultInstance() {
    method getMainThreadScheduler (line 32) | public Scheduler getMainThreadScheduler() {
    method onSchedule (line 43) | public Action0 onSchedule(Action0 action) {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/RxTextView.java
  class RxTextView (line 18) | public final class RxTextView {
    method editorActions (line 28) | @Nonnull
    method editorActions (line 46) | @Nonnull
    method editorActionEvents (line 63) | @Nonnull
    method editorActionEvents (line 81) | @Nonnull
    method textChanges (line 103) | @Nonnull
    method textChangeEvents (line 123) | @Nonnull
    method beforeTextChangeEvents (line 137) | @Nonnull
    method afterTextChangeEvents (line 152) | @Nonnull
    method text (line 165) | @Nonnull
    method textRes (line 181) | @Nonnull
    method error (line 197) | @Nonnull
    method errorRes (line 213) | @Nonnull
    method hint (line 229) | @Nonnull
    method hintRes (line 245) | @Nonnull
    method color (line 261) | @Nonnull
    method RxTextView (line 271) | private RxTextView() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/RxView.java
  class RxView (line 16) | public final class RxView {
    method clicks (line 28) | @Nonnull

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewAfterTextChangeEvent.java
  class TextViewAfterTextChangeEvent (line 16) | public final class TextViewAfterTextChangeEvent extends ViewEvent<TextVi...
    method create (line 17) | @Nonnull
    method TextViewAfterTextChangeEvent (line 25) | private TextViewAfterTextChangeEvent(@Nonnull TextView view, @Nullable...
    method editable (line 30) | @Nullable
    method equals (line 35) | @Override public boolean equals(Object o) {
    method hashCode (line 43) | @Override public int hashCode() {
    method toString (line 50) | @Override public String toString() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewAfterTextChangeEventOnSubscribe.java
  class TextViewAfterTextChangeEventOnSubscribe (line 12) | final class TextViewAfterTextChangeEventOnSubscribe
    method TextViewAfterTextChangeEventOnSubscribe (line 16) | TextViewAfterTextChangeEventOnSubscribe(TextView view) {
    method call (line 20) | @Override public void call(final Subscriber<? super TextViewAfterTextC...

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewBeforeTextChangeEvent.java
  class TextViewBeforeTextChangeEvent (line 14) | public final class TextViewBeforeTextChangeEvent extends ViewEvent<TextV...
    method create (line 15) | @Nonnull
    method TextViewBeforeTextChangeEvent (line 26) | private TextViewBeforeTextChangeEvent(@Nonnull TextView view, @Nonnull...
    method text (line 35) | @Nonnull
    method start (line 40) | public int start() {
    method count (line 44) | public int count() {
    method after (line 48) | public int after() {
    method equals (line 52) | @Override public boolean equals(Object o) {
    method hashCode (line 63) | @Override public int hashCode() {
    method toString (line 73) | @Override public String toString() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewBeforeTextChangeEventOnSubscribe.java
  class TextViewBeforeTextChangeEventOnSubscribe (line 12) | final class TextViewBeforeTextChangeEventOnSubscribe
    method TextViewBeforeTextChangeEventOnSubscribe (line 16) | TextViewBeforeTextChangeEventOnSubscribe(TextView view) {
    method call (line 20) | @Override public void call(final Subscriber<? super TextViewBeforeText...

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewEditorActionEvent.java
  class TextViewEditorActionEvent (line 8) | public final class TextViewEditorActionEvent extends ViewEvent<TextView> {
    method create (line 10) | public static TextViewEditorActionEvent create( TextView view, int act...
    method TextViewEditorActionEvent (line 18) | private TextViewEditorActionEvent( TextView view, int actionId,
    method actionId (line 25) | public int actionId() {
    method keyEvent (line 29) | @Nullable public KeyEvent keyEvent() {
    method equals (line 33) | @Override public boolean equals(Object o) {
    method hashCode (line 42) | @Override public int hashCode() {
    method toString (line 50) | @Override public String toString() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewEditorActionEventOnSubscribe.java
  class TextViewEditorActionEventOnSubscribe (line 12) | final class TextViewEditorActionEventOnSubscribe
    method TextViewEditorActionEventOnSubscribe (line 17) | TextViewEditorActionEventOnSubscribe(TextView view,
    method call (line 23) | @Override public void call(final Subscriber<? super TextViewEditorActi...

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewEditorActionOnSubscribe.java
  class TextViewEditorActionOnSubscribe (line 12) | final class TextViewEditorActionOnSubscribe implements Observable.OnSubs...
    method TextViewEditorActionOnSubscribe (line 16) | TextViewEditorActionOnSubscribe(TextView view, Func1<? super Integer, ...
    method call (line 21) | @Override public void call(final Subscriber<? super Integer> subscribe...

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewTextChangeEvent.java
  class TextViewTextChangeEvent (line 14) | public final class TextViewTextChangeEvent extends ViewEvent<TextView> {
    method create (line 15) | @Nonnull
    method TextViewTextChangeEvent (line 26) | private TextViewTextChangeEvent(@Nonnull TextView view, @Nonnull CharS...
    method text (line 35) | @Nonnull
    method start (line 40) | public int start() {
    method before (line 44) | public int before() {
    method count (line 48) | public int count() {
    method equals (line 52) | @Override public boolean equals(Object o) {
    method hashCode (line 63) | @Override public int hashCode() {
    method toString (line 73) | @Override public String toString() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewTextChangeEventOnSubscribe.java
  class TextViewTextChangeEventOnSubscribe (line 12) | final class TextViewTextChangeEventOnSubscribe
    method TextViewTextChangeEventOnSubscribe (line 16) | TextViewTextChangeEventOnSubscribe(TextView view) {
    method call (line 20) | @Override public void call(final Subscriber<? super TextViewTextChange...

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewTextOnSubscribe.java
  class TextViewTextOnSubscribe (line 12) | final class TextViewTextOnSubscribe implements Observable.OnSubscribe<Ch...
    method TextViewTextOnSubscribe (line 15) | TextViewTextOnSubscribe(TextView view) {
    method call (line 19) | @Override public void call(final Subscriber<? super CharSequence> subs...

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/ViewClickOnSubscribe.java
  class ViewClickOnSubscribe (line 10) | final class ViewClickOnSubscribe implements Observable.OnSubscribe<Void> {
    method ViewClickOnSubscribe (line 13) | ViewClickOnSubscribe(View view) {
    method call (line 17) | @Override public void call(final Subscriber<? super Void> subscriber) {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/ViewEvent.java
  class ViewEvent (line 16) | public abstract class ViewEvent<T extends View> {
    method ViewEvent (line 19) | protected ViewEvent(@Nonnull T view) {
    method view (line 24) | @Nonnull public T view() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/internal/Functions.java
  class Functions (line 6) | public final class Functions {
    class Always (line 11) | private static final class Always<T> implements Func1<Object, T>, Func...
      method Always (line 14) | Always(T value) {
      method call (line 18) | @Override public T call(Object o) {
      method call (line 22) | @Override public T call() {
    method Functions (line 27) | private Functions() {

FILE: src/test/java/com/oreilly/rxjava/ch8/rxbinding/internal/Preconditions.java
  class Preconditions (line 16) | public final class Preconditions {
    method checkArgument (line 17) | public static void checkArgument(boolean assertion, String message) {
    method checkNotNull (line 23) | public static <T> T checkNotNull(T value, String message) {
    method Preconditions (line 30) | private Preconditions() {

FILE: src/test/java/com/oreilly/rxjava/ch9/Chapter9.java
  class Chapter9 (line 5) | @Ignore

FILE: src/test/java/com/oreilly/rxjava/util/Sleeper.java
  class Sleeper (line 10) | public class Sleeper {
    method sleep (line 15) | public static void sleep(Duration duration, Duration stdDev) {
    method sleep (line 20) | public static void sleep(Duration duration) {
Condensed preview — 146 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (255K chars).
[
  {
    "path": ".gitignore",
    "chars": 26,
    "preview": "build\n.gradle\n*.iml\n.idea\n"
  },
  {
    "path": "LICENSE.md",
    "chars": 1074,
    "preview": "MIT License\n\nCopyright (c) 2019 Tomasz Nurkiewicz\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "README.md",
    "chars": 1883,
    "preview": "# Source code of examples from _Reactive Programming with RxJava_\n\nBook is available on [O'Reilly](http://shop.oreilly.c"
  },
  {
    "path": "build.gradle",
    "chars": 2141,
    "preview": "apply plugin: 'java'\n\nsourceCompatibility = 1.8\ntargetCompatibility = 1.8\n\nrepositories {\n    mavenCentral()\n}\n\n\ndepende"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Sat Nov 19 14:44:58 CET 2016\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradlew",
    "chars": 5242,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2176,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/appendix1/ClientConnection.java",
    "chars": 1505,
    "preview": "package com.oreilly.rxjava.appendix1;\n\nimport org.apache.commons.io.IOUtils;\n\nimport java.io.BufferedReader;\nimport java"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/appendix1/HttpServer.java",
    "chars": 512,
    "preview": "package com.oreilly.rxjava.appendix1;\n\nimport java.io.IOException;\nimport java.net.ServerSocket;\nimport java.net.Socket;"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/appendix1/SingleThread.java",
    "chars": 301,
    "preview": "package com.oreilly.rxjava.appendix1;\n\npublic class SingleThread extends HttpServer {\n\n    public static void main(Strin"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/appendix1/ThreadPerConnection.java",
    "chars": 360,
    "preview": "package com.oreilly.rxjava.appendix1;\n\nimport java.io.IOException;\n\npublic class ThreadPerConnection extends HttpServer "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/appendix1/ThreadPool.java",
    "chars": 916,
    "preview": "package com.oreilly.rxjava.appendix1;\n\nimport java.io.IOException;\nimport java.util.concurrent.ArrayBlockingQueue;\nimpor"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch1/Callback.java",
    "chars": 522,
    "preview": "package com.oreilly.rxjava.ch1;\n\nimport java.util.function.Consumer;\n\nclass Callback {\n\tprivate Consumer<String> onRespo"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch1/Chapter1.java",
    "chars": 7723,
    "preview": "package com.oreilly.rxjava.ch1;\n\nimport com.oreilly.rxjava.util.Sleeper;\nimport org.junit.Ignore;\nimport org.junit.Test;"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/Chapter2.java",
    "chars": 7121,
    "preview": "package com.oreilly.rxjava.ch2;\n\nimport com.oreilly.rxjava.util.Sleeper;\nimport org.junit.Ignore;\nimport org.junit.Test;"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/Config.java",
    "chars": 1692,
    "preview": "package com.oreilly.rxjava.ch2;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.bea"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/Data.java",
    "chars": 48,
    "preview": "package com.oreilly.rxjava.ch2;\n\nclass Data {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/LazyTwitterObservable.java",
    "chars": 1841,
    "preview": "package com.oreilly.rxjava.ch2;\n\nimport rx.Observable;\nimport rx.Subscriber;\nimport rx.subscriptions.Subscriptions;\nimpo"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/NaturalNumbersIterator.java",
    "chars": 352,
    "preview": "package com.oreilly.rxjava.ch2;\n\nimport java.math.BigInteger;\nimport java.util.Iterator;\n\nclass NaturalNumbersIterator i"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/Tweet.java",
    "chars": 163,
    "preview": "package com.oreilly.rxjava.ch2;\n\nclass Tweet {\n\n\tprivate final String text;\n\n\tTweet(String text) {\n\t\tthis.text = text;\n\t"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/TwitterSample.java",
    "chars": 5000,
    "preview": "package com.oreilly.rxjava.ch2;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch2/TwitterSubject.java",
    "chars": 1012,
    "preview": "package com.oreilly.rxjava.ch2;\n\nimport rx.Observable;\nimport rx.subjects.PublishSubject;\nimport twitter4j.*;\n\nclass Twi"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Car.java",
    "chars": 47,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Car {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/CarPhoto.java",
    "chars": 52,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass CarPhoto {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/CashTransfer.java",
    "chars": 142,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport java.math.BigDecimal;\n\nclass CashTransfer {\n\n\tBigDecimal getAmount() {\n\t\treturn "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/CassandraFactStore.java",
    "chars": 219,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport rx.Observable;\n\nclass CassandraFactStore implements FactStore {\n\t@Override\n\tpubl"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Chapter3.java",
    "chars": 15310,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport com.oreilly.rxjava.util.Sleeper;\nimport org.apache.commons.lang3.RandomUtils;\nim"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/City.java",
    "chars": 81,
    "preview": "package com.oreilly.rxjava.ch3;\n\nenum City {\n\n\tWarsaw, London, Paris, NewYork\n\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/CustomOperators.java",
    "chars": 2494,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport org.apache.commons.lang3.tuple.Pair;\nimport org.junit.Ignore;\nimport org.junit.T"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Customer.java",
    "chars": 183,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nclass Customer {\n\n\tList<Order> getOrde"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Data.java",
    "chars": 48,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Data {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/FactStore.java",
    "chars": 121,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport rx.Observable;\n\ninterface FactStore {\n\tObservable<ReservationEvent> observe();\n}"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Flight.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Flight {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Hotel.java",
    "chars": 49,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Hotel {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/LicensePlate.java",
    "chars": 56,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass LicensePlate {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Licenses.java",
    "chars": 1201,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport rx.Observable;\n\n@Ignore\npublic c"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/OperatorMap.java",
    "chars": 935,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport rx.Observable;\nimport rx.Subscriber;\nimport rx.functions.Func1;\n\nfinal class Ope"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Order.java",
    "chars": 49,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Order {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Profile.java",
    "chars": 51,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Profile {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Rating.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Rating {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Reservation.java",
    "chars": 158,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Reservation {\n\n    Reservation consume(ReservationEvent event) {\n        //mutate"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/ReservationEvent.java",
    "chars": 184,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport java.util.UUID;\n\nclass ReservationEvent {\n\tprivate final UUID uuid = UUID.random"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Reservations.java",
    "chars": 1433,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport rx.Observable;\nimport rx.observa"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Shakespeare.java",
    "chars": 2295,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport com.oreilly.rxjava.util.Sleeper;\nimport org.apache.commons.lang3.tuple.Pair;\nimp"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Sound.java",
    "chars": 56,
    "preview": "package com.oreilly.rxjava.ch3;\n\nenum Sound { DI, DAH }\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/User.java",
    "chars": 195,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport rx.Observable;\n\nclass User {\n    Observable<Profile> loadProfile() {\n        //M"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Vacation.java",
    "chars": 570,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport rx.Observable;\n\nimport java.time.LocalDate;\n\nclass Vacation {\n\tprivate final Cit"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/Weather.java",
    "chars": 340,
    "preview": "package com.oreilly.rxjava.ch3;\n\nclass Weather {\n    private final Temperature temperature;\n\n    public Weather(Temperat"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch3/WeatherStation.java",
    "chars": 477,
    "preview": "package com.oreilly.rxjava.ch3;\n\nimport rx.Observable;\n\ninterface WeatherStation {\n    Observable<Temperature> temperatu"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Book.java",
    "chars": 97,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass Book {\n\tpublic String getTitle() {\n\t\treturn \"Title\";\n\t}\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Chapter4.java",
    "chars": 4697,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport com.oreilly.rxjav"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Flight.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass Flight {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Flights.java",
    "chars": 5433,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport org.apache.commons.lang3.tuple.Pair;\nimport org.junit.Ignore;\nimport org.junit.T"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Item.java",
    "chars": 48,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass Item {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/JmsConsumer.java",
    "chars": 554,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport org.springframework.jms.annotation.JmsListener;\nimport org.springframework.messa"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Messaging.java",
    "chars": 1848,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport org.apache.activemq.ActiveMQConnectionFactory;\nimport org.apache.activemq.comman"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Passenger.java",
    "chars": 53,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass Passenger {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Person.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass Person {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/PersonDao.java",
    "chars": 1381,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport rx.Observable;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static r"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/RxGroceries.java",
    "chars": 1002,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport rx.Observable;\n\nimport "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Schedulers.java",
    "chars": 6351,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport org.apache.common"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/SimplifiedHandlerScheduler.java",
    "chars": 1799,
    "preview": "package com.oreilly.rxjava.ch4;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport rx.Scheduler;\nimport rx.Sub"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/SmtpResponse.java",
    "chars": 56,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass SmtpResponse {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch4/Ticket.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch4;\n\nclass Ticket {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/Chapter5.java",
    "chars": 1000,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.netty.buffer.ByteBuf;\nimport io.reactivex.netty.protocol.http.client.HttpClie"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/CompletableFutures.java",
    "chars": 4999,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport org.apache.commons.lang3.tuple.Pair;\nimport org.junit.Ignore;\nimport org.junit.T"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/EurUsdCurrencyTcpServer.java",
    "chars": 1320,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.netty.handler.codec.LineBasedFrameDecoder;\nimport io.netty.handler.codec.stri"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/Flight.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch5;\n\nclass Flight {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/GeoLocation.java",
    "chars": 55,
    "preview": "package com.oreilly.rxjava.ch5;\n\nclass GeoLocation {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/HttpHandler.java",
    "chars": 1512,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.netty.buffer.Unpooled;\nimport io.netty.channel.ChannelHandler;\nimport io.nett"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/HttpInitializer.java",
    "chars": 504,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.netty.channel.ChannelInitializer;\nimport io.netty.channel.socket.SocketChanne"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/HttpTcpNettyServer.java",
    "chars": 1035,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.netty.bootstrap.ServerBootstrap;\nimport io.netty.channel.ChannelOption;\nimpor"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/HttpTcpRxNettyServer.java",
    "chars": 1299,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.netty.handler.codec.LineBasedFrameDecoder;\nimport io.netty.handler.codec.stri"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/Postgres.java",
    "chars": 3010,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.postgresql.PGNotification;\ni"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/RestCurrencyServer.java",
    "chars": 978,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.reactivex.netty.protocol.http.server.HttpServer;\nimport rx.Observable;\n\nimpor"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/RxNettyHttpServer.java",
    "chars": 605,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport io.reactivex.netty.protocol.http.server.HttpServer;\nimport rx.Observable;\n\nimpor"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/SingleThread.java",
    "chars": 1433,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport org.apache.commons.io.IOUtils;\n\nimport java.io.BufferedReader;\nimport java.io.IO"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/Singles.java",
    "chars": 3471,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport com.ning.http.client.AsyncCompletionHandler;\nimport com.ning.http.client.AsyncHt"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/Ticket.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch5;\n\nclass Ticket {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/TravelAgency.java",
    "chars": 624,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport rx.Observable;\n\nimport java.util.concurrent.CompletableFuture;\n\ninterface Travel"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/User.java",
    "chars": 147,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport java.time.LocalDate;\n\nclass User {\n\n\tLocalDate getBirth() {\n\t\treturn LocalDate.n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch5/Util.java",
    "chars": 1073,
    "preview": "package com.oreilly.rxjava.ch5;\n\nimport rx.Observable;\n\nimport java.util.List;\nimport java.util.concurrent.CompletableFu"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/Backpressure.java",
    "chars": 6000,
    "preview": "package com.oreilly.rxjava.ch6;\n\nimport com.oreilly.rxjava.util.Sleeper;\nimport org.apache.commons.dbutils.ResultSetIter"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/Chapter6.java",
    "chars": 5335,
    "preview": "package com.oreilly.rxjava.ch6;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport rx.Observable;\n\nimport java.time"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/Debounce.java",
    "chars": 2282,
    "preview": "package com.oreilly.rxjava.ch6;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport rx.Observable;\nimport rx.observa"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/Dish.java",
    "chars": 291,
    "preview": "package com.oreilly.rxjava.ch6;\n\nclass Dish {\n    private final byte[] oneKb = new byte[1_024];\n    private final int id"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/KeyEvent.java",
    "chars": 52,
    "preview": "package com.oreilly.rxjava.ch6;\n\nclass KeyEvent {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/Record.java",
    "chars": 50,
    "preview": "package com.oreilly.rxjava.ch6;\n\nclass Record {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/Repository.java",
    "chars": 331,
    "preview": "package com.oreilly.rxjava.ch6;\n\nimport java.util.List;\n\ninterface Repository {\n    void store(Record record);\n    void "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/TeleData.java",
    "chars": 52,
    "preview": "package com.oreilly.rxjava.ch6;\n\nclass TeleData {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch6/TradingPlatform.java",
    "chars": 617,
    "preview": "package com.oreilly.rxjava.ch6;\n\nimport rx.Observable;\n\nimport java.math.BigDecimal;\n\nimport static java.util.concurrent"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/Agreement.java",
    "chars": 103,
    "preview": "package com.oreilly.rxjava.ch7;\n\nclass Agreement {\n\tboolean postalMailRequired() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/Chapter7.java",
    "chars": 7422,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/Confirmation.java",
    "chars": 56,
    "preview": "package com.oreilly.rxjava.ch7;\n\nclass Confirmation {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/Monitoring.java",
    "chars": 2199,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport com.codahale.metrics.Counter;\nimport com.codahale.metrics.MetricRegistry;\nimport"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/MyService.java",
    "chars": 151,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport rx.Observable;\n\nimport java.time.LocalDate;\n\ninterface MyService {\n    Observabl"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/MyServiceWithTimeout.java",
    "chars": 636,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport rx.Observable;\nimport rx.Scheduler;\n\nimport java.time.LocalDate;\nimport java.uti"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/Person.java",
    "chars": 250,
    "preview": "package com.oreilly.rxjava.ch7;\n\nclass Person {\n}\n\nclass Health {\n}\n\nclass Score {\n\tboolean isHigh() {\n\t\treturn true;\n\t}"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/PrintHouse.java",
    "chars": 181,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport rx.Observable;\n\nclass PrintHouse {\n\n\tObservable<TrackingId> deliver(Agreement ag"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/RetryTimeouts.java",
    "chars": 2390,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/Testing.java",
    "chars": 6123,
    "preview": "package com.oreilly.rxjava.ch7;\n\nimport com.google.common.io.Files;\nimport org.junit.Before;\nimport org.junit.Ignore;\nim"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch7/TrackingId.java",
    "chars": 54,
    "preview": "package com.oreilly.rxjava.ch7;\n\nclass TrackingId {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Android.java",
    "chars": 4530,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport android.app.Activity;\nimport android.util.Log;\nimport android.view.View;\nimport "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/ApiFactory.java",
    "chars": 1257,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jack"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Chapter8.java",
    "chars": 6358,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport com.couchbase.client.java.CouchbaseAsyncCluster;\nimport com.couchbase.client.jav"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Cities.java",
    "chars": 270,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport java.util.List;\n\npublic class Cities {\n    private List<City> results;\n\n    publ"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/City.java",
    "chars": 1927,
    "preview": "package com.oreilly.rxjava.ch8;\n\npublic class City {\n    private String city;\n    private String country;\n    private Do"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/GeoNames.java",
    "chars": 1125,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport retrofit2.http.GET;\nimp"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Geoname.java",
    "chars": 1106,
    "preview": "package com.oreilly.rxjava.ch8;\n\npublic class Geoname {\n    private String lat;\n    private String lng;\n    private Inte"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Incident.java",
    "chars": 98,
    "preview": "package com.oreilly.rxjava.ch8;\n\nclass Incident {\n\tboolean isHIghPriority() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Insurance.java",
    "chars": 53,
    "preview": "package com.oreilly.rxjava.ch8;\n\nclass Insurance {\n}\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/MeetupApi.java",
    "chars": 265,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport retrofit2.http.GET;\nimport retrofit2.http.Query;\nimport rx.Observable;\n\n\npublic "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Person.java",
    "chars": 131,
    "preview": "package com.oreilly.rxjava.ch8;\n\nclass Person {\n\n\tint getAge() {\n\t\treturn 42;\n\t}\n\n\tString getFirstName() {\n\t\treturn \"Smi"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/Picture.java",
    "chars": 622,
    "preview": "package com.oreilly.rxjava.ch8;\n\nclass Picture {\n    private final byte[] blob = new byte[128 * 1024];\n    private final"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/SearchResult.java",
    "chars": 332,
    "preview": "package com.oreilly.rxjava.ch8;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass SearchResult {\n    private Li"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/hystrix/BlockingCmd.java",
    "chars": 659,
    "preview": "package com.oreilly.rxjava.ch8.hystrix;\n\nimport com.netflix.hystrix.HystrixCommand;\nimport com.netflix.hystrix.HystrixCo"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/hystrix/Book.java",
    "chars": 189,
    "preview": "package com.oreilly.rxjava.ch8.hystrix;\n\nclass Book {\n}\n\nclass Rating {\n\n\tprivate final Book book;\n\n\tRating(Book book) {"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/hystrix/CitiesCmd.java",
    "chars": 718,
    "preview": "package com.oreilly.rxjava.ch8.hystrix;\n\nimport com.netflix.hystrix.HystrixCommandGroupKey;\nimport com.netflix.hystrix.H"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/hystrix/FetchManyRatings.java",
    "chars": 743,
    "preview": "package com.oreilly.rxjava.ch8.hystrix;\n\nimport com.netflix.hystrix.HystrixCommandGroupKey;\nimport com.netflix.hystrix.H"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/hystrix/FetchRatingsCollapser.java",
    "chars": 1705,
    "preview": "package com.oreilly.rxjava.ch8.hystrix;\n\nimport com.netflix.hystrix.*;\nimport rx.functions.Func1;\n\nimport java.util.Coll"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/hystrix/Hystrix.java",
    "chars": 3424,
    "preview": "package com.oreilly.rxjava.ch8.hystrix;\n\nimport com.netflix.hystrix.HystrixCommandKey;\nimport com.netflix.hystrix.contri"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxandroid/AndroidSchedulers.java",
    "chars": 2400,
    "preview": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxandroid/LooperScheduler.java",
    "chars": 4250,
    "preview": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxandroid/MainActivity.java",
    "chars": 954,
    "preview": "package com.oreilly.rxjava.ch8.rxandroid;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport rx.Observable;\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxandroid/MainThreadSubscription.java",
    "chars": 3045,
    "preview": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxandroid/RxAndroidPlugins.java",
    "chars": 2944,
    "preview": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxandroid/RxAndroidSchedulersHook.java",
    "chars": 1524,
    "preview": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/RxTextView.java",
    "chars": 10197,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.widget.TextView;\nimport com.oreilly.rxjava.ch8.rxbinding.inter"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/RxView.java",
    "chars": 1055,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.view.View;\nimport rx.Observable;\nimport rx.functions.Action1;\n"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewAfterTextChangeEvent.java",
    "chars": 1597,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.content.Context;\nimport android.text.Editable;\nimport android."
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewAfterTextChangeEventOnSubscribe.java",
    "chars": 1486,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewBeforeTextChangeEvent.java",
    "chars": 2195,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.content.Context;\nimport android.widget.TextView;\n\nimport javax"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewBeforeTextChangeEventOnSubscribe.java",
    "chars": 1514,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewEditorActionEvent.java",
    "chars": 1609,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.view.KeyEvent;\nimport android.widget.TextView;\n\nimport javax.a"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewEditorActionEventOnSubscribe.java",
    "chars": 1527,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.view.KeyEvent;\nimport android.widget.TextView;\nimport com.orei"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewEditorActionOnSubscribe.java",
    "chars": 1339,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.view.KeyEvent;\nimport android.widget.TextView;\nimport com.orei"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewTextChangeEvent.java",
    "chars": 2193,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.content.Context;\nimport android.widget.TextView;\n\nimport javax"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewTextChangeEventOnSubscribe.java",
    "chars": 1479,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/TextViewTextOnSubscribe.java",
    "chars": 1324,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/ViewClickOnSubscribe.java",
    "chars": 939,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.view.View;\nimport com.oreilly.rxjava.ch8.rxandroid.MainThreadS"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/ViewEvent.java",
    "chars": 738,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding;\n\nimport android.content.Context;\nimport android.view.View;\n\nimport javax.annot"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/internal/Functions.java",
    "chars": 728,
    "preview": "package com.oreilly.rxjava.ch8.rxbinding.internal;\n\nimport rx.functions.Func0;\nimport rx.functions.Func1;\n\npublic final "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch8/rxbinding/internal/Preconditions.java",
    "chars": 1044,
    "preview": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance "
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/ch9/Chapter9.java",
    "chars": 125,
    "preview": "package com.oreilly.rxjava.ch9;\n\nimport org.junit.Ignore;\n\n@Ignore\npublic class Chapter9 {\n\n\t//no samples in this chapte"
  },
  {
    "path": "src/test/java/com/oreilly/rxjava/util/Sleeper.java",
    "chars": 736,
    "preview": "package com.oreilly.rxjava.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.time.Duration;\ni"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the nurkiewicz/rxjava-book-examples GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 146 files (217.1 KB), approximately 59.6k tokens, and a symbol index with 814 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!