Looping thru a RecList and using a branch statement

I am looping through records in a recList, and trying to branch on the evaluation of a string within the record to perform different mapping based on the evaluations for each map.

Loop over /invoice/invoic01/IDoc/E1EDKA1
branch (set evaluate - labels = true)
Map %/invoice/invoic01/IDoc/E1EDKA1[0]/PARVW% = A
Map %/invoice/invoic01/IDoc/E1EDKA1[0]/PARVW% = B
Map %/invoice/invoic01/IDoc/E1EDKA1[0]/PARVW% = C

My question is how do set the index of the loop in the map step’s label so that it will be the index of the loop and not always “[0]” the first one. Currently my loop will iterate through the recList and execute the branch statement, but only evaluate the first record index [0], because I could figure out how to specify the index dynamically. Could someone tell me where this documenation lives or and example.

No need to eval labels on this one. Try this:

LOOP over /invoice/invoic01/IDoc/E1EDKA1
…BRANCH on /invoice/invoic01/IDoc/E1EDKA1/PARVW
…A: MAP
…B: MAP
…C: MAP
…$default: MAP

Set evaluate labels to false on the BRANCH.

HTH

ok, I gotcha. Set the switch value of the branch statement to /invoice/invoic01/IDoc/E1EDKA1/PARVW and set evaluate labels to false. Then just set the label for each map to the value I want.

Just out of curiousity, how do you solve that index issue, is there a way to get a handle on the index of the loop?
–steve

Well, I have follow up question, now that the branch statement is working, the problem now is I am mapping to values in records in a record list to values in records in recordList. So what is happening is that I run thru this loop, iterating over the records in the record list and when my branch statement has a hit on a value it maps the values from the Record[0] | string source to Record[0] | string destination. Then on the next interation thru the record list my branch statement has another hit, and it maps Record[1] | string to Record[0] | string, thus overwritting the previous value, so the end result in I have a record list with one record instead of a record list where the number of records are equal to the length of records in the source record list where my branch statment had a hit. How do I set the index in the destination record dynamically?

The pipeline var $iteration contains the index of the loop.

Review this thread. It is a discussion about mapping record lists and the options available.

http://www.wmusers.com/wmusers/messages/117/366.shtml?

Basically, you don’t want/need to use indexing when mapping lists even though that’s a natural inclination because that’s how it’s done in Java, C, C++…

Option 1: Use LOOP with an in-array and an out-array. In this case your map steps are mapping records and the run-time environment manages the indexing into the lists. No need to use $iteration or any other index. Be sure to follow the advice of the above thread wrt creating a new record for each loop iteration.

Option 2: Use LOOP with an in-array and no out-array. You map from the in record to a temp out record. Then use appendToRecordList to add the out record to a list. Then drop the temp record from the pipeline. Again, no need to manage the index yourself. Be aware that this option is a Bad Thing if the list is large (the record list is reallocated for each append).

HTH

Rob,

So how do you set the index, using $iteration, for the destination records that I am creating, when mapping records in a recordlist to records in a record list? I know on each of the maps I can hard code the index by right click | properties| indexing, but I am guessing that is not the best approach, any suggestions?
–steve

you beat me to the punch, IGNORE the previous POST
–steve

a bit more info on mapping to recordLists - when using right click | properties| indexing, you can only hardcode an index number and not use a variable like %myIndex% which would be nice.
Instead you need to use pub.list.getRecordListItem and pub.list.setRecordListItem, or write java frags to IDataUtil.getIDataArray().

Also I’ve found that if you have a structure:
outerRecordList
–innerRecordList

and then have two instances of this structure ie. instance1 and instance2,
then if you

  1. map instance1 to instance2
  2. loop over /instance1/outerRecordList
    – loop over /instance1/outerRecordList/innerRecordList
    ----- try to get pub.list.getRecordListItem from innerRecordList for instance2 (not 1) you find that instance2
    innerRecordList is not a list but just an innerRecord that matches the current iteration of instance1 innerRecordList.

This shows you how the map step (1) performs a reference copy. This occurs even if you initially map instance1 to instance3 then map instance3 to instance2 and drop instance3.
Does any one have suggestions on how to perform a map/deep copy without creating references. ?
Does pub.list.copyListItem create reference copies ?

If you map the fields of the record, rather than the record itself, to a temp record then you’ll get a copy.

outerRecordList
–innerRecordList
----field1
----field2

TempRec
–field1
–field2

Map the fields from the source innerRecord to the TempRec fields. Then map TempRec to the target innerRecord. Then drop TempRec.

If the record is large, this is quite tedious. Click. Drag. click.click.click CLICK CLICK…AUGGHH!

IDataUtil.deepClone, in the Java API, will create a deep copy. You’ll have to write a Java service to do the clone, calling it from within your loop.

If the record is relatively small (it’s not a PIP, or cXML or something huge) then I’d recommend using FLOW mapping steps at the field level (don’t map ANY record level things as you’ll get references).

Hope this rather scattered explanation makes sense.

Alright, I recovering from information overload. I read all the posting in this thread as well as the the thread Rob, pointed out above. So let me see if I got all this right.

There are three options here to deal with mapping and transformations of data for a complex structure, like recordList containing record and other record list.

Option 1) In Flow create a loop and specify the input and output arrays, then create your mappings under that loop. This options seems to be the best approach for a quick and simple mappings and is probably the fastest way to implement you logic; however, do I understand that in this flow implementation, that the flow will create references (shallow copy) of the structures, like record in the recordList, and perform the mappings from those references to the output record, which are also references, which has better performance, in that I do not have a physical copy of each structure as I loop through the list, but that the flow editor has, shall we say, some difficulties when it comes to editing the maps.

Option 2) As suggested by Rob, you create a loop specifing only the input array. Then create a temp structure,get the data via getRecordListItem and map to the temp structure, then append that temp structure to the output recordList, using the appendToRecordList service. The Cons here are having more work to do and having to manage the creation and clean up of the temporary structures that are created at each iteration. As well as, you are basically performing your own deep copy of the structures that you are mapping and therefore you are taking a performance hit in terms of memory and the number of step it take to perform the work, which could me non-trival if you have a large structure, and clean up for the temp structures. Good news is the flow editor has less difficulty in dealing with editing or the order of events used to create the overall flow and you are guarenteed to have the correct and physical copy of the data you want appened.

Option 3) Don’t do this in flow, do this as a Java service.
What are the pros and cons for writing a java service to preform this work?

Just wanted to make sure I understand the logic presented in this thread as well as the thread Rob mentioned above http://www.wmusers.com/wmusers/messages/117/366.shtml?

Any other thoughts, along the lines of evaluating different implemenations for this problem?

I guess the other thing I was going to ask was, when you are mapping values from a record inside a record list to other values in record inside recordList, what is the best approach if some of your values in the output record are not mapped, but you need to set the value. I understand how the mappings work in flow to create a new records in the record list, but how do you set the value for elements in the records so they are added to correct record iand appended to the output record list?

Here’s a fundamental item to be aware of: when mapping, IS creates new strings when mapping from one string to another. Thus, mapping A --> B results in two independent strings. For records, only references are copied as you’ve pointed out. Thus, if you map from one record to another, and map only strings (never the record and never nested records as a whole) then you’ll have independent records.

For options 1 AND 2 you need to create a temp structure (a new record) for the target list if you want to be able to make changes to one of the lists without impacting the other.

Maybe this way of thinking about it will help:

Consider the following Java frag:

Foo a = new Foo(“icky”); // constructor init for Bar field
Foo b = a;
System.out.println(a.getBar()); // will print icky
System.out.println(b.getBar()); // will print icky
a.setBar(“pooh”);
System.out.println(a.getBar()); // will print pooh
System.out.println(b.getBar()); // will print pooh

Changes to a are reflected in b, since both vars refer to the same underlying object. If you want to be able to manipulate a without it messing up b, then b needs to be allocated separately.

Foo a = new Foo();
Foo b = new Foo(a); // assuming a “clone” constructor exists
System.out.println(a.getBar()); // will print icky
System.out.println(b.getBar()); // will print icky
a.setBar(“pooh”);
System.out.println(a.getBar()); // will print pooh
System.out.println(b.getBar()); // will print icky

So, if your source and target structures need to be independently modifiable, you MUST create temp structures (think of it as doing a “new”) regardless of doing Option 1 or 2.

Option 3 doesn’t improve things. It will be just as complex as doing it in flow, and harder to troubleshoot (can’t trace) and maintain.

Just use the “Set value…” button in Developer to hard-code values for any record field you desire.

Thanks Rob, it help to think of this in terms of Java, good example.

thank you Rob Eamon! I’ve been punishing myself for days by overcomplicating a (now) simple mapping into a deeply nested structure. reading your post really helped!

i want flow steps of EDI to FlatFile.
could any one tell me

hi Syam,
Go through Edi documentation provided in the Integration Server
where u can acess through the Administartor mode (solutions\EDI\EDI module users guide) u can find the solution

hi all,
i am new to webmethods.i am creating an outbound-812,webmethods6.1 from the database(ms-access).
i have created individual flowservices from each table that populate the segments.i am a bit unclear about the process of connecting the segments.and creating the main map.i would like somebody to help me in the process.
i have gone through samples.i am confused. plz, suggest me with the right approach.i will be glad if you provide me with an example.