Pass an expression to tokenize() - apache-camel

I have a route that consumes a file and splits it:
from("file:etc.")
.split(body().tokenize("\n", 100, false)).streaming()
The second parameter is set to a constant 100. Is there a way to have it wary, based on the file. For instance, just before I hit the "split" I could set a value in the header, and it would be cool if I could then do:
.split(body().tokenize("\n", simple("...pull header value..."), false))
but, tokenize() needs an integer, not an expression.
Is there a neat way to achieve what I want: varying the value of 'group'?

I haven't seen that you can pass expressions to your tokenize method. However you can do like this:
.split().method("mySplitterBean", "splitBody")
Pass the entire exchange and then you can access the headers and properties.
See an example here under streaming mode pojo;
http://camel.apache.org/splitter.html

Related

Can't get Logic App Contains to work with array or comma separated string

I'm trying to look for specific keywords inside of text from a for each loop.
var text = "The lazy fox jumped over the brown dog."
var keywords = "fox,dog,sun";
If true, I want to do something with the text. If false, I want to ignore the text.
Does anyone know how to use an Array filter, Function, Select, Condition or inline code to check for this? If so, specific examples would be great.
By the way, I have a C# function that handles this extremely well in an ASP.net Core app.
UPDATE 1:
This doesn't work.
UPDATE 2:
The Condition is always false after the for each loop even after changing the settings and parallelism to 1.
Azure Logic App Condition does not work in loop if based on changing values
Thanks in advance!
There are so many ways to achieve what you need. Here are the 3 options that came to my mind within a minute.
The first one does use a For each loop, but I wouldn't recommend using it as it's not very efficient.
The For each parameter looks like this:
The Condition parameter looks like this:
The second option is much easier - no need for a loop, just filter the array straight away, then you can check whether it's empty or it has some items:
The Filter array parameters look as follows.
The split function is identical to the one used in option 1.
If you know JavaScript, you might decide to use regular expressions in inline code instead, e.g.:
Then you'd just need to check the output of the inline code. JavaScript code used in the example above:
var text = workflowContext.actions.Compose_text.outputs;
var keywords = workflowContext.actions.Compose_keywords.outputs;
return text.match(new RegExp("(" + keywords.split(",").join("|") + ")", "gi"));
My personal preference is option 2. However, please note that all 3 options above would find "sun" in text "The weather was sunny" even though there's no word "sun" in the text. If you do need "sun" to match only word "sun" - not "sunny", "asunder" or "unsung" - then go for option 3, just use a different, more complex regular expression.
One of the workaround would be use of Condition Connector. I have initialized the sentence in a string and then used Condition Connector which will be checking the conditions.
Finally, In the true section you can add the connectors accordingly.
Placing a Compose behind the for each loop and referencing the Output in the Condition is what finally worked for me. I used the toLower() function in my Compose. The Compose looks like this.
toLower(items('For_each_2')?['day']?['longPhrase'])

Is it possible to pass a dynamic group value to tokenizer in camel?

I want to specify the grouping size dynamically.
Is something like this possible ?
split().tokenize("\n", ..value from header or property...)
how to specify this value ?
--Clarifying: my question reads like I intend to dynamically change it during the execution of the route.
This is not what I need,
I need just a way to pass in a configurable splitsize, that is calculated in a bean.
No that is not possible, the group is a fixed number.
However instead of using tokenize you can use a java method call and return an Expression where you can do something similar to what TokenizeLanguage#createExpression does but where you can set the group value with a dynamic value.

Formatting values with AngularJs filters

I am writing a common control that will be used to format data inside a grid. It has 2 parameters that user can set:
filter (string) that is used to format value
parameters (any[]) that are used by the filter
In the code I am going to call $filter(filter)(value, ...) - here is my problem. How do I pass my parameters? Each filter can have from no parameters to who knows how many. So, is there a nice way to pass variable number of parameters in Angular? So far I did not run into a way of doing it.
You should be able to do:
$filter(filter).apply(this, parameters)

eval in function scope (accessing function args)

Given:
abstract ABSGene
type NuGene <: Genetic.ABSGene
fqnn::ANN
dcqnn::ANN
score::Float32
end
function mutate_copy{T<:ABSGene}(gene::T)
all_fields_except_score = filter(x->x != :score, names(T))
all_fields_except_score = map(x->("mutate_copy(gene.$x)"),all_fields_except_score)
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
end
ng = NuGene()
mutated_ng = mutate_copy(ng)
results in:
ERROR: gene not defined
in mutate_copy at none:4
If I just look at it as a string (prior to running parse and eval) it looks fine:
"NuGene(mutate_copy(gene.fqnn),mutate_copy(gene.dcqnn))"
However, eval doesn't seem to know about gene that has been passed into the mutate_copy function.
How do I access the gene argument that's been passed into the mutate copy?
I tried this:
function mutate_copy{T<:ABSGene}(gene::T)
all_fields_except_score = filter(x->x != :score, names(T))
all_fields_except_score = map(x-> ("mutate_copy($gene.$x)"),all_fields_except_score)
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
end
But that expands the gene in the string which is not what I want.
Don't use eval! In almost all cases, unless you really know what you're doing, you shouldn't be using eval. And in this case, eval simply won't work because it operates in the global (or module) scope and doesn't have access to the variables local to the function (like the argument gene).
While the code you posted isn't quite enough for a minimal working example, I can take a few guesses as to what you want to do here.
Instead of map(x->("mutate_copy(gene.$x)"),all_fields_except_score), you can dynamically look up the field name:
map(x->mutate_copy(gene.(x)), all_fields_except_score)
This is a special syntax that may eventually be replaced by getfield(gene, x). Either one will work right now, though.
And then instead of eval(parse("$(T)("*join(all_fields_except_score,",")*")")), call T directly and "splat" the field values:
T(all_fields_except_score...)
I think the field order should be stable through all those transforms, but it looks a pretty fragile (you're depending on the score being the last field, and all constructors to have their arguments in the same order as their fields). It looks like you're trying to perform a deepcopy sort of operation, but leaving the score field uninitialized. You could alternatively use Base's deepcopy and then recursively set the scores to zero.

AugluarJS truncating trailing equal sign

AngularJS truncates the trailing equal signs when routing to them. I have a base64 string which need to be added as a query parameter to the url(route)
ex: http://example.com/#!/updatepassword?code=NnuW3q49QW38Mf-Cg==
this loads as:
http://example.com/#!/updatepassword?code=NnuW3q49QW38Mf-Cg
Is there a workaround for this?
If you try to set route as a string, then you need to escape = sign. That's because this character has a special meaning in the query string - it separates parameter name from its value.
So, one solution could be:
var query = "code=NnuW3q49QW38Mf-Cg==";
$location.url("/some/path?" + encodeURIComponent(query));
What encodeURIComponent() will do, is it will replace all special characters - = will be replaced with %3D for instance. This will prevent it from being interpreted as a key-value separator.
If you only want to change the query string parameters, not the whole URL, you can also use $location.search() method:
$location.search("code", "NnuW3q49QW38Mf-Cg==");
Just remember to pass two parameters to that method, not one. If you do:
$location.search("code=NnuW3q49QW38Mf-Cg==");
the = sign will not get escaped, only stripped.
Angular uses parseKeyValue() function internally to parse query string, it can be found here. You can see that the split is being done over the = sign. That's why they get stripped.
But if you take a look at .search() method implementation, you see that parseKeyValue() is being called only if you supply one argument to .search(). It's not invoked if you supply name of the parameter as a first, and value as a second argument.
Peeking at the source code also suggests yet another solution:
$location.search({"code": "NnuW3q49QW38Mf-Cg=="});

Resources