Introduction
In PI B2B add-on, there are one set of ESR design objects called B2B Mapping Kit. Under namespace MappingFunctions have a set of function libraries. I personally find that these set of function libraries are very useful to handle various tricky context handling and complex message mapping requirements between EDI/EDIFACT/X12 and IDOC. Content of EDI/IDOC are highly hierarchical in nature. These deep level of EDI/IDOC field nodes with possible non-existed fields added complexity to message mapping. Fortunately B2B add-on come with these libraries functions to greatly simplified the mapping effort. In this blog post I will explain about UDFNodePool which handle the context handling. It is a complement of standard NodeFunctions.
UDFNodePool Functions
These are list of UDFNodePool functions covered in this blog post and I explained in my own way
Function Name | Meaning ( I = source, You = target) |
---|
createIfHasValue | I only create you if I am non-empty value, otherwise you will not be created. |
createIfHasOneOfSuchValues | I only create you if my 1st input is one of these values in my 2nd input that separated by semicolon, otherwise you will not be created. |
passIfHasValue | I give you the same value if I am non-empty value, otherwise you got nothing. |
assignValueByCondition | I give you my 3rd input, if my 1st input is one of these values in my 2nd input that separated by semicolon, otherwise you got nothing. |
getFirstContextValue | I only give you the first value in my list that is non-empty, otherwise you got nothing. |
concatToOneQueue | I append all 5 inputs in sequence, then give you 1 list. |
concatContextValues | I combine all values in my 1st input separated by value from my 2nd input, then give you 1 string. |
splitValueStringToContextValues | I split string in my 1st input by delimiter in my 2nd input, then give you 1 list. |
getValueByIndex | I pick a value in my 1st input by position(starting at 1) specified in my 2nd input, then give that value to you. |
suppressMultipleContextValues | I only give you unique list of value, regardless how many time the value existed or in what order. Duplicated value are suppressed. |
deleteMultipleContextValues | I only give you unique list of value, regardless how many time the value existed or in what order. Duplicated value are deleted. |
createMultipleCopies | I duplicate myself from 1st input as many time as specify at 2nd input, then give you a list. |
fragmentSingleValue | I cut myself as string from 1st input into maximum pieces count specify at 2nd input where each piece is with length of 3rd input, then send you a list contain all pieces. The last piece might be shorter. |
contextHasOneOfSuchValues | I will tell you single answer "true" if my 1st input is one of these values in my 2nd input that separated by semicolon, otherwise single answer "false" |
useOneContextAsMany | I duplicate myself from 1st input separated with context change, as many time as context values count at my 2nd input, then give you duplicated list. |
createMultipleContextCopies | I duplicate myself from 1st input separated with context change, as many time as numeric value at my 2nd input, then give you duplicated list. |
createIfHasValue I only create you if I am non-empty value, otherwise you will not be created. |
---|
Source message type and target message type:
Source data and target data: If source message col1 do not have value or is with blank space, do not create node ‘row’, and col1 will not be copied to target message.
mapping for field row: If is value ‘A’,’C’,’E’, created empty string “”. Empty string will create node “row” If is “”(empty string) or ” “(a blank space), become SUPPRESS. SUPPRESS will not create node “row” mapping for field col1: 1 to 1 direct mapping.
|
createIfHasOneOfSuchValues I only create you if my 1st input is one of these values in my 2nd input that separated by semicolon, otherwise you will not be created. |
---|
Source message type and target message type:
Source data and target data: If source message col1 is with value ‘B’ or ‘D’, will create node ‘row’ and copy col1 to target message. mapping for field row: If is value ‘A’,’C’,’E’, is not one of values ‘B’ or ‘D’. become SUPPRESS. SUPPRESS will not create node “row”. If is value ‘B’, ‘D’, matched with constant “B;D” specified in 2nd parameter, so created empty string “”. Empty string will create node “row”. mapping for field col1: 1 to 1 direct mapping.
|
passIfHasValue I give you the same value if I am non-empty value, otherwise you got nothing. |
---|
Source message type and target message type:
Source data and target data: If source message col1 do not have value or is with blank space, do not pass value to list1 at target message. Only pass if has value.
mapping for field list1: If is value ‘A’,’C’,’E’, pass the exact value ‘A’,’C’,’E’ to list1 at target message. If is “”(empty string) or ” “(a blank space), become SUPPRESS. SUPPRESS will not create list1.
|
assignValueByCondition I give you my 3rd input, if my 1st input is one of these values in my 2nd input that separated by semicolon, otherwise you got nothing.
|
---|
Source message type and target message type:
Source data and target data: If source message col1 have value “C”, then copy corresponding col2 value “Code” to string1 at target message. mapping for field list1 if constant is “C”: AssignValueByCondition will use constant “C”, searched col1, and found matched, get corresponding value “Code” at col2. Other not matched will become SUPPRESS.
mapping for field list1 if constant is “X”: assignValueByCondition will use constant “X”, searched col1, and none is matched, so all will become SUPPRESS. deleteSuppress and mapWithDefault will turn SUPPRESS become empty string, to avoid run-time error. This is because string1 is mandatory field. Target message string1 is empty string:
mapping for field list1 if constant is “C;E”: assignValueByCondition will use constant “C;E”, splitted become 2 values “C” and “E”, searched col1, found 2 matched and get 2 corresponding values “Code” and “Encryption”.
Target message string1 is value “Code”. Value “Encryption” is not copied because string1 is only single value.
|
getFirstContextValue I only give you the first value in my list that is non-empty, otherwise you got nothing.
|
---|
Followed example from above:
mapping for field list1 if constant is “C;E” and added function getFirstContextValue: getFirstContextValue will ignore all SUPPRESS and only get first non-empty value, which is “Code” |
concatToOneQueue I append all 5 inputs in sequence, then give you 1 list.
|
---|
Source message type and target message type:
Scenario 1: Source data and target data: Put all values from col1 to col5 under single queue, starting at first row, then follow by subsequent rows. mapping for field list1: concatToOneQueue take 5 queues that with context change as input, concatenate first row, followed by second and third row.
Scenario 2: Source data and target data: Put all values for col1 from all row under single queue, starting at col1, then follow by col2, col3, col4 and col5. mapping for field list1: concatToOneQueue take 5 queues that removed context as input, concat col1, followed by col2 until col5.
|
concatContextValues I combine all values in my 1st input separated by value from my 2nd input, then give you 1 string.
|
---|
Followed example from above: Scenario 3: Source data and target data: Put all values from col1 until col5 under single string separated by delimiter “@”, starting at first row until last row.
mapping for field list1: concatToOneQueue take 5 queues as input, for each row concatenate col1 until col5 into one context. concatContextValues will concatenate each context’s values into long string separated by “@”
|
splitValueStringToContextValues I split string in my 1st input by delimiter in my 2nd input, then give you 1 list.
getValueByIndex I pick a value in my 1st input by position(starting at 1) specified in my 2nd input, then give that value to you.
|
---|
Source message type and target message type:
Source data and target data: mapping for field row:
mapping for field col1: splitValueStringToContextValues split single value string by “@” to multiple split values. getValueByIndex take single value in a context values by specify an index number. mapping for field col1, col2, col3, col4 and col5 are the same, just the constant index is different.
|
suppressMultipleContextValues I only give you unique list of value, regardless how many time the value existed or in what order. Duplicated value are suppressed.
|
---|
Source message type and target message type:
Source data and target data:
mapping for field row: If same value existed more than 1 time, will be suppressed. mapping for field col1: 1 to 1 direct mapping.
|
deleteMultipleContextValues I only give you unique list of value, regardless how many time the value existed or in what order. Duplicated value are deleted.
|
---|
Source message type and target message type:
Source data and target data: mapping for field list1: If same value existed more than 1 time, will be deleted.
|
createMultipleCopies I duplicate myself from 1st input as many time as specify at 2nd input, then give you a list.
|
---|
Source message type and target message type:
Source data and target data:
mapping for field list1: Values at queue1 is created many times according to numeric values at queue2. Example ‘A’ created 2 times. ‘B’ created 3 times, and so on.
|
fragmentSingleValue I cut myself as string from 1st input into maximum pieces count specify at 2nd input where each piece is with length of 3rd input, then send you a list contain all pieces. The last piece might be shorter.
|
---|
Source message type and target message type:
Source data and target data: mapping for field list1: Single value with total 30 characters length is fragment to maximum 10 pieces. Each piece is 4 characters length. 8 pieces will be created, due to 30 divide by 4 will 7.5, round up is 8. Last piece (8th) is shorter because only remain 2 characters, after 30 minus 28(4 time 7) = 2.
|
contextHasOneOfSuchValues I will tell you single answer "true" if my 1st input is one of these values in my 2nd input that separated by semicolon, otherwise single answer "false"
|
---|
Source message type and target message type:
Source data and target data:
mapping for field string1: 1st queue is list from ‘A’ to ‘G’. 2nd queue is string “B;D;Z” 1st queue has one of such values from (‘B’,’D’,’Z’). 2 matches and 1 not matched. As long as at least one matched, output will be single string value “true”.
Another example: Both ‘M’ and ‘N’ also not matched any value from ‘A’ to ‘G’, so output is single string value ‘false’.
|
createMultipleContextCopies I duplicate myself from 1st input separated with context change, as many time as numeric value at my 2nd input, then give you duplicated list.
|
---|
The objective is to convert 2 different recordsets(SINGER and SONG) under same message, to single nested recordset (SONG nested under SINGER). The message type: The mapping: For node SINGER, SINGERID and FULLNAME, is direct one-to-one mapping. For node SONG and SONGNAME, please see below. The idea is for each SINGER, compare all SONG, if the SONG’s SINGERID is match, then map to target. Due to the list of SONG need to be compared as many as the SINGER count (6), so need to use function createMultipleContextCopies to create multiple copies of SONG list.
The queues:
|
useOneContextAsMany I duplicate myself from 1st input separated with context change, as many time as context values count at my 2nd input, then give you duplicated list. |
---|
Take an example from previous post: The output is exactly the same with previous post, if changed to use useOneContextAsMany like below:
Below show queue at point 2: Left is useOneContextAsMany which accept a queue contain second input to repeat context values. Right is createMultipleContextCopies which accept single numeric value at second input to repeat context values. Both way will achieve same result.
|
Thanks for viewing. This is my first blog post in B2B space, hope you find it useful and like it.