From ccb314f107152d7aa67ddb788cd596c6ab200e84 Mon Sep 17 00:00:00 2001 From: box-sdk-build Date: Thu, 3 Sep 2026 08:03:48 -0700 Subject: [PATCH 1/3] feat: support chunk upload avoidance API (box/box-openapi#616) --- .codegen.json | 2 +- docs/sdkgen/chunkeduploads.md | 70 +++++++++++ .../chunkeduploads/ChunkedUploadsManager.java | 117 ++++++++++++++++++ ...eateFileUploadSessionPlanByUrlHeaders.java | 42 +++++++ .../CreateFileUploadSessionPlanHeaders.java | 42 +++++++ .../uploadpartplan/UploadPartPlan.java | 81 ++++++++++++ .../uploadpartplanhit/UploadPartPlanHit.java | 96 ++++++++++++++ .../UploadSessionSessionEndpointsField.java | 26 +++- .../UploadSessionPlanRequest.java | 50 ++++++++ .../UploadSessionPlanResponse.java | 85 +++++++++++++ 10 files changed, 608 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanByUrlHeaders.java create mode 100644 src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanHeaders.java create mode 100644 src/main/java/com/box/sdkgen/schemas/uploadpartplan/UploadPartPlan.java create mode 100644 src/main/java/com/box/sdkgen/schemas/uploadpartplanhit/UploadPartPlanHit.java create mode 100644 src/main/java/com/box/sdkgen/schemas/uploadsessionplanrequest/UploadSessionPlanRequest.java create mode 100644 src/main/java/com/box/sdkgen/schemas/uploadsessionplanresponse/UploadSessionPlanResponse.java diff --git a/.codegen.json b/.codegen.json index f5f7e2679..33b8585ec 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "04310d4", "specHash": "be75fa1", "version": "5.15.2" } +{ "engineHash": "04310d4", "specHash": "88cd5aa", "version": "5.15.2" } diff --git a/docs/sdkgen/chunkeduploads.md b/docs/sdkgen/chunkeduploads.md index 715868fb4..07203bfd6 100644 --- a/docs/sdkgen/chunkeduploads.md +++ b/docs/sdkgen/chunkeduploads.md @@ -12,6 +12,8 @@ This is a manager for chunked uploads (allowed for files at least 20MB). - [Remove upload session](#remove-upload-session) - [List parts by URL](#list-parts-by-url) - [List parts](#list-parts) +- [Plan upload session by URL](#plan-upload-session-by-url) +- [Plan upload session](#plan-upload-session) - [Commit upload session by URL](#commit-upload-session-by-url) - [Commit upload session](#commit-upload-session) - [Upload big file](#upload-big-file) @@ -341,6 +343,74 @@ This function returns a value of type `UploadParts`. Returns a list of parts that have been uploaded. +## Plan upload session by URL + +Plan an upload session by checking which parts already exist on the server. +This endpoint allows clients to optimize uploads by skipping parts that +have already been uploaded (cache hits) and only uploading missing parts. + +The actual endpoint URL is returned by the [`Create upload session`](e://post-files-upload-sessions) +and [`Get upload session`](e://get-files-upload-sessions-id) endpoints. + +This operation is performed by calling function `createFileUploadSessionPlanByUrl`. + +See the endpoint docs at +[API Reference](https://developer.box.com/reference/post-files-upload-sessions-id-plan/). + +*Currently we don't have an example for calling `createFileUploadSessionPlanByUrl` in integration tests* + +### Arguments + +- url `String` + - URL of createFileUploadSessionPlan method +- requestBody `UploadSessionPlanRequest` + - Request body of createFileUploadSessionPlan method +- headers `CreateFileUploadSessionPlanByUrlHeaders` + - Headers of createFileUploadSessionPlan method + + +### Returns + +This function returns a value of type `UploadSessionPlanResponse`. + +Returns information about which parts already exist (hits) +and which parts need to be uploaded (misses). + + +## Plan upload session + +Plan an upload session by checking which parts already exist on the server. +This endpoint allows clients to optimize uploads by skipping parts that +have already been uploaded (cache hits) and only uploading missing parts. + +The actual endpoint URL is returned by the [`Create upload session`](e://post-files-upload-sessions) +and [`Get upload session`](e://get-files-upload-sessions-id) endpoints. + +This operation is performed by calling function `createFileUploadSessionPlan`. + +See the endpoint docs at +[API Reference](https://developer.box.com/reference/post-files-upload-sessions-id-plan/). + +*Currently we don't have an example for calling `createFileUploadSessionPlan` in integration tests* + +### Arguments + +- uploadSessionId `String` + - The ID of the upload session. Example: "D5E3F7A" +- requestBody `UploadSessionPlanRequest` + - Request body of createFileUploadSessionPlan method +- headers `CreateFileUploadSessionPlanHeaders` + - Headers of createFileUploadSessionPlan method + + +### Returns + +This function returns a value of type `UploadSessionPlanResponse`. + +Returns information about which parts already exist (hits) +and which parts need to be uploaded (misses). + + ## Commit upload session by URL Close an upload session and create a file from the uploaded chunks. diff --git a/src/main/java/com/box/sdkgen/managers/chunkeduploads/ChunkedUploadsManager.java b/src/main/java/com/box/sdkgen/managers/chunkeduploads/ChunkedUploadsManager.java index 999b5fc69..efcc13a92 100644 --- a/src/main/java/com/box/sdkgen/managers/chunkeduploads/ChunkedUploadsManager.java +++ b/src/main/java/com/box/sdkgen/managers/chunkeduploads/ChunkedUploadsManager.java @@ -25,6 +25,8 @@ import com.box.sdkgen.schemas.uploadpart.UploadPart; import com.box.sdkgen.schemas.uploadparts.UploadParts; import com.box.sdkgen.schemas.uploadsession.UploadSession; +import com.box.sdkgen.schemas.uploadsessionplanrequest.UploadSessionPlanRequest; +import com.box.sdkgen.schemas.uploadsessionplanresponse.UploadSessionPlanResponse; import com.box.sdkgen.serialization.json.JsonManager; import java.io.InputStream; import java.util.Arrays; @@ -586,6 +588,121 @@ public UploadParts getFileUploadSessionParts( return JsonManager.deserialize(response.getData(), UploadParts.class); } + /** + * Using this method with urls provided in response when creating a new upload session is + * preferred to use over CreateFileUploadSessionPlan method. This allows to always upload your + * content to the closest Box data center and can significantly improve upload speed. Plan an + * upload session by checking which parts already exist on the server. This endpoint allows + * clients to optimize uploads by skipping parts that have already been uploaded (cache hits) and + * only uploading missing parts. + * + *

The actual endpoint URL is returned by the [`Create upload + * session`](e://post-files-upload-sessions) and [`Get upload + * session`](e://get-files-upload-sessions-id) endpoints. + * + * @param url URL of createFileUploadSessionPlan method + * @param requestBody Request body of createFileUploadSessionPlan method + */ + public UploadSessionPlanResponse createFileUploadSessionPlanByUrl( + String url, UploadSessionPlanRequest requestBody) { + return createFileUploadSessionPlanByUrl( + url, requestBody, new CreateFileUploadSessionPlanByUrlHeaders()); + } + + /** + * Using this method with urls provided in response when creating a new upload session is + * preferred to use over CreateFileUploadSessionPlan method. This allows to always upload your + * content to the closest Box data center and can significantly improve upload speed. Plan an + * upload session by checking which parts already exist on the server. This endpoint allows + * clients to optimize uploads by skipping parts that have already been uploaded (cache hits) and + * only uploading missing parts. + * + *

The actual endpoint URL is returned by the [`Create upload + * session`](e://post-files-upload-sessions) and [`Get upload + * session`](e://get-files-upload-sessions-id) endpoints. + * + * @param url URL of createFileUploadSessionPlan method + * @param requestBody Request body of createFileUploadSessionPlan method + * @param headers Headers of createFileUploadSessionPlan method + */ + public UploadSessionPlanResponse createFileUploadSessionPlanByUrl( + String url, + UploadSessionPlanRequest requestBody, + CreateFileUploadSessionPlanByUrlHeaders headers) { + Map headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders())); + FetchResponse response = + this.networkSession + .getNetworkClient() + .fetch( + new FetchOptions.Builder(url, "POST") + .headers(headersMap) + .data(JsonManager.serialize(requestBody)) + .contentType("application/json") + .responseFormat(ResponseFormat.JSON) + .auth(this.auth) + .networkSession(this.networkSession) + .build()); + return JsonManager.deserialize(response.getData(), UploadSessionPlanResponse.class); + } + + /** + * Plan an upload session by checking which parts already exist on the server. This endpoint + * allows clients to optimize uploads by skipping parts that have already been uploaded (cache + * hits) and only uploading missing parts. + * + *

The actual endpoint URL is returned by the [`Create upload + * session`](e://post-files-upload-sessions) and [`Get upload + * session`](e://get-files-upload-sessions-id) endpoints. + * + * @param uploadSessionId The ID of the upload session. Example: "D5E3F7A" + * @param requestBody Request body of createFileUploadSessionPlan method + */ + public UploadSessionPlanResponse createFileUploadSessionPlan( + String uploadSessionId, UploadSessionPlanRequest requestBody) { + return createFileUploadSessionPlan( + uploadSessionId, requestBody, new CreateFileUploadSessionPlanHeaders()); + } + + /** + * Plan an upload session by checking which parts already exist on the server. This endpoint + * allows clients to optimize uploads by skipping parts that have already been uploaded (cache + * hits) and only uploading missing parts. + * + *

The actual endpoint URL is returned by the [`Create upload + * session`](e://post-files-upload-sessions) and [`Get upload + * session`](e://get-files-upload-sessions-id) endpoints. + * + * @param uploadSessionId The ID of the upload session. Example: "D5E3F7A" + * @param requestBody Request body of createFileUploadSessionPlan method + * @param headers Headers of createFileUploadSessionPlan method + */ + public UploadSessionPlanResponse createFileUploadSessionPlan( + String uploadSessionId, + UploadSessionPlanRequest requestBody, + CreateFileUploadSessionPlanHeaders headers) { + Map headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders())); + FetchResponse response = + this.networkSession + .getNetworkClient() + .fetch( + new FetchOptions.Builder( + String.join( + "", + this.networkSession.getBaseUrls().getUploadUrl(), + "/2.0/files/upload_sessions/", + convertToString(uploadSessionId), + "/plan"), + "POST") + .headers(headersMap) + .data(JsonManager.serialize(requestBody)) + .contentType("application/json") + .responseFormat(ResponseFormat.JSON) + .auth(this.auth) + .networkSession(this.networkSession) + .build()); + return JsonManager.deserialize(response.getData(), UploadSessionPlanResponse.class); + } + /** * Using this method with urls provided in response when creating a new upload session is * preferred to use over CreateFileUploadSessionCommit method. This allows to always upload your diff --git a/src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanByUrlHeaders.java b/src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanByUrlHeaders.java new file mode 100644 index 000000000..460036659 --- /dev/null +++ b/src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanByUrlHeaders.java @@ -0,0 +1,42 @@ +package com.box.sdkgen.managers.chunkeduploads; + +import static com.box.sdkgen.internal.utils.UtilsManager.mapOf; + +import java.util.Map; + +public class CreateFileUploadSessionPlanByUrlHeaders { + + /** Extra headers that will be included in the HTTP request. */ + public Map extraHeaders; + + public CreateFileUploadSessionPlanByUrlHeaders() { + this.extraHeaders = mapOf(); + } + + protected CreateFileUploadSessionPlanByUrlHeaders(Builder builder) { + this.extraHeaders = builder.extraHeaders; + } + + public Map getExtraHeaders() { + return extraHeaders; + } + + public static class Builder { + + protected Map extraHeaders; + + public Builder() {} + + public Builder extraHeaders(Map extraHeaders) { + this.extraHeaders = extraHeaders; + return this; + } + + public CreateFileUploadSessionPlanByUrlHeaders build() { + if (this.extraHeaders == null) { + this.extraHeaders = mapOf(); + } + return new CreateFileUploadSessionPlanByUrlHeaders(this); + } + } +} diff --git a/src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanHeaders.java b/src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanHeaders.java new file mode 100644 index 000000000..bfe820e92 --- /dev/null +++ b/src/main/java/com/box/sdkgen/managers/chunkeduploads/CreateFileUploadSessionPlanHeaders.java @@ -0,0 +1,42 @@ +package com.box.sdkgen.managers.chunkeduploads; + +import static com.box.sdkgen.internal.utils.UtilsManager.mapOf; + +import java.util.Map; + +public class CreateFileUploadSessionPlanHeaders { + + /** Extra headers that will be included in the HTTP request. */ + public Map extraHeaders; + + public CreateFileUploadSessionPlanHeaders() { + this.extraHeaders = mapOf(); + } + + protected CreateFileUploadSessionPlanHeaders(Builder builder) { + this.extraHeaders = builder.extraHeaders; + } + + public Map getExtraHeaders() { + return extraHeaders; + } + + public static class Builder { + + protected Map extraHeaders; + + public Builder() {} + + public Builder extraHeaders(Map extraHeaders) { + this.extraHeaders = extraHeaders; + return this; + } + + public CreateFileUploadSessionPlanHeaders build() { + if (this.extraHeaders == null) { + this.extraHeaders = mapOf(); + } + return new CreateFileUploadSessionPlanHeaders(this); + } + } +} diff --git a/src/main/java/com/box/sdkgen/schemas/uploadpartplan/UploadPartPlan.java b/src/main/java/com/box/sdkgen/schemas/uploadpartplan/UploadPartPlan.java new file mode 100644 index 000000000..40ac5fe0b --- /dev/null +++ b/src/main/java/com/box/sdkgen/schemas/uploadpartplan/UploadPartPlan.java @@ -0,0 +1,81 @@ +package com.box.sdkgen.schemas.uploadpartplan; + +import com.box.sdkgen.internal.SerializableObject; +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + +/** Represents a planned upload part with `SHA-512` hash for upload session planning. */ +@JsonFilter("nullablePropertyFilter") +public class UploadPartPlan extends SerializableObject { + + /** + * The offset of the chunk within the file in bytes. The lower bound of the position of the chunk + * within the file. + */ + protected final long offset; + + /** The size of the chunk in bytes. */ + protected final long size; + + /** The `SHA-512` hash of the chunk. */ + protected final String sha512; + + public UploadPartPlan( + @JsonProperty("offset") long offset, + @JsonProperty("size") long size, + @JsonProperty("sha512") String sha512) { + super(); + this.offset = offset; + this.size = size; + this.sha512 = sha512; + } + + public long getOffset() { + return offset; + } + + public long getSize() { + return size; + } + + public String getSha512() { + return sha512; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UploadPartPlan casted = (UploadPartPlan) o; + return Objects.equals(offset, casted.offset) + && Objects.equals(size, casted.size) + && Objects.equals(sha512, casted.sha512); + } + + @Override + public int hashCode() { + return Objects.hash(offset, size, sha512); + } + + @Override + public String toString() { + return "UploadPartPlan{" + + "offset='" + + offset + + '\'' + + ", " + + "size='" + + size + + '\'' + + ", " + + "sha512='" + + sha512 + + '\'' + + "}"; + } +} diff --git a/src/main/java/com/box/sdkgen/schemas/uploadpartplanhit/UploadPartPlanHit.java b/src/main/java/com/box/sdkgen/schemas/uploadpartplanhit/UploadPartPlanHit.java new file mode 100644 index 000000000..ba04991a5 --- /dev/null +++ b/src/main/java/com/box/sdkgen/schemas/uploadpartplanhit/UploadPartPlanHit.java @@ -0,0 +1,96 @@ +package com.box.sdkgen.schemas.uploadpartplanhit; + +import com.box.sdkgen.internal.SerializableObject; +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + +/** Represents a planned upload part that already exists on the server (cache hit). */ +@JsonFilter("nullablePropertyFilter") +public class UploadPartPlanHit extends SerializableObject { + + /** + * The offset of the chunk within the file in bytes. The lower bound of the position of the chunk + * within the file. + */ + protected final long offset; + + /** The size of the chunk in bytes. */ + protected final long size; + + /** The `SHA-512` hash of the chunk. */ + protected final String sha512; + + /** The unique ID of the chunk. */ + @JsonProperty("part_id") + protected final String partId; + + public UploadPartPlanHit( + @JsonProperty("offset") long offset, + @JsonProperty("size") long size, + @JsonProperty("sha512") String sha512, + @JsonProperty("part_id") String partId) { + super(); + this.offset = offset; + this.size = size; + this.sha512 = sha512; + this.partId = partId; + } + + public long getOffset() { + return offset; + } + + public long getSize() { + return size; + } + + public String getSha512() { + return sha512; + } + + public String getPartId() { + return partId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UploadPartPlanHit casted = (UploadPartPlanHit) o; + return Objects.equals(offset, casted.offset) + && Objects.equals(size, casted.size) + && Objects.equals(sha512, casted.sha512) + && Objects.equals(partId, casted.partId); + } + + @Override + public int hashCode() { + return Objects.hash(offset, size, sha512, partId); + } + + @Override + public String toString() { + return "UploadPartPlanHit{" + + "offset='" + + offset + + '\'' + + ", " + + "size='" + + size + + '\'' + + ", " + + "sha512='" + + sha512 + + '\'' + + ", " + + "partId='" + + partId + + '\'' + + "}"; + } +} diff --git a/src/main/java/com/box/sdkgen/schemas/uploadsession/UploadSessionSessionEndpointsField.java b/src/main/java/com/box/sdkgen/schemas/uploadsession/UploadSessionSessionEndpointsField.java index 11c205c5f..e202f1e21 100644 --- a/src/main/java/com/box/sdkgen/schemas/uploadsession/UploadSessionSessionEndpointsField.java +++ b/src/main/java/com/box/sdkgen/schemas/uploadsession/UploadSessionSessionEndpointsField.java @@ -9,6 +9,11 @@ @JsonFilter("nullablePropertyFilter") public class UploadSessionSessionEndpointsField extends SerializableObject { + /** + * The URL used to plan the upload session by checking which parts already exist on the server. + */ + protected String plan; + /** The URL to upload parts to. */ @JsonProperty("upload_part") protected String uploadPart; @@ -36,6 +41,7 @@ public UploadSessionSessionEndpointsField() { protected UploadSessionSessionEndpointsField(Builder builder) { super(); + this.plan = builder.plan; this.uploadPart = builder.uploadPart; this.commit = builder.commit; this.abort = builder.abort; @@ -45,6 +51,10 @@ protected UploadSessionSessionEndpointsField(Builder builder) { markNullableFieldsAsSet(builder.getExplicitlySetNullableFields()); } + public String getPlan() { + return plan; + } + public String getUploadPart() { return uploadPart; } @@ -78,7 +88,8 @@ public boolean equals(Object o) { return false; } UploadSessionSessionEndpointsField casted = (UploadSessionSessionEndpointsField) o; - return Objects.equals(uploadPart, casted.uploadPart) + return Objects.equals(plan, casted.plan) + && Objects.equals(uploadPart, casted.uploadPart) && Objects.equals(commit, casted.commit) && Objects.equals(abort, casted.abort) && Objects.equals(listParts, casted.listParts) @@ -88,12 +99,16 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(uploadPart, commit, abort, listParts, status, logEvent); + return Objects.hash(plan, uploadPart, commit, abort, listParts, status, logEvent); } @Override public String toString() { return "UploadSessionSessionEndpointsField{" + + "plan='" + + plan + + '\'' + + ", " + "uploadPart='" + uploadPart + '\'' @@ -122,6 +137,8 @@ public String toString() { public static class Builder extends NullableFieldTracker { + protected String plan; + protected String uploadPart; protected String commit; @@ -134,6 +151,11 @@ public static class Builder extends NullableFieldTracker { protected String logEvent; + public Builder plan(String plan) { + this.plan = plan; + return this; + } + public Builder uploadPart(String uploadPart) { this.uploadPart = uploadPart; return this; diff --git a/src/main/java/com/box/sdkgen/schemas/uploadsessionplanrequest/UploadSessionPlanRequest.java b/src/main/java/com/box/sdkgen/schemas/uploadsessionplanrequest/UploadSessionPlanRequest.java new file mode 100644 index 000000000..86b65f512 --- /dev/null +++ b/src/main/java/com/box/sdkgen/schemas/uploadsessionplanrequest/UploadSessionPlanRequest.java @@ -0,0 +1,50 @@ +package com.box.sdkgen.schemas.uploadsessionplanrequest; + +import com.box.sdkgen.internal.SerializableObject; +import com.box.sdkgen.schemas.uploadpartplan.UploadPartPlan; +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Objects; + +/** + * Request body for planning an upload session. This allows checking which parts already exist on + * the server before uploading. + */ +@JsonFilter("nullablePropertyFilter") +public class UploadSessionPlanRequest extends SerializableObject { + + /** The list of parts to check for existence. */ + protected final List parts; + + public UploadSessionPlanRequest(@JsonProperty("parts") List parts) { + super(); + this.parts = parts; + } + + public List getParts() { + return parts; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UploadSessionPlanRequest casted = (UploadSessionPlanRequest) o; + return Objects.equals(parts, casted.parts); + } + + @Override + public int hashCode() { + return Objects.hash(parts); + } + + @Override + public String toString() { + return "UploadSessionPlanRequest{" + "parts='" + parts + '\'' + "}"; + } +} diff --git a/src/main/java/com/box/sdkgen/schemas/uploadsessionplanresponse/UploadSessionPlanResponse.java b/src/main/java/com/box/sdkgen/schemas/uploadsessionplanresponse/UploadSessionPlanResponse.java new file mode 100644 index 000000000..488e8d56e --- /dev/null +++ b/src/main/java/com/box/sdkgen/schemas/uploadsessionplanresponse/UploadSessionPlanResponse.java @@ -0,0 +1,85 @@ +package com.box.sdkgen.schemas.uploadsessionplanresponse; + +import com.box.sdkgen.internal.SerializableObject; +import com.box.sdkgen.schemas.uploadpartplan.UploadPartPlan; +import com.box.sdkgen.schemas.uploadpartplanhit.UploadPartPlanHit; +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Objects; + +/** + * Response from planning an upload session. Contains information about which parts already exist + * (hits) and which need to be uploaded (misses). + */ +@JsonFilter("nullablePropertyFilter") +public class UploadSessionPlanResponse extends SerializableObject { + + /** The unique identifier for this upload session. */ + @JsonProperty("upload_session_id") + protected final String uploadSessionId; + + /** Parts that already exist on the server and do not need to be uploaded again. */ + protected final List hits; + + /** Parts that do not exist on the server and need to be uploaded. */ + protected final List misses; + + public UploadSessionPlanResponse( + @JsonProperty("upload_session_id") String uploadSessionId, + @JsonProperty("hits") List hits, + @JsonProperty("misses") List misses) { + super(); + this.uploadSessionId = uploadSessionId; + this.hits = hits; + this.misses = misses; + } + + public String getUploadSessionId() { + return uploadSessionId; + } + + public List getHits() { + return hits; + } + + public List getMisses() { + return misses; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UploadSessionPlanResponse casted = (UploadSessionPlanResponse) o; + return Objects.equals(uploadSessionId, casted.uploadSessionId) + && Objects.equals(hits, casted.hits) + && Objects.equals(misses, casted.misses); + } + + @Override + public int hashCode() { + return Objects.hash(uploadSessionId, hits, misses); + } + + @Override + public String toString() { + return "UploadSessionPlanResponse{" + + "uploadSessionId='" + + uploadSessionId + + '\'' + + ", " + + "hits='" + + hits + + '\'' + + ", " + + "misses='" + + misses + + '\'' + + "}"; + } +} From ce197a2890e987220787a31739d78cea1d414823 Mon Sep 17 00:00:00 2001 From: box-sdk-build Date: Thu, 3 Sep 2026 08:05:53 -0700 Subject: [PATCH 2/3] chore: Update `.codegen.json` with commit hash of `codegen` and `openapi` spec [skip ci] --- .codegen.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codegen.json b/.codegen.json index 33b8585ec..27a0e6777 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "04310d4", "specHash": "88cd5aa", "version": "5.15.2" } +{ "engineHash": "db84f4c", "specHash": "88cd5aa", "version": "5.15.2" } From e856f68dd0f30383d582be1201d012e6a33a6d8c Mon Sep 17 00:00:00 2001 From: box-sdk-build Date: Fri, 4 Sep 2026 08:45:36 -0700 Subject: [PATCH 3/3] chore: Update `.codegen.json` with commit hash of `codegen` and `openapi` spec [skip ci] --- .codegen.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codegen.json b/.codegen.json index 27a0e6777..59e51b1bc 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "db84f4c", "specHash": "88cd5aa", "version": "5.15.2" } +{ "engineHash": "ad1ed4e", "specHash": "88cd5aa", "version": "5.15.2" }