diff --git a/.github/instructions/dotnet.instructions.md b/.github/instructions/dotnet.instructions.md index 7fc8939..521f63d 100644 --- a/.github/instructions/dotnet.instructions.md +++ b/.github/instructions/dotnet.instructions.md @@ -66,9 +66,22 @@ To provide the broadest compatiblity, the projects target .NET Standard 2.0, all - Avoid catching generic `Exception` types; catch specific exceptions - Log exceptions with sufficient context for troubleshooting +### RowAction Semantics +Understanding RowAction values is critical for proper row state management in ScriptLink operations. The RowAction determines which rows are included in the response payload sent back to myAvatar: +- **RowActions.None** (`""` empty string or `null`): No action pending on the row. Both empty string and null are treated equivalently as None. Rows with RowAction.None are **excluded from the response payload** and not sent back to myAvatar, effectively preserving them as-is. When modifying fields in a row initially in None state, set it to RowActions.Edit to include it in the response payload. +- **RowActions.Add** (`"ADD"`): A new row is being added to the form. This row **is included in the response payload** to instruct myAvatar to add it. Preserve this action when modifying the row; do not override with Edit. +- **RowActions.Edit** (`"EDIT"`): An existing row is being modified. This row **is included in the response payload** to instruct myAvatar to update it. Set a row's RowAction to Edit when making field changes on a row that was previously in None state to ensure the modifications are sent to myAvatar. +- **RowActions.Delete** (`"DELETE"`): The row is marked for removal from the form. This row **is included in the response payload** to instruct myAvatar to delete it. Do not change this action even if fields are modified; the row deletion takes precedence. + +When implementing helper methods that modify rows (e.g., `DisableAllFieldObjects`, `SetFieldValue`): +- Only set RowAction to Edit if it's currently None (use `string.IsNullOrEmpty()` to check for None), so the modified row is included in the response payload +- Preserve existing RowAction values (Add, Edit, Delete) to avoid overriding the intended operation +- This ensures that a row marked for deletion remains marked for deletion, a row being added retains that intent, and rows with no changes are not unnecessarily included in the response + ### Documentation - Include XML documentation for all public types and members - Document non-obvious logic with inline comments +- Explain why certain decisions are made, especially regarding RowAction handling - Include examples in XML documentation for complex methods - Keep documentation up-to-date with code changes - Document breaking changes and migration paths in release notes diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs index 4518474..9add358 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs @@ -1190,4 +1190,246 @@ public void TestFormObjectDecorator_AddRowObject_WithNullOtherRows_BecomesCurren } #endregion + + #region DisableAllFieldObjects + + [TestMethod] + public void DisableAllFieldObjects_NullExclusionList_ThrowsException() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var decorator = new FormObjectDecorator(formObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(null)); + } + + [TestMethod] + public void DisableAllFieldObjects_DisablesFieldsInCurrentRow() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_DisablesFieldsInOtherRowsWhenMultipleIteration() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var currentRow = new RowObject() + { + Fields = [fieldObject1], + RowId = "1" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject2], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = currentRow, + MultipleIteration = true, + OtherRows = [otherRow] + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.OtherRows[0].Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_DisablesFieldsInOtherRowsEvenWhenNotMultipleIteration() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var currentRow = new RowObject() + { + Fields = [fieldObject1], + RowId = "1" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject2], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = currentRow, + MultipleIteration = false, + OtherRows = [otherRow] + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.OtherRows[0].Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_ExcludedFieldsRemainEnabled() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject1, fieldObject2], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(new List { "123" }); + Assert.IsTrue(decorator.CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.CurrentRow.Fields[1].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_WithNullCurrentRow() + { + var formObject = new FormObject() + { + FormId = "1" + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsNull(decorator.CurrentRow); + } + + [TestMethod] + public void DisableAllFieldObjects_SetsRowActionToEdit() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(new List()); + Assert.AreEqual(RowActions.Edit, decorator.CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_WithoutExclusionList() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.CurrentRow.Fields[0].Enabled); + Assert.AreEqual(RowActions.Edit, decorator.CurrentRow.RowAction); + } + + #endregion } \ No newline at end of file diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs index 8a08216..9806780 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs @@ -1713,4 +1713,396 @@ public void TestOptionObject2015Decorator_Constructor_WithEmptyFormsCollection() } #endregion + + #region DisableAllFieldObjects + + [TestMethod] + public void DisableAllFieldObjects_AllFieldsDisabled() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_WithExcludedFields() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject1, fieldObject2], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(new List { "123" }); + Assert.IsTrue(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[1].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_NullExcludedFieldsList_ThrowsException() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(null)); + } + + [TestMethod] + public void DisableAllFieldObjects_EmptyForms_ThrowsException() + { + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObject2015Decorator(optionObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects()); + } + + [TestMethod] + public void DisableAllFieldObjects_NullForms_ThrowsException() + { + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.Forms = null; + Assert.ThrowsException(() => decorator.DisableAllFieldObjects()); + } + + [TestMethod] + public void DisableAllFieldObjects_NullForms_WithExclusionList_ThrowsException() + { + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.Forms = null; + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(new List())); + } + + [TestMethod] + public void DisableAllFieldObjects_EmptyExclusionList() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesSessionToken() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + SessionToken = "SESSIONTOKEN123", + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("SESSIONTOKEN123", decorator.SessionToken); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesNamespaceName() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + NamespaceName = "NAMESPACE", + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("NAMESPACE", decorator.NamespaceName); + } + + [TestMethod] + public void DisableAllFieldObjects_MultipleIterationForm() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + MultipleIteration = true, + OtherRows = [otherRow] + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].OtherRows[0].Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_SetsRowActionToEdit() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("EDIT", decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesExistingRowAction() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "DELETE" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("DELETE", decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_WithNullCurrentRow() + { + var formObject = new FormObject() + { + FormId = "1" + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsNull(decorator.Forms[0].CurrentRow); + } + + [TestMethod] + public void DisableAllFieldObjects_NonMultipleIterationForm() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject, + MultipleIteration = false, + OtherRows = [otherRow] + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.Forms[0].OtherRows[0].Fields[0].Enabled); + } + + #endregion } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs index 3d77109..d623150 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs @@ -1730,4 +1730,396 @@ public void TestOptionObject2Decorator_Constructor_WithEmptyFormsCollection() } #endregion + + #region DisableAllFieldObjects + + [TestMethod] + public void DisableAllFieldObjects_AllFieldsDisabled() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_WithExcludedFields() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject1, fieldObject2], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(new List { "123" }); + Assert.IsTrue(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[1].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_NullExcludedFieldsList_ThrowsException() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(null)); + } + + [TestMethod] + public void DisableAllFieldObjects_EmptyForms_ThrowsException() + { + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObject2Decorator(optionObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects()); + } + + [TestMethod] + public void DisableAllFieldObjects_NullForms_ThrowsException() + { + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.Forms = null; + Assert.ThrowsException(() => decorator.DisableAllFieldObjects()); + } + + [TestMethod] + public void DisableAllFieldObjects_NullForms_WithExclusionList_ThrowsException() + { + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.Forms = null; + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(new List())); + } + + [TestMethod] + public void DisableAllFieldObjects_EmptyExclusionList() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesNamespaceName() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + NamespaceName = "NAMESPACE", + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("NAMESPACE", decorator.NamespaceName); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesServerName() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + ServerName = "SERVERNAME", + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("SERVERNAME", decorator.ServerName); + } + + [TestMethod] + public void DisableAllFieldObjects_MultipleIterationForm() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + MultipleIteration = true, + OtherRows = [otherRow] + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].OtherRows[0].Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_SetsRowActionToEdit() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("EDIT", decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesExistingRowAction() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "DELETE" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("DELETE", decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_WithNullCurrentRow() + { + var formObject = new FormObject() + { + FormId = "1" + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsNull(decorator.Forms[0].CurrentRow); + } + + [TestMethod] + public void DisableAllFieldObjects_NonMultipleIterationForm() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject, + MultipleIteration = false, + OtherRows = [otherRow] + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.Forms[0].OtherRows[0].Fields[0].Enabled); + } + + #endregion } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs index b012985..4f974cf 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs @@ -1731,4 +1731,394 @@ public void TestOptionObjectDecorator_Constructor_WithEmptyFormsCollection() } #endregion + + #region DisableAllFieldObjects + + [TestMethod] + public void DisableAllFieldObjects_AllFieldsDisabled() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_WithExcludedFields() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject1, fieldObject2], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(new List { "123" }); + Assert.IsTrue(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[1].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_EmptyExclusionList() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_NullExcludedFieldsList_ThrowsException() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(null)); + } + + [TestMethod] + public void DisableAllFieldObjects_EmptyForms_ThrowsException() + { + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObjectDecorator(optionObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects()); + } + + [TestMethod] + public void DisableAllFieldObjects_NullForms_ThrowsException() + { + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.Forms = null; + Assert.ThrowsException(() => decorator.DisableAllFieldObjects()); + } + + [TestMethod] + public void DisableAllFieldObjects_NullForms_WithExclusionList_ThrowsException() + { + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = new List() + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.Forms = null; + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(new List())); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesEntityID() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + EntityID = "123456", + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("123456", decorator.EntityID); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesOptionId() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("TEST123", decorator.OptionId); + } + + [TestMethod] + public void DisableAllFieldObjects_MultipleIterationForm() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject], + RowId = "2", + ParentRowId = "1" + }; + var formObject = new FormObject() + { + FormId = "1", + MultipleIteration = true, + OtherRows = [otherRow] + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].OtherRows[0].Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_SetsRowActionToEdit() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("EDIT", decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesExistingRowAction() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "DELETE" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.AreEqual("DELETE", decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_WithNullCurrentRow() + { + var formObject = new FormObject() + { + FormId = "1" + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsNull(decorator.Forms[0].CurrentRow); + } + + [TestMethod] + public void DisableAllFieldObjects_NonMultipleIterationForm() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var otherRow = new RowObject() + { + Fields = [fieldObject], + RowId = "2" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject, + MultipleIteration = false, + OtherRows = [otherRow] + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Forms[0].CurrentRow.Fields[0].Enabled); + Assert.IsFalse(decorator.Forms[0].OtherRows[0].Fields[0].Enabled); + } + + #endregion } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs index 819b513..1d6494c 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs @@ -484,4 +484,184 @@ public void TestRowObjectDecorator_SetFieldValue_ReturnsExpectedFields() } #endregion + + #region DisableAllFieldObjects + + [TestMethod] + public void DisableAllFieldObjects_NullExclusionList_ThrowsException() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var decorator = new RowObjectDecorator(rowObject); + Assert.ThrowsException(() => decorator.DisableAllFieldObjects(null)); + } + + [TestMethod] + public void DisableAllFieldObjects_DisablesAllFields() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var decorator = new RowObjectDecorator(rowObject); + decorator.DisableAllFieldObjects(new List()); + Assert.IsFalse(decorator.Fields[0].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_ExcludedFieldsRemainEnabled() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject1, fieldObject2], + RowId = "1" + }; + var decorator = new RowObjectDecorator(rowObject); + decorator.DisableAllFieldObjects(new List { "123" }); + Assert.IsTrue(decorator.Fields[0].Enabled); + Assert.IsFalse(decorator.Fields[1].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_MultipleFields() + { + var fieldObject1 = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject2 = new FieldObject() + { + Enabled = "1", + FieldNumber = "124", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var fieldObject3 = new FieldObject() + { + Enabled = "1", + FieldNumber = "125", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject1, fieldObject2, fieldObject3], + RowId = "1" + }; + var decorator = new RowObjectDecorator(rowObject); + decorator.DisableAllFieldObjects(new List { "124" }); + Assert.IsFalse(decorator.Fields[0].Enabled); + Assert.IsTrue(decorator.Fields[1].Enabled); + Assert.IsFalse(decorator.Fields[2].Enabled); + } + + [TestMethod] + public void DisableAllFieldObjects_SetsRowActionToEdit() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "" + }; + var decorator = new RowObjectDecorator(rowObject); + decorator.DisableAllFieldObjects(new List()); + Assert.AreEqual(RowActions.Edit, decorator.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_PreservesExistingRowAction() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1", + RowAction = "DELETE" + }; + var decorator = new RowObjectDecorator(rowObject); + decorator.DisableAllFieldObjects(new List()); + Assert.AreEqual("DELETE", decorator.RowAction); + } + + [TestMethod] + public void DisableAllFieldObjects_WithoutExclusionList() + { + var fieldObject = new FieldObject() + { + Enabled = "1", + FieldNumber = "123", + FieldValue = "test", + Lock = "0", + Required = "0" + }; + var rowObject = new RowObject() + { + Fields = [fieldObject], + RowId = "1" + }; + var decorator = new RowObjectDecorator(rowObject); + decorator.DisableAllFieldObjects(); + Assert.IsFalse(decorator.Fields[0].Enabled); + Assert.AreEqual(RowActions.Edit, decorator.RowAction); + } + + #endregion } \ No newline at end of file diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs index e7a7c22..d4e525e 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs @@ -96,6 +96,27 @@ public void DeleteRowObject(string rowId) OtherRows = tempDecorator.OtherRows; } + /// + /// Disables all in the . + /// + public void DisableAllFieldObjects() + { + var tempDecorator = Helper.DisableAllFieldObjects(this); + CurrentRow = tempDecorator.CurrentRow; + OtherRows = tempDecorator.OtherRows; + } + + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + public void DisableAllFieldObjects(List excludedFields) + { + var tempDecorator = Helper.DisableAllFieldObjects(this, excludedFields); + CurrentRow = tempDecorator.CurrentRow; + OtherRows = tempDecorator.OtherRows; + } + /// /// Returns the RowId of the . /// diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecoratorHelper.cs index 0618933..3a00e59 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecoratorHelper.cs @@ -407,6 +407,41 @@ public static FormObjectDecorator DeleteRowObject(FormObjectDecorator formObject throw new ArgumentException(resourceManager.GetString("noRowObjectsFoundByRowId", CultureInfo.CurrentCulture), nameof(rowId)); } + /// + /// Disables all in the . + /// + /// + /// + public static FormObjectDecorator DisableAllFieldObjects(FormObjectDecorator formObject) + { + if (formObject == null) + throw new ArgumentNullException(nameof(formObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return DisableAllFieldObjects(formObject, new List()); + } + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + /// + /// + public static FormObjectDecorator DisableAllFieldObjects(FormObjectDecorator formObject, List excludedFields) + { + if (formObject == null) + throw new ArgumentNullException(nameof(formObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (excludedFields == null) + throw new ArgumentNullException(nameof(excludedFields), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + + if (formObject.CurrentRow != null) + { + formObject.CurrentRow.DisableAllFieldObjects(excludedFields); + } + + // Process all OtherRows unconditionally, matching legacy implementation behavior. + // This ensures fields in OtherRows are disabled regardless of the MultipleIteration flag. + formObject.OtherRows.ForEach(r => r.DisableAllFieldObjects(excludedFields)); + + return formObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs index 28739af..39414c2 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs @@ -77,6 +77,17 @@ public OptionObject2015Decorator(OptionObject2015 optionObject) /// public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).Forms; + /// + /// Disables all in the . + /// + public void DisableAllFieldObjects() => Forms = Helper.DisableAllFieldObjects(this).Forms; + + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + public void DisableAllFieldObjects(List excludedFields) => Forms = Helper.DisableAllFieldObjects(this, excludedFields).Forms; + /// /// Returns the CurrentRow RowId of the form matching the FormId. /// diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs index 0ba8292..d3c9293 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs @@ -444,6 +444,37 @@ public static OptionObject2015Decorator DeleteRowObject(OptionObject2015Decorato throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); } + /// + /// Disables all in the . + /// + /// + /// + public static OptionObject2015Decorator DisableAllFieldObjects(OptionObject2015Decorator optionObject) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return DisableAllFieldObjects(optionObject, new List()); + } + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + /// + /// + public static OptionObject2015Decorator DisableAllFieldObjects(OptionObject2015Decorator optionObject, List excludedFields) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture)); + if (optionObject.Forms.Count == 0) + throw new ArgumentException(resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture), nameof(optionObject)); + if (excludedFields == null) + throw new ArgumentNullException(nameof(excludedFields), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + + optionObject.Forms.ForEach(f => f.DisableAllFieldObjects(excludedFields)); + return optionObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs index f678991..fc11de1 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs @@ -76,6 +76,17 @@ public OptionObject2Decorator(OptionObject2 optionObject) /// public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).Forms; + /// + /// Disables all in the . + /// + public void DisableAllFieldObjects() => Forms = Helper.DisableAllFieldObjects(this).Forms; + + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + public void DisableAllFieldObjects(List excludedFields) => Forms = Helper.DisableAllFieldObjects(this, excludedFields).Forms; + /// /// Returns the CurrentRow RowId of the form matching the FormId. /// diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs index e75ec1c..692c409 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs @@ -444,6 +444,37 @@ public static OptionObject2Decorator DeleteRowObject(OptionObject2Decorator opti throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); } + /// + /// Disables all in the . + /// + /// + /// + public static OptionObject2Decorator DisableAllFieldObjects(OptionObject2Decorator optionObject) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return DisableAllFieldObjects(optionObject, new List()); + } + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + /// + /// + public static OptionObject2Decorator DisableAllFieldObjects(OptionObject2Decorator optionObject, List excludedFields) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture)); + if (optionObject.Forms.Count == 0) + throw new ArgumentException(resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture), nameof(optionObject)); + if (excludedFields == null) + throw new ArgumentNullException(nameof(excludedFields), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + + optionObject.Forms.ForEach(f => f.DisableAllFieldObjects(excludedFields)); + return optionObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs index 17a8d51..0d703e6 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs @@ -73,6 +73,17 @@ public OptionObjectDecorator(OptionObject optionObject) /// public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).Forms; + /// + /// Disables all in the . + /// + public void DisableAllFieldObjects() => Forms = Helper.DisableAllFieldObjects(this).Forms; + + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + public void DisableAllFieldObjects(List excludedFields) => Forms = Helper.DisableAllFieldObjects(this, excludedFields).Forms; + /// /// Returns the CurrentRow RowId of the form matching the FormId. /// diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs index 2196424..40193d6 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs @@ -444,6 +444,37 @@ public static OptionObjectDecorator DeleteRowObject(OptionObjectDecorator option throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); } + /// + /// Disables all in the . + /// + /// + /// + public static OptionObjectDecorator DisableAllFieldObjects(OptionObjectDecorator optionObject) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return DisableAllFieldObjects(optionObject, new List()); + } + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + /// + /// + public static OptionObjectDecorator DisableAllFieldObjects(OptionObjectDecorator optionObject, List excludedFields) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture)); + if (optionObject.Forms.Count == 0) + throw new ArgumentException(resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture), nameof(optionObject)); + if (excludedFields == null) + throw new ArgumentNullException(nameof(excludedFields), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + + optionObject.Forms.ForEach(f => f.DisableAllFieldObjects(excludedFields)); + return optionObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs index 981df77..a3a13b6 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs @@ -85,5 +85,22 @@ public RowObjectDecoratorReturnBuilder Return() /// /// public void SetFieldValue(string fieldNumber, string fieldValue) => Fields = Helper.SetFieldValue(this, fieldNumber, fieldValue).Fields; + + /// + /// Disables all in the . + /// + public void DisableAllFieldObjects() + { + Fields = Helper.DisableAllFieldObjects(this).Fields; + } + + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + public void DisableAllFieldObjects(List excludedFields) + { + Fields = Helper.DisableAllFieldObjects(this, excludedFields).Fields; + } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecoratorHelper.cs index a91b94f..d25e8c8 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecoratorHelper.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Reflection; using System.Resources; using RarelySimple.AvatarScriptLink.Net.Exceptions; @@ -189,6 +191,46 @@ public static RowObjectDecorator SetFieldValue(RowObjectDecorator decorator, str } return decorator; } + /// + /// Disables all in the . + /// + /// + /// + public static RowObjectDecorator DisableAllFieldObjects(RowObjectDecorator rowObject) + { + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return DisableAllFieldObjects(rowObject, new List()); + } + /// + /// Disables all in the , except for the FieldNumbers specified in the list. + /// + /// + /// + /// + public static RowObjectDecorator DisableAllFieldObjects(RowObjectDecorator rowObject, List excludedFields) + { + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (excludedFields == null) + throw new ArgumentNullException(nameof(excludedFields), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + + foreach (var field in rowObject.Fields.Where(f => !excludedFields.Contains(f.FieldNumber))) + { + field.Enabled = false; + } + + // Only set RowAction to Edit if it's currently None (no action). + // This preserves existing RowActions like DELETE, ADD, or EDIT: + // - RowActions.None: No action pending (preserve the row; enable Edit mode) + // - RowActions.Add: Adding a new row to the form (don't override) + // - RowActions.Edit: Modifying an existing row (don't override) + // - RowActions.Delete: Removing the row (don't override) + if (rowObject.RowAction == RowActions.None) + rowObject.RowAction = RowActions.Edit; + + return rowObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DisableAllFieldObjectsTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DisableAllFieldObjectsTests.cs index 5dcb7a7..84920ea 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DisableAllFieldObjectsTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DisableAllFieldObjectsTests.cs @@ -103,6 +103,34 @@ public void DisableAllFieldObjects_OptionObject_Null() Assert.ThrowsException(() => (OptionObject)OptionObjectHelpers.DisableAllFieldObjects(null)); } + [TestMethod] + [TestCategory("ScriptLinkHelpers")] + public void DisableAllFieldObjects_OptionObject_NullForms_Throws() + { + var invalidOptionObject = new OptionObject + { + EntityID = "123456", + EpisodeNumber = 1, + OptionId = "USER00", + Forms = null + }; + Assert.ThrowsException(() => (OptionObject)OptionObjectHelpers.DisableAllFieldObjects(invalidOptionObject)); + } + + [TestMethod] + [TestCategory("ScriptLinkHelpers")] + public void DisableAllFieldObjects_OptionObject_NullForms_WithExcludedFields_Throws() + { + var invalidOptionObject = new OptionObject + { + EntityID = "123456", + EpisodeNumber = 1, + OptionId = "USER00", + Forms = null + }; + Assert.ThrowsException(() => (OptionObject)OptionObjectHelpers.DisableAllFieldObjects(invalidOptionObject, new List())); + } + [TestMethod] [TestCategory("ScriptLinkHelpers")] public void DisableAllFieldObjects_OptionObject_EntityID_AreEqual() @@ -429,7 +457,7 @@ public void DisableAllFieldObjects_OptionObject2015_ExcludesFields_NoForms() "2", "4" ]; - Assert.ThrowsException(() => (OptionObject2015)OptionObjectHelpers.DisableAllFieldObjects(optionObject2015, excludedFields)); + Assert.ThrowsException(() => (OptionObject2015)OptionObjectHelpers.DisableAllFieldObjects(optionObject2015, excludedFields)); } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DisableAllFieldObjects.cs b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DisableAllFieldObjects.cs index 972cc55..66c5d1a 100644 --- a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DisableAllFieldObjects.cs +++ b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DisableAllFieldObjects.cs @@ -29,8 +29,10 @@ public static IOptionObject DisableAllFieldObjects(IOptionObject optionObject, L { if (optionObject == null) throw new ArgumentNullException(nameof(optionObject), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (optionObject.Forms.Count == 0) + if (optionObject.Forms == null) throw new ArgumentNullException(nameof(optionObject), ScriptLinkHelpers.GetLocalizedString("optionObjectMissingForms", CultureInfo.CurrentCulture)); + if (optionObject.Forms.Count == 0) + throw new ArgumentException(ScriptLinkHelpers.GetLocalizedString("optionObjectMissingForms", CultureInfo.CurrentCulture), nameof(optionObject)); if (excludedFields == null) throw new ArgumentNullException(nameof(excludedFields), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return DisableAllFieldObjectsByOptionObject(optionObject, excludedFields);