From bb924d75419a57a2dac04ce5979d83d91ae9db7a Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 16 Jun 2026 09:38:05 +0200 Subject: [PATCH 1/5] Add remote operations for governance. Assisted-by: ClaudeCode:claude-sonnet-4-6 Assisted-by: Copilot:claude-sonnet-4-6 Signed-off-by: tobiasKaminsky --- .../lib/resources/governance/EntityLabels.kt | 14 ++++ .../GetAllSelectableLabelsRemoteOperation.kt | 64 +++++++++++++++ .../GetAvailableHoldLabelsRemoteOperation.kt | 72 +++++++++++++++++ ...AvailableRetentionLabelsRemoteOperation.kt | 72 +++++++++++++++++ ...ailableSensitivityLabelsRemoteOperation.kt | 72 +++++++++++++++++ .../GetEntityLabelsRemoteOperation.kt | 70 +++++++++++++++++ .../governance/GovernanceLabelResponse.kt | 12 +++ .../lib/resources/governance/HoldLabelInfo.kt | 17 ++++ .../lib/resources/governance/LabelScope.kt | 18 +++++ .../lib/resources/governance/LabelType.kt | 16 ++++ .../governance/RemoveLabelRemoteOperation.kt | 73 ++++++++++++++++++ .../governance/RetentionLabelInfo.kt | 17 ++++ .../governance/SensitivityLabelInfo.kt | 17 ++++ .../governance/SensitivityLabelScope.kt | 18 +++++ .../governance/SetLabelRemoteOperation.kt | 77 +++++++++++++++++++ .../GetCapabilitiesRemoteOperation.java | 10 +++ .../lib/resources/status/OCCapability.kt | 3 + .../GovernanceLabelResponseParsingTest.kt | 39 ++++++++++ .../governance/HoldLabelInfoParsingTest.kt | 66 ++++++++++++++++ .../lib/resources/governance/LabelTypeTest.kt | 20 +++++ .../RetentionLabelInfoParsingTest.kt | 66 ++++++++++++++++ .../SensitivityLabelInfoParsingTest.kt | 66 ++++++++++++++++ 22 files changed, 899 insertions(+) create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt create mode 100644 library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt create mode 100644 library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt create mode 100644 library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt create mode 100644 library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt create mode 100644 library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt new file mode 100644 index 0000000000..d74aeb8ba7 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt @@ -0,0 +1,14 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +data class EntityLabels( + val sensitivity: List, + val retention: List, + val hold: List +) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt new file mode 100644 index 0000000000..1339d0bbf7 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt @@ -0,0 +1,64 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.GetMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +class GetAllSelectableLabelsRemoteOperation( + private val entityType: String, + private val entityId: Long +) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult { + var result: RemoteOperationResult + var getMethod: GetMethod? = null + try { + getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + AVAILABLE + JSON_FORMAT, + true + ) + val status = client.execute(getMethod) + if (status == HttpStatus.SC_OK) { + val labels = + getServerResponse( + getMethod, + object : TypeToken>() {} + )?.ocs?.data + + if (labels != null) { + result = RemoteOperationResult(true, getMethod) + result.setResultData(labels) + } else { + result = RemoteOperationResult(false, getMethod) + } + } else { + result = RemoteOperationResult(false, getMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e(TAG, "Get all selectable labels failed: " + result.logMessage, result.exception) + } finally { + getMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = GetAllSelectableLabelsRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + private const val AVAILABLE = "/available" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt new file mode 100644 index 0000000000..65fd60da35 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt @@ -0,0 +1,72 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.GetMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +/** + * Get the hold labels the user may apply to an entity + */ +class GetAvailableHoldLabelsRemoteOperation( + private val entityType: String, + private val entityId: Long +) : OCSRemoteOperation>() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult> { + var result: RemoteOperationResult> + var getMethod: GetMethod? = null + try { + getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + HOLD_AVAILABLE + JSON_FORMAT, + true + ) + val status = client.execute(getMethod) + if (status == HttpStatus.SC_OK) { + val labels = + getServerResponse( + getMethod, + object : TypeToken>>() {} + )?.ocs?.data + + if (labels != null) { + result = RemoteOperationResult(true, getMethod) + result.setResultData(labels) + } else { + result = RemoteOperationResult(false, getMethod) + } + } else { + result = RemoteOperationResult(false, getMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Get available hold labels failed: " + result.logMessage, + result.exception + ) + } finally { + getMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = GetAvailableHoldLabelsRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + private const val HOLD_AVAILABLE = "/hold/available" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt new file mode 100644 index 0000000000..787940de5c --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt @@ -0,0 +1,72 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.GetMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +/** + * Get the retention labels the user may apply to an entity + */ +class GetAvailableRetentionLabelsRemoteOperation( + private val entityType: String, + private val entityId: Long +) : OCSRemoteOperation>() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult> { + var result: RemoteOperationResult> + var getMethod: GetMethod? = null + try { + getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + RETENTION_AVAILABLE + JSON_FORMAT, + true + ) + val status = client.execute(getMethod) + if (status == HttpStatus.SC_OK) { + val labels = + getServerResponse( + getMethod, + object : TypeToken>>() {} + )?.ocs?.data + + if (labels != null) { + result = RemoteOperationResult(true, getMethod) + result.setResultData(labels) + } else { + result = RemoteOperationResult(false, getMethod) + } + } else { + result = RemoteOperationResult(false, getMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Get available retention labels failed: " + result.logMessage, + result.exception + ) + } finally { + getMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = GetAvailableRetentionLabelsRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + private const val RETENTION_AVAILABLE = "/retention/available" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt new file mode 100644 index 0000000000..f95ab4778b --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt @@ -0,0 +1,72 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.GetMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +/** + * Get the sensitivity labels the user may apply to an entity + */ +class GetAvailableSensitivityLabelsRemoteOperation( + private val entityType: String, + private val entityId: Long +) : OCSRemoteOperation>() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult> { + var result: RemoteOperationResult> + var getMethod: GetMethod? = null + try { + getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + SENSITIVITY_AVAILABLE + JSON_FORMAT, + true + ) + val status = client.execute(getMethod) + if (status == HttpStatus.SC_OK) { + val labels = + getServerResponse( + getMethod, + object : TypeToken>>() {} + )?.ocs?.data + + if (labels != null) { + result = RemoteOperationResult(true, getMethod) + result.setResultData(labels) + } else { + result = RemoteOperationResult(false, getMethod) + } + } else { + result = RemoteOperationResult(false, getMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Get available sensitivity labels failed: " + result.logMessage, + result.exception + ) + } finally { + getMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = GetAvailableSensitivityLabelsRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + private const val SENSITIVITY_AVAILABLE = "/sensitivity/available" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt new file mode 100644 index 0000000000..61c19fdbed --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt @@ -0,0 +1,70 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.GetMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +/** + * Get all labels applied to an entity, grouped by type, filtered to those visible to the calling user + */ +class GetEntityLabelsRemoteOperation( + private val entityType: String, + private val entityId: String +) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult { + var result: RemoteOperationResult + var getMethod: GetMethod? = null + try { + getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + JSON_FORMAT, + true + ) + val status = client.execute(getMethod) + if (status == HttpStatus.SC_OK) { + val entityLabels = + getServerResponse( + getMethod, + object : TypeToken>() {} + )?.ocs?.data + + if (entityLabels != null) { + result = RemoteOperationResult(true, getMethod) + result.setResultData(entityLabels) + } else { + result = RemoteOperationResult(false, getMethod) + } + } else { + result = RemoteOperationResult(false, getMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Get entity labels failed: " + result.logMessage, + result.exception + ) + } finally { + getMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = GetEntityLabelsRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt new file mode 100644 index 0000000000..7bfa0fbeb1 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt @@ -0,0 +1,12 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +data class GovernanceLabelResponse( + val message: String +) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt new file mode 100644 index 0000000000..75221e4047 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt @@ -0,0 +1,17 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +data class HoldLabelInfo( + val id: String, + val name: String, + val priority: Long, + val description: String, + val color: String, + val scopes: List +) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt new file mode 100644 index 0000000000..50bea0e191 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt @@ -0,0 +1,18 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.annotations.SerializedName + +enum class LabelScope { + @SerializedName("FILES") + FILES, + + @SerializedName("MAILS") + MAILS +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt new file mode 100644 index 0000000000..15c4fb219f --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt @@ -0,0 +1,16 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +enum class LabelType( + val value: String +) { + SENSITIVITY("SENSITIVITY"), + RETENTION("RETENTION"), + HOLD("HOLD") +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt new file mode 100644 index 0000000000..38682a063c --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt @@ -0,0 +1,73 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.DeleteMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import org.apache.commons.httpclient.HttpStatus + +/** + * Remove a label from an entity + */ +class RemoveLabelRemoteOperation( + private val entityType: String, + private val entityId: Long, + private val labelType: LabelType, + private val labelId: String +) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult { + var result: RemoteOperationResult + var deleteMethod: DeleteMethod? = null + try { + deleteMethod = + DeleteMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + + labelType.value + "/" + labelId + JSON_FORMAT, + true + ) + val status = client.execute(deleteMethod) + if (status == HttpStatus.SC_OK) { + val response = + getServerResponse( + deleteMethod, + object : TypeToken>() {} + )?.ocs?.data + + if (response != null) { + result = RemoteOperationResult(true, deleteMethod) + result.resultData = response + } else { + result = RemoteOperationResult(false, deleteMethod) + } + } else { + result = RemoteOperationResult(false, deleteMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Remove label from entity failed: " + result.logMessage, + result.exception + ) + } finally { + deleteMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = RemoveLabelRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt new file mode 100644 index 0000000000..b9151bc3f8 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt @@ -0,0 +1,17 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +data class RetentionLabelInfo( + val id: String, + val name: String, + val priority: Long, + val description: String, + val color: String, + val scopes: List +) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt new file mode 100644 index 0000000000..c6a3a556b7 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt @@ -0,0 +1,17 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +data class SensitivityLabelInfo( + val id: String, + val name: String, + val priority: Long, + val description: String, + val color: String, + val scopes: List +) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt new file mode 100644 index 0000000000..9ef8ae4cd4 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt @@ -0,0 +1,18 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.annotations.SerializedName + +enum class SensitivityLabelScope { + @SerializedName("FILES") + FILES, + + @SerializedName("MAILS") + MAILS +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt new file mode 100644 index 0000000000..38ee9ef57f --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt @@ -0,0 +1,77 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.reflect.TypeToken +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.PostMethod +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.ServerResponse +import com.owncloud.android.lib.resources.OCSRemoteOperation +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.RequestBody.Companion.toRequestBody +import org.apache.commons.httpclient.HttpStatus + +/** + * Apply a label to an entity + */ +class SetLabelRemoteOperation( + private val entityType: String, + private val entityId: Long, + private val labelType: LabelType, + private val labelId: String +) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult { + var result: RemoteOperationResult + var postMethod: PostMethod? = null + try { + val body = "".toRequestBody("application/json".toMediaTypeOrNull()) + postMethod = + PostMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + + labelType.value + "/" + labelId + JSON_FORMAT, + true, + body + ) + val status = client.execute(postMethod) + if (status == HttpStatus.SC_OK) { + val response = + getServerResponse( + postMethod, + object : TypeToken>() {} + )?.ocs?.data + + if (response != null) { + result = RemoteOperationResult(true, postMethod) + result.resultData = response + } else { + result = RemoteOperationResult(false, postMethod) + } + } else { + result = RemoteOperationResult(false, postMethod) + } + } catch (e: Exception) { + result = RemoteOperationResult(e) + Log_OC.e( + TAG, + "Apply label to entity failed: " + result.logMessage, + result.exception + ) + } finally { + postMethod?.releaseConnection() + } + return result + } + + companion object { + private val TAG = SetLabelRemoteOperation::class.java.simpleName + private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java b/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java index 3aca2ca3f7..d1a96fce37 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java +++ b/library/src/main/java/com/owncloud/android/lib/resources/status/GetCapabilitiesRemoteOperation.java @@ -162,6 +162,9 @@ public class GetCapabilitiesRemoteOperation extends RemoteOperation>() {}.type + val response: ServerResponse = Gson().fromJson(element, type) + + val data = response.ocs?.data + assertNotNull(data) + assertEquals("Label applied", data!!.message) + } +} diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt new file mode 100644 index 0000000000..9efe0d9bce --- /dev/null +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt @@ -0,0 +1,66 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.Gson +import com.google.gson.JsonParser +import com.google.gson.reflect.TypeToken +import com.owncloud.android.lib.ocs.ServerResponse +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Test + +class HoldLabelInfoParsingTest { + @Test + fun parsesAvailableHoldLabelsResponse() { + val json = + """ + { + "ocs": { + "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, + "data": [ + { + "id": "litigation-hold", + "name": "Litigation hold", + "priority": 30, + "description": "Preserve for legal proceedings", + "color": "#ff0000", + "scopes": ["FILES", "MAILS"] + }, + { + "id": "no-hold", + "name": "No hold", + "priority": 10, + "description": "No legal hold applied", + "color": "#00ff00", + "scopes": ["FILES"] + } + ] + } + } + """.trimIndent() + + val element = JsonParser.parseString(json) + val type = object : TypeToken>>() {}.type + val response: ServerResponse> = Gson().fromJson(element, type) + + val labels = response.ocs?.data + assertNotNull(labels) + assertEquals(2, labels!!.size) + + val first = labels[0] + assertEquals("litigation-hold", first.id) + assertEquals("Litigation hold", first.name) + assertEquals(30L, first.priority) + assertEquals("Preserve for legal proceedings", first.description) + assertEquals("#ff0000", first.color) + assertEquals(listOf(LabelScope.FILES, LabelScope.MAILS), first.scopes) + + assertEquals(listOf(LabelScope.FILES), labels[1].scopes) + } +} diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt new file mode 100644 index 0000000000..9cfccf5dc9 --- /dev/null +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt @@ -0,0 +1,20 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import org.junit.Assert.assertEquals +import org.junit.Test + +class LabelTypeTest { + @Test + fun pathValuesMatchSpecEnum() { + assertEquals("SENSITIVITY", LabelType.SENSITIVITY.value) + assertEquals("RETENTION", LabelType.RETENTION.value) + assertEquals("HOLD", LabelType.HOLD.value) + } +} diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt new file mode 100644 index 0000000000..14fd7df4dd --- /dev/null +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt @@ -0,0 +1,66 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.Gson +import com.google.gson.JsonParser +import com.google.gson.reflect.TypeToken +import com.owncloud.android.lib.ocs.ServerResponse +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Test + +class RetentionLabelInfoParsingTest { + @Test + fun parsesAvailableRetentionLabelsResponse() { + val json = + """ + { + "ocs": { + "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, + "data": [ + { + "id": "keep-10-years", + "name": "Keep 10 years", + "priority": 30, + "description": "Retain for ten years", + "color": "#ff0000", + "scopes": ["FILES", "MAILS"] + }, + { + "id": "no-retention", + "name": "No retention", + "priority": 10, + "description": "May be deleted any time", + "color": "#00ff00", + "scopes": ["FILES"] + } + ] + } + } + """.trimIndent() + + val element = JsonParser.parseString(json) + val type = object : TypeToken>>() {}.type + val response: ServerResponse> = Gson().fromJson(element, type) + + val labels = response.ocs?.data + assertNotNull(labels) + assertEquals(2, labels!!.size) + + val first = labels[0] + assertEquals("keep-10-years", first.id) + assertEquals("Keep 10 years", first.name) + assertEquals(30L, first.priority) + assertEquals("Retain for ten years", first.description) + assertEquals("#ff0000", first.color) + assertEquals(listOf(LabelScope.FILES, LabelScope.MAILS), first.scopes) + + assertEquals(listOf(LabelScope.FILES), labels[1].scopes) + } +} diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt new file mode 100644 index 0000000000..b7659bae5b --- /dev/null +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt @@ -0,0 +1,66 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import com.google.gson.Gson +import com.google.gson.JsonParser +import com.google.gson.reflect.TypeToken +import com.owncloud.android.lib.ocs.ServerResponse +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Test + +class SensitivityLabelInfoParsingTest { + @Test + fun parsesAvailableSensitivityLabelsResponse() { + val json = + """ + { + "ocs": { + "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, + "data": [ + { + "id": "confidential", + "name": "Confidential", + "priority": 30, + "description": "Restricted to a small group", + "color": "#ff0000", + "scopes": ["FILES", "MAILS"] + }, + { + "id": "public", + "name": "Public", + "priority": 10, + "description": "Anyone may access", + "color": "#00ff00", + "scopes": ["FILES"] + } + ] + } + } + """.trimIndent() + + val element = JsonParser.parseString(json) + val type = object : TypeToken>>() {}.type + val response: ServerResponse> = Gson().fromJson(element, type) + + val labels = response.ocs?.data + assertNotNull(labels) + assertEquals(2, labels!!.size) + + val first = labels[0] + assertEquals("confidential", first.id) + assertEquals("Confidential", first.name) + assertEquals(30L, first.priority) + assertEquals("Restricted to a small group", first.description) + assertEquals("#ff0000", first.color) + assertEquals(listOf(SensitivityLabelScope.FILES, SensitivityLabelScope.MAILS), first.scopes) + + assertEquals(listOf(SensitivityLabelScope.FILES), labels[1].scopes) + } +} From c0b42f72961a29e7987a98c9c6c636305bb569e0 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 16 Jul 2026 12:48:34 +0200 Subject: [PATCH 2/5] use kotlinx.serialization and fail fast in remote operations Signed-off-by: alperozturk96 --- library/build.gradle | 2 + .../lib/resources/governance/EntityLabels.kt | 3 + .../GetAllSelectableLabelsRemoteOperation.kt | 53 +++++++--------- .../GetAvailableHoldLabelsRemoteOperation.kt | 59 ++++++++--------- ...AvailableRetentionLabelsRemoteOperation.kt | 59 ++++++++--------- ...ailableSensitivityLabelsRemoteOperation.kt | 59 ++++++++--------- .../GetEntityLabelsRemoteOperation.kt | 57 +++++++---------- .../governance/GovernanceLabelResponse.kt | 3 + .../governance/GovernanceOcsResponse.kt | 30 +++++++++ .../lib/resources/governance/HoldLabelInfo.kt | 3 + .../lib/resources/governance/LabelScope.kt | 8 ++- .../governance/RemoveLabelRemoteOperation.kt | 59 ++++++++--------- .../governance/RetentionLabelInfo.kt | 3 + .../governance/SensitivityLabelInfo.kt | 3 + .../governance/SensitivityLabelScope.kt | 8 ++- .../governance/SetLabelRemoteOperation.kt | 63 ++++++++----------- .../GovernanceLabelResponseParsingTest.kt | 15 ++--- .../governance/HoldLabelInfoParsingTest.kt | 18 +++--- .../RetentionLabelInfoParsingTest.kt | 18 +++--- .../SensitivityLabelInfoParsingTest.kt | 18 +++--- 20 files changed, 257 insertions(+), 284 deletions(-) create mode 100644 library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt diff --git a/library/build.gradle b/library/build.gradle index 97790b00e7..2791591454 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -21,6 +21,7 @@ buildscript { classpath 'com.android.tools.build:gradle:9.2.1' classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:6.5.9' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.8" classpath "org.jacoco:org.jacoco.core:$jacoco_version" classpath "org.jacoco:org.jacoco.report:$jacoco_version" @@ -35,6 +36,7 @@ plugins { apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' +apply plugin: 'org.jetbrains.kotlin.plugin.serialization' apply from: "$rootProject.projectDir/jacoco.gradle" apply plugin: "com.github.spotbugs" apply plugin: 'io.gitlab.arturbosch.detekt' diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt index d74aeb8ba7..c6883a3165 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt @@ -7,6 +7,9 @@ package com.nextcloud.android.lib.resources.governance +import kotlinx.serialization.Serializable + +@Serializable data class EntityLabels( val sensitivity: List, val retention: List, diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt index 1339d0bbf7..b3a1413d35 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt @@ -7,55 +7,50 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus +import java.io.IOException class GetAllSelectableLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { - var result: RemoteOperationResult - var getMethod: GetMethod? = null - try { - getMethod = - GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + AVAILABLE + JSON_FORMAT, - true - ) + val getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + AVAILABLE + JSON_FORMAT, + true + ) + return try { val status = client.execute(getMethod) if (status == HttpStatus.SC_OK) { - val labels = - getServerResponse( - getMethod, - object : TypeToken>() {} - )?.ocs?.data - - if (labels != null) { - result = RemoteOperationResult(true, getMethod) - result.setResultData(labels) - } else { - result = RemoteOperationResult(false, getMethod) - } + val response = governanceJson.decodeFromString>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, getMethod).apply { setResultData(data) } } else { - result = RemoteOperationResult(false, getMethod) + RemoteOperationResult(false, getMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e(TAG, "Get all selectable labels failed: " + result.logMessage, result.exception) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - getMethod?.releaseConnection() + getMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult = + RemoteOperationResult(e).also { + Log_OC.e(TAG, "Get all selectable labels failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = GetAllSelectableLabelsRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt index 65fd60da35..c7d4421584 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt @@ -7,14 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus +import java.io.IOException /** * Get the hold labels the user may apply to an entity @@ -23,47 +23,38 @@ class GetAvailableHoldLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation>() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult> { - var result: RemoteOperationResult> - var getMethod: GetMethod? = null - try { - getMethod = - GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + - HOLD_AVAILABLE + JSON_FORMAT, - true - ) + val getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + HOLD_AVAILABLE + JSON_FORMAT, + true + ) + return try { val status = client.execute(getMethod) if (status == HttpStatus.SC_OK) { - val labels = - getServerResponse( - getMethod, - object : TypeToken>>() {} - )?.ocs?.data - - if (labels != null) { - result = RemoteOperationResult(true, getMethod) - result.setResultData(labels) - } else { - result = RemoteOperationResult(false, getMethod) - } + val response = governanceJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult>(true, getMethod).apply { setResultData(data) } } else { - result = RemoteOperationResult(false, getMethod) + RemoteOperationResult(false, getMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, - "Get available hold labels failed: " + result.logMessage, - result.exception - ) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - getMethod?.releaseConnection() + getMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult> = + RemoteOperationResult>(e).also { + Log_OC.e(TAG, "Get available hold labels failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = GetAvailableHoldLabelsRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt index 787940de5c..34d2b26372 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt @@ -7,14 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus +import java.io.IOException /** * Get the retention labels the user may apply to an entity @@ -23,47 +23,38 @@ class GetAvailableRetentionLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation>() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult> { - var result: RemoteOperationResult> - var getMethod: GetMethod? = null - try { - getMethod = - GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + - RETENTION_AVAILABLE + JSON_FORMAT, - true - ) + val getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + RETENTION_AVAILABLE + JSON_FORMAT, + true + ) + return try { val status = client.execute(getMethod) if (status == HttpStatus.SC_OK) { - val labels = - getServerResponse( - getMethod, - object : TypeToken>>() {} - )?.ocs?.data - - if (labels != null) { - result = RemoteOperationResult(true, getMethod) - result.setResultData(labels) - } else { - result = RemoteOperationResult(false, getMethod) - } + val response = governanceJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult>(true, getMethod).apply { setResultData(data) } } else { - result = RemoteOperationResult(false, getMethod) + RemoteOperationResult(false, getMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, - "Get available retention labels failed: " + result.logMessage, - result.exception - ) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - getMethod?.releaseConnection() + getMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult> = + RemoteOperationResult>(e).also { + Log_OC.e(TAG, "Get available retention labels failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = GetAvailableRetentionLabelsRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt index f95ab4778b..bfa17a2449 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt @@ -7,14 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus +import java.io.IOException /** * Get the sensitivity labels the user may apply to an entity @@ -23,47 +23,38 @@ class GetAvailableSensitivityLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation>() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult> { - var result: RemoteOperationResult> - var getMethod: GetMethod? = null - try { - getMethod = - GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + - SENSITIVITY_AVAILABLE + JSON_FORMAT, - true - ) + val getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + SENSITIVITY_AVAILABLE + JSON_FORMAT, + true + ) + return try { val status = client.execute(getMethod) if (status == HttpStatus.SC_OK) { - val labels = - getServerResponse( - getMethod, - object : TypeToken>>() {} - )?.ocs?.data - - if (labels != null) { - result = RemoteOperationResult(true, getMethod) - result.setResultData(labels) - } else { - result = RemoteOperationResult(false, getMethod) - } + val response = governanceJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult>(true, getMethod).apply { setResultData(data) } } else { - result = RemoteOperationResult(false, getMethod) + RemoteOperationResult(false, getMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, - "Get available sensitivity labels failed: " + result.logMessage, - result.exception - ) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - getMethod?.releaseConnection() + getMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult> = + RemoteOperationResult>(e).also { + Log_OC.e(TAG, "Get available sensitivity labels failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = GetAvailableSensitivityLabelsRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt index 61c19fdbed..e40e4d45ff 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt @@ -7,14 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus +import java.io.IOException /** * Get all labels applied to an entity, grouped by type, filtered to those visible to the calling user @@ -23,46 +23,37 @@ class GetEntityLabelsRemoteOperation( private val entityType: String, private val entityId: String ) : OCSRemoteOperation() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { - var result: RemoteOperationResult - var getMethod: GetMethod? = null - try { - getMethod = - GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + JSON_FORMAT, - true - ) + val getMethod = + GetMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + JSON_FORMAT, + true + ) + return try { val status = client.execute(getMethod) if (status == HttpStatus.SC_OK) { - val entityLabels = - getServerResponse( - getMethod, - object : TypeToken>() {} - )?.ocs?.data - - if (entityLabels != null) { - result = RemoteOperationResult(true, getMethod) - result.setResultData(entityLabels) - } else { - result = RemoteOperationResult(false, getMethod) - } + val response = governanceJson.decodeFromString>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, getMethod).apply { setResultData(data) } } else { - result = RemoteOperationResult(false, getMethod) + RemoteOperationResult(false, getMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, - "Get entity labels failed: " + result.logMessage, - result.exception - ) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - getMethod?.releaseConnection() + getMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult = + RemoteOperationResult(e).also { + Log_OC.e(TAG, "Get entity labels failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = GetEntityLabelsRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt index 7bfa0fbeb1..373326b238 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt @@ -7,6 +7,9 @@ package com.nextcloud.android.lib.resources.governance +import kotlinx.serialization.Serializable + +@Serializable data class GovernanceLabelResponse( val message: String ) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt new file mode 100644 index 0000000000..c2c17c15f6 --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt @@ -0,0 +1,30 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +package com.nextcloud.android.lib.resources.governance + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json + +/** + * Strict [Json] used to decode governance responses. + * + * Unknown keys (e.g. the OCS `meta` wrapper or additive server fields) are ignored, but required + * fields are enforced: a missing or type-mismatched field fails the decode immediately (fail fast) + * instead of silently producing a half-populated object. + */ +internal val governanceJson = Json { ignoreUnknownKeys = true } + +@Serializable +internal data class GovernanceOcsResponse( + val ocs: GovernanceOcs +) + +@Serializable +internal data class GovernanceOcs( + val data: T +) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt index 75221e4047..579a75262b 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt @@ -7,6 +7,9 @@ package com.nextcloud.android.lib.resources.governance +import kotlinx.serialization.Serializable + +@Serializable data class HoldLabelInfo( val id: String, val name: String, diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt index 50bea0e191..52202726fd 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt @@ -7,12 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +@Serializable enum class LabelScope { - @SerializedName("FILES") + @SerialName("FILES") FILES, - @SerializedName("MAILS") + @SerialName("MAILS") MAILS } diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt index 38682a063c..77c683b6c0 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt @@ -7,14 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.DeleteMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus +import java.io.IOException /** * Remove a label from an entity @@ -25,47 +25,38 @@ class RemoveLabelRemoteOperation( private val labelType: LabelType, private val labelId: String ) : OCSRemoteOperation() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { - var result: RemoteOperationResult - var deleteMethod: DeleteMethod? = null - try { - deleteMethod = - DeleteMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + - labelType.value + "/" + labelId + JSON_FORMAT, - true - ) + val deleteMethod = + DeleteMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + + labelType.value + "/" + labelId + JSON_FORMAT, + true + ) + return try { val status = client.execute(deleteMethod) if (status == HttpStatus.SC_OK) { - val response = - getServerResponse( - deleteMethod, - object : TypeToken>() {} - )?.ocs?.data - - if (response != null) { - result = RemoteOperationResult(true, deleteMethod) - result.resultData = response - } else { - result = RemoteOperationResult(false, deleteMethod) - } + val response = governanceJson.decodeFromString>( + deleteMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, deleteMethod).apply { resultData = data } } else { - result = RemoteOperationResult(false, deleteMethod) + RemoteOperationResult(false, deleteMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, - "Remove label from entity failed: " + result.logMessage, - result.exception - ) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - deleteMethod?.releaseConnection() + deleteMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult = + RemoteOperationResult(e).also { + Log_OC.e(TAG, "Remove label from entity failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = RemoveLabelRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt index b9151bc3f8..b55dae0e24 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt @@ -7,6 +7,9 @@ package com.nextcloud.android.lib.resources.governance +import kotlinx.serialization.Serializable + +@Serializable data class RetentionLabelInfo( val id: String, val name: String, diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt index c6a3a556b7..bb6d763c4e 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt @@ -7,6 +7,9 @@ package com.nextcloud.android.lib.resources.governance +import kotlinx.serialization.Serializable + +@Serializable data class SensitivityLabelInfo( val id: String, val name: String, diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt index 9ef8ae4cd4..02e1a79774 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt @@ -7,12 +7,14 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +@Serializable enum class SensitivityLabelScope { - @SerializedName("FILES") + @SerialName("FILES") FILES, - @SerializedName("MAILS") + @SerialName("MAILS") MAILS } diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt index 38ee9ef57f..fc34019cf8 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt @@ -7,16 +7,16 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.reflect.TypeToken import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.PostMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.ServerResponse import com.owncloud.android.lib.resources.OCSRemoteOperation +import kotlinx.serialization.SerializationException import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import org.apache.commons.httpclient.HttpStatus +import java.io.IOException /** * Apply a label to an entity @@ -27,49 +27,40 @@ class SetLabelRemoteOperation( private val labelType: LabelType, private val labelId: String ) : OCSRemoteOperation() { - @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { - var result: RemoteOperationResult - var postMethod: PostMethod? = null - try { - val body = "".toRequestBody("application/json".toMediaTypeOrNull()) - postMethod = - PostMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + - labelType.value + "/" + labelId + JSON_FORMAT, - true, - body - ) + val body = "".toRequestBody("application/json".toMediaTypeOrNull()) + val postMethod = + PostMethod( + client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + + labelType.value + "/" + labelId + JSON_FORMAT, + true, + body + ) + return try { val status = client.execute(postMethod) if (status == HttpStatus.SC_OK) { - val response = - getServerResponse( - postMethod, - object : TypeToken>() {} - )?.ocs?.data - - if (response != null) { - result = RemoteOperationResult(true, postMethod) - result.resultData = response - } else { - result = RemoteOperationResult(false, postMethod) - } + val response = governanceJson.decodeFromString>( + postMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, postMethod).apply { resultData = data } } else { - result = RemoteOperationResult(false, postMethod) + RemoteOperationResult(false, postMethod) } - } catch (e: Exception) { - result = RemoteOperationResult(e) - Log_OC.e( - TAG, - "Apply label to entity failed: " + result.logMessage, - result.exception - ) + } catch (e: SerializationException) { + failure(e) + } catch (e: IOException) { + failure(e) } finally { - postMethod?.releaseConnection() + postMethod.releaseConnection() } - return result } + private fun failure(e: Exception): RemoteOperationResult = + RemoteOperationResult(e).also { + Log_OC.e(TAG, "Apply label to entity failed: " + it.logMessage, it.exception) + } + companion object { private val TAG = SetLabelRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt index 92fcfbd40c..cb89b7bc9a 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt @@ -7,12 +7,8 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.Gson -import com.google.gson.JsonParser -import com.google.gson.reflect.TypeToken -import com.owncloud.android.lib.ocs.ServerResponse +import kotlinx.serialization.decodeFromString import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull import org.junit.Test class GovernanceLabelResponseParsingTest { @@ -28,12 +24,9 @@ class GovernanceLabelResponseParsingTest { } """.trimIndent() - val element = JsonParser.parseString(json) - val type = object : TypeToken>() {}.type - val response: ServerResponse = Gson().fromJson(element, type) + val data = + governanceJson.decodeFromString>(json).ocs.data - val data = response.ocs?.data - assertNotNull(data) - assertEquals("Label applied", data!!.message) + assertEquals("Label applied", data.message) } } diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt index 9efe0d9bce..bddd8abf70 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt @@ -7,12 +7,8 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.Gson -import com.google.gson.JsonParser -import com.google.gson.reflect.TypeToken -import com.owncloud.android.lib.ocs.ServerResponse +import kotlinx.serialization.decodeFromString import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull import org.junit.Test class HoldLabelInfoParsingTest { @@ -45,13 +41,13 @@ class HoldLabelInfoParsingTest { } """.trimIndent() - val element = JsonParser.parseString(json) - val type = object : TypeToken>>() {}.type - val response: ServerResponse> = Gson().fromJson(element, type) + val labels = + governanceJson + .decodeFromString>>(json) + .ocs + .data - val labels = response.ocs?.data - assertNotNull(labels) - assertEquals(2, labels!!.size) + assertEquals(2, labels.size) val first = labels[0] assertEquals("litigation-hold", first.id) diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt index 14fd7df4dd..d1bdffbab1 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt @@ -7,12 +7,8 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.Gson -import com.google.gson.JsonParser -import com.google.gson.reflect.TypeToken -import com.owncloud.android.lib.ocs.ServerResponse +import kotlinx.serialization.decodeFromString import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull import org.junit.Test class RetentionLabelInfoParsingTest { @@ -45,13 +41,13 @@ class RetentionLabelInfoParsingTest { } """.trimIndent() - val element = JsonParser.parseString(json) - val type = object : TypeToken>>() {}.type - val response: ServerResponse> = Gson().fromJson(element, type) + val labels = + governanceJson + .decodeFromString>>(json) + .ocs + .data - val labels = response.ocs?.data - assertNotNull(labels) - assertEquals(2, labels!!.size) + assertEquals(2, labels.size) val first = labels[0] assertEquals("keep-10-years", first.id) diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt index b7659bae5b..a5d538e75f 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt @@ -7,12 +7,8 @@ package com.nextcloud.android.lib.resources.governance -import com.google.gson.Gson -import com.google.gson.JsonParser -import com.google.gson.reflect.TypeToken -import com.owncloud.android.lib.ocs.ServerResponse +import kotlinx.serialization.decodeFromString import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull import org.junit.Test class SensitivityLabelInfoParsingTest { @@ -45,13 +41,13 @@ class SensitivityLabelInfoParsingTest { } """.trimIndent() - val element = JsonParser.parseString(json) - val type = object : TypeToken>>() {}.type - val response: ServerResponse> = Gson().fromJson(element, type) + val labels = + governanceJson + .decodeFromString>>(json) + .ocs + .data - val labels = response.ocs?.data - assertNotNull(labels) - assertEquals(2, labels!!.size) + assertEquals(2, labels.size) val first = labels[0] assertEquals("confidential", first.id) From a7db4615d7867c1161f53fd3e7ff0c89b1dd5c95 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 16 Jul 2026 13:05:38 +0200 Subject: [PATCH 3/5] refactor Signed-off-by: alperozturk96 --- .../GetAllSelectableLabelsRemoteOperation.kt | 29 +++++++-------- .../GetAvailableHoldLabelsRemoteOperation.kt | 32 ++++++++--------- ...AvailableRetentionLabelsRemoteOperation.kt | 32 ++++++++--------- ...ailableSensitivityLabelsRemoteOperation.kt | 32 ++++++++--------- .../GetEntityLabelsRemoteOperation.kt | 32 ++++++++--------- .../governance/RemoveLabelRemoteOperation.kt | 35 +++++++++---------- .../governance/SetLabelRemoteOperation.kt | 35 +++++++++---------- .../governance/{ => model}/EntityLabels.kt | 2 +- .../{ => model}/GovernanceLabelResponse.kt | 2 +- .../governance/{ => model}/HoldLabelInfo.kt | 2 +- .../governance/{ => model}/LabelScope.kt | 2 +- .../governance/{ => model}/LabelType.kt | 2 +- .../{ => model}/RetentionLabelInfo.kt | 2 +- .../{ => model}/SensitivityLabelInfo.kt | 2 +- .../{ => model}/SensitivityLabelScope.kt | 2 +- .../android/lib/ocs/OcsResponse.kt} | 18 ++++++---- .../GovernanceLabelResponseParsingTest.kt | 5 ++- .../governance/HoldLabelInfoParsingTest.kt | 8 +++-- .../lib/resources/governance/LabelTypeTest.kt | 1 + .../RetentionLabelInfoParsingTest.kt | 8 +++-- .../SensitivityLabelInfoParsingTest.kt | 8 +++-- 21 files changed, 152 insertions(+), 139 deletions(-) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/EntityLabels.kt (85%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/GovernanceLabelResponse.kt (81%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/HoldLabelInfo.kt (86%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/LabelScope.kt (84%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/LabelType.kt (81%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/RetentionLabelInfo.kt (86%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/SensitivityLabelInfo.kt (86%) rename library/src/main/java/com/nextcloud/android/lib/resources/governance/{ => model}/SensitivityLabelScope.kt (85%) rename library/src/main/java/com/{nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt => owncloud/android/lib/ocs/OcsResponse.kt} (52%) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt index b3a1413d35..2c2300367c 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt @@ -7,45 +7,46 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.EntityLabels import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.SEPARATOR +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus -import java.io.IOException class GetAllSelectableLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { val getMethod = GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + AVAILABLE + JSON_FORMAT, + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + AVAILABLE + JSON_FORMAT, true ) return try { val status = client.execute(getMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>( - getMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult(true, getMethod).apply { setResultData(data) } - } else { - RemoteOperationResult(false, getMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, getMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, getMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { getMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult = RemoteOperationResult(e).also { Log_OC.e(TAG, "Get all selectable labels failed: " + it.logMessage, it.exception) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt index c7d4421584..5a61529289 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt @@ -7,49 +7,47 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.HoldLabelInfo import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.SEPARATOR +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus -import java.io.IOException -/** - * Get the hold labels the user may apply to an entity - */ class GetAvailableHoldLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation>() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult> { val getMethod = GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + HOLD_AVAILABLE + JSON_FORMAT, true ) return try { val status = client.execute(getMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>>( - getMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult>(true, getMethod).apply { setResultData(data) } - } else { - RemoteOperationResult(false, getMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, getMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult>(true, getMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { getMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult> = RemoteOperationResult>(e).also { Log_OC.e(TAG, "Get available hold labels failed: " + it.logMessage, it.exception) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt index 34d2b26372..402d795471 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt @@ -7,49 +7,47 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.RetentionLabelInfo import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.SEPARATOR +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus -import java.io.IOException -/** - * Get the retention labels the user may apply to an entity - */ class GetAvailableRetentionLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation>() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult> { val getMethod = GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + RETENTION_AVAILABLE + JSON_FORMAT, true ) return try { val status = client.execute(getMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>>( - getMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult>(true, getMethod).apply { setResultData(data) } - } else { - RemoteOperationResult(false, getMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, getMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult>(true, getMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { getMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult> = RemoteOperationResult>(e).also { Log_OC.e(TAG, "Get available retention labels failed: " + it.logMessage, it.exception) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt index bfa17a2449..6ee1dd82c6 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt @@ -7,49 +7,47 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.SensitivityLabelInfo import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.SEPARATOR +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus -import java.io.IOException -/** - * Get the sensitivity labels the user may apply to an entity - */ class GetAvailableSensitivityLabelsRemoteOperation( private val entityType: String, private val entityId: Long ) : OCSRemoteOperation>() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult> { val getMethod = GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + SENSITIVITY_AVAILABLE + JSON_FORMAT, true ) return try { val status = client.execute(getMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>>( - getMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult>(true, getMethod).apply { setResultData(data) } - } else { - RemoteOperationResult(false, getMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, getMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult>(true, getMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { getMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult> = RemoteOperationResult>(e).also { Log_OC.e(TAG, "Get available sensitivity labels failed: " + it.logMessage, it.exception) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt index e40e4d45ff..c99a07f07d 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt @@ -7,48 +7,46 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.EntityLabels import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.SEPARATOR +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus -import java.io.IOException -/** - * Get all labels applied to an entity, grouped by type, filtered to those visible to the calling user - */ class GetEntityLabelsRemoteOperation( private val entityType: String, private val entityId: String ) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { val getMethod = GetMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + JSON_FORMAT, + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + JSON_FORMAT, true ) return try { val status = client.execute(getMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>( - getMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult(true, getMethod).apply { setResultData(data) } - } else { - RemoteOperationResult(false, getMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, getMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>( + getMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, getMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { getMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult = RemoteOperationResult(e).also { Log_OC.e(TAG, "Get entity labels failed: " + it.logMessage, it.exception) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt index 77c683b6c0..90fe375f99 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt @@ -7,51 +7,49 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.GovernanceLabelResponse +import com.nextcloud.android.lib.resources.governance.model.LabelType import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.DeleteMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import org.apache.commons.httpclient.HttpStatus -import java.io.IOException -/** - * Remove a label from an entity - */ class RemoveLabelRemoteOperation( private val entityType: String, private val entityId: Long, private val labelType: LabelType, private val labelId: String ) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { val deleteMethod = DeleteMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + - labelType.value + "/" + labelId + JSON_FORMAT, + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + SEPARATOR + + labelType.value + SEPARATOR + labelId + JSON_FORMAT, true ) return try { val status = client.execute(deleteMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>( - deleteMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult(true, deleteMethod).apply { resultData = data } - } else { - RemoteOperationResult(false, deleteMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, deleteMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>( + deleteMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, deleteMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { deleteMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult = RemoteOperationResult(e).also { Log_OC.e(TAG, "Remove label from entity failed: " + it.logMessage, it.exception) @@ -60,5 +58,6 @@ class RemoveLabelRemoteOperation( companion object { private val TAG = RemoveLabelRemoteOperation::class.java.simpleName private const val ENDPOINT = "/ocs/v2.php/apps/governance/v1/labels/" + private const val SEPARATOR = "/" } } diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt index fc34019cf8..c87c9ccd84 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt @@ -7,55 +7,54 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.GovernanceLabelResponse +import com.nextcloud.android.lib.resources.governance.model.LabelType import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.PostMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.SEPARATOR +import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation -import kotlinx.serialization.SerializationException import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import org.apache.commons.httpclient.HttpStatus -import java.io.IOException -/** - * Apply a label to an entity - */ class SetLabelRemoteOperation( private val entityType: String, private val entityId: Long, private val labelType: LabelType, private val labelId: String ) : OCSRemoteOperation() { + @Suppress("TooGenericExceptionCaught") override fun run(client: NextcloudClient): RemoteOperationResult { val body = "".toRequestBody("application/json".toMediaTypeOrNull()) val postMethod = PostMethod( - client.baseUri.toString() + ENDPOINT + entityType + "/" + entityId + "/" + - labelType.value + "/" + labelId + JSON_FORMAT, + client.baseUri.toString() + ENDPOINT + entityType + SEPARATOR + entityId + SEPARATOR + + labelType.value + SEPARATOR + labelId + JSON_FORMAT, true, body ) return try { val status = client.execute(postMethod) - if (status == HttpStatus.SC_OK) { - val response = governanceJson.decodeFromString>( - postMethod.getResponseBodyAsString() - ) - val data = response.ocs.data - RemoteOperationResult(true, postMethod).apply { resultData = data } - } else { - RemoteOperationResult(false, postMethod) + if (status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, postMethod) } - } catch (e: SerializationException) { - failure(e) - } catch (e: IOException) { + val response = ocsJson.decodeFromString>( + postMethod.getResponseBodyAsString() + ) + val data = response.ocs.data + RemoteOperationResult(true, postMethod).apply { resultData = data } + } catch (e: Exception) { failure(e) } finally { postMethod.releaseConnection() } } + @Suppress("DEPRECATION") private fun failure(e: Exception): RemoteOperationResult = RemoteOperationResult(e).also { Log_OC.e(TAG, "Apply label to entity failed: " + it.logMessage, it.exception) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/EntityLabels.kt similarity index 85% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/EntityLabels.kt index c6883a3165..7cb246e114 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/EntityLabels.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/EntityLabels.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/GovernanceLabelResponse.kt similarity index 81% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/GovernanceLabelResponse.kt index 373326b238..ea06cb8d41 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponse.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/GovernanceLabelResponse.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt similarity index 86% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt index 579a75262b..71fe32e34b 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/LabelScope.kt similarity index 84% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/LabelScope.kt index 52202726fd..f631090abd 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelScope.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/LabelScope.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/LabelType.kt similarity index 81% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/LabelType.kt index 15c4fb219f..712d5f1fba 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/LabelType.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/LabelType.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model enum class LabelType( val value: String diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt similarity index 86% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt index b55dae0e24..ec170abd87 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt similarity index 86% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt index bb6d763c4e..86fdcaf516 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelScope.kt similarity index 85% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt rename to library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelScope.kt index 02e1a79774..d0e5f79935 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelScope.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelScope.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.nextcloud.android.lib.resources.governance.model import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt b/library/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt similarity index 52% rename from library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt rename to library/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt index c2c17c15f6..ebcc77f53b 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GovernanceOcsResponse.kt +++ b/library/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt @@ -5,26 +5,32 @@ * SPDX-License-Identifier: MIT */ -package com.nextcloud.android.lib.resources.governance +package com.owncloud.android.lib.ocs import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json +const val SEPARATOR = "/" + /** - * Strict [Json] used to decode governance responses. + * Strict [Json] used to decode OCS responses with kotlinx.serialization. * * Unknown keys (e.g. the OCS `meta` wrapper or additive server fields) are ignored, but required * fields are enforced: a missing or type-mismatched field fails the decode immediately (fail fast) * instead of silently producing a half-populated object. */ -internal val governanceJson = Json { ignoreUnknownKeys = true } +internal val ocsJson = Json { ignoreUnknownKeys = true } +/** + * Serializable counterpart of [ServerResponse]: the outer `{ "ocs": { "data": ... } }` envelope + * shared by every OCS endpoint. Reusable for any endpoint whose payload type [T] is `@Serializable`. + */ @Serializable -internal data class GovernanceOcsResponse( - val ocs: GovernanceOcs +internal data class OcsResponse( + val ocs: Ocs ) @Serializable -internal data class GovernanceOcs( +internal data class Ocs( val data: T ) diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt index cb89b7bc9a..9e35ff511e 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt @@ -8,6 +8,9 @@ package com.nextcloud.android.lib.resources.governance import kotlinx.serialization.decodeFromString +import com.nextcloud.android.lib.resources.governance.model.GovernanceLabelResponse +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -25,7 +28,7 @@ class GovernanceLabelResponseParsingTest { """.trimIndent() val data = - governanceJson.decodeFromString>(json).ocs.data + ocsJson.decodeFromString>(json).ocs.data assertEquals("Label applied", data.message) } diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt index bddd8abf70..acb479a2ad 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt @@ -8,6 +8,10 @@ package com.nextcloud.android.lib.resources.governance import kotlinx.serialization.decodeFromString +import com.nextcloud.android.lib.resources.governance.model.HoldLabelInfo +import com.nextcloud.android.lib.resources.governance.model.LabelScope +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -42,8 +46,8 @@ class HoldLabelInfoParsingTest { """.trimIndent() val labels = - governanceJson - .decodeFromString>>(json) + ocsJson + .decodeFromString>>(json) .ocs .data diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt index 9cfccf5dc9..c651a791cd 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/LabelTypeTest.kt @@ -7,6 +7,7 @@ package com.nextcloud.android.lib.resources.governance +import com.nextcloud.android.lib.resources.governance.model.LabelType import org.junit.Assert.assertEquals import org.junit.Test diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt index d1bdffbab1..30da1c047f 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt @@ -8,6 +8,10 @@ package com.nextcloud.android.lib.resources.governance import kotlinx.serialization.decodeFromString +import com.nextcloud.android.lib.resources.governance.model.LabelScope +import com.nextcloud.android.lib.resources.governance.model.RetentionLabelInfo +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -42,8 +46,8 @@ class RetentionLabelInfoParsingTest { """.trimIndent() val labels = - governanceJson - .decodeFromString>>(json) + ocsJson + .decodeFromString>>(json) .ocs .data diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt index a5d538e75f..50e158b8ba 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt @@ -8,6 +8,10 @@ package com.nextcloud.android.lib.resources.governance import kotlinx.serialization.decodeFromString +import com.nextcloud.android.lib.resources.governance.model.SensitivityLabelInfo +import com.nextcloud.android.lib.resources.governance.model.SensitivityLabelScope +import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -42,8 +46,8 @@ class SensitivityLabelInfoParsingTest { """.trimIndent() val labels = - governanceJson - .decodeFromString>>(json) + ocsJson + .decodeFromString>>(json) .ocs .data From 0f65e9241349c2d8abded062a5fb78e76db8aec7 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 16 Jul 2026 13:39:04 +0200 Subject: [PATCH 4/5] wip Signed-off-by: alperozturk96 --- .../governance/GetAllSelectableLabelsRemoteOperation.kt | 4 ++-- .../governance/GetAvailableHoldLabelsRemoteOperation.kt | 4 ++-- .../GetAvailableRetentionLabelsRemoteOperation.kt | 4 ++-- .../GetAvailableSensitivityLabelsRemoteOperation.kt | 4 ++-- .../resources/governance/GetEntityLabelsRemoteOperation.kt | 4 ++-- .../lib/resources/governance/RemoveLabelRemoteOperation.kt | 4 ++-- .../lib/resources/governance/SetLabelRemoteOperation.kt | 4 ++-- .../android/lib/resources/governance/model/HoldLabelInfo.kt | 2 +- .../lib/resources/governance/model/RetentionLabelInfo.kt | 2 +- .../lib/resources/governance/model/SensitivityLabelInfo.kt | 2 +- .../lib/ocs/{OcsResponse.kt => OcsKotlinResponse.kt} | 6 +++--- .../governance/GovernanceLabelResponseParsingTest.kt | 5 ++--- .../lib/resources/governance/HoldLabelInfoParsingTest.kt | 5 ++--- .../resources/governance/RetentionLabelInfoParsingTest.kt | 5 ++--- .../resources/governance/SensitivityLabelInfoParsingTest.kt | 5 ++--- 15 files changed, 28 insertions(+), 32 deletions(-) rename library/src/main/java/com/owncloud/android/lib/ocs/{OcsResponse.kt => OcsKotlinResponse.kt} (90%) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt index 2c2300367c..4077926599 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt @@ -12,7 +12,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.SEPARATOR import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation @@ -34,7 +34,7 @@ class GetAllSelectableLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>( + val response = ocsJson.decodeFromString>( getMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt index 5a61529289..f5fbc1ab22 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt @@ -12,7 +12,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.SEPARATOR import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation @@ -35,7 +35,7 @@ class GetAvailableHoldLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>>( + val response = ocsJson.decodeFromString>>( getMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt index 402d795471..53074a8704 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt @@ -12,7 +12,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.SEPARATOR import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation @@ -35,7 +35,7 @@ class GetAvailableRetentionLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>>( + val response = ocsJson.decodeFromString>>( getMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt index 6ee1dd82c6..5b3d58c238 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt @@ -12,7 +12,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.SEPARATOR import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation @@ -35,7 +35,7 @@ class GetAvailableSensitivityLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>>( + val response = ocsJson.decodeFromString>>( getMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt index c99a07f07d..f69bd43e95 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt @@ -12,7 +12,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.GetMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.SEPARATOR import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation @@ -34,7 +34,7 @@ class GetEntityLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>( + val response = ocsJson.decodeFromString>( getMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt index 90fe375f99..6e6050ec25 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt @@ -13,7 +13,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.DeleteMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation import org.apache.commons.httpclient.HttpStatus @@ -37,7 +37,7 @@ class RemoveLabelRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, deleteMethod) } - val response = ocsJson.decodeFromString>( + val response = ocsJson.decodeFromString>( deleteMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt index c87c9ccd84..ad25c86ca3 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt @@ -13,7 +13,7 @@ import com.nextcloud.common.NextcloudClient import com.nextcloud.operations.PostMethod import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.SEPARATOR import com.owncloud.android.lib.ocs.ocsJson import com.owncloud.android.lib.resources.OCSRemoteOperation @@ -42,7 +42,7 @@ class SetLabelRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, postMethod) } - val response = ocsJson.decodeFromString>( + val response = ocsJson.decodeFromString>( postMethod.getResponseBodyAsString() ) val data = response.ocs.data diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt index 71fe32e34b..16a6c2a123 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/HoldLabelInfo.kt @@ -16,5 +16,5 @@ data class HoldLabelInfo( val priority: Long, val description: String, val color: String, - val scopes: List + val scopes: List = emptyList() ) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt index ec170abd87..a40035dbca 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/RetentionLabelInfo.kt @@ -16,5 +16,5 @@ data class RetentionLabelInfo( val priority: Long, val description: String, val color: String, - val scopes: List + val scopes: List = emptyList() ) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt index 86fdcaf516..5427a9b323 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/model/SensitivityLabelInfo.kt @@ -16,5 +16,5 @@ data class SensitivityLabelInfo( val priority: Long, val description: String, val color: String, - val scopes: List + val scopes: List = emptyList() ) diff --git a/library/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt b/library/src/main/java/com/owncloud/android/lib/ocs/OcsKotlinResponse.kt similarity index 90% rename from library/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt rename to library/src/main/java/com/owncloud/android/lib/ocs/OcsKotlinResponse.kt index ebcc77f53b..5bd6a6806f 100644 --- a/library/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt +++ b/library/src/main/java/com/owncloud/android/lib/ocs/OcsKotlinResponse.kt @@ -26,11 +26,11 @@ internal val ocsJson = Json { ignoreUnknownKeys = true } * shared by every OCS endpoint. Reusable for any endpoint whose payload type [T] is `@Serializable`. */ @Serializable -internal data class OcsResponse( - val ocs: Ocs +internal data class OcsKotlinResponse( + val ocs: OcsKotlin ) @Serializable -internal data class Ocs( +internal data class OcsKotlin( val data: T ) diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt index 9e35ff511e..270b658b7e 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/GovernanceLabelResponseParsingTest.kt @@ -7,9 +7,8 @@ package com.nextcloud.android.lib.resources.governance -import kotlinx.serialization.decodeFromString import com.nextcloud.android.lib.resources.governance.model.GovernanceLabelResponse -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -28,7 +27,7 @@ class GovernanceLabelResponseParsingTest { """.trimIndent() val data = - ocsJson.decodeFromString>(json).ocs.data + ocsJson.decodeFromString>(json).ocs.data assertEquals("Label applied", data.message) } diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt index acb479a2ad..f696c54fd5 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/HoldLabelInfoParsingTest.kt @@ -7,10 +7,9 @@ package com.nextcloud.android.lib.resources.governance -import kotlinx.serialization.decodeFromString import com.nextcloud.android.lib.resources.governance.model.HoldLabelInfo import com.nextcloud.android.lib.resources.governance.model.LabelScope -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -47,7 +46,7 @@ class HoldLabelInfoParsingTest { val labels = ocsJson - .decodeFromString>>(json) + .decodeFromString>>(json) .ocs .data diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt index 30da1c047f..eff665e6d3 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/RetentionLabelInfoParsingTest.kt @@ -7,10 +7,9 @@ package com.nextcloud.android.lib.resources.governance -import kotlinx.serialization.decodeFromString import com.nextcloud.android.lib.resources.governance.model.LabelScope import com.nextcloud.android.lib.resources.governance.model.RetentionLabelInfo -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -47,7 +46,7 @@ class RetentionLabelInfoParsingTest { val labels = ocsJson - .decodeFromString>>(json) + .decodeFromString>>(json) .ocs .data diff --git a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt index 50e158b8ba..89bc3f7e96 100644 --- a/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt +++ b/library/src/test/java/com/nextcloud/android/lib/resources/governance/SensitivityLabelInfoParsingTest.kt @@ -7,10 +7,9 @@ package com.nextcloud.android.lib.resources.governance -import kotlinx.serialization.decodeFromString import com.nextcloud.android.lib.resources.governance.model.SensitivityLabelInfo import com.nextcloud.android.lib.resources.governance.model.SensitivityLabelScope -import com.owncloud.android.lib.ocs.OcsResponse +import com.owncloud.android.lib.ocs.OcsKotlinResponse import com.owncloud.android.lib.ocs.ocsJson import org.junit.Assert.assertEquals import org.junit.Test @@ -47,7 +46,7 @@ class SensitivityLabelInfoParsingTest { val labels = ocsJson - .decodeFromString>>(json) + .decodeFromString>>(json) .ocs .data From 29ed9d187b68ab791bc9cdf47178f71ea7dc09aa Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 16 Jul 2026 14:13:14 +0200 Subject: [PATCH 5/5] spotless Signed-off-by: tobiasKaminsky --- .../governance/GetAllSelectableLabelsRemoteOperation.kt | 7 ++++--- .../governance/GetAvailableHoldLabelsRemoteOperation.kt | 7 ++++--- .../GetAvailableRetentionLabelsRemoteOperation.kt | 7 ++++--- .../GetAvailableSensitivityLabelsRemoteOperation.kt | 7 ++++--- .../resources/governance/GetEntityLabelsRemoteOperation.kt | 7 ++++--- .../lib/resources/governance/RemoveLabelRemoteOperation.kt | 7 ++++--- .../lib/resources/governance/SetLabelRemoteOperation.kt | 7 ++++--- 7 files changed, 28 insertions(+), 21 deletions(-) diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt index 4077926599..5edccadebe 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAllSelectableLabelsRemoteOperation.kt @@ -34,9 +34,10 @@ class GetAllSelectableLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>( - getMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>( + getMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult(true, getMethod).apply { resultData = data } } catch (e: Exception) { diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt index f5fbc1ab22..6b4fb0a1ac 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableHoldLabelsRemoteOperation.kt @@ -35,9 +35,10 @@ class GetAvailableHoldLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>>( - getMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult>(true, getMethod).apply { resultData = data } } catch (e: Exception) { diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt index 53074a8704..0bf686482c 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableRetentionLabelsRemoteOperation.kt @@ -35,9 +35,10 @@ class GetAvailableRetentionLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>>( - getMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult>(true, getMethod).apply { resultData = data } } catch (e: Exception) { diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt index 5b3d58c238..df4e355a9a 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetAvailableSensitivityLabelsRemoteOperation.kt @@ -35,9 +35,10 @@ class GetAvailableSensitivityLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>>( - getMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>>( + getMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult>(true, getMethod).apply { resultData = data } } catch (e: Exception) { diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt index f69bd43e95..5de6d55d6f 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/GetEntityLabelsRemoteOperation.kt @@ -34,9 +34,10 @@ class GetEntityLabelsRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, getMethod) } - val response = ocsJson.decodeFromString>( - getMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>( + getMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult(true, getMethod).apply { resultData = data } } catch (e: Exception) { diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt index 6e6050ec25..293208f04c 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/RemoveLabelRemoteOperation.kt @@ -37,9 +37,10 @@ class RemoveLabelRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, deleteMethod) } - val response = ocsJson.decodeFromString>( - deleteMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>( + deleteMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult(true, deleteMethod).apply { resultData = data } } catch (e: Exception) { diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt index ad25c86ca3..e2a5b494e1 100644 --- a/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt +++ b/library/src/main/java/com/nextcloud/android/lib/resources/governance/SetLabelRemoteOperation.kt @@ -42,9 +42,10 @@ class SetLabelRemoteOperation( if (status != HttpStatus.SC_OK) { return RemoteOperationResult(false, postMethod) } - val response = ocsJson.decodeFromString>( - postMethod.getResponseBodyAsString() - ) + val response = + ocsJson.decodeFromString>( + postMethod.getResponseBodyAsString() + ) val data = response.ocs.data RemoteOperationResult(true, postMethod).apply { resultData = data } } catch (e: Exception) {