Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support pagination of file versions #1240

Merged
Merged
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
14 changes: 13 additions & 1 deletion doc/files.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ Get Previous Versions of a File
-------------------------------

For users with premium accounts, versions of a file can be retrieved with the
[`getVersions()`][get-versions] method. It will return versions with all default fields set.
[`getVersions()`][get-versions] method. By default, it will return up to 1000 file versions with all default fields set.

<!-- sample get_files_id_versions -->
```java
Expand All @@ -488,6 +488,18 @@ for (BoxFileVersion version : versions) {
}
```

File versions can be retrieved with specified starting position with the
[`getVersionsRange(long offset, long limit)`][get-versions-range] method.
You can use the `limit` and `offset` parameters to page through the all available file versions.

```java
BoxFile file = new BoxFile(api, "id");
Collection<BoxFileVersion> versions = file.getVersionsRange(1000, 2000);
for (BoxFileVersion version : versions) {
System.out.format("SHA1 of \"%s\": %s\n", file.getInfo().getName(), version.getSha1());
}
```

You can specify selected fields to be returned while getting versions information.
Assume we want to get version SHA1 and version number:
```java
Expand Down
36 changes: 36 additions & 0 deletions src/intTest/java/com/box/sdk/BoxFileIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import static com.box.sdk.UniqueTestFolder.setupUniqeFolder;
import static com.box.sdk.UniqueTestFolder.uploadFileToUniqueFolder;
import static com.box.sdk.UniqueTestFolder.uploadFileToUniqueFolderWithSomeContent;
import static com.box.sdk.UniqueTestFolder.uploadFileWithContentToSpecifiedFolder;
import static com.box.sdk.UniqueTestFolder.uploadFileWithSomeContent;
import static com.box.sdk.UniqueTestFolder.uploadSampleFileToUniqueFolder;
import static com.box.sdk.UniqueTestFolder.uploadTwoFileVersionsToUniqueFolder;
Expand Down Expand Up @@ -492,6 +493,41 @@ public void canListVersions() {
}
}

@Test
public void canPaginateOverListOfVersions() {
BoxFile uploadedFile = null;
String fileName = "[canPaginateOverListOfVersions] Multi-version File.txt";
try {
BoxAPIConnection api = jwtApiForServiceAccount();
BoxFolder uniqueFolder = getUniqueFolder(api);
uploadedFile = uploadFileWithContentToSpecifiedFolder(fileName, "Version 1", uniqueFolder);

byte[] fileBytes = "Version 2".getBytes(StandardCharsets.UTF_8);
uploadedFile.uploadNewVersion(
new ByteArrayInputStream(fileBytes), null, fileBytes.length, mock(ProgressListener.class));

fileBytes = "Version 3".getBytes(StandardCharsets.UTF_8);
uploadedFile.uploadNewVersion(
new ByteArrayInputStream(fileBytes), null, fileBytes.length, mock(ProgressListener.class));

Collection<BoxFileVersion> versionsPart1 = uploadedFile.getVersionsRange(0, 1);
assertThat(versionsPart1.size(), is(1));
BoxFileVersion boxFileVersion1 = versionsPart1.iterator().next();

Collection<BoxFileVersion> versionsPart2 = uploadedFile.getVersionsRange(1, 2);
assertThat(versionsPart2.size(), is(1));
BoxFileVersion boxFileVersion2 = versionsPart2.iterator().next();

Collection<BoxFileVersion> allVersions = uploadedFile.getVersionsRange(0, 10);
assertThat(allVersions.size(), is(2));
Iterator<BoxFileVersion> iterator = allVersions.iterator();
assertThat(iterator.next(), is(boxFileVersion1));
assertThat(iterator.next(), is(boxFileVersion2));
} finally {
deleteFile(uploadedFile);
}
}

@Test
public void canListVersionsWithSpecificFields() {
BoxFile uploadedFile = null;
Expand Down
6 changes: 3 additions & 3 deletions src/intTest/java/com/box/sdk/UniqueTestFolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ public static BoxFile uploadFileWithSomeContent(String fileName, BoxFolder folde
return uploadFileWithContentToSpecifiedFolder(fileName, "Test file", folder);
}

private static BoxFile uploadFileWithContentToSpecifiedFolder(
String fileName, String fileContent, BoxFolder folder
static BoxFile uploadFileWithContentToSpecifiedFolder(
String fileName, String fileContent, BoxFolder folder
) {
byte[] fileBytes = fileContent.getBytes(StandardCharsets.UTF_8);

Expand Down Expand Up @@ -128,7 +128,7 @@ public static BoxFile uploadTwoFileVersionsToSpecifiedFolder(
) {
byte[] version1Bytes = version1Content.getBytes(StandardCharsets.UTF_8);
byte[] version2Bytes = version2Content.getBytes(StandardCharsets.UTF_8);
long version2Size = version1Bytes.length;
long version2Size = version2Bytes.length;

InputStream uploadStream = new ByteArrayInputStream(version1Bytes);
BoxFile uploadedFile = folder.uploadFile(uploadStream, fileName).getResource();
Expand Down
36 changes: 25 additions & 11 deletions src/main/java/com/box/sdk/BoxFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ public void updateInfo(BoxFile.Info info) {
}

/**
* Gets any previous versions of this file. Note that only users with premium accounts will be able to retrieve
* Gets up to 1000 versions of this file. Note that only users with premium accounts will be able to retrieve
* previous versions of their files. `fields` parameter is optional, if specified only requested fields will
* be returned:
* <pre>
Expand All @@ -620,22 +620,36 @@ public void updateInfo(BoxFile.Info info) {
* @return a list of previous file versions.
*/
public Collection<BoxFileVersion> getVersions(String... fields) {
URL url = VERSIONS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
try {
if (fields.length > 0) {
QueryStringBuilder builder = new QueryStringBuilder(url.getQuery());
builder.appendParam("fields", fields);
url = builder.addToURL(url);
}
} catch (MalformedURLException e) {
throw new BoxAPIException("Couldn't append a query string to the provided URL.", e);
return getVersionsRange(0, BoxFileVersion.DEFAULT_LIMIT, fields);
}


/**
* Retrieves a specific range of versions of this file.
*
* @param offset the index of the first version of this file to retrieve.
* @param limit the maximum number of versions to retrieve after the offset.
* @param fields the fields to retrieve.
* @return a partial collection containing the specified range of versions of this file.
*/
public PartialCollection<BoxFileVersion> getVersionsRange(long offset, long limit, String... fields) {
QueryStringBuilder builder = new QueryStringBuilder()
.appendParam("limit", limit)
.appendParam("offset", offset);

if (fields.length > 0) {
builder.appendParam("fields", fields);
}

URL url = VERSIONS_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID());
BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET");
try (BoxJSONResponse response = request.send()) {

JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
String totalCountString = jsonObject.get("total_count").toString();
long fullSize = Double.valueOf(totalCountString).longValue();
PartialCollection<BoxFileVersion> versions = new PartialCollection<>(offset, limit, fullSize);
JsonArray entries = jsonObject.get("entries").asArray();
Collection<BoxFileVersion> versions = new ArrayList<>();
for (JsonValue entry : entries) {
versions.add(new BoxFileVersion(this.getAPI(), entry.asObject(), this.getID()));
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/box/sdk/BoxFileVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public class BoxFileVersion extends BoxResource {
*/
public static final URLTemplate VERSION_URL_TEMPLATE = new URLTemplate("files/%s/versions/%s");

/**
* The default limit of entries per response.
*/
public static final long DEFAULT_LIMIT = 1000;

private String fileID;

private String versionID;
Expand Down
34 changes: 31 additions & 3 deletions src/test/java/com/box/sdk/BoxFileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ public String getJSON() {
}

@Test
public void getVersionsWithSpecificFields() {
public void getVersionsWithSpecificFieldsAndDefaultLimit() {
// given
BoxAPIConnection api = new BoxAPIConnectionForTests("");
BoxFile file = new BoxFile(api, "6543");
Expand All @@ -1077,11 +1077,11 @@ public void getVersionsWithSpecificFields() {
request -> {
try {
String query = URLDecoder.decode(request.getUrl().getQuery(), "UTF-8");
assertThat(query, containsString("fields=name,version_number"));
assertThat(query, containsString("limit=1000&offset=0&fields=name,version_number"));
return new BoxJSONResponse() {
@Override
public String getJSON() {
return "{\"entries\": []}";
return "{\"entries\": [], \"total_count\": 100}";
}
};
} catch (UnsupportedEncodingException e) {
Expand All @@ -1094,6 +1094,34 @@ public String getJSON() {
file.getVersions("name", "version_number");
}

@Test
public void getVersionsWithLimitAndOffset() {
// given
BoxAPIConnection api = new BoxAPIConnectionForTests("");
BoxFile file = new BoxFile(api, "6543");

// then
api.setRequestInterceptor(
request -> {
try {
String query = URLDecoder.decode(request.getUrl().getQuery(), "UTF-8");
assertThat(query, containsString("limit=10&offset=0&fields=name,version_number"));
return new BoxJSONResponse() {
@Override
public String getJSON() {
return "{\"entries\": [], \"total_count\": 100}";
}
};
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
);

// when
file.getVersionsRange(0, 10, "name", "version_number");
}

@Test
public void setsDispositionAt() throws ParseException {
//given
Expand Down
Loading