Categories
Uncategorized

Modifying a Multiple Iteration FieldValue Using ScriptLink

Interacting with Multiple Iteration forms is the most complicated ScriptLink task by far. This is due, in large part, to the data model not being intuitive at first glance and limited documentation. Over the next few weeks, we will be looking specifically at some basic multiple iteration interactions. This week, modifying a value found in an existing row.

Interacting with Multiple Iteration forms is the most complicated ScriptLink task by far. This is due, in large part, to the data model not being intuitive at first glance and limited documentation. Over the next few weeks, we will be looking specifically at some basic multiple iteration interactions. This week, modifying a value found in an existing row.

This article builds off of the previous week’s article that demonstrates how to modify a field value in general. The technique used in that article would also work for multiple iteration tables, if you only want to work with the currently selected row. However, if the row you wish to interact with is not selected, then we have to look into the FormObject.OtherRows property.

The Specification

So for our example today. We will be checking our multiple iteration table’s rows for misspellings of the acronym HIPAA. It is common to see it misspelled as HIPPA. So our script will check for HIPPA and replace it HIPAA.

The Unit Tests

As before, let write our unit tests first. Here is my basic set for this demonstration. What other tests would you add?

[TestMethod]
public void Execute_HippaToHipaaCommand_ReturnsOptionObject()
{
    // Arrange
    OptionObject expected = new OptionObject();

    OptionObject optionObject = new OptionObject();
    var command = new HippaToHipaaCommand(optionObject);

    // Act
    var actual = (OptionObject)command.Execute();

    // Assert
    Assert.AreEqual(expected.GetType(), actual.GetType());
}

[TestMethod]
public void Execute_HippaToHipaaCommand_ReturnsOptionObject2()
{
    // Arrange
    OptionObject2 expected = new OptionObject2();

    OptionObject2 optionObject2 = new OptionObject2();
    var command = new HippaToHipaaCommand(optionObject2);

    // Act
    var actual = (OptionObject2)command.Execute();

    // Assert
    Assert.AreEqual(expected.GetType(), actual.GetType());
}

[TestMethod]
public void Execute_HippaToHipaaCommand_ReturnsOptionObject2015()
{
    // Arrange
    OptionObject2015 expected = new OptionObject2015();

    OptionObject2015 optionObject2015 = new OptionObject2015();
    var command = new HippaToHipaaCommand(optionObject2015);

    // Act
    var actual = command.Execute();

    // Assert
    Assert.AreEqual(expected.GetType(), actual.GetType());
}

[TestMethod]
public void Execute_HippaToHipaaCommand_HIPAA_CurrentRow_ReturnsExpectedValue()
{
    // Arrange
    OptionObject2015 expected = new OptionObject2015();
    FieldObject fieldObject01 = new FieldObject()
    {
        Enabled = "1",
        FieldNumber = "153.01",
        FieldValue = "This is my test paragraph with the word HIPAA in place. This paragraph should remain unmodified.",
        Lock = "0",
        Required = "1"
    };
    List<FieldObject> fields = new List<FieldObject>() { fieldObject01 };
    RowObject rowObject = new RowObject() { RowId = "321||1", Fields = fields };
    FormObject formObject = new FormObject() { FormId = "321", CurrentRow = rowObject, MultipleIteration = true, OtherRows = new List<RowObject>() };
    OptionObject2015 optionObject2015 = new OptionObject2015()
    {
        Forms = new List<FormObject>()
        {
            formObject
        }
    };
    var command = new HippaToHipaaCommand(optionObject2015);

    // Act
    bool hippaIsPresent = false;
    IOptionObject2015 actual = command.Execute();
    foreach (var form in actual.Forms)
    {
        if (form.FormId == "321")
        {
            foreach (var field in form.CurrentRow.Fields)
            {
                if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                {
                    hippaIsPresent = true;
                }
            }
            foreach (var row in form.OtherRows)
            {
                foreach (var field in row.Fields)
                {
                    if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                    {
                        hippaIsPresent = true;
                    }
                }
            }
        }
    }

    // Assert
    Assert.IsFalse(hippaIsPresent);
}

[TestMethod]
public void Execute_HippaToHipaaCommand_HIPAA_OtherRow_ReturnsExpectedValue()
{
    // Arrange
    OptionObject2015 expected = new OptionObject2015();
    FieldObject fieldObject01 = new FieldObject()
    {
        Enabled = "1",
        FieldNumber = "153.01",
        FieldValue = "This is my test paragraph which doesn't reference the misspelled word. This paragraph should remain unmodified.",
        Lock = "0",
        Required = "1"
    };
    FieldObject fieldObject02 = new FieldObject()
    {
        Enabled = "1",
        FieldNumber = "153.01",
        FieldValue = "This is my test paragraph with the word HIPAA in place. This paragraph should remain unmodified.",
        Lock = "0",
        Required = "1"
    };
    List<FieldObject> fields01 = new List<FieldObject>() { fieldObject01 };
    RowObject rowObject01 = new RowObject() { RowId = "321||1", Fields = fields01 };
    List<FieldObject> fields02 = new List<FieldObject>() { fieldObject02 };
    RowObject rowObject02 = new RowObject() { RowId = "321||2", Fields = fields02 };
    FormObject formObject = new FormObject() { FormId = "321", CurrentRow = rowObject01, MultipleIteration = true, OtherRows = new List<RowObject>() { rowObject02 } };
    OptionObject2015 optionObject2015 = new OptionObject2015()
    {
        Forms = new List<FormObject>()
        {
            formObject
        }
    };
    var command = new HippaToHipaaCommand(optionObject2015);

    // Act
    bool hippaIsPresent = false;
    IOptionObject2015 actual = command.Execute();
    foreach (var form in actual.Forms)
    {
        if (form.FormId == "321")
        {
            foreach (var field in form.CurrentRow.Fields)
            {
                if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                {
                    hippaIsPresent = true;
                }
            }
            foreach (var row in form.OtherRows)
            {
                foreach (var field in row.Fields)
                {
                    if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                    {
                        hippaIsPresent = true;
                    }
                }
            }
        }
    }

    // Assert
    Assert.IsFalse(hippaIsPresent);
}

[TestMethod]
public void Execute_HippaToHipaaCommand_HIPPA_CurrentRow_ReturnsExpectedValue()
{
    // Arrange
    OptionObject2015 expected = new OptionObject2015();
    FieldObject fieldObject01 = new FieldObject()
    {
        Enabled = "1",
        FieldNumber = "153.01",
        FieldValue = "This is my test paragraph with the word HIPPA in place. This paragraph should be modified.",
        Lock = "0",
        Required = "1"
    };
    List<FieldObject> fields = new List<FieldObject>() { fieldObject01 };
    RowObject rowObject = new RowObject() { RowId = "321||1", Fields = fields };
    FormObject formObject = new FormObject() { FormId = "321", CurrentRow = rowObject, MultipleIteration = true, OtherRows = new List<RowObject>() };
    OptionObject2015 optionObject2015 = new OptionObject2015()
    {
        Forms = new List<FormObject>()
        {
            formObject
        }
    };
    var command = new HippaToHipaaCommand(optionObject2015);

    // Act
    bool hippaIsPresent = false;
    IOptionObject2015 actual = command.Execute();
    foreach (var form in actual.Forms)
    {
        if (form.FormId == "321")
        {
            foreach (var field in form.CurrentRow.Fields)
            {
                if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                {
                    hippaIsPresent = true;
                }
            }
            foreach (var row in form.OtherRows)
            {
                foreach (var field in row.Fields)
                {
                    if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                    {
                        hippaIsPresent = true;
                    }
                }
            }
        }
    }

    // Assert
    Assert.IsFalse(hippaIsPresent);
}

[TestMethod]
public void Execute_HippaToHipaaCommand_HIPPA_OtherRow_ReturnsExpectedValue()
{
    // Arrange
    OptionObject2015 expected = new OptionObject2015();
    FieldObject fieldObject01 = new FieldObject()
    {
        Enabled = "1",
        FieldNumber = "153.01",
        FieldValue = "This is my test paragraph which doesn't reference the misspelled word. This paragraph should remain unmodified.",
        Lock = "0",
        Required = "1"
    };
    FieldObject fieldObject02 = new FieldObject()
    {
        Enabled = "1",
        FieldNumber = "153.01",
        FieldValue = "This is my test paragraph with the word HIPPA in place. This paragraph should be modified.",
        Lock = "0",
        Required = "1"
    };
    List<FieldObject> fields01 = new List<FieldObject>() { fieldObject01 };
    RowObject rowObject01 = new RowObject() { RowId = "321||1", Fields = fields01 };
    List<FieldObject> fields02 = new List<FieldObject>() { fieldObject02 };
    RowObject rowObject02 = new RowObject() { RowId = "321||2", Fields = fields02 };
    FormObject formObject = new FormObject() { FormId = "321", CurrentRow = rowObject01, MultipleIteration = true, OtherRows = new List<RowObject>() { rowObject02 } };
    OptionObject2015 optionObject2015 = new OptionObject2015()
    {
        Forms = new List<FormObject>()
        {
            formObject
        }
    };
    var command = new HippaToHipaaCommand(optionObject2015);

    // Act
    bool hippaIsPresent = false;
    IOptionObject2015 actual = command.Execute();
    foreach (var form in actual.Forms)
    {
        if (form.FormId == "321")
        {
            if (form.CurrentRow != null)
            {
                foreach (var field in form.CurrentRow.Fields)
                {
                    if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                    {
                        hippaIsPresent = true;
                    }
                }
            }
            foreach (var row in form.OtherRows)
            {
                foreach (var field in row.Fields)
                {
                    if (field.FieldNumber == "153.01" && field.FieldValue.Contains("HIPPA"))
                    {
                        hippaIsPresent = true;
                    }
                }
            }
        }
    }

    // Assert
    Assert.IsFalse(hippaIsPresent);
}

Since we don’t have our command yet, we cannot compile. So let’s create our command.

The Command

Let’s build out the command just enough to compile, but throw a not implemented exception. Our goal is to be able to run our tests and get the NotImplementedException returned for all tests.

public class HippaToHipaaCommand : IRunScriptCommand
{
    private static readonly Logger logger = LogManager.GetCurrentClassLogger();

    private readonly OptionObjectBase _optionObject;

    public HippaToHipaaCommand(OptionObjectBase optionObject)
    {
        _optionObject = optionObject;
    }

    public IOptionObject2015 Execute()
    {
        logger.Debug("HippaToHipaaCommand executed.");

        throw new NotImplementedException();
    }
}

Ok. With the reference to our new command in the unit tests, they should all fail with the NotImplementedException. Now to write out the logic.

This will work in a similar manner to our two previous articles. We will read through both the CurrentRow and OtherRows and we will construct a FormObject to return the modified values, if any.

public IOptionObject2015 Execute()
{
    logger.Debug("HippaToHipaaCommand executed.");

    FormObject miForm = new FormObject()
    {
        FormId = "321",
        MultipleIteration = true,
        OtherRows = new List<RowObject>()
    };
    OptionObjectBase returnOptionObject = _optionObject.ToReturnOptionObject();

    if (_optionObject.Forms != null)
    {
        foreach (var form in _optionObject.Forms)
        {
            if (form.FormId == "321") 
            {
                if (form.CurrentRow != null && form.CurrentRow.Fields != null)
                {
                    foreach (var field in form.CurrentRow.Fields)
                    {
                        switch (field.FieldNumber)
                        {
                            case "153.01":
                                if (field.FieldValue.Contains("HIPPA"))
                                {
                                    FieldObject fieldObject = new FieldObject()
                                    {
                                        Enabled = field.Enabled,
                                        FieldNumber = field.FieldNumber,
                                        FieldValue = field.FieldValue.Replace("HIPPA", "HIPAA"),
                                        Lock = field.Lock,
                                        Required = field.Required
                                    };
                                    miForm.CurrentRow = new RowObject() 
                                    { 
                                        Fields = new List<FieldObject>() { fieldObject },
                                        RowAction = "EDIT",
                                        RowId = form.CurrentRow.RowId
                                    };
                                }
                                break;
                        }
                    }
                }

                if (form.OtherRows != null && form.OtherRows.Count > 0)
                {
                    foreach (var row in form.OtherRows)
                    {
                        foreach (var field in row.Fields)
                        {
                            switch (field.FieldNumber)
                            {
                                case "153.01":
                                    if (field.FieldValue.Contains("HIPPA"))
                                    {
                                        FieldObject fieldObject = new FieldObject()
                                        {
                                            Enabled = field.Enabled,
                                            FieldNumber = field.FieldNumber,
                                            FieldValue = field.FieldValue.Replace("HIPPA", "HIPAA"),
                                            Lock = field.Lock,
                                            Required = field.Required
                                        };
                                        miForm.OtherRows.Add(new RowObject()
                                        {
                                            Fields = new List<FieldObject>() { fieldObject },
                                            RowAction = "EDIT",
                                            RowId = form.CurrentRow.RowId
                                        });
                                    }
                                    break;
                            }
                        }
                    }
                }
            }
        }
    }
    if (miForm.CurrentRow != null || miForm.OtherRows.Count > 0)
    {
        returnOptionObject.Forms = new List<FormObject>() { miForm };
    }

    return returnOptionObject;
}

A couple items of note in the above code. In addition to checking for the presence of the FieldObject, we also check for the specific FormObject. This will reduce the number of loops that have to be processed for the other forms. We also move the edited FormObject creation earlier in the process than in previous examples as we could be making multiple modifications to the same form.

Wrap Up

Like before, let’s wrap up by updating our CommandSelector and our SoapUI Test. Here is my added CommandSelector Unit Test and the updated CommandSelector.

[TestMethod]
public void GetCommand_HippaToHipaa_ReturnsHelloWorld()
{
    // Arrange
    OptionObject2015 optionObject2015 = new OptionObject2015();
    string parameter = "HippaToHipaa";
    HippaToHipaaCommand expected = new HippaToHipaaCommand(optionObject2015);

    // Act
    IRunScriptCommand actual = CommandSelector.GetCommand(optionObject2015, parameter);

    // Assert
    Assert.AreEqual(expected.GetType(), actual.GetType());
}

And the CommandSelector.

public static IRunScriptCommand GetCommand(IOptionObject2015 iOptionObject, string parameter)
{
    OptionObjectBase optionObjectBase = (OptionObjectBase)iOptionObject;

    switch (parameter)
    {
        case "GetAreaOfRectangle":
            logger.Debug("Creating a GetAreaOfRectangleCommand.");
            return new GetAreaOfRectangleCommand(optionObjectBase);
        case "HasMrPinchyPet":
            logger.Debug("Creating a HasMrPinchyPetCommand.");
            return new HasMrPinchyPetCommand(optionObjectBase);
        case "HelloWorld":
            logger.Debug("Creating a HelloWorld command.");
            return new HelloWorld(optionObjectBase);
        case "HippaToHipaa":
            logger.Debug("Creating a HippaToHipaaCommand.");
            return new HippaToHipaaCommand(optionObjectBase);
        case "IsDraft":
            logger.Debug("Creating an IsDraftCommand.");
            return new IsDraftCommand(optionObjectBase);
        default:
            logger.Warn("No command found matching parameter '" + (parameter ?? "") + "'. Creating a DefaultCommand.");
            return new DefaultCommand(optionObjectBase, parameter);
    }
}

Now you should be able to run your unit tests and see everything pass as well as run the solution and test it out using SoapUI or other tool.

Closing Thoughts

I hope the structure of the OptionObject is becoming clear as well as the options for manipulating it. It may be obvious at this point that the more fields you wish to interact with, especially when dealing with multiple iteration tables can get unreadable very quickly. The RarelySimple.AvatarScriptLink library does make this process much easier, but honestly any refactoring process can help. Many other users have created their own libraries to help keep the code readable.

I hope you have a great week!