Creating an index or iterator controlled loop in an MDM workflow.
book
Article ID: KB0093365
calendar_today
Updated On:
Products
Versions
TIBCO MDM
-
Not Applicable
-
Description
Description: It is sometimes required to create an index or iterator controlled loop in an MDM workflow. To assist in this process, this knowledge article provides a template of how this can be achieved for various scenarios. Each scenario follows the same basic (template) pattern.
Issue/Introduction
Creating an index or iterator controlled loop in an MDM workflow.
Resolution
Template Pattern: Creating an index or iterator controlled loop in an MDM workflow is made possible by use of the InterpretCommand activity. The pattern used follows.
Scenario 1: Suppose there is a need to iterate over two arrays VALUE_ARRAY_ID, and VALUE_ARRAY_IDEXT, extracting the (String) values from each arrays for the current position each time, and using them in some loop body activities. For simplicity, this loop assumes that VALUE_ARRAY_ID and VALUE_ARRAY_IDEXT are the same length.
<!-- Loop Activities : Start --> <Activity Name="InitializeLoop"> <Action>InterpretCommand</Action> <Description lang="en">Set counter=0 and limit=VALUE_ARRAY_ID.length</Description> <Parameter direction="in" name="ValueArrayID" eval="variable" type="arraylist">VALUE_ARRAY_ID</Parameter> <Parameter direction="out" name="Counter" eval="variable" type="long">Counter</Parameter> <Parameter direction="out" name="Limit" eval="variable" type="long">Limit</Parameter> <Script format="bsh"><![CDATA[Counter = new java.lang.Long(0L);Limit = new java.lang.Long(ValueArrayID.length);]]></Script> </Activity> <Activity Name="LoopPoint"> <Action>NoOperation</Action> <Description lang="en">Loop point to enable single test point for loop</Description> </Activity> <Activity Name="NextRecord"> <Action>InterpretCommand</Action> <Description lang="en">Get Next Value from two arrays - assumes two arrays the same length</Description> <Parameter direction="in" name="ValueArrayID" eval="variable" type="arraylist">VALUE_ARRAY_ID</Parameter> <Parameter direction="in" name="ValueArrayIDEXT" eval="variable" type="arraylist">VALUE_ARRAY_IDEXT</Parameter> <Parameter direction="in" name="Counter" eval="variable" type="number">Counter</Parameter> <Parameter direction="out" name="NextID" eval="variable" type="string">NEXT_ID</Parameter> <Parameter direction="out" name="NextIDEXT" eval="variable" type="string">NEXT_IDEXT</Parameter> <Script format="bsh"> <![CDATA[NextID = (java.lang.String) ValueArrayID.get(Counter.intValue());NextIDEXT = (java.lang.String) ValueArrayIDEXT.get(Counter.intValue());]]> </Script> </Activity> <!-- Start user-specific loop body --> <Activity Name="...first activity in loop body..."> <Action>...</Action> <Description>...</Description> ... <Parameter name="NextId" direction="in" eval="variable" type="string">NEXT_ID</Parameter> <Parameter name="NextIdExt" direction="in" eval="variable" type="string">NEXT_IDEXT</Parameter> ... </Activity> ... <Activity Name="...last activity in loop body..."> <Action>...</Action> <Description>...</Description> ... <Parameter name="NextId" direction="in" eval="variable" type="string">NEXT_ID</Parameter> <Parameter name="NextIdExt" direction="in" eval="variable" type="string">NEXT_IDEXT</Parameter> ... </Activity> <!-- End user-specific loop body --> <Activity Name="MovePointer"> <Action>InterpretCommand</Action> <Description lang="en">counter = counter + 1</Description> <Parameter direction="in" name="CounterIn" eval="variable" type="number">Counter</Parameter> <Parameter direction="out" name="CounterOut" eval="variable" type="number">Counter</Parameter> <Script format="bsh"><![CDATA[CounterOut = new java.lang.Long(CounterIn.longValue() + 1L);]]></Script> </Activity> <!-- Loop Activities : End --> ... <!-- Loop Transitions : Start --> <Transition FromActivity="...lead in activity..." ToActivity="InitializeLoop"/> <Transition FromActivity="InitializeLoop" ToActivity="LoopPoint"/> <Transition FromActivity="LoopPoint" ToActivity="NextRecord"> <Rule> <Parameter direction="in" name="Counter" eval="variable" type="long">Counter</Parameter> <Parameter direction="in" name="Limit" eval="variable" type="long">Limit</Parameter> <Parameter name="result" type="boolean" direction="out" /> <Condition format="bsh"><![CDATA[result = Counter.intValue() < Limit.intValue();]]></Condition> </Rule> </Transition> <!-- Counter >= Limit, so Exit --> <Transition FromActivity="LoopPoint" ToActivity="SetStatusToSuccess"/> <!-- Start user-specific loop body --> <Transition FromActivity="NextRecord" ToActivity="...first activity in loop body..."/> ... <Transition FromActivity="...last activity in loop body..." ToActivity="MovePointer"/> <!-- End user-specific loop body --> <Transition FromActivity="MovePointer" ToActivity="LoopPoint"/> <!-- Loop Transitions : End --> ...
Scenario 2: Suppose there is a need to iterate over one array VALUE_ARRAY, extracting a Structure (in this case, ID String/IDEXT String) from the array for the current position each time, and using it in some loop body activities.
<!-- Loop Activities : Start --> <Activity Name="InitializeLoop"> <Action>InterpretCommand</Action> <Description lang="en">Set counter=0 and limit=VALUE_ARRAY.length</Description> <Parameter direction="in" name="ValueArray" eval="variable" type="arraylist">VALUE_ARRAY</Parameter> <Parameter direction="out" name="Counter" eval="variable" type="long">Counter</Parameter> <Parameter direction="out" name="Limit" eval="variable" type="long">Limit</Parameter> <Script format="bsh"><![CDATA[Counter = new java.lang.Long(0L);Limit = new java.lang.Long(ValueArray.length);]]></Script> </Activity> <Activity Name="LoopPoint"> <Action>NoOperation</Action> <Description lang="en">Loop point to enable single test point for loop</Description> </Activity> <Activity Name="NextRecord"> <Action>InterpretCommand</Action> <Description lang="en">Get Next Value from array</Description> <Parameter direction="in" name="ValueArray" eval="variable" type="arraylist">VALUE_ARRAY</Parameter> <Parameter direction="in" name="Counter" eval="variable" type="number">Counter</Parameter> <Parameter direction="out" name="NextID" eval="variable" type="string">NEXT_ID</Parameter> <Parameter direction="out" name="NextIDEXT" eval="variable" type="string">NEXT_IDEXT</Parameter> <Script format="bsh"> <![CDATA[NextID = (java.lang.String) (ValueArrayID.get(Counter.intValue())).ID;NextIDEXT = (java.lang.String) (ValueArrayID.get(Counter.intValue())).IDEXT;]]> </Script> </Activity> <!-- Start user-specific loop body --> <Activity Name="...first activity in loop body..."> <Action>...</Action> <Description>...</Description> ... <Parameter name="NextId" direction="in" eval="variable" type="string">NEXT_ID</Parameter> <Parameter name="NextIdExt" direction="in" eval="variable" type="string">NEXT_IDEXT</Parameter> ... </Activity> ... <Activity Name="...last activity in loop body..."> <Action>...</Action> <Description>...</Description> ... <Parameter name="NextId" direction="in" eval="variable" type="string">NEXT_ID</Parameter> <Parameter name="NextIdExt" direction="in" eval="variable" type="string">NEXT_IDEXT</Parameter> ... </Activity> <!-- End user-specific loop body --> <Activity Name="MovePointer"> <Action>InterpretCommand</Action> <Description lang="en">counter = counter + 1</Description> <Parameter direction="in" name="CounterIn" eval="variable" type="number">Counter</Parameter> <Parameter direction="out" name="CounterOut" eval="variable" type="number">Counter</Parameter> <Script format="bsh"><![CDATA[CounterOut = new java.lang.Long(CounterIn.longValue() + 1L);]]></Script> </Activity> <!-- Loop Activities : End --> ... <!-- Loop Transitions : Start --> <Transition FromActivity="...lead in activity..." ToActivity="InitializeLoop"/> <Transition FromActivity="InitializeLoop" ToActivity="LoopPoint"/> <Transition FromActivity="LoopPoint" ToActivity="NextRecord"> <Rule> <Parameter direction="in" name="Counter" eval="variable" type="long">Counter</Parameter> <Parameter direction="in" name="Limit" eval="variable" type="long">Limit</Parameter> <Parameter name="result" type="boolean" direction="out" /> <Condition format="bsh"><![CDATA[result = Counter.intValue() < Limit.intValue();]]></Condition> </Rule> </Transition> <!-- Counter >= Limit, so Exit --> <Transition FromActivity="LoopPoint" ToActivity="SetStatusToSuccess"/> <!-- Start user-specific loop body --> <Transition FromActivity="NextRecord" ToActivity="...first activity in loop body..."/> ... <Transition FromActivity="...last activity in loop body..." ToActivity="MovePointer"/> <!-- End user-specific loop body --> <Transition FromActivity="MovePointer" ToActivity="LoopPoint"/> <!-- Loop Transitions : End --> ...
Scenario 3: Scenario 3 is the same as scenario 2 except that Java iterators are now being used - this may not work in MDM as it currently stands as of MDM 8.3.2 hotfix 1 or lower versions of CIM/MDM - it depends on whether Iterator, when specified as a "recordlist" parameter, will actually be treated as a java.lang.Object.
<!-- Loop Activities : Start --> <Activity Name="InitializeLoop"> <Action>InterpretCommand</Action> <Description lang="en">Fetch iterator for VALUE_ARRAY</Description> <Parameter direction="in" name="ValueArray" eval="variable" type="arraylist">VALUE_ARRAY</Parameter> <Parameter direction="out" name="Iterator" eval="variable" type="recordlist">Iterator</Parameter> <Script format="bsh"><![CDATA[java.util.ListIterator<java.util.List> Iterator = (java.util.ListIterator<java.util.List>) ValueArray.iterator();]]></Script> </Activity> <Activity Name="LoopPoint"> <Action>NoOperation</Action> <Description lang="en">Loop point to enable single test point for loop</Description> </Activity> <Activity Name="NextRecord"> <Action>InterpretCommand</Action> <Description lang="en">Get Next Value from array</Description> <Parameter direction="in" name="Iterator" eval="variable" type="recordlist">Iterator</Parameter> <Parameter direction="out" name="NextID" eval="variable" type="string">NEXT_ID</Parameter> <Parameter direction="out" name="NextIDEXT" eval="variable" type="string">NEXT_IDEXT</Parameter> <Script format="bsh"> <![CDATA[java.util.List<java.lang.String> NextValue = Iterator.next();NextID = (java.lang.String) NextValue.get(0);NextIDEXT = (java.lang.String) NextValue.get(1);]]> </Script> </Activity> <!-- Start user-specific loop body --> <Activity Name="...first activity in loop body..."> <Action>...</Action> <Description>...</Description> ... <Parameter name="NextId" direction="in" eval="variable" type="string">NEXT_ID</Parameter> <Parameter name="NextIdExt" direction="in" eval="variable" type="string">NEXT_IDEXT</Parameter> ... </Activity> ... <Activity Name="...last activity in loop body..."> <Action>...</Action> <Description>...</Description> ... <Parameter name="NextId" direction="in" eval="variable" type="string">NEXT_ID</Parameter> <Parameter name="NextIdExt" direction="in" eval="variable" type="string">NEXT_IDEXT</Parameter> ... </Activity> <!-- End user-specific loop body --> <!-- Loop Activities : End --> ... <!-- Loop Transitions : Start --> <Transition FromActivity="...lead in activity..." ToActivity="InitializeLoop"/> <Transition FromActivity="InitializeLoop" ToActivity="LoopPoint"/> <Transition FromActivity="LoopPoint" ToActivity="NextRecord"> <Rule> <Parameter direction="in" name="Iterator" eval="variable" type="recordlist">Iterator</Parameter> <Parameter name="result" type="boolean" direction="out" /> <Condition format="bsh"><![CDATA[result = Iterator.hasNext();]]></Condition> </Rule> </Transition> <!-- hasNext() is false, so Exit --> <Transition FromActivity="LoopPoint" ToActivity="SetStatusToSuccess"/> <!-- Start user-specific loop body --> <Transition FromActivity="NextRecord" ToActivity="...first activity in loop body..."/> ... <Transition FromActivity="...last activity in loop body..." ToActivity="LoopPoint"/> <!-- End user-specific loop body --> <!-- Loop Transitions : End --> ...