From eb514479256c1da090fe2a126f8f2ce14d7bcf1d Mon Sep 17 00:00:00 2001 From: Scott Olson Jr Date: Fri, 13 Feb 2026 16:44:25 -0800 Subject: [PATCH 1/5] Implement DeleteRowObject functionality in decorators and add corresponding unit tests --- .../Decorators/FormObjectDecoratorTests.cs | 61 +++++++++++++++++++ .../OptionObject2015DecoratorTests.cs | 39 ++++++++++++ .../Decorators/OptionObject2DecoratorTests.cs | 39 ++++++++++++ .../Decorators/OptionObjectDecoratorTests.cs | 39 ++++++++++++ .../Decorators/FormObjectDecorator.cs | 22 +++++++ .../Decorators/FormObjectDecoratorHelper.cs | 43 +++++++++++++ .../Decorators/OptionObject2015Decorator.cs | 6 ++ .../OptionObject2015DecoratorHelper.cs | 29 +++++++++ .../Decorators/OptionObject2Decorator.cs | 7 +++ .../OptionObject2DecoratorHelper.cs | 29 +++++++++ .../Decorators/OptionObjectDecorator.cs | 7 +++ .../Decorators/OptionObjectDecoratorHelper.cs | 29 +++++++++ .../Helpers/OptionObject/DeleteRowObject.cs | 22 +++---- 13 files changed, 359 insertions(+), 13 deletions(-) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs index eb8cefd9..4ebc237e 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs @@ -1036,6 +1036,67 @@ public void TestFormObjectDecorator_GetNextAvailableRowId_WithExistingRows() #endregion + #region DeleteRowObject + + [TestMethod] + public void TestFormObjectDecorator_DeleteRowObject_CurrentRow() + { + var rowObject = new RowObject() + { + RowId = "1||1" + }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = rowObject + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DeleteRowObject("1||1"); + Assert.AreEqual(RowActions.Delete, decorator.CurrentRow.RowAction); + } + + [TestMethod] + public void TestFormObjectDecorator_DeleteRowObject_OtherRow() + { + var row1 = new RowObject() { RowId = "1||1" }; + var row2 = new RowObject() { RowId = "1||2" }; + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = row1, + MultipleIteration = true, + OtherRows = [row2] + }; + var decorator = new FormObjectDecorator(formObject); + decorator.DeleteRowObject("1||2"); + Assert.AreEqual(RowActions.Delete, decorator.OtherRows[0].RowAction); + } + + [TestMethod] + public void TestFormObjectDecorator_DeleteRowObject_NullRowId() + { + var formObject = new FormObject() + { + FormId = "1" + }; + var decorator = new FormObjectDecorator(formObject); + Assert.ThrowsException(() => decorator.DeleteRowObject((string)null)); + } + + [TestMethod] + public void TestFormObjectDecorator_DeleteRowObject_NotFound() + { + var formObject = new FormObject() + { + FormId = "1", + CurrentRow = new RowObject() { RowId = "1||1" } + }; + var decorator = new FormObjectDecorator(formObject); + Assert.ThrowsException(() => decorator.DeleteRowObject("1||2")); + } + + #endregion + #region Edge Case Tests - Regression & Coverage [TestMethod] diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs index 158aacad..ab30db2c 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs @@ -1389,6 +1389,45 @@ public void IsRowMarkedForDeletion_NullRowId() #endregion + #region DeleteRowObject + + [TestMethod] + public void TestOptionObject2015Decorator_DeleteRowObject_CurrentRow() + { + var rowObject = new RowObject() + { + RowId = "456||1" + }; + var formObject = new FormObject() + { + FormId = "456", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DeleteRowObject("456", "456||1"); + Assert.AreEqual(RowActions.Delete, decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void TestOptionObject2015Decorator_DeleteRowObject_Errors() + { + var optionObject = new OptionObject2015() + { + OptionId = "TEST123" + }; + var decorator = new OptionObject2015Decorator(optionObject); + Assert.ThrowsException(() => decorator.DeleteRowObject(null, "1||1")); + Assert.ThrowsException(() => decorator.DeleteRowObject("456", null)); + Assert.ThrowsException(() => decorator.DeleteRowObject("999", "1||1")); + } + + #endregion + #region IsRowPresent [TestMethod] diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs index 8201f4ad..ad45e688 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs @@ -1406,6 +1406,45 @@ public void IsRowMarkedForDeletion_NullRowId() #endregion + #region DeleteRowObject + + [TestMethod] + public void TestOptionObject2Decorator_DeleteRowObject_CurrentRow() + { + var rowObject = new RowObject() + { + RowId = "456||1" + }; + var formObject = new FormObject() + { + FormId = "456", + CurrentRow = rowObject + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DeleteRowObject("456", "456||1"); + Assert.AreEqual(RowActions.Delete, decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void TestOptionObject2Decorator_DeleteRowObject_Errors() + { + var optionObject = new OptionObject2() + { + OptionId = "TEST123" + }; + var decorator = new OptionObject2Decorator(optionObject); + Assert.ThrowsException(() => decorator.DeleteRowObject(null, "1||1")); + Assert.ThrowsException(() => decorator.DeleteRowObject("456", null)); + Assert.ThrowsException(() => decorator.DeleteRowObject("999", "1||1")); + } + + #endregion + #region IsRowPresent [TestMethod] diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs index 91ada853..d2c757a2 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs @@ -1389,6 +1389,45 @@ public void IsRowMarkedForDeletion_NullRowId() #endregion + #region DeleteRowObject + + [TestMethod] + public void TestOptionObjectDecorator_DeleteRowObject_CurrentRow() + { + var rowObject = new RowObject() + { + RowId = "456||1" + }; + var formObject = new FormObject() + { + FormId = "456", + CurrentRow = rowObject + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DeleteRowObject("456", "456||1"); + Assert.AreEqual(RowActions.Delete, decorator.Forms[0].CurrentRow.RowAction); + } + + [TestMethod] + public void TestOptionObjectDecorator_DeleteRowObject_Errors() + { + var optionObject = new OptionObject() + { + OptionId = "TEST123" + }; + var decorator = new OptionObjectDecorator(optionObject); + Assert.ThrowsException(() => decorator.DeleteRowObject(null, "1||1")); + Assert.ThrowsException(() => decorator.DeleteRowObject("456", null)); + Assert.ThrowsException(() => decorator.DeleteRowObject("999", "1||1")); + } + + #endregion + #region IsRowPresent [TestMethod] diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs index 98649bdf..112c54b1 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs @@ -71,6 +71,28 @@ public void AddRowObject(string rowId, string parentRowId, string rowAction) OtherRows = tempDecorator.OtherRows; } + /// + /// Flags a for deletion in a . + /// + /// + public void DeleteRowObject(RowObject rowObject) + { + var tempDecorator = Helper.DeleteRowObject(this, rowObject); + CurrentRow = tempDecorator.CurrentRow; + OtherRows = tempDecorator.OtherRows; + } + + /// + /// Flags a for deletion in a by RowId. + /// + /// + public void DeleteRowObject(string rowId) + { + var tempDecorator = Helper.DeleteRowObject(this, rowId); + 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 320e1c56..06189337 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecoratorHelper.cs @@ -364,6 +364,49 @@ public static FormObjectDecorator AddRowObject(FormObjectDecorator formObject, s }; return AddRowObject(formObject, rowObject); } + /// + /// Flags a for deletion in a . + /// + /// + /// + /// + public static FormObjectDecorator DeleteRowObject(FormObjectDecorator formObject, RowObject rowObject) + { + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return DeleteRowObject(formObject, rowObject.RowId); + } + /// + /// Flags a for deletion in a by RowId. + /// + /// + /// + /// + public static FormObjectDecorator DeleteRowObject(FormObjectDecorator formObject, string rowId) + { + if (formObject == null) + throw new ArgumentNullException(nameof(formObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(rowId)) + throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + + if (formObject.CurrentRow?.RowId == rowId) + { + formObject.CurrentRow.RowAction = RowActions.Delete; + return formObject; + } + + if (formObject.MultipleIteration) + { + int rowIndex = formObject.OtherRows.FindIndex(r => r.RowId == rowId); + if (rowIndex >= 0) + { + formObject.OtherRows[rowIndex].RowAction = RowActions.Delete; + return formObject; + } + } + + throw new ArgumentException(resourceManager.GetString("noRowObjectsFoundByRowId", CultureInfo.CurrentCulture), nameof(rowId)); + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs index 25058d1d..35eea4ab 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs @@ -67,6 +67,12 @@ public OptionObject2015Decorator(OptionObject2015 optionObject) /// public void AddRowObject(string formId, RowObject rowObject) => Forms = Helper.AddRowObject(this, formId, rowObject).Forms; + /// + /// Flags a for deletion in a specified within the by RowId. + /// + /// + /// + public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).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 d3ce2fa9..0215bf1e 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs @@ -414,6 +414,35 @@ public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator o } return optionObject; } + /// + /// Flags a for deletion in a specified within the by RowId. + /// + /// + /// + /// + /// + public static OptionObject2015Decorator DeleteRowObject(OptionObject2015Decorator optionObject, string formId, string rowId) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(rowId)) + throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms.Exists(f => f.FormId == formId)) + { + int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); + if (formIndex >= 0) + { + optionObject.Forms[formIndex].DeleteRowObject(rowId); + } + } + else + { + throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); + } + return optionObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs index 1d27ddc5..118d4900 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs @@ -66,6 +66,13 @@ public OptionObject2Decorator(OptionObject2 optionObject) /// public void AddRowObject(string formId, RowObject rowObject) => Forms = Helper.AddRowObject(this, formId, rowObject).Forms; + /// + /// Flags a for deletion in a specified within the by RowId. + /// + /// + /// + public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).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 dacebd72..a2c76a90 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs @@ -414,6 +414,35 @@ public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionO } return optionObject; } + /// + /// Flags a for deletion in a specified within the by RowId. + /// + /// + /// + /// + /// + public static OptionObject2Decorator DeleteRowObject(OptionObject2Decorator optionObject, string formId, string rowId) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(rowId)) + throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms.Exists(f => f.FormId == formId)) + { + int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); + if (formIndex >= 0) + { + optionObject.Forms[formIndex].DeleteRowObject(rowId); + } + } + else + { + throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); + } + return optionObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs index 4497a2c9..fde701f9 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs @@ -63,6 +63,13 @@ public OptionObjectDecorator(OptionObject optionObject) /// public void AddRowObject(string formId, RowObject rowObject) => Forms = Helper.AddRowObject(this, formId, rowObject).Forms; + /// + /// Flags a for deletion in a specified within the by RowId. + /// + /// + /// + public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).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 bc132249..8cdced43 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs @@ -414,6 +414,35 @@ public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObj } return optionObject; } + /// + /// Flags a for deletion in a specified within the by RowId. + /// + /// + /// + /// + /// + public static OptionObjectDecorator DeleteRowObject(OptionObjectDecorator optionObject, string formId, string rowId) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(rowId)) + throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms.Exists(f => f.FormId == formId)) + { + int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); + if (formIndex >= 0) + { + optionObject.Forms[formIndex].DeleteRowObject(rowId); + } + } + else + { + throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); + } + return optionObject; + } } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs index 19f2782a..cb3a0d36 100644 --- a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs +++ b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs @@ -19,7 +19,7 @@ public static IOptionObject DeleteRowObject(IOptionObject optionObject, IRowObje return DeleteRowObject(optionObject, rowObject.RowId); } /// - /// Flags a for deletion in specified by RowId. + /// Flags a for deletion in specified by RowId. /// /// /// @@ -28,13 +28,11 @@ public static IOptionObject DeleteRowObject(IOptionObject optionObject, string r { if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - for (int i = 0; i < optionObject.Forms.Count; i++) + int formIndex = optionObject.Forms.FindIndex(f => IsRowPresent(f, rowId)); + if (formIndex >= 0) { - if (IsRowPresent(optionObject.Forms[i], rowId)) - { - optionObject.Forms[i] = (FormObject)DeleteRowObject(optionObject.Forms[i], rowId); - return optionObject; - } + optionObject.Forms[formIndex] = (FormObject)DeleteRowObject(optionObject.Forms[formIndex], rowId); + return optionObject; } throw new ArgumentException(ScriptLinkHelpers.GetLocalizedString("noRowObjectsFoundByRowId", CultureInfo.CurrentCulture), nameof(rowId)); } @@ -65,13 +63,11 @@ public static IFormObject DeleteRowObject(IFormObject formObject, string rowId) } if (formObject.MultipleIteration) { - foreach (RowObject rowObject in formObject.OtherRows) + int rowIndex = formObject.OtherRows.FindIndex(r => r.RowId == rowId); + if (rowIndex >= 0) { - if (rowObject.RowId == rowId) - { - rowObject.RowAction = RowAction.Delete; - return formObject; - } + formObject.OtherRows[rowIndex].RowAction = RowAction.Delete; + return formObject; } } throw new ArgumentException(ScriptLinkHelpers.GetLocalizedString("noRowObjectsFoundByRowId", CultureInfo.CurrentCulture), nameof(rowId)); From 47dce4e5813f326bf2e9bbc04d300e6d1aa6f147 Mon Sep 17 00:00:00 2001 From: Scott Olson Jr Date: Fri, 13 Feb 2026 16:53:39 -0800 Subject: [PATCH 2/5] Refactor AddRowObject and DeleteRowObject methods to use a common ExecuteOnForm helper for improved code reuse and clarity --- .../OptionObject2015DecoratorHelper.cs | 47 ++++++++++--------- .../OptionObject2DecoratorHelper.cs | 47 ++++++++++--------- .../Decorators/OptionObjectDecoratorHelper.cs | 47 ++++++++++--------- 3 files changed, 72 insertions(+), 69 deletions(-) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs index 0215bf1e..7e276f3f 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs @@ -386,26 +386,22 @@ public static OptionObject2015Decorator SetFieldValue(OptionObject2015Decorator return decorator; } /// - /// Adds a to a specified within provided . + /// Executes an operation on a form within the OptionObject2015Decorator by FormId. /// /// /// - /// + /// /// - public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator optionObject, string formId, RowObject rowObject) + private static OptionObject2015Decorator ExecuteOnForm(OptionObject2015Decorator optionObject, string formId, Action action) { - if (optionObject == null) - throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (rowObject == null) - throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture)); if (optionObject.Forms.Exists(f => f.FormId == formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); if (formIndex >= 0) { - optionObject.Forms[formIndex].AddRowObject(rowObject); + action(optionObject.Forms[formIndex]); } } else @@ -415,6 +411,23 @@ public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator o return optionObject; } /// + /// Adds a to a specified within provided . + /// + /// + /// + /// + /// + public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator optionObject, string formId, RowObject rowObject) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); + } + /// /// Flags a for deletion in a specified within the by RowId. /// /// @@ -429,19 +442,7 @@ public static OptionObject2015Decorator DeleteRowObject(OptionObject2015Decorato throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (optionObject.Forms.Exists(f => f.FormId == formId)) - { - int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); - if (formIndex >= 0) - { - optionObject.Forms[formIndex].DeleteRowObject(rowId); - } - } - else - { - throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); - } - return optionObject; + return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs index a2c76a90..250e43df 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs @@ -386,26 +386,22 @@ public static OptionObject2Decorator SetFieldValue(OptionObject2Decorator decora return decorator; } /// - /// Adds a to a specified within provided . + /// Executes an operation on a form within the OptionObject2Decorator by FormId. /// /// /// - /// + /// /// - public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionObject, string formId, RowObject rowObject) + private static OptionObject2Decorator ExecuteOnForm(OptionObject2Decorator optionObject, string formId, Action action) { - if (optionObject == null) - throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (rowObject == null) - throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture)); if (optionObject.Forms.Exists(f => f.FormId == formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); if (formIndex >= 0) { - optionObject.Forms[formIndex].AddRowObject(rowObject); + action(optionObject.Forms[formIndex]); } } else @@ -415,6 +411,23 @@ public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionO return optionObject; } /// + /// Adds a to a specified within provided . + /// + /// + /// + /// + /// + public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionObject, string formId, RowObject rowObject) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); + } + /// /// Flags a for deletion in a specified within the by RowId. /// /// @@ -429,19 +442,7 @@ public static OptionObject2Decorator DeleteRowObject(OptionObject2Decorator opti throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (optionObject.Forms.Exists(f => f.FormId == formId)) - { - int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); - if (formIndex >= 0) - { - optionObject.Forms[formIndex].DeleteRowObject(rowId); - } - } - else - { - throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); - } - return optionObject; + return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs index 8cdced43..9e371bb7 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs @@ -386,26 +386,22 @@ public static OptionObjectDecorator SetFieldValue(OptionObjectDecorator decorato return decorator; } /// - /// Adds a to a specified within provided . + /// Executes an operation on a form within the OptionObjectDecorator by FormId. /// /// /// - /// + /// /// - public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObject, string formId, RowObject rowObject) + private static OptionObjectDecorator ExecuteOnForm(OptionObjectDecorator optionObject, string formId, Action action) { - if (optionObject == null) - throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (rowObject == null) - throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(OptionObjectMissingForms, CultureInfo.CurrentCulture)); if (optionObject.Forms.Exists(f => f.FormId == formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); if (formIndex >= 0) { - optionObject.Forms[formIndex].AddRowObject(rowObject); + action(optionObject.Forms[formIndex]); } } else @@ -415,6 +411,23 @@ public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObj return optionObject; } /// + /// Adds a to a specified within provided . + /// + /// + /// + /// + /// + public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObject, string formId, RowObject rowObject) + { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); + } + /// /// Flags a for deletion in a specified within the by RowId. /// /// @@ -429,19 +442,7 @@ public static OptionObjectDecorator DeleteRowObject(OptionObjectDecorator option throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); - if (optionObject.Forms.Exists(f => f.FormId == formId)) - { - int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); - if (formIndex >= 0) - { - optionObject.Forms[formIndex].DeleteRowObject(rowId); - } - } - else - { - throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); - } - return optionObject; + return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); } } } From 9c84eb488f14e8f5ee098881e49e744eeefe6c3c Mon Sep 17 00:00:00 2001 From: Scott Olson Jr Date: Fri, 13 Feb 2026 16:57:48 -0800 Subject: [PATCH 3/5] Enhance error handling in OptionObject decorators by adding null checks for Forms property --- .../Decorators/OptionObject2015DecoratorHelper.cs | 6 +++++- .../Decorators/OptionObject2DecoratorHelper.cs | 6 +++++- .../Decorators/OptionObjectDecoratorHelper.cs | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs index 7e276f3f..c5543818 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs @@ -406,7 +406,7 @@ private static OptionObject2015Decorator ExecuteOnForm(OptionObject2015Decorator } else { - throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); + throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(formId)); } return optionObject; } @@ -421,6 +421,8 @@ public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator o { 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 (string.IsNullOrEmpty(formId)) throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) @@ -438,6 +440,8 @@ public static OptionObject2015Decorator DeleteRowObject(OptionObject2015Decorato { 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 (string.IsNullOrEmpty(formId)) throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs index 250e43df..f28abf20 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs @@ -406,7 +406,7 @@ private static OptionObject2Decorator ExecuteOnForm(OptionObject2Decorator optio } else { - throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); + throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(formId)); } return optionObject; } @@ -421,6 +421,8 @@ public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionO { 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 (string.IsNullOrEmpty(formId)) throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) @@ -438,6 +440,8 @@ public static OptionObject2Decorator DeleteRowObject(OptionObject2Decorator opti { 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 (string.IsNullOrEmpty(formId)) throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs index 9e371bb7..9e03ab99 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs @@ -406,7 +406,7 @@ private static OptionObjectDecorator ExecuteOnForm(OptionObjectDecorator optionO } else { - throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(optionObject)); + throw new ArgumentException(resourceManager.GetString("noFormObjectsFoundByFormId", CultureInfo.CurrentCulture), nameof(formId)); } return optionObject; } @@ -421,6 +421,8 @@ public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObj { 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 (string.IsNullOrEmpty(formId)) throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) @@ -438,6 +440,8 @@ public static OptionObjectDecorator DeleteRowObject(OptionObjectDecorator option { 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 (string.IsNullOrEmpty(formId)) throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) From 4734d0bfef7c3a74d04c064af526749b2e400ce2 Mon Sep 17 00:00:00 2001 From: Scott Olson Jr Date: Fri, 13 Feb 2026 17:13:25 -0800 Subject: [PATCH 4/5] Add null checks for optionObject and formId in ExecuteOnForm method across decorators --- .../OptionObject2015DecoratorHelper.cs | 16 ++++------------ .../Decorators/OptionObject2DecoratorHelper.cs | 16 ++++------------ .../Decorators/OptionObjectDecoratorHelper.cs | 16 ++++------------ 3 files changed, 12 insertions(+), 36 deletions(-) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs index c5543818..663748da 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs @@ -394,8 +394,12 @@ public static OptionObject2015Decorator SetFieldValue(OptionObject2015Decorator /// private static OptionObject2015Decorator ExecuteOnForm(OptionObject2015Decorator optionObject, string formId, Action action) { + 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 (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (optionObject.Forms.Exists(f => f.FormId == formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); @@ -419,12 +423,6 @@ private static OptionObject2015Decorator ExecuteOnForm(OptionObject2015Decorator /// public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator optionObject, string formId, RowObject rowObject) { - 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 (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); @@ -438,12 +436,6 @@ public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator o /// public static OptionObject2015Decorator DeleteRowObject(OptionObject2015Decorator optionObject, string formId, string rowId) { - 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 (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs index f28abf20..0be2f748 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs @@ -394,8 +394,12 @@ public static OptionObject2Decorator SetFieldValue(OptionObject2Decorator decora /// private static OptionObject2Decorator ExecuteOnForm(OptionObject2Decorator optionObject, string formId, Action action) { + 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 (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (optionObject.Forms.Exists(f => f.FormId == formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); @@ -419,12 +423,6 @@ private static OptionObject2Decorator ExecuteOnForm(OptionObject2Decorator optio /// public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionObject, string formId, RowObject rowObject) { - 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 (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); @@ -438,12 +436,6 @@ public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionO /// public static OptionObject2Decorator DeleteRowObject(OptionObject2Decorator optionObject, string formId, string rowId) { - 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 (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs index 9e03ab99..2434357f 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs @@ -394,8 +394,12 @@ public static OptionObjectDecorator SetFieldValue(OptionObjectDecorator decorato /// private static OptionObjectDecorator ExecuteOnForm(OptionObjectDecorator optionObject, string formId, Action action) { + 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 (string.IsNullOrEmpty(formId)) + throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (optionObject.Forms.Exists(f => f.FormId == formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); @@ -419,12 +423,6 @@ private static OptionObjectDecorator ExecuteOnForm(OptionObjectDecorator optionO /// public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObject, string formId, RowObject rowObject) { - 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 (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); @@ -438,12 +436,6 @@ public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObj /// public static OptionObjectDecorator DeleteRowObject(OptionObjectDecorator optionObject, string formId, string rowId) { - 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 (string.IsNullOrEmpty(formId)) - throw new ArgumentNullException(nameof(formId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); From 0ccccb033910ff52d296a9fee3107af2073bcefc Mon Sep 17 00:00:00 2001 From: Scott Olson Jr Date: Fri, 13 Feb 2026 18:03:03 -0800 Subject: [PATCH 5/5] Add null checks for decorators and enhance DeleteRowObject functionality with corresponding tests --- .../Decorators/FieldObjectDecoratorTests.cs | 10 +++++ .../Decorators/FormObjectDecoratorTests.cs | 10 +++++ .../OptionObject2015DecoratorTests.cs | 42 ++++++++++++++----- .../Decorators/OptionObject2DecoratorTests.cs | 42 ++++++++++++++----- .../Decorators/OptionObjectDecoratorTests.cs | 42 ++++++++++++++----- .../Decorators/RowObjectDecoratorTests.cs | 10 +++++ .../Decorators/FieldObjectDecorator.cs | 3 ++ .../Decorators/FormObjectDecorator.cs | 3 ++ .../Decorators/OptionObject2015Decorator.cs | 4 ++ .../OptionObject2015DecoratorHelper.cs | 4 ++ .../Decorators/OptionObject2Decorator.cs | 3 ++ .../OptionObject2DecoratorHelper.cs | 4 ++ .../Decorators/OptionObjectDecorator.cs | 3 ++ .../Decorators/OptionObjectDecoratorHelper.cs | 4 ++ .../Decorators/RowObjectDecorator.cs | 3 ++ .../Helpers/OptionObject/AddRowObjectTests.cs | 13 ++++++ .../OptionObject/DeleteRowObjectTests.cs | 36 +++++++++++++++- .../Helpers/OptionObject/AddRowObject.cs | 2 + .../Helpers/OptionObject/DeleteRowObject.cs | 10 +++++ 19 files changed, 217 insertions(+), 31 deletions(-) diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FieldObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FieldObjectDecoratorTests.cs index 8a511e2a..c9202ecc 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FieldObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FieldObjectDecoratorTests.cs @@ -6,6 +6,16 @@ namespace RarelySimple.AvatarScriptLink.Net.Tests.Decorators [TestClass] public class FieldObjectDecoratorTests { + #region Constructor + + [TestMethod] + public void TestFieldObjectDecorator_Constructor_NullFieldObject() + { + Assert.ThrowsException(() => new FieldObjectDecorator((FieldObject)null)); + } + + #endregion + [TestMethod] public void TestFieldObjectIsNotModified() { diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs index 4ebc237e..45184741 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/FormObjectDecoratorTests.cs @@ -8,6 +8,16 @@ namespace RarelySimple.AvatarScriptLink.Net.Tests.Decorators; [TestClass] public class FormObjectDecoratorTests { + #region Constructor + + [TestMethod] + public void TestFormObjectDecorator_Constructor_NullFormObject() + { + Assert.ThrowsException(() => new FormObjectDecorator(null)); + } + + #endregion + [TestMethod] public void TestFormObjectDecorator_ReturnsNoRows() { diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs index ab30db2c..8a082165 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2015DecoratorTests.cs @@ -8,6 +8,16 @@ namespace RarelySimple.AvatarScriptLink.Net.Tests.Decorators; [TestClass] public class OptionObject2015DecoratorTests { + #region Constructor + + [TestMethod] + public void TestOptionObject2015Decorator_Constructor_NullOptionObject() + { + Assert.ThrowsException(() => new OptionObject2015Decorator(null)); + } + + #endregion + [TestMethod] public void TestOptionObject2015Decorator_ReturnsNoForms() { @@ -1426,6 +1436,28 @@ public void TestOptionObject2015Decorator_DeleteRowObject_Errors() Assert.ThrowsException(() => decorator.DeleteRowObject("999", "1||1")); } + [TestMethod] + public void TestOptionObject2015Decorator_DeleteRowObject_OtherRow() + { + var row1 = new RowObject() { RowId = "456||1" }; + var row2 = new RowObject() { RowId = "456||2" }; + var formObject = new FormObject() + { + FormId = "456", + CurrentRow = row1, + MultipleIteration = true, + OtherRows = [row2] + }; + var optionObject = new OptionObject2015() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2015Decorator(optionObject); + decorator.DeleteRowObject("456", "456||2"); + Assert.AreEqual(RowActions.Delete, decorator.Forms[0].OtherRows[0].RowAction); + } + #endregion #region IsRowPresent @@ -1680,15 +1712,5 @@ public void TestOptionObject2015Decorator_Constructor_WithEmptyFormsCollection() Assert.AreEqual(0, decorator.Forms.Count); } - [TestMethod] - public void TestOptionObject2015Decorator_AddRowObject_RegressionNullFormIdHandling() - { - var formObject = new FormObject() { FormId = "1", MultipleIteration = true }; - var optionObject = new OptionObject2015() { OptionId = "TEST123", Forms = [formObject] }; - var decorator = new OptionObject2015Decorator(optionObject); - var rowObject = new RowObject(); - Assert.ThrowsException(() => decorator.AddRowObject(null, rowObject)); - } - #endregion } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs index ad45e688..3d771098 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObject2DecoratorTests.cs @@ -8,6 +8,16 @@ namespace RarelySimple.AvatarScriptLink.Net.Tests.Decorators; [TestClass] public class OptionObject2DecoratorTests { + #region Constructor + + [TestMethod] + public void TestOptionObject2Decorator_Constructor_NullOptionObject() + { + Assert.ThrowsException(() => new OptionObject2Decorator(null)); + } + + #endregion + [TestMethod] public void TestOptionObject2Decorator_ReturnsNoForms() { @@ -1443,6 +1453,28 @@ public void TestOptionObject2Decorator_DeleteRowObject_Errors() Assert.ThrowsException(() => decorator.DeleteRowObject("999", "1||1")); } + [TestMethod] + public void TestOptionObject2Decorator_DeleteRowObject_OtherRow() + { + var row1 = new RowObject() { RowId = "456||1" }; + var row2 = new RowObject() { RowId = "456||2" }; + var formObject = new FormObject() + { + FormId = "456", + CurrentRow = row1, + MultipleIteration = true, + OtherRows = [row2] + }; + var optionObject = new OptionObject2() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObject2Decorator(optionObject); + decorator.DeleteRowObject("456", "456||2"); + Assert.AreEqual(RowActions.Delete, decorator.Forms[0].OtherRows[0].RowAction); + } + #endregion #region IsRowPresent @@ -1697,15 +1729,5 @@ public void TestOptionObject2Decorator_Constructor_WithEmptyFormsCollection() Assert.AreEqual(0, decorator.Forms.Count); } - [TestMethod] - public void TestOptionObject2Decorator_AddRowObject_RegressionNullFormIdHandling() - { - var formObject = new FormObject() { FormId = "1", MultipleIteration = true }; - var optionObject = new OptionObject2() { OptionId = "TEST123", Forms = [formObject] }; - var decorator = new OptionObject2Decorator(optionObject); - var rowObject = new RowObject(); - Assert.ThrowsException(() => decorator.AddRowObject(null, rowObject)); - } - #endregion } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs index d2c757a2..b012985d 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/OptionObjectDecoratorTests.cs @@ -8,6 +8,16 @@ namespace RarelySimple.AvatarScriptLink.Net.Tests.Decorators; [TestClass] public class OptionObjectDecoratorTests { + #region Constructor + + [TestMethod] + public void TestOptionObjectDecorator_Constructor_NullOptionObject() + { + Assert.ThrowsException(() => new OptionObjectDecorator(null)); + } + + #endregion + [TestMethod] public void TestOptionObjectDecorator_ReturnsNoForms() { @@ -1426,6 +1436,28 @@ public void TestOptionObjectDecorator_DeleteRowObject_Errors() Assert.ThrowsException(() => decorator.DeleteRowObject("999", "1||1")); } + [TestMethod] + public void TestOptionObjectDecorator_DeleteRowObject_OtherRow() + { + var row1 = new RowObject() { RowId = "456||1" }; + var row2 = new RowObject() { RowId = "456||2" }; + var formObject = new FormObject() + { + FormId = "456", + CurrentRow = row1, + MultipleIteration = true, + OtherRows = [row2] + }; + var optionObject = new OptionObject() + { + OptionId = "TEST123", + Forms = [formObject] + }; + var decorator = new OptionObjectDecorator(optionObject); + decorator.DeleteRowObject("456", "456||2"); + Assert.AreEqual(RowActions.Delete, decorator.Forms[0].OtherRows[0].RowAction); + } + #endregion #region IsRowPresent @@ -1698,15 +1730,5 @@ public void TestOptionObjectDecorator_Constructor_WithEmptyFormsCollection() Assert.AreEqual(0, decorator.Forms.Count); } - [TestMethod] - public void TestOptionObjectDecorator_AddRowObject_RegressionNullFormIdHandling() - { - var formObject = new FormObject() { FormId = "1", MultipleIteration = true }; - var optionObject = new OptionObject() { OptionId = "TEST123", Forms = [formObject] }; - var decorator = new OptionObjectDecorator(optionObject); - var rowObject = new RowObject(); - Assert.ThrowsException(() => decorator.AddRowObject(null, rowObject)); - } - #endregion } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs index 938f477f..819b5133 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net.Tests/Decorators/RowObjectDecoratorTests.cs @@ -8,6 +8,16 @@ namespace RarelySimple.AvatarScriptLink.Net.Tests.Decorators; [TestClass] public class RowObjectDecoratorTests { + #region Constructor + + [TestMethod] + public void TestRowObjectDecorator_Constructor_NullRowObject() + { + Assert.ThrowsException(() => new RowObjectDecorator(null)); + } + + #endregion + [TestMethod] public void TestRowObjectDecorator_ReturnsNoFields() { diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FieldObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FieldObjectDecorator.cs index 09d61e6a..9d23c98b 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FieldObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FieldObjectDecorator.cs @@ -1,4 +1,5 @@ using RarelySimple.AvatarScriptLink.Objects; +using System; namespace RarelySimple.AvatarScriptLink.Net.Decorators { @@ -34,6 +35,8 @@ public FieldObjectDecorator(string fieldNumber) public FieldObjectDecorator(FieldObject fieldObject) { + if (fieldObject == null) + throw new ArgumentNullException(nameof(fieldObject)); _fieldObject = fieldObject; Enabled = fieldObject.IsEnabled(); FieldNumber = fieldObject.FieldNumber; diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs index 112c54b1..e7a7c225 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/FormObjectDecorator.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using RarelySimple.AvatarScriptLink.Objects; @@ -12,6 +13,8 @@ public sealed partial class FormObjectDecorator public FormObjectDecorator(FormObject formObject) { + if (formObject == null) + throw new ArgumentNullException(nameof(formObject)); _formObject = formObject; if (formObject.CurrentRow != null) CurrentRow = new RowObjectDecorator(formObject.CurrentRow); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs index 35eea4ab..28739afd 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015Decorator.cs @@ -1,5 +1,6 @@ using RarelySimple.AvatarScriptLink.Objects; using RarelySimple.AvatarScriptLink.Objects.Advanced.Interfaces; +using System; using System.Collections.Generic; namespace RarelySimple.AvatarScriptLink.Net.Decorators @@ -14,6 +15,8 @@ public sealed partial class OptionObject2015Decorator public OptionObject2015Decorator(OptionObject2015 optionObject) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject)); _optionObject = optionObject.Clone(); Forms = new List(); @@ -73,6 +76,7 @@ public OptionObject2015Decorator(OptionObject2015 optionObject) /// /// public void DeleteRowObject(string formId, string rowId) => Forms = Helper.DeleteRowObject(this, formId, rowId).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 663748da..0ba8292a 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2015DecoratorHelper.cs @@ -423,6 +423,8 @@ private static OptionObject2015Decorator ExecuteOnForm(OptionObject2015Decorator /// public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator optionObject, string formId, RowObject rowObject) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); @@ -436,6 +438,8 @@ public static OptionObject2015Decorator AddRowObject(OptionObject2015Decorator o /// public static OptionObject2015Decorator DeleteRowObject(OptionObject2015Decorator optionObject, string formId, string rowId) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs index 118d4900..f6789915 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2Decorator.cs @@ -1,5 +1,6 @@ using RarelySimple.AvatarScriptLink.Objects; using RarelySimple.AvatarScriptLink.Objects.Advanced.Interfaces; +using System; using System.Collections.Generic; namespace RarelySimple.AvatarScriptLink.Net.Decorators @@ -14,6 +15,8 @@ public sealed partial class OptionObject2Decorator public OptionObject2Decorator(OptionObject2 optionObject) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject)); _optionObject = optionObject.Clone(); Forms = new List(); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs index 0be2f748..e75ec1c1 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObject2DecoratorHelper.cs @@ -423,6 +423,8 @@ private static OptionObject2Decorator ExecuteOnForm(OptionObject2Decorator optio /// public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionObject, string formId, RowObject rowObject) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); @@ -436,6 +438,8 @@ public static OptionObject2Decorator AddRowObject(OptionObject2Decorator optionO /// public static OptionObject2Decorator DeleteRowObject(OptionObject2Decorator optionObject, string formId, string rowId) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs index fde701f9..17a8d51c 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecorator.cs @@ -1,5 +1,6 @@ using RarelySimple.AvatarScriptLink.Objects; using RarelySimple.AvatarScriptLink.Objects.Advanced.Interfaces; +using System; using System.Collections.Generic; namespace RarelySimple.AvatarScriptLink.Net.Decorators @@ -14,6 +15,8 @@ public sealed partial class OptionObjectDecorator public OptionObjectDecorator(OptionObject optionObject) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject)); _optionObject = optionObject.Clone(); Forms = new List(); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs index 2434357f..21964244 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/OptionObjectDecoratorHelper.cs @@ -423,6 +423,8 @@ private static OptionObjectDecorator ExecuteOnForm(OptionObjectDecorator optionO /// public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObject, string formId, RowObject rowObject) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.AddRowObject(rowObject)); @@ -436,6 +438,8 @@ public static OptionObjectDecorator AddRowObject(OptionObjectDecorator optionObj /// public static OptionObjectDecorator DeleteRowObject(OptionObjectDecorator optionObject, string formId, string rowId) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), resourceManager.GetString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return ExecuteOnForm(optionObject, formId, form => form.DeleteRowObject(rowId)); diff --git a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs index 9f455ab4..981df774 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Net/Decorators/RowObjectDecorator.cs @@ -1,4 +1,5 @@ using RarelySimple.AvatarScriptLink.Objects; +using System; using System.Collections.Generic; namespace RarelySimple.AvatarScriptLink.Net.Decorators @@ -12,6 +13,8 @@ public sealed partial class RowObjectDecorator public RowObjectDecorator(RowObject rowObject) { + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject)); _rowObject = rowObject; RowAction = rowObject.RowAction; diff --git a/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/AddRowObjectTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/AddRowObjectTests.cs index 7b26d892..10ff4a90 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/AddRowObjectTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/AddRowObjectTests.cs @@ -349,5 +349,18 @@ public void AddRowObject_TooManyRowsAdded() Assert.ThrowsException(() => formObject.AddRowObject(new RowObject())); } + + [TestMethod] + public void AddRowObject_OptionObject_NullOptionObject() + { + Assert.ThrowsException(() => OptionObjectHelpers.AddRowObject((OptionObject)null, "1", new RowObject())); + } + + [TestMethod] + public void AddRowObject_OptionObject_NullForms() + { + OptionObject optionObject = new() { Forms = null }; + Assert.ThrowsException(() => optionObject.AddRowObject("1", new RowObject())); + } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DeleteRowObjectTests.cs b/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DeleteRowObjectTests.cs index 0a3e6aea..331f3599 100644 --- a/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DeleteRowObjectTests.cs +++ b/dotnet/RarelySimple.AvatarScriptLink.Tests/Helpers/OptionObject/DeleteRowObjectTests.cs @@ -1,4 +1,5 @@ -using RarelySimple.AvatarScriptLink.Objects; +using RarelySimple.AvatarScriptLink.Helpers; +using RarelySimple.AvatarScriptLink.Objects; namespace RarelySimple.AvatarScriptLink.Tests.Helpers { @@ -722,5 +723,38 @@ public void DeleteRowObject_FormObject_MI_RowId_IsNotFound() Assert.ThrowsException(() => formObject.DeleteRowObject(rowObject2.RowId)); } + + [TestMethod] + public void DeleteRowObject_OptionObject_RowObject_NullRowObject() + { + OptionObject optionObject = new(); + Assert.ThrowsException(() => optionObject.DeleteRowObject((RowObject)null)); + } + + [TestMethod] + public void DeleteRowObject_OptionObject_RowId_NullOptionObject() + { + Assert.ThrowsException(() => OptionObjectHelpers.DeleteRowObject((OptionObject)null, "1||1")); + } + + [TestMethod] + public void DeleteRowObject_OptionObject_RowId_NullForms() + { + OptionObject optionObject = new() { Forms = null }; + Assert.ThrowsException(() => optionObject.DeleteRowObject("1||1")); + } + + [TestMethod] + public void DeleteRowObject_FormObject_RowObject_NullRowObject() + { + FormObject formObject = new() { FormId = "1" }; + Assert.ThrowsException(() => formObject.DeleteRowObject((RowObject)null)); + } + + [TestMethod] + public void DeleteRowObject_FormObject_RowId_NullFormObject() + { + Assert.ThrowsException(() => OptionObjectHelpers.DeleteRowObject((FormObject)null, "1||1")); + } } } diff --git a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/AddRowObject.cs b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/AddRowObject.cs index d9e7c3ed..a727be7c 100644 --- a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/AddRowObject.cs +++ b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/AddRowObject.cs @@ -22,6 +22,8 @@ public static IOptionObject AddRowObject(IOptionObject optionObject, string form throw new ArgumentNullException(nameof(formId), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (rowObject == null) throw new ArgumentNullException(nameof(rowObject), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), ScriptLinkHelpers.GetLocalizedString("optionObjectMissingForms", CultureInfo.CurrentCulture)); if (IsFormPresent(optionObject, formId)) { int formIndex = optionObject.Forms.FindIndex(f => f.FormId == formId); diff --git a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs index cb3a0d36..2e24db3f 100644 --- a/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs +++ b/dotnet/RarelySimple.AvatarScriptLink/Helpers/OptionObject/DeleteRowObject.cs @@ -16,6 +16,8 @@ public static partial class OptionObjectHelpers /// public static IOptionObject DeleteRowObject(IOptionObject optionObject, IRowObject rowObject) { + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return DeleteRowObject(optionObject, rowObject.RowId); } /// @@ -26,6 +28,10 @@ public static IOptionObject DeleteRowObject(IOptionObject optionObject, IRowObje /// public static IOptionObject DeleteRowObject(IOptionObject optionObject, string rowId) { + if (optionObject == null) + throw new ArgumentNullException(nameof(optionObject), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); + if (optionObject.Forms == null) + throw new ArgumentNullException(nameof(optionObject), ScriptLinkHelpers.GetLocalizedString("optionObjectMissingForms", CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); int formIndex = optionObject.Forms.FindIndex(f => IsRowPresent(f, rowId)); @@ -44,6 +50,8 @@ public static IOptionObject DeleteRowObject(IOptionObject optionObject, string r /// public static IFormObject DeleteRowObject(IFormObject formObject, IRowObject rowObject) { + if (rowObject == null) + throw new ArgumentNullException(nameof(rowObject), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); return DeleteRowObject(formObject, rowObject.RowId); } /// @@ -54,6 +62,8 @@ public static IFormObject DeleteRowObject(IFormObject formObject, IRowObject row /// public static IFormObject DeleteRowObject(IFormObject formObject, string rowId) { + if (formObject == null) + throw new ArgumentNullException(nameof(formObject), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (string.IsNullOrEmpty(rowId)) throw new ArgumentNullException(nameof(rowId), ScriptLinkHelpers.GetLocalizedString(ParameterCannotBeNull, CultureInfo.CurrentCulture)); if (formObject.CurrentRow?.RowId == rowId)