// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/cache/Cache.java
// public interface Cache extends RxCache, AsyncCache {
// 
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/cache/RxCache.java
// public interface RxCache {
// 
//     /**
//      * Get from cache.
//      *
//      * @param key key
//      * @param typeOfT type of cache value
//      * @param <T> T of cache value
//      * @return Observable that emits the cache value
//      */
//     <T> Observable<T> get(String key, Type typeOfT);
// 
//     /**
//      * Put value to cache.
//      *
//      * @param key key
//      * @param object value
//      * @return Observable that emits <tt>true</tt> if successful, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> put(String key, Object object);
// 
//     /**
//      * Cache contains key.
//      *
//      * @param key key
//      * @return Observable that emits <tt>true</tt> if cache contains key, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> contains(String key);
// 
//     /**
//      * Remove cache value.
//      *
//      * @param key key
//      * @return Observable that emits <tt>true</tt> if successful, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> remove(String key);
// 
//     /**
//      * Clear all cache values.
//      *
//      * @return Observable that emits <tt>true</tt> if successful, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> clear();
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/callback/WaterfallCallback.java
// public interface WaterfallCallback extends WaterfallFailureCallback {
// 
//     /**
//      * Called on success.
//      */
//     void onSuccess();
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/callback/WaterfallGetCallback.java
// public interface WaterfallGetCallback<T> extends WaterfallFailureCallback {
// 
//     /**
//      * Called on success. Returns the value.
//      *
//      * @param object returned object
//      */
//     void onSuccess(T object);
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/utils/AsyncUtils.java
// public final class AsyncUtils {
// 
//     private AsyncUtils() {
//         //no instance
//     }
// 
//     public static void doAsync(Observable<Boolean> observable, final WaterfallCallback callback) {
//         observable.subscribe(success -> {
//             if (callback != null) {
//                 callback.onSuccess();
//             }
//         }, asyncOnError(callback));
//     }
// 
//     public static <T> void doAsync(Observable<T> observable, final WaterfallGetCallback<T> callback) {
//         observable.subscribe(value -> {
//             if (callback != null) {
//                 callback.onSuccess(value);
//             }
//         }, asyncOnError(callback));
//     }
// 
//     private static Action1<Throwable> asyncOnError(final WaterfallFailureCallback callback) {
//         return throwable -> {
//             if (callback != null) {
//                 callback.onFailure(throwable);
//             }
//         };
//     }
// }


import com.github.simonpercic.waterfallcache.cache.Cache;
import com.github.simonpercic.waterfallcache.cache.RxCache;
import com.github.simonpercic.waterfallcache.callback.WaterfallCallback;
import com.github.simonpercic.waterfallcache.callback.WaterfallGetCallback;
import com.github.simonpercic.waterfallcache.utils.AsyncUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.TimeUnit;
import rx.Observable;
     */
    @Override
    public Observable<Boolean> contains(String key) {
        return get(key, Object.class).flatMap(o -> Observable.just(o != null));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Observable<Boolean> remove(String key) {
        return underlyingCache.remove(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Observable<Boolean> clear() {
        return underlyingCache.clear();
    }

    // endregion Reactive methods

    // region asynchronous methods

    @Override public <T> void getAsync(String key, Type typeOfT, WaterfallGetCallback<T> callback) {
        AsyncUtils.doAsync(get(key, typeOfT), callback);
    }

// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/cache/Cache.java
// public interface Cache extends RxCache, AsyncCache {
// 
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/cache/RxCache.java
// public interface RxCache {
// 
//     /**
//      * Get from cache.
//      *
//      * @param key key
//      * @param typeOfT type of cache value
//      * @param <T> T of cache value
//      * @return Observable that emits the cache value
//      */
//     <T> Observable<T> get(String key, Type typeOfT);
// 
//     /**
//      * Put value to cache.
//      *
//      * @param key key
//      * @param object value
//      * @return Observable that emits <tt>true</tt> if successful, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> put(String key, Object object);
// 
//     /**
//      * Cache contains key.
//      *
//      * @param key key
//      * @return Observable that emits <tt>true</tt> if cache contains key, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> contains(String key);
// 
//     /**
//      * Remove cache value.
//      *
//      * @param key key
//      * @return Observable that emits <tt>true</tt> if successful, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> remove(String key);
// 
//     /**
//      * Clear all cache values.
//      *
//      * @return Observable that emits <tt>true</tt> if successful, <tt>false</tt> otherwise
//      */
//     Observable<Boolean> clear();
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/callback/WaterfallCallback.java
// public interface WaterfallCallback extends WaterfallFailureCallback {
// 
//     /**
//      * Called on success.
//      */
//     void onSuccess();
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/callback/WaterfallGetCallback.java
// public interface WaterfallGetCallback<T> extends WaterfallFailureCallback {
// 
//     /**
//      * Called on success. Returns the value.
//      *
//      * @param object returned object
//      */
//     void onSuccess(T object);
// }
// 
// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/utils/AsyncUtils.java
// public final class AsyncUtils {
// 
//     private AsyncUtils() {
//         //no instance
//     }
// 
//     public static void doAsync(Observable<Boolean> observable, final WaterfallCallback callback) {
//         observable.subscribe(success -> {
//             if (callback != null) {
//                 callback.onSuccess();
//             }
//         }, asyncOnError(callback));
//     }
// 
//     public static <T> void doAsync(Observable<T> observable, final WaterfallGetCallback<T> callback) {
//         observable.subscribe(value -> {
//             if (callback != null) {
//                 callback.onSuccess(value);
//             }
//         }, asyncOnError(callback));
//     }
// 
//     private static Action1<Throwable> asyncOnError(final WaterfallFailureCallback callback) {
//         return throwable -> {
//             if (callback != null) {
//                 callback.onFailure(throwable);
//             }
//         };
//     }
// }


// Path: waterfallcache/src/main/java/com/github/simonpercic/waterfallcache/expire/LazyExpirableCache.java
import com.github.simonpercic.waterfallcache.cache.Cache;
import com.github.simonpercic.waterfallcache.cache.RxCache;
import com.github.simonpercic.waterfallcache.callback.WaterfallCallback;
import com.github.simonpercic.waterfallcache.callback.WaterfallGetCallback;
import com.github.simonpercic.waterfallcache.utils.AsyncUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.TimeUnit;
import rx.Observable;

     */
    @Override
    public Observable<Boolean> contains(String key) {
        return get(key, Object.class).flatMap(o -> Observable.just(o != null));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Observable<Boolean> remove(String key) {
        return underlyingCache.remove(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Observable<Boolean> clear() {
        return underlyingCache.clear();
    }

    // endregion Reactive methods

    // region asynchronous methods

    @Override public <T> void getAsync(String key, Type typeOfT, WaterfallGetCallback<T> callback) {
        AsyncUtils.doAsync(get(key, typeOfT), callback);
    }

    @Override public void putAsync(String key, Object object, WaterfallCallback callback) {