Is it possible to modify the original collection in foreach inside loop? - mule

I want to mimick this:
for (int i = 0; i < items.getTotal(); i++) {
// ....
items = // new items get assigned.
}
Is it possible with foreach component?

I think you will better of using a collection-splitter and a collection-aggregator which will modify the original payload.
<collection-splitter />
<set-payload value="do something" />
<collection-aggregator />
Alternatively, if you must use foreach, you could use a flowVar to keep track of the items and the set the payload to the flowVar after the foreach:
<set-variable variableName="items" value="#[[]]" />
<foreach>
<set-payload value="do something" />
<expression-component>flowVars.items.add(payload)</expression-component>
</foreach>
<set-payload value="#[flowVars.items]" />

A workaround:
Outside the foreach:
Set a session variable X to the content of the linkedlist thru which
you want to loop.
All my MS JDBC 4.1 stored procedure calls return 1-n hashmaps with key=resultSetx and value of a linkedlist. Each occurrence in the linkedlist is another hashmap containing a 1 row's worth of resultset pairs (key=value) - so we run into this a lot.
At the foreach top level:
Set the payload collection reference to the payload which contains
the linkedlist. Reminder: (The default counter flowVar starts
at 1. Linkedlist offsets begin at 0.)
Inside the foreach:
Set another variable (ctr-1) equal to counter - 1; if you don't it
can make some ugly and difficult MEL with those counter -1
references).
Point your list inserts at the session variable X linkedlist.
After completion of foreach:
- Don't forget to remove the redundant list it wastes space.
Cheers-MPC:-)

Related

MutableList of MutableLists in Kotlin: adding element error

Why I'm getting "java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0" while running next code??? :
val totalList = mutableListOf<MutableList<Int>>()
fun main() {
for (i in 0..15) {
for (j in 0..10) {
*some operations and calculations with **var element of type Int***
totalList[i].add(element)
}
}
}
I was thinking that in such case while iterating through 'j' it should add elements to mutableList[i], after this it should start adding elements to mutableList[i + 1] etc.... But instead I am recieving IndexOutOfBoundsException....
val totalList = mutableListOf<MutableList<Int>>()
All this does is create one list which is going to contain MutableList<Int> items. Right now, there's nothing in it (you've supplied no initial elements in the parentheses).
Skip forward a bit, and you do this:
totalList[0].add(element)
You're trying to get the first element of that empty list and add to it. But there is no first element (index 0) because the list is empty (length 0). That's what the error is telling you.
There's lots of ways to handle this - one thing you could do is create your lists up-front:
// create the 16 list items you want to access in the loop
// (the number is the item count, the lambda generates each item)
val totalList = MutableList(16) { mutableListOf<Int>() }
// then refer to that list's properties in your loop (no hardcoded 0..15)
for (i in totalList.indices) {
...
// guaranteed to exist since i is generated from the list's indices
totalList[i].add(element)
}
Or you could do it the way you are now, only using getOrElse to generate the empty list on-demand, when you try to get it but it doesn't exist:
for (i in 0..15) {
for (j in 0..10) {
// if the element at i doesn't exist, create a list instead, but also
// add it to the main list (see below)
totalList.getOrElse(i) {
mutableListOf<Int>().also { totalList.add(it) }
}.add(element)
}
}
Personally I don't really like this, you're using explicit indices but you're adding new list items to the end of the main list. That implicity requires that you're iterating over the list items in order - which you are here, but there's nothing enforcing that. If the order ever changed, it would break.
I'd prefer the first approach - create your structure of lists in advance, then iterate over those and fill them as necessary. Or you might want to consider arrays instead, since you have a fixed collection size you're "completing" by adding items to specific indices
Another approach (that I mentioned in the comments) is to create each list as a whole, complete thing, and then add that to your main list. This is generally how you do things in Kotlin - the standard library contains a lot of functional tools to allow you to chain operations together, transform things, and create immutable collections (which are safer and more explicit about whether they're meant to be changed or they're a fixed set of data).
for (i in 0..15) {
// map transforms each element of the range (each number) to an item,
// resulting in a list of items
val items = (0..10).map { j ->
// do whatever you're doing
// the last expression in the lambda is its resulting value,
// i.e. the item that ends up in the list
element
}
// now you have a complete list of items, add them to totalList
totalList.add(items)
}
(Or you could create the list directly with List(11) { j -> ... } but this is a more general example of transforming a bunch of things to a bunch of other things)
That example there is kinda half and half - you still have the imperative for loop going on as well. Writing it all using the same approach, you can get:
val totalList = (0..15).map { i ->
(0..10).map { j ->
// do stuff
element
}
}
I'd probably prefer the List(count) { i -> ... } approach for this, it's a better fit (this is a general example). That would also be better since you could use MutableList instead of List, if you really need them to be mutable (with the maps you could just chain .toMutableList() after the mapping function, as another step in the chain). Generally in Kotlin, collections are immutable by default, and this kind of approach is how you build them up without having to create a mutable list etc. and add items to it yourself

Why can't I use map on Kotlins Regex Result sequence

I worked with Kotlin's Regex API to get occurences of some regular expression. I wanted to convert the finding directly into another object so I intuitively used map() on the result sequence.
I was very surprised that the map function is never called but forEach is working. This example should make it clear:
val regex = "a.".toRegex()
val txt = "abacad"
var counter = 0
regex.findAll(txt).forEach { counter++ }
println(counter) // 3
regex.findAll(txt).map { counter++ }
println(counter) // still 3 since map is not called
regex.findAll(txt).forEach { counter++ }
println(counter) // 6
My question is why? Did I oversee it in the documentation?
(tested on Kotlin 1.5.30)
findAll() returns a Sequence<MatchResult>. Operations on Sequence are classified either as intermediate or terminal. The documentation for the functions declares which type they are. map and onEach are intermediate. Their action is deferred until a terminal operation is made. forEach is terminal.
Manipulating a Sequence with map returns a new Sequence that will perform the mapping function only when it is actually iterated, such as by a call to forEach or using it in a for loop.
This is the purpose of Sequence, to defer mutating functional calls. It can reduce allocations of intermediate Lists, or in some cases avoid applying the mutations on every single item, such as if the terminal call in the chain is a find() call.

Choice flow control component fails in Mule ESB

i have a choice flow control component that uses an expression as follows:
<choice>
<when expression="${LoggingFlag} == YES">SOME CODE</when>
<otherwise>SOME OTHER CODE</otherwise>
</choice>
Here LoggingFlag used is a key-value pair defined in the app.properties file.
LoggingFlag=NO
when i run the code i see the following error:
Execution of the expression "NO == YES" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: String
Exception stack is:
1. [Error: unresolvable property or identifier: NO]
[Near : {... NO == YES ....}]
Can someone tell me what is the reason behind this issue?
This error occurs due to Mule not being able to resolve the type of value, set to LoggingFlag while comparing it in choice.
For this you need to explicitly change the type to string, so that Mule can compare the two easily.
For that you need to use:
<choice>
<when expression="'${LoggingFlag}' == 'YES'">SOME CODE</when>
<otherwise>SOME OTHER CODE</otherwise>
</choice>
You need to enclose the variables in when expression within single quotes ' '
<choice doc:name="Choice">
<when expression="'${LoggingFlag}' == 'YES'"><set-payload value="payload 1" doc:name="Set Payload"/></when>
<otherwise><set-payload value="payload 2" doc:name="Set Payload"/></otherwise>
</choice>
You can even try by reading the property value and storing it in a variable and then comparing the variable value with the string in choice component as follows:
<set-variable variableName="SetLoggingFlag" value="${LoggingFlag}" doc:name="SetLoggingFlag"/>
<choice>
<when expression="#[flowVars.SetLoggingFlag=='YES']">SOME CODE</when>
<otherwise>SOME OTHER CODE</otherwise>
</choice>
Hope this helps you!

Modifying self in `iter_mut().map(..)`, aka mutable functional collection operations

How do I convert something like this:
let mut a = vec![1, 2, 3, 4i32];
for i in a.iter_mut() {
*i += 1;
}
to a one line operation using map and a closure?
I tried:
a.iter_mut().map(|i| *i + 1).collect::<Vec<i32>>();
The above only works if I reassign it to a. Why is this? Is map getting a copy of a instead of a mutable reference? If so, how can I get a mutable reference?
Your code dereferences the variable (*i) then adds one to it. Nowhere in there does the original value get changed.
The best way to do what you asked is to use Iterator::for_each:
a.iter_mut().for_each(|i| *i += 1);
This gets an iterator of mutable references to the numbers in your vector. For each item, it dereferences the reference and then increments it.
You could use map and collect, but doing so is non-idiomatic and potentially wasteful. This uses map for the side-effect of mutating the original value. The "return value" of assignment is the unit type () - an empty tuple. We use collect::<Vec<()>> to force the Iterator adapter to iterate. This last bit ::<...> is called the turbofish and allows us to provide a type parameter to the collect call, informing it what type to use, as nothing else would constrain the return type.:
let _ = a.iter_mut().map(|i| *i += 1).collect::<Vec<()>>();
You could also use something like Iterator::count, which is lighter than creating a Vec, but still ultimately unneeded:
a.iter_mut().map(|i| *i += 1).count();
As Ry- says, using a for loop is more idiomatic:
for i in &mut a {
*i += 1;
}

Is there a while loop in Camel?

Is there an idea of a while loop in Camel?
We are using Camel for doing batch processing (not really the remit of an ESB I know). I want to keep checking on the status of something else whilst I am processing messages in the ESB. I can only find a loop that loops for a defined number of times, i.e. for testing or a quartz timer that will check every x seconds. Neither of these are really suitable.
Any suggestions, or am I asking for something simply outside of the remit of an ESB?
What about doing something like this:
<camelContext id="myContext">
<route id ="initializer">
<!--This will be created only once -->
<from uri="timer://foo?repeatCount=1"/>
<to uri="seda:mySedaQueue"/>
</route>
<route id ="myRoute">
<from uri="seda:mySedaQueue"/>
<choice>
<when>
<simple>{your condition if you want to continue}</simple>
...
<to uri="seda:mySedaQueue" />
</when>
<otherwise>
...
</otherwise>
</choice>
</route>
</camelContext>
How about the camel timer:?
E.g.
from("timer://foo?fixedRate=true&period=1000")
.to("bean:myBean?method=someMethodName");
Reference: Camel Timer Component
Try using DynamicRouter.
It uses an Expression class to determine the next route to dispatch the exchange. If the expression returns null it means that it will stop routing.
This way you can evaluate the exchange contents and continue routing to the same route until you decide is time to stop, and then return null.
from("direct:start")
.dynamicRouter(new Expression() {
#Override
public <T> T evaluate(Exchange exchange, Class<T> type) {
if (<your condition>) return (T) "direct:whileRoute";
return null;
}
})
.to("mock:finish");
from("direct:whileRoute")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
// Do whatever you want
}
});