Datawave extract string using regexp - mule

I'm trying to extract a part of a string using a regular expression:
\[CODE\] \((.*?)\)
Given the string [CODE] (ABC-212) Rest of the title this match (https://regexr.com/557qd)
I used this regexp in my current java application, and now I'm trying to transform this on a Mule App.
Reading the documentation I see that I need to use a Transform, so I setup like this:
%dw 2.0
output application/json
---
vars.subject match(/\[CODE\] \((.*?)\)/)
I stored the string on the var called subject.
Using that regexp on Mule, do not works.. but in my java application does. What I'm doing wrong ?

DataWeave doesn't seem to have a global search flag (the g at the end of the original regex). This means the regular expression has to match the entire string. You use the parenthesis to indicate capture groups that will be returned additionally to the matched string.
Script:
vars.subject match(/^\[CODE\] \((.*)\).*/)
Output:
[
"[CODE] (ABC-212) Rest of the title",
"ABC-212"
]

Match in DataWeave returns an array that contains the entire matching expression, followed by all of the capture groups that match the provided regex. And in your case "Rest of the title" was not matching as per per Regex provided by you.
%dw 2.0
output application/json
var subject="[CODE] (ABC-212) Rest of the title"
---
//Catch here is, Regex should be fully matching as per input,
{
matchesOnly:subject matches /(\[CODE\]) \((.*?)\)[\w\W]*/,
matchOnly: subject match /(\[CODE\]) \((.*?)\)[\w\W]*/
}

Related

Bigquery named parameters regex in Java

I am looking for a way to use a regex as value in a named parameter in the Java SDK. According to the documentation, there is no datatype for that, and using a String parameter does not work.
Is there any way to use a regex as value in a named parameter?
QueryParameterValue Class has no datatype for that:
https://googleapis.dev/java/google-cloud-clients/0.91.0-alpha/com/google/cloud/bigquery/QueryParameterValue.html#of-T-com.google.cloud.bigquery.StandardSQLTypeName-
A regex in the query would e.g. look like this:
REGEXP_CONTAINS(some_attribute, r"^any\sregex\ssearchstring$")
and should be replaced by a named parameter like:
REGEXP_CONTAINS(some_attribute, #named_regex_parameter)
I tried different syntax in the query like
REGEXP_CONTAINS(some_attribute, r#named_regex_parameter)
etc. but none of them worked. The #named_regex_parameter is of type String. I tried to use values in the form of r"regex_expression" and just the regex_expression in the parameter value.
Seems like I need to build the query String without a named parameter for the regex part. Any hints to solve this with parameters would be really appreciated!
//Edit: added code example how the named parameters are used in the query config
QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query)
.setDestinationTable(TableId.of(destinationDataset, destinationTable))
.setAllowLargeResults(true)
.setCreateDisposition(CreateDisposition.CREATE_IF_NEEDED)
.setTimePartitioning(partitioning)
.setWriteDisposition(WriteDisposition.WRITE_APPEND)
.setParameterMode("NAMED")
.addNamedParameter("regexExpressionParam", QueryParameterValue.string(someRegexExpressionStringVariable)) //this does not work
.addNamedParameter("someStringParam", QueryParameterValue.string(stringVariable))
.setPriority(Priority.BATCH)
.build();
The query should use the parameter #regexExpressionParam like so:
REGEXP_CONTAINS(theAttributeToQuery, #regexExpressionParam))
You need to pass the regular expression string without r'...'
I had a very similar problem with running parameterized queries on Python: it was something like this.
from google.cloud import bigquery
regex_input = "^begin_word.*end_here$"
# Construct a BigQuery client object.
client = bigquery.Client()
query = """
SELECT word, word_count
FROM `bigquery-public-data.samples.shakespeare`
WHERE REGEXP_CONTAINS(word, #regex)
ORDER BY word_count DESC;
"""
job_config = bigquery.QueryJobConfig(
query_parameters=[
bigquery.ScalarQueryParameter("regex", "STRING", f"r'{regex_input}'"),
]
)
query_job = client.query(query, job_config=job_config)
At first, I thought the input had to be wrapped by r'...'; just like how I normally write a regex on BQ explorer.
I tried to modify the string input to make it like a regular expression, which was this pard f"r'{regex_input}'" of the code.
but apparently BQ correctly escapes string without our help and I can just pass down the regex string like bigquery.ScalarQueryParameter("regex", "STRING", regex_input)

mule3 to mule 4 expression to dataweave 2.0

I'm new to migrating the mule 3 apps to mule 4 I have done almost conversion but one expression stopped my flow and not able to achieve the logic for it if anyone has an idea regarding the expression to transform please help me
Expression:
if(flowVars.maindata.keySet().contains(payload.idCaseNumber))
{
flowVars.temporary=[];
flowVars.maindata.get(payload.idCaseNumber).add(map);
}
else
{
flowVars.temporary.add(previousdata);
vars.maindata.put(payload.idCaseNumber,temporary);
}
I have tried up to my knowledge on the above code but still I'm getting problem
flowVars.maindata.get(payload.idCaseNumber).add(map);
In Mule 3 the expression language is MEL. In Mule 4 it is DataWeave 2.0. You can't just translate directly. MEL is an imperative scripting language, similar to a subset of Java and it is easy to call Java methods. DataWeave 2.0 is a functional language. Furthermore Mule 4 operations (example: a , , etc) can only return one value, which can be assigned to the payload or to one variable.
For your snippet I'll assume that maindata is a map. You can use two set-variable to assign each variable:
<set-variable variableName="temporary" value="#[ if( namesOf(vars.maindata) contains payload.idCaseNumber ) [] else vars.temporary ++ **previousdata** ]" />
I don't know exactly what do you use for previousdata.
To update the variable maindata it is probably a good match for the update operator, in a separate or Transform operation, with the same condition than for vars.temporary.
Update:
I'll assume vars.maindata is a map, which DataWeave will consider an object, and each element is a list. As an example of doing an 'upsert' operation with a dynamic selector:
%dw 2.0
output application/java
var temporary=[5]
var maindata={ a:[1,2,3,4] }
var myKey="a"
---
maindata update {
case data at ."$(myKey)"! -> if (data != null) data ++ temporary else temporary
}
You could replace in above script the DataWeave var temporary with the expression from my example above, and the other DataWeave variables with the Mule variables (vars.name) or payload. If you change in above example myKey to have value "b" you will see that key being added.

compare with properties file values with local variable in dataweave

In below dataweave code, comparision is not working properly for me.
Properties file key and value as below :
domain=Sales Domain, Retail Domain
Dataweave code :
%dw 2.0
output application/json
var test = 'Sales Domain'
---
{
result: if(upper(test) != (upper(Mule::p('domain')))) "Not equal" else ("equal")
}
Could you please help on this ?
The property domain contains the string Sales Domain, Retail Domain. The comparison with the variable test which contain the string Sales Domain. Obviously both strings are different, even converting to uppercase (upper()).
If you want to check if one string contains the other you could use the contains() function instead.
In DataWeave there is not a not-equal operator to compare the values. You can use the not operator to negate the result of an expression.
For example:
%dw 2.0
output application/json
var test = 'Sales Domain'
---
{
result: if(upper(Mule::p('domain')) contains upper(test)) "contains" else "not contains"
}

How to generate dynamic XML Response in Mule4?

In Mule4, I need to convert json sample data in to dynamic XML format, I have tried with dataweave(2.0) field mapping, getting null values. Does anyone can help me on this?
If the question is just asking out to build up XML output from JSON input, that is a pretty open-ended question. What do you want to evaluate dynamically? You could, for example, use part of the payload to set values in the DataWeave expression.
There is a more difficult version of this question: how to dynamically evaluate DataWeave code constructed into an input string, where this string could be read from various script files, or even constructed in-line from some input data (payload, attributes, or variables).
Here is another example covered in our MuleSoft DataWeave training course at http://training.mulesoft.com.
You can use a Dynamic Evaluate component to dynamically evaluate a constructed DataWeave expression string. Here is an example that replaces the uName parameter with a dynamic value.
Also, the expression is configured to read in different script files based on some condition:
output application/json
---
do {
var choice = attributes.queryParams.script default "NO_SCRIPT"
---
if(choice == "NO_SCRIPT")
"output application/json --- {result: 'NO SCRIPT ENTERED'}"
else if(choice == "script1") vars.script1
else if (choice == "script2") vars.script2
else read(choice)
}
Here are two example scripts that substitutes values for uName and produce different types of output (XML vs. JSON).
This is script1:
output application/xml
---
root: { message: "order "
++ attributes.queryParams.orderid
++ " has been received from "
++ uName, items: payload.items}
This is script2:
output application/json
---
root: { message: "Order2 "
++ attributes.queryParams.orderid
++ " has been received from "
++ uName, items: payload.items}
Notice that this example is dangerous. It lets the web client inject any DataWeave code into the Mule flow, so this example should never be copied into production code, but it does demonstrate the ability to run any DataWeave code passed into a Mule application.

How to concatenate 2 values in mule?

Can someone please let me know how to concatenate multiple values in mule?
Something like,
#[payload.getPayload()].concat(#[getSubject()])
I assume you are using Mule 3.3.x or above. If so you can use Mule Expression Language(MEL).
One example using MEL is:
#['Hello' + 'World']
Or MEL also allows you to use standard Java method invocation:
#[message.payload.concat(' Another String')]
Cheat sheet on MEL
MULE 4 Update
For Mule 4. Dataweave 2.0 is the main expression language:
Simple concat:
#['Hello' ++ ' World']
Other alternative is to use Mule Design plugin :
Drop an "Append String" operation as many times as you need.
This operation takes the message payload of the previous step and concats a specified string to it.
Not sure about performance details, but it will be surely more easy to maintain.
Append to String - MuleSoft
you can declare a string buffer using expression component
<expression-component doc:name="Expression"><![CDATA[StringBuffer sb = new
StringBuffer();
flowVars.stBuffer=sb;
]]></expression-component>
and then append use append on string buffer any where in the flow.
flowVars.stBuffer.append("string to append")
Once done use #[flowVars.stBuffer] to access the concatenated string
If you want to add two different values received through payload in the mule flow then we can use concat() method.
For example below we have received values through arraylist where i am adding two diffrent fields i.e. FirstName and the LastName -
concat(#[payload[0].'firstname']," " #[payload[0].'lastname']