Skip to content

Commit cedb4fe

Browse files
Copilotmanisha1997
andcommitted
Reduce code duplication by extracting common iteration logic to helper class
Co-authored-by: manisha1997 <[email protected]>
1 parent 686053a commit cedb4fe

File tree

3 files changed

+101
-52
lines changed

3 files changed

+101
-52
lines changed

src/main/java/com/twilio/base/ResourceSet.java

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@ public class ResourceSet<E extends Resource> implements Iterable<E> {
1515
private final Reader<E> reader;
1616
private final TwilioRestClient client;
1717
private final Page<E> firstPage; // Store reference to first page to enable multiple iterations
18+
private final ResourceSetIterationHelper.ResourceSetState<Page<E>, E> state;
1819

1920
private boolean autoPaging;
20-
private long pages = 1;
2121
private long pageLimit = Long.MAX_VALUE;
22-
private long processed = 0;
23-
private Page<E> page;
24-
private Iterator<E> iterator;
2522

2623
/**
2724
* Initialize the resource set.
@@ -34,8 +31,9 @@ public ResourceSet(final Reader<E> reader, final TwilioRestClient client, final
3431
this.reader = reader;
3532
this.client = client;
3633
this.firstPage = page; // Save first page to allow resetting iterator state
37-
this.page = page;
38-
this.iterator = page.getRecords().iterator();
34+
this.state = new ResourceSetIterationHelper.ResourceSetState<>(p -> p.getRecords().iterator());
35+
this.state.page = page;
36+
this.state.iterator = page.getRecords().iterator();
3937
this.autoPaging = true;
4038

4139
if (reader.getLimit() != null) {
@@ -53,7 +51,7 @@ public ResourceSet setAutoPaging(final boolean autoPaging) {
5351
}
5452

5553
public Integer getPageSize() {
56-
return page.getPageSize();
54+
return state.page.getPageSize();
5755
}
5856

5957
public ResourceSet<E> setPageSize(final int pageSize) {
@@ -76,23 +74,19 @@ public long getPageLimit() {
7674

7775
@Override
7876
public Iterator<E> iterator() {
79-
// Reset state to allow multiple iterations
80-
this.processed = 0;
81-
this.pages = 1;
82-
this.page = this.firstPage; // Reset to first page for new iteration
83-
this.iterator = this.firstPage.getRecords().iterator(); // Reset iterator to start of first page
84-
77+
// Reset state to allow multiple iterations using helper
78+
ResourceSetIterationHelper.resetIterationState(firstPage, state);
8579
return new ResourceSetIterator<>(this);
8680
}
8781

8882
private void fetchNextPage() {
89-
if (!page.hasNextPage() || pages >= pageLimit) {
83+
if (!state.page.hasNextPage() || state.pages >= pageLimit) {
9084
return;
9185
}
9286

93-
pages++;
94-
page = reader.nextPage(page, client);
95-
iterator = page.getRecords().iterator();
87+
state.pages++;
88+
state.page = reader.nextPage(state.page, client);
89+
state.iterator = state.page.getRecords().iterator();
9690
}
9791

9892
private class ResourceSetIterator<E extends Resource> implements Iterator<E> {
@@ -104,33 +98,33 @@ public ResourceSetIterator(final ResourceSet<E> resourceSet) {
10498

10599
@Override
106100
public boolean hasNext() {
107-
if (resourceSet.getLimit() != null && resourceSet.processed >= resourceSet.getLimit()) {
101+
if (resourceSet.getLimit() != null && resourceSet.state.processed >= resourceSet.getLimit()) {
108102
return false;
109103
}
110104

111-
return resourceSet.iterator.hasNext();
105+
return resourceSet.state.iterator.hasNext();
112106
}
113107

114108
@Override
115109
public E next() {
116-
if (resourceSet == null || resourceSet.iterator == null) {
110+
if (resourceSet == null || resourceSet.state.iterator == null) {
117111
throw new NoSuchElementException();
118112
}
119113

120-
E element = resourceSet.iterator.next();
121-
if (resourceSet.isAutoPaging() && !resourceSet.iterator.hasNext()) {
114+
E element = resourceSet.state.iterator.next();
115+
if (resourceSet.isAutoPaging() && !resourceSet.state.iterator.hasNext()) {
122116
resourceSet.fetchNextPage();
123117
}
124118

125-
resourceSet.processed++;
119+
resourceSet.state.processed++;
126120
return element;
127121
}
128122

129123
@Override
130124
public void remove() {
131-
if (resourceSet.iterator != null) {
132-
resourceSet.processed++;
133-
resourceSet.iterator.remove();
125+
if (resourceSet.state.iterator != null) {
126+
resourceSet.state.processed++;
127+
resourceSet.state.iterator.remove();
134128
}
135129
}
136130

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.twilio.base;
2+
3+
import java.util.Iterator;
4+
5+
/**
6+
* Helper class containing common iteration logic for ResourceSet implementations.
7+
* This eliminates code duplication between different ResourceSet classes while maintaining
8+
* type safety and existing APIs.
9+
*/
10+
public final class ResourceSetIterationHelper {
11+
12+
private ResourceSetIterationHelper() {
13+
// Utility class - prevent instantiation
14+
}
15+
16+
/**
17+
* Reset the state of a ResourceSet to allow multiple iterations.
18+
* This method should be called at the beginning of iterator() method.
19+
*
20+
* @param <T> the page type containing records
21+
* @param <E> the resource type
22+
* @param firstPage the first page to reset to
23+
* @param state the state object to reset
24+
*/
25+
public static <T, E> void resetIterationState(T firstPage, ResourceSetState<T, E> state) {
26+
state.processed = 0;
27+
state.pages = 1;
28+
state.page = firstPage;
29+
state.iterator = state.getPageIterator(firstPage);
30+
}
31+
32+
/**
33+
* State holder for ResourceSet iteration state.
34+
* Encapsulates the mutable state that needs to be reset for multiple iterations.
35+
*/
36+
public static final class ResourceSetState<T, E> {
37+
public long processed = 0;
38+
public long pages = 1;
39+
public T page;
40+
public Iterator<E> iterator;
41+
private final PageIteratorProvider<T, E> pageIteratorProvider;
42+
43+
public ResourceSetState(PageIteratorProvider<T, E> pageIteratorProvider) {
44+
this.pageIteratorProvider = pageIteratorProvider;
45+
}
46+
47+
public Iterator<E> getPageIterator(T page) {
48+
return pageIteratorProvider.getIterator(page);
49+
}
50+
}
51+
52+
/**
53+
* Interface to provide page iterators.
54+
* This allows the helper to work with different Page types.
55+
*/
56+
@FunctionalInterface
57+
public interface PageIteratorProvider<T, E> {
58+
Iterator<E> getIterator(T page);
59+
}
60+
}

src/main/java/com/twilio/base/bearertoken/ResourceSet.java

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.twilio.base.bearertoken;
22

3+
import com.twilio.base.ResourceSetIterationHelper;
34
import com.twilio.http.bearertoken.BearerTokenTwilioRestClient;
45

56
import java.util.Iterator;
@@ -15,13 +16,10 @@ public class ResourceSet<E extends Resource> implements Iterable<E> {
1516
private final Reader<E> reader;
1617
private final BearerTokenTwilioRestClient client;
1718
private final Page<E> firstPage; // Store reference to first page to enable multiple iterations
19+
private final ResourceSetIterationHelper.ResourceSetState<Page<E>, E> state;
1820

1921
private boolean autoPaging;
20-
private long pages = 1;
2122
private long pageLimit = Long.MAX_VALUE;
22-
private long processed = 0;
23-
private Page<E> page;
24-
private Iterator<E> iterator;
2523

2624
/**
2725
* Initialize the resource set.
@@ -34,8 +32,9 @@ public ResourceSet(final Reader<E> reader, final BearerTokenTwilioRestClient cli
3432
this.reader = reader;
3533
this.client = client;
3634
this.firstPage = page; // Save first page to allow resetting iterator state
37-
this.page = page;
38-
this.iterator = page.getRecords().iterator();
35+
this.state = new ResourceSetIterationHelper.ResourceSetState<>(p -> p.getRecords().iterator());
36+
this.state.page = page;
37+
this.state.iterator = page.getRecords().iterator();
3938
this.autoPaging = true;
4039

4140
if (reader.getLimit() != null) {
@@ -53,7 +52,7 @@ public ResourceSet setAutoPaging(final boolean autoPaging) {
5352
}
5453

5554
public Integer getPageSize() {
56-
return page.getPageSize();
55+
return state.page.getPageSize();
5756
}
5857

5958
public ResourceSet<E> setPageSize(final int pageSize) {
@@ -76,23 +75,19 @@ public long getPageLimit() {
7675

7776
@Override
7877
public Iterator<E> iterator() {
79-
// Reset state to allow multiple iterations
80-
this.processed = 0;
81-
this.pages = 1;
82-
this.page = this.firstPage; // Reset to first page for new iteration
83-
this.iterator = this.firstPage.getRecords().iterator(); // Reset iterator to start of first page
84-
78+
// Reset state to allow multiple iterations using helper
79+
ResourceSetIterationHelper.resetIterationState(firstPage, state);
8580
return new ResourceSetIterator<>(this);
8681
}
8782

8883
private void fetchNextPage() {
89-
if (!page.hasNextPage() || pages >= pageLimit) {
84+
if (!state.page.hasNextPage() || state.pages >= pageLimit) {
9085
return;
9186
}
9287

93-
pages++;
94-
page = reader.nextPage(page, client);
95-
iterator = page.getRecords().iterator();
88+
state.pages++;
89+
state.page = reader.nextPage(state.page, client);
90+
state.iterator = state.page.getRecords().iterator();
9691
}
9792

9893
private class ResourceSetIterator<E extends Resource> implements Iterator<E> {
@@ -104,33 +99,33 @@ public ResourceSetIterator(final ResourceSet<E> resourceSet) {
10499

105100
@Override
106101
public boolean hasNext() {
107-
if (resourceSet.getLimit() != null && resourceSet.processed >= resourceSet.getLimit()) {
102+
if (resourceSet.getLimit() != null && resourceSet.state.processed >= resourceSet.getLimit()) {
108103
return false;
109104
}
110105

111-
return resourceSet.iterator.hasNext();
106+
return resourceSet.state.iterator.hasNext();
112107
}
113108

114109
@Override
115110
public E next() {
116-
if (resourceSet == null || resourceSet.iterator == null) {
111+
if (resourceSet == null || resourceSet.state.iterator == null) {
117112
throw new NoSuchElementException();
118113
}
119114

120-
E element = resourceSet.iterator.next();
121-
if (resourceSet.isAutoPaging() && !resourceSet.iterator.hasNext()) {
115+
E element = resourceSet.state.iterator.next();
116+
if (resourceSet.isAutoPaging() && !resourceSet.state.iterator.hasNext()) {
122117
resourceSet.fetchNextPage();
123118
}
124119

125-
resourceSet.processed++;
120+
resourceSet.state.processed++;
126121
return element;
127122
}
128123

129124
@Override
130125
public void remove() {
131-
if (resourceSet.iterator != null) {
132-
resourceSet.processed++;
133-
resourceSet.iterator.remove();
126+
if (resourceSet.state.iterator != null) {
127+
resourceSet.state.processed++;
128+
resourceSet.state.iterator.remove();
134129
}
135130
}
136131

0 commit comments

Comments
 (0)