Skip to content

Commit

Permalink
feat: Support pagination of file versions (#1240)
Browse files Browse the repository at this point in the history
Closes: SDK-3649
  • Loading branch information
lukaszsocha2 committed Mar 29, 2024
1 parent a608f9a commit 7e7af3f
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 18 deletions.
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

0 comments on commit 7e7af3f

Please sign in to comment.