From feae018ded7bcf85be32cdd9a1eeff86c2fb9106 Mon Sep 17 00:00:00 2001 From: Ivan Velev Date: Mon, 4 May 2026 22:51:31 +0300 Subject: [PATCH 1/4] Data classification Put and Delete --- .../com/smartsheet/api/SheetResources.java | 32 +++++ .../api/internal/SheetResourcesImpl.java | 37 ++++++ .../api/models/DataClassification.java | 47 ++++++++ .../models/enums/DataClassificationType.java | 27 +++++ .../sdktest/sheets/CommonTestConstants.java | 21 ++++ .../sheets/TestDeleteDataClassification.java | 92 +++++++++++++++ .../sheets/TestSetDataClassification.java | 111 ++++++++++++++++++ 7 files changed, 367 insertions(+) create mode 100644 src/main/java/com/smartsheet/api/models/DataClassification.java create mode 100644 src/main/java/com/smartsheet/api/models/enums/DataClassificationType.java create mode 100644 src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java create mode 100644 src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java create mode 100644 src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java diff --git a/src/main/java/com/smartsheet/api/SheetResources.java b/src/main/java/com/smartsheet/api/SheetResources.java index 1e0a7428c..e5b7abce8 100644 --- a/src/main/java/com/smartsheet/api/SheetResources.java +++ b/src/main/java/com/smartsheet/api/SheetResources.java @@ -17,6 +17,7 @@ package com.smartsheet.api; import com.smartsheet.api.models.ContainerDestination; +import com.smartsheet.api.models.DataClassification; import com.smartsheet.api.models.MultiRowEmail; import com.smartsheet.api.models.PagedResult; import com.smartsheet.api.models.PaginationParameters; @@ -548,6 +549,37 @@ Sheet importXlsxInWorkspace( */ void deleteSheet(long id) throws SmartsheetException; + /** + *

Sets the data classification on a sheet.

+ * + *

It mirrors to the following Smartsheet REST API method: PUT /sheets/{sheetId}/dataclassification

+ * + * @param sheetId the sheet id + * @param dataClassification the DataClassification object + * @throws IllegalArgumentException if any argument is null or empty string + * @throws InvalidRequestException if there is any problem with the REST API request + * @throws AuthorizationException if there is any problem with the REST API authorization (access token) + * @throws ResourceNotFoundException if the resource cannot be found + * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting) + * @throws SmartsheetException if there is any other error during the operation + */ + void setDataClassification(long sheetId, DataClassification dataClassification) throws SmartsheetException; + + /** + *

Removes the data classification from a sheet. Requires ADMIN or OWNER access.

+ * + *

It mirrors to the following Smartsheet REST API method: DELETE /sheets/{sheetId}/dataclassification

+ * + * @param sheetId the sheet id + * @throws IllegalArgumentException if any argument is null or empty string + * @throws InvalidRequestException if there is any problem with the REST API request + * @throws AuthorizationException if there is any problem with the REST API authorization (access token) + * @throws ResourceNotFoundException if the resource cannot be found + * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting) + * @throws SmartsheetException if there is any other error during the operation + */ + void deleteDataClassification(long sheetId) throws SmartsheetException; + /** *

Update a sheet.

* diff --git a/src/main/java/com/smartsheet/api/internal/SheetResourcesImpl.java b/src/main/java/com/smartsheet/api/internal/SheetResourcesImpl.java index e506861d7..da1a6a2ab 100644 --- a/src/main/java/com/smartsheet/api/internal/SheetResourcesImpl.java +++ b/src/main/java/com/smartsheet/api/internal/SheetResourcesImpl.java @@ -42,6 +42,7 @@ import com.smartsheet.api.internal.util.QueryUtil; import com.smartsheet.api.internal.util.Util; import com.smartsheet.api.models.ContainerDestination; +import com.smartsheet.api.models.DataClassification; import com.smartsheet.api.models.MultiRowEmail; import com.smartsheet.api.models.PagedResult; import com.smartsheet.api.models.PaginationParameters; @@ -806,6 +807,42 @@ public void deleteSheet(long id) throws SmartsheetException { this.deleteResource(SHEETS + "/" + id, Sheet.class); } + /** + * Sets the data classification on a sheet. + *

+ * It mirrors to the following Smartsheet REST API method: PUT /sheets/{sheetId}/dataclassification + * + * @param sheetId the sheet id + * @param dataClassification the DataClassification object + * @throws IllegalArgumentException : if any argument is null + * @throws InvalidRequestException : if there is any problem with the REST API request + * @throws AuthorizationException : if there is any problem with the REST API authorization(access token) + * @throws ResourceNotFoundException : if the resource can not be found + * @throws ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting) + * @throws SmartsheetRestException : if there is any other REST API related error occurred during the operation + * @throws SmartsheetException : if there is any other error occurred during the operation + */ + public void setDataClassification(long sheetId, DataClassification dataClassification) throws SmartsheetException { + this.updateResource(SHEETS + "/" + sheetId + "/dataclassification", DataClassification.class, dataClassification); + } + + /** + * Removes the data classification from a sheet. Requires ADMIN or OWNER access. + *

+ * It mirrors to the following Smartsheet REST API method: DELETE /sheets/{sheetId}/dataclassification + * + * @param sheetId the sheet id + * @throws InvalidRequestException : if there is any problem with the REST API request + * @throws AuthorizationException : if there is any problem with the REST API authorization(access token) + * @throws ResourceNotFoundException : if the resource can not be found + * @throws ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting) + * @throws SmartsheetRestException : if there is any other REST API related error occurred during the operation + * @throws SmartsheetException : if there is any other error occurred during the operation + */ + public void deleteDataClassification(long sheetId) throws SmartsheetException { + this.deleteResource(SHEETS + "/" + sheetId + "/dataclassification", DataClassification.class); + } + /** * Update a sheet. *

diff --git a/src/main/java/com/smartsheet/api/models/DataClassification.java b/src/main/java/com/smartsheet/api/models/DataClassification.java new file mode 100644 index 000000000..6a7e3f11d --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/DataClassification.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2026 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.DataClassificationType; + +/** + * Represents the data classification of a sheet. + */ +public class DataClassification { + + private DataClassificationType dataClassification; + + /** + * Gets the data classification. + * + * @return the data classification + */ + public DataClassificationType getDataClassification() { + return dataClassification; + } + + /** + * Sets the data classification. + * + * @param dataClassification the data classification + * @return this DataClassification object for chaining + */ + public DataClassification setDataClassification(DataClassificationType dataClassification) { + this.dataClassification = dataClassification; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/enums/DataClassificationType.java b/src/main/java/com/smartsheet/api/models/enums/DataClassificationType.java new file mode 100644 index 000000000..bc8f1c2c2 --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/enums/DataClassificationType.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2026 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models.enums; + +/** + * Represents the data classification level of a sheet. + */ +public enum DataClassificationType { + PUBLIC, + INTERNAL, + CONFIDENTIAL, + SECRET, +} diff --git a/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java b/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java new file mode 100644 index 000000000..088e15884 --- /dev/null +++ b/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2026 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.sdktest.sheets; + +public class CommonTestConstants { + public static final long TEST_SHEET_ID = 1234567890123456L; +} diff --git a/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java b/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java new file mode 100644 index 000000000..f476e06b7 --- /dev/null +++ b/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2026 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.sdktest.sheets; + +import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import com.smartsheet.api.Smartsheet; +import com.smartsheet.api.SmartsheetException; +import com.smartsheet.api.WiremockClient; +import com.smartsheet.api.WiremockClientWrapper; +import com.smartsheet.api.sdktest.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.UUID; + +import static com.smartsheet.api.sdktest.sheets.CommonTestConstants.TEST_SHEET_ID; +import static org.assertj.core.api.Assertions.assertThat; + +public class TestDeleteDataClassification { + + @Test + void testDeleteDataClassificationGeneratedUrlIsCorrect() throws SmartsheetException { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/sheets/delete-data-classification/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + WiremockClient wiremockClient = wrapper.getWiremockClient(); + + smartsheet.sheetResources().deleteDataClassification(TEST_SHEET_ID); + LoggedRequest wiremockRequest = wiremockClient.findWiremockRequest(requestId); + String path = URI.create(wiremockRequest.getUrl()).getPath(); + + assertThat(path).isEqualTo("/2.0/sheets/" + TEST_SHEET_ID + "/dataclassification"); + } + + @Test + void testDeleteDataClassificationAllResponseBodyProperties() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/sheets/delete-data-classification/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + Assertions.assertDoesNotThrow(() -> + smartsheet.sheetResources().deleteDataClassification(TEST_SHEET_ID) + ); + } + + @Test + void testDeleteDataClassificationError500Response() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient("/errors/500-response", requestId); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + SmartsheetException exception = Assertions.assertThrows(SmartsheetException.class, () -> + smartsheet.sheetResources().deleteDataClassification(TEST_SHEET_ID) + ); + + assertThat(exception.getMessage()).isEqualTo("Internal Server Error"); + } + + @Test + void testDeleteDataClassificationError400Response() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient("/errors/400-response", requestId); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + SmartsheetException exception = Assertions.assertThrows(SmartsheetException.class, () -> + smartsheet.sheetResources().deleteDataClassification(TEST_SHEET_ID) + ); + + assertThat(exception.getMessage()).isEqualTo("Malformed Request"); + } +} diff --git a/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java b/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java new file mode 100644 index 000000000..251f7aacc --- /dev/null +++ b/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2026 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.sdktest.sheets; + +import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import com.smartsheet.api.Smartsheet; +import com.smartsheet.api.SmartsheetException; +import com.smartsheet.api.WiremockClient; +import com.smartsheet.api.WiremockClientWrapper; +import com.smartsheet.api.models.DataClassification; +import com.smartsheet.api.models.enums.DataClassificationType; +import com.smartsheet.api.sdktest.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.UUID; + +import static com.smartsheet.api.sdktest.sheets.CommonTestConstants.TEST_SHEET_ID; +import static org.assertj.core.api.Assertions.assertThat; + +public class TestSetDataClassification { + + @Test + void testSetDataClassificationGeneratedUrlIsCorrect() throws SmartsheetException { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/sheets/set-data-classification/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + WiremockClient wiremockClient = wrapper.getWiremockClient(); + + DataClassification dataClassification = new DataClassification() + .setDataClassification(DataClassificationType.CONFIDENTIAL); + + smartsheet.sheetResources().setDataClassification(TEST_SHEET_ID, dataClassification); + LoggedRequest wiremockRequest = wiremockClient.findWiremockRequest(requestId); + String path = URI.create(wiremockRequest.getUrl()).getPath(); + + assertThat(path).isEqualTo("/2.0/sheets/" + TEST_SHEET_ID + "/dataclassification"); + } + + @Test + void testSetDataClassificationAllResponseBodyProperties() throws SmartsheetException { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/sheets/set-data-classification/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + WiremockClient wiremockClient = wrapper.getWiremockClient(); + + DataClassification dataClassification = new DataClassification() + .setDataClassification(DataClassificationType.CONFIDENTIAL); + + Assertions.assertDoesNotThrow(() -> + smartsheet.sheetResources().setDataClassification(TEST_SHEET_ID, dataClassification) + ); + + LoggedRequest wiremockRequest = wiremockClient.findWiremockRequest(requestId); + String requestBody = wiremockRequest.getBodyAsString(); + assertThat(requestBody).isEqualTo("{\"dataClassification\":\"CONFIDENTIAL\"}"); + } + + @Test + void testSetDataClassificationError500Response() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient("/errors/500-response", requestId); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + DataClassification dataClassification = new DataClassification() + .setDataClassification(DataClassificationType.CONFIDENTIAL); + + SmartsheetException exception = Assertions.assertThrows(SmartsheetException.class, () -> + smartsheet.sheetResources().setDataClassification(TEST_SHEET_ID, dataClassification) + ); + + assertThat(exception.getMessage()).isEqualTo("Internal Server Error"); + } + + @Test + void testSetDataClassificationError400Response() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient("/errors/400-response", requestId); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + DataClassification dataClassification = new DataClassification() + .setDataClassification(DataClassificationType.CONFIDENTIAL); + + SmartsheetException exception = Assertions.assertThrows(SmartsheetException.class, () -> + smartsheet.sheetResources().setDataClassification(TEST_SHEET_ID, dataClassification) + ); + + assertThat(exception.getMessage()).isEqualTo("Malformed Request"); + } +} From 0562ba43e734e0dd56171ee65125b5b3275a1f21 Mon Sep 17 00:00:00 2001 From: Ivan Velev Date: Tue, 5 May 2026 11:31:11 +0300 Subject: [PATCH 2/4] Data classification field --- .../smartsheet/api/models/AbstractSheet.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/com/smartsheet/api/models/AbstractSheet.java b/src/main/java/com/smartsheet/api/models/AbstractSheet.java index e5bff16eb..a5c2ba479 100644 --- a/src/main/java/com/smartsheet/api/models/AbstractSheet.java +++ b/src/main/java/com/smartsheet/api/models/AbstractSheet.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.smartsheet.api.models.enums.AccessLevel; import com.smartsheet.api.models.enums.AttachmentType; +import com.smartsheet.api.models.enums.DataClassificationType; import com.smartsheet.api.models.enums.ResourceManagementType; import java.util.Date; @@ -76,6 +77,11 @@ public abstract class AbstractSheet, TC */ private Boolean dependenciesEnabled; + /** + * Represents the data classification of the sheet. + */ + private DataClassificationType dataClassification; + /** * Represents the discussions for the sheet. */ @@ -367,6 +373,26 @@ public > T setDependenciesEnabled( return (T) this; } + /** + * Gets the data classification of the sheet. + * + * @return the data classification + */ + public DataClassificationType getDataClassification() { + return dataClassification; + } + + /** + * Sets the data classification of the sheet. + * + * @param dataClassification the data classification + */ + @SuppressWarnings("unchecked") + public > T setDataClassification(DataClassificationType dataClassification) { + this.dataClassification = dataClassification; + return (T) this; + } + /** * Gets the discussions for the sheet. * From b71b8d8a39f15de5b85ee567b9b77dccde175760 Mon Sep 17 00:00:00 2001 From: Ivan Velev Date: Thu, 7 May 2026 18:25:49 +0300 Subject: [PATCH 3/4] Changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7eec040b..b74111b4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [x.x.x] - unreleased +### Added +- Support for PUT /sheets/{sheetId}/dataclassification endpoint (Set Data Classification) +- Support for DELETE /sheets/{sheetId}/dataclassification endpoint (Remove Data Classification) +- Added `dataClassification` field to Sheet model ## [3.11.0] - 2026-04-30 ### Added From 3d9479eb009d51ff6b22854fd0a25afbd5c9b7a1 Mon Sep 17 00:00:00 2001 From: Ivan Velev Date: Thu, 7 May 2026 19:27:34 +0300 Subject: [PATCH 4/4] fix year to match checktyle --- .../com/smartsheet/api/sdktest/sheets/CommonTestConstants.java | 2 +- .../api/sdktest/sheets/TestDeleteDataClassification.java | 2 +- .../api/sdktest/sheets/TestSetDataClassification.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java b/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java index 088e15884..c5f19d4bd 100644 --- a/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java +++ b/src/test/java/com/smartsheet/api/sdktest/sheets/CommonTestConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2026 Smartsheet + * Copyright (C) 2025 Smartsheet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java b/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java index f476e06b7..0e5a6a80c 100644 --- a/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java +++ b/src/test/java/com/smartsheet/api/sdktest/sheets/TestDeleteDataClassification.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2026 Smartsheet + * Copyright (C) 2025 Smartsheet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java b/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java index 251f7aacc..99f3b32ff 100644 --- a/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java +++ b/src/test/java/com/smartsheet/api/sdktest/sheets/TestSetDataClassification.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2026 Smartsheet + * Copyright (C) 2025 Smartsheet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.