• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
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  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.core.pagination.sync;
17 
18 import java.util.Collections;
19 import java.util.Iterator;
20 import java.util.NoSuchElementException;
21 import java.util.function.Function;
22 import software.amazon.awssdk.annotations.SdkProtectedApi;
23 
24 /**
25  * Iterable for the paginated items. This class can be used through iterate through
26  * all the items across multiple pages until there is no more response from the service.
27  *
28  * @param <ResponseT> The type of a single response page
29  * @param <ItemT> The type of paginated member in a response page
30  */
31 @SdkProtectedApi
32 public final class PaginatedItemsIterable<ResponseT, ItemT> implements SdkIterable<ItemT> {
33 
34     private final SdkIterable<ResponseT> pagesIterable;
35     private final Function<ResponseT, Iterator<ItemT>> getItemIterator;
36 
PaginatedItemsIterable(BuilderImpl<ResponseT, ItemT> builder)37     private PaginatedItemsIterable(BuilderImpl<ResponseT, ItemT> builder) {
38         this.pagesIterable = builder.pagesIterable;
39         this.getItemIterator = builder.itemIteratorFunction;
40     }
41 
builder()42     public static <R, T> Builder<R, T> builder() {
43         return new BuilderImpl<>();
44     }
45 
46     @Override
iterator()47     public Iterator<ItemT> iterator() {
48         return new ItemsIterator(pagesIterable.iterator());
49     }
50 
51     private class ItemsIterator implements Iterator<ItemT> {
52 
53         private final Iterator<ResponseT> pagesIterator;
54         private Iterator<ItemT> singlePageItemsIterator;
55 
ItemsIterator(final Iterator<ResponseT> pagesIterator)56         ItemsIterator(final Iterator<ResponseT> pagesIterator) {
57             this.pagesIterator = pagesIterator;
58             this.singlePageItemsIterator = pagesIterator.hasNext() ? getItemIterator.apply(pagesIterator.next())
59                                                                    : Collections.emptyIterator();
60         }
61 
62         @Override
hasNext()63         public boolean hasNext() {
64             while (!hasMoreItems() && pagesIterator.hasNext()) {
65                 singlePageItemsIterator = getItemIterator.apply(pagesIterator.next());
66             }
67 
68             if (hasMoreItems()) {
69                 return true;
70             }
71 
72             return false;
73         }
74 
75         @Override
next()76         public ItemT next() {
77             if (!hasNext()) {
78                 throw new NoSuchElementException("No more elements left");
79             }
80 
81             return singlePageItemsIterator.next();
82         }
83 
hasMoreItems()84         private boolean hasMoreItems() {
85             return singlePageItemsIterator.hasNext();
86         }
87     }
88 
89     public interface Builder<ResponseT, ItemT> {
pagesIterable(SdkIterable<ResponseT> sdkIterable)90         Builder<ResponseT, ItemT> pagesIterable(SdkIterable<ResponseT> sdkIterable);
91 
itemIteratorFunction(Function<ResponseT, Iterator<ItemT>> itemIteratorFunction)92         Builder<ResponseT, ItemT> itemIteratorFunction(Function<ResponseT, Iterator<ItemT>> itemIteratorFunction);
93 
build()94         PaginatedItemsIterable<ResponseT, ItemT> build();
95     }
96 
97     private static final class BuilderImpl<ResponseT, ItemT> implements Builder<ResponseT, ItemT> {
98         private SdkIterable<ResponseT> pagesIterable;
99         private Function<ResponseT, Iterator<ItemT>> itemIteratorFunction;
100 
BuilderImpl()101         private BuilderImpl() {
102         }
103 
104         @Override
pagesIterable(SdkIterable<ResponseT> pagesIterable)105         public Builder<ResponseT, ItemT> pagesIterable(SdkIterable<ResponseT> pagesIterable) {
106             this.pagesIterable = pagesIterable;
107             return this;
108         }
109 
110         @Override
itemIteratorFunction(Function<ResponseT, Iterator<ItemT>> itemIteratorFunction)111         public Builder<ResponseT, ItemT> itemIteratorFunction(Function<ResponseT, Iterator<ItemT>> itemIteratorFunction) {
112             this.itemIteratorFunction = itemIteratorFunction;
113             return this;
114         }
115 
116         @Override
build()117         public PaginatedItemsIterable<ResponseT, ItemT> build() {
118             return new PaginatedItemsIterable<>(this);
119         }
120     }
121 }
122