/* * Copyright 2016-2017 the original author or authors. * * 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 org.example.api; import retrofit2.Response; import rx.Observable; import javax.annotation.Nonnull; import java.util.List; import static java.util.Objects.requireNonNull; public final class ObservableUtils { private ObservableUtils() { // prevent instantiation } @Nonnull public static <T> Observable<T> paginatedObservable(@Nonnull final FirstPageSupplier<T> firstPage, @Nonnull final NextPageSupplier<T> nextPage) { requireNonNull(firstPage, "Argument 'firstPage' must not be null"); requireNonNull(nextPage, "Argument 'nextPage' must not be null"); return processPage(nextPage, firstPage.get()); } private static <T> Observable<T> processPage(@Nonnull final NextPageSupplier<T> supplier, @Nonnull Observable<Response<List<T>>> items) { return items.flatMap(response -> { if (response.isSuccessful()) { Links links = Links.of(response.headers().get("Link")); Observable<T> currentPage = Observable.from(response.body()); if (links.hasNext()) { return currentPage.concatWith(processPage(supplier, supplier.get(links))); } return currentPage; } return Observable.error(new HttpResponseException(response.code(), response.message())); }); } public interface FirstPageSupplier<T> { @Nonnull Observable<Response<List<T>>> get(); } public interface NextPageSupplier<T> { @Nonnull Observable<Response<List<T>>> get(@Nonnull Links links); } }