Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
with:
distribution: 'zulu'
java-version: '17'

- name: SonarCloud Scan
if: ${{ (github.event_name == 'pull_request' || github.ref_type == 'branch') && matrix.java == 11 && !github.event.pull_request.head.repo.fork }}
env:
Expand Down Expand Up @@ -94,7 +94,7 @@ jobs:
- name: Create GitHub Release
uses: sendgrid/dx-automator/actions/release@main
with:
footer: '**[Maven](https://mvnrepository.com/artifact/com.twilio.sdk/twilio/${version})**'
footer: '**[Maven](https://central.sonatype.com/artifact/com.twilio.sdk/twilio/${version})**'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/twilio/base/ResourceSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class ResourceSet<E extends Resource> implements Iterable<E> {

private final Reader<E> reader;
private final TwilioRestClient client;
private final Page<E> firstPage; // Store reference to first page to enable multiple iterations

private boolean autoPaging;
private long pages = 1;
Expand All @@ -32,6 +33,7 @@ public class ResourceSet<E extends Resource> implements Iterable<E> {
public ResourceSet(final Reader<E> reader, final TwilioRestClient client, final Page<E> page) {
this.reader = reader;
this.client = client;
this.firstPage = page; // Save first page to allow resetting iterator state
this.page = page;
this.iterator = page.getRecords().iterator();
this.autoPaging = true;
Expand Down Expand Up @@ -74,6 +76,12 @@ public long getPageLimit() {

@Override
public Iterator<E> iterator() {
// Reset state to allow multiple iterations
this.processed = 0;
this.pages = 1;
this.page = this.firstPage; // Reset to first page for new iteration
this.iterator = this.firstPage.getRecords().iterator(); // Reset iterator to start of first page

return new ResourceSetIterator<>(this);
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/twilio/base/bearertoken/ResourceSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class ResourceSet<E extends Resource> implements Iterable<E> {

private final Reader<E> reader;
private final BearerTokenTwilioRestClient client;
private final Page<E> firstPage; // Store reference to first page to enable multiple iterations

private boolean autoPaging;
private long pages = 1;
Expand All @@ -32,6 +33,7 @@ public class ResourceSet<E extends Resource> implements Iterable<E> {
public ResourceSet(final Reader<E> reader, final BearerTokenTwilioRestClient client, final Page<E> page) {
this.reader = reader;
this.client = client;
this.firstPage = page; // Save first page to allow resetting iterator state
this.page = page;
this.iterator = page.getRecords().iterator();
this.autoPaging = true;
Expand Down Expand Up @@ -74,6 +76,12 @@ public long getPageLimit() {

@Override
public Iterator<E> iterator() {
// Reset state to allow multiple iterations
this.processed = 0;
this.pages = 1;
this.page = this.firstPage; // Reset to first page for new iteration
this.iterator = this.firstPage.getRecords().iterator(); // Reset iterator to start of first page

return new ResourceSetIterator<>(this);
}

Expand Down
46 changes: 46 additions & 0 deletions src/main/java/com/twilio/type/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.twilio.type;

import java.util.Objects;

public class App implements Endpoint {

public static final String PREFIX = "app:";

private final String app;

public App(String app) {
if (!app.toLowerCase().startsWith(PREFIX)) {
app = PREFIX + app;
}

this.app = app;
}

@Override
public String getEndpoint() {
return this.app;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

App other = (App) o;
return Objects.equals(this.app, other.app);
}

@Override
public int hashCode() {
return Objects.hash(this.app);
}

@Override
public String toString() {
return this.app;
}
}
148 changes: 148 additions & 0 deletions src/test/java/com/twilio/base/ResourceSetIterationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package com.twilio.base;

import com.twilio.http.TwilioRestClient;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import static org.mockito.Mockito.when;

// Simple test resource for testing ResourceSet iteration
class TestResource extends Resource {
private final String id;

public TestResource(String id) {
this.id = id;
}

public String getId() {
return id;
}
}

// Simple test reader for testing ResourceSet iteration
class TestReader extends Reader<TestResource> {
@Override
public ResourceSet<TestResource> read(TwilioRestClient client) {
return null; // Not needed for our test
}

@Override
public Page<TestResource> firstPage(TwilioRestClient client) {
return null; // Not needed for our test
}

@Override
public Page<TestResource> previousPage(Page<TestResource> page, TwilioRestClient client) {
return null; // Not needed for our test
}

@Override
public Page<TestResource> nextPage(Page<TestResource> page, TwilioRestClient client) {
return null; // Not needed for our test
}

@Override
public Page<TestResource> getPage(String targetUrl, TwilioRestClient client) {
return null; // Not needed for our test
}
}

public class ResourceSetIterationTest {

@Mock
TwilioRestClient client;

@Mock
Page<TestResource> page;

@Before
public void init() {
MockitoAnnotations.initMocks(this);
}

@Test
public void testResourceSetCanBeIteratedMultipleTimes() {
// Setup mock data with concrete objects
TestResource resource1 = new TestResource("resource1");
TestResource resource2 = new TestResource("resource2");
List<TestResource> resources = Arrays.asList(resource1, resource2);

when(page.getRecords()).thenReturn(resources);
when(page.getPageSize()).thenReturn(2);
when(page.hasNextPage()).thenReturn(false);

Reader<TestResource> reader = new TestReader().limit(2);
ResourceSet<TestResource> resourceSet = new ResourceSet<>(reader, client, page);

// First iteration - should work
List<String> firstIterationResults = new ArrayList<>();
for (TestResource resource : resourceSet) {
firstIterationResults.add(resource.getId());
}
Assert.assertEquals(2, firstIterationResults.size());
Assert.assertEquals("resource1", firstIterationResults.get(0));
Assert.assertEquals("resource2", firstIterationResults.get(1));

// Second iteration - should also work and return the same results
List<String> secondIterationResults = new ArrayList<>();
for (TestResource resource : resourceSet) {
secondIterationResults.add(resource.getId());
}
Assert.assertEquals("Second iteration should return same number of elements", 2, secondIterationResults.size());
Assert.assertEquals("resource1", secondIterationResults.get(0));
Assert.assertEquals("resource2", secondIterationResults.get(1));

// Third iteration using explicit iterator - should also work
List<String> thirdIterationResults = new ArrayList<>();
for (Iterator<TestResource> it = resourceSet.iterator(); it.hasNext(); ) {
TestResource resource = it.next();
thirdIterationResults.add(resource.getId());
}
Assert.assertEquals("Third iteration should return same number of elements", 2, thirdIterationResults.size());
Assert.assertEquals("resource1", thirdIterationResults.get(0));
Assert.assertEquals("resource2", thirdIterationResults.get(1));
}

@Test
public void testResourceSetWithLimitCanBeIteratedMultipleTimes() {
// Setup mock data with more resources than the limit
TestResource resource1 = new TestResource("resource1");
TestResource resource2 = new TestResource("resource2");
TestResource resource3 = new TestResource("resource3");
List<TestResource> resources = Arrays.asList(resource1, resource2, resource3);

when(page.getRecords()).thenReturn(resources);
when(page.getPageSize()).thenReturn(3);
when(page.hasNextPage()).thenReturn(false);

// Set limit to 2, so only first 2 should be returned
Reader<TestResource> reader = new TestReader().limit(2);
ResourceSet<TestResource> resourceSet = new ResourceSet<>(reader, client, page);

// First iteration - should only return 2 elements due to limit
List<String> firstIterationResults = new ArrayList<>();
for (TestResource resource : resourceSet) {
firstIterationResults.add(resource.getId());
}
Assert.assertEquals("First iteration should respect limit", 2, firstIterationResults.size());
Assert.assertEquals("resource1", firstIterationResults.get(0));
Assert.assertEquals("resource2", firstIterationResults.get(1));

// Second iteration - should also respect limit and return same results
List<String> secondIterationResults = new ArrayList<>();
for (TestResource resource : resourceSet) {
secondIterationResults.add(resource.getId());
}
Assert.assertEquals("Second iteration should respect limit", 2, secondIterationResults.size());
Assert.assertEquals("resource1", secondIterationResults.get(0));
Assert.assertEquals("resource2", secondIterationResults.get(1));
}
}
17 changes: 17 additions & 0 deletions src/test/java/com/twilio/type/AppTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.twilio.type;

import org.junit.Assert;
import org.junit.Test;

public class AppTest {

@Test
public void testGetEndpoint() {
Assert.assertEquals("app:me", new App("me").getEndpoint());
Assert.assertEquals("app:YOU", new App("YOU").getEndpoint());
Assert.assertEquals("APP:HIM", new App("APP:HIM").getEndpoint());
Assert.assertEquals("aPp:her", new App("aPp:her").getEndpoint());
Assert.assertEquals("app:AP12345?mycustomparam1=foo&mycustomparam2=bar", new App("app:AP12345?mycustomparam1=foo&mycustomparam2=bar").getEndpoint());
Assert.assertEquals("app:AP12345?mycustomparam1=foo&mycustomparam2=bar", new App("AP12345?mycustomparam1=foo&mycustomparam2=bar").getEndpoint());
}
}