1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.arch.paging;
18
19import android.support.annotation.Nullable;
20import android.support.annotation.RestrictTo;
21import android.support.annotation.WorkerThread;
22
23import java.util.ArrayList;
24import java.util.Collections;
25import java.util.List;
26
27/**
28 * Simplest data source form that provides all of its data through a single loadRange() method.
29 * <p>
30 * Requires that your data resides in positions <code>0</code> through <code>N</code>, where
31 * <code>N</code> is the value returned from {@link #countItems()}. You must return the exact number
32 * requested, so that the data as returned can be safely prepended/appended to what has already
33 * been loaded.
34 * <p>
35 * For more flexibility in how many items to load, or to avoid counting your data source, override
36 * {@link PositionalDataSource} directly.
37 *
38 * @param  Value type returned by the data source.
39 *
40 * @hide
41 */
42@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
43public abstract class BoundedDataSource<Value> extends PositionalDataSource<Value> {
44    /**
45     * Called to load items at from the specified position range.
46     *
47     * @param startPosition Index of first item to load.
48     * @param loadCount     Exact number of items to load. Returning a different number will cause
49     *                      an exception to be thrown.
50     * @return List of loaded items. Null if the BoundedDataSource is no longer valid, and should
51     *         not be queried again.
52     */
53    @WorkerThread
54    @Nullable
55    public abstract List<Value> loadRange(int startPosition, int loadCount);
56
57    @WorkerThread
58    @Nullable
59    @Override
60    public List<Value> loadAfter(int startIndex, int pageSize) {
61        return loadRange(startIndex, pageSize);
62    }
63
64    @WorkerThread
65    @Nullable
66    @Override
67    public List<Value> loadBefore(int startIndex, int pageSize) {
68        if (startIndex < 0) {
69            return new ArrayList<>();
70        }
71        int loadSize = Math.min(pageSize, startIndex + 1);
72        startIndex = startIndex - loadSize + 1;
73        List<Value> result = loadRange(startIndex, loadSize);
74        if (result != null) {
75            if (result.size() != loadSize) {
76                throw new IllegalStateException("invalid number of items returned.");
77            }
78            Collections.reverse(result);
79        }
80        return result;
81    }
82}
83