def host = /\/\/([a-zA-Z0-9-]+(\.[a-zA-Z0-9-])*?)(:|\/)/
assertHost 'http://a.b.c.d:8080/bla', host, 'a.b.c.d'
def assertHost (candidate, regex, expected){
candidate.eachMatch(regex){assert it[1] == expected}
}
I know the above code is asserting my inputs! But in line 4, inside the closure, the magic variable (it) is being represented in an array! I'm bit confused on it. How does it work?
How does this work in Groovy (illustrate with simple code)?
From http://groovy.codehaus.org/groovy-jdk/java/lang/String.html:
replaceAll
public String replaceAll(String regex, Closure closure)
Replaces all occurrences of a captured group by the result of a closure on that text.
For examples,
assert "hellO wOrld" == "hello world".replaceAll("(o)") { it[0].toUpperCase() }
assert "FOOBAR-FOOBAR-" == "foobar-FooBar-".replaceAll("(([fF][oO]{2})[bB]ar)", { Object[] it -> it[0].toUpperCase() })
Here,
it[0] is the global string of the matched group
it[1] is the first string in the matched group
it[2] is the second string in the matched group
Related
I receive a string like this: "The code is ${code}. Your currency is ${currency}".
The ${...} characters are already part of the string, not variables.
I have a map with key-value and I would like to replace all the occurrences of the ${key} with the value:
def myMap = [
'code' : '123456',
'currency' : 'CHF'
]
myMap.each{
fieldValue.replaceAll("${$.key}", it.value)
}
The expected result is the following one: "The code is 123456. Your currency is CHF".
I'm stuck because I don't know how to deal with the $ {} character escapes. I can escape the $ character but not {}. Any idea in order to achieve the expected result?
You need to quote the outer $ and use it.key: "\\${$it.key}"
Also you can use each here as it is for side-effects and replaceAll
does not modify the string (strings in java are immutable). So you need
something like this:
def result = myMap.inject(fieldValue){ acc, kv ->
acc.replaceAll("\\${$kv.key}", kv.value)
}
Or by using a regexp:
fieldValue.replaceAll(/\$\{(.+?)\}/, { _, k -> myMap[k] })
It works also with closure and with delegate strategy. You can evaluate your string in the context of the map. See this example:
def myMap = [
'code' : '123456',
'currency' : 'CHF'
]
closure = { "The code is ${code}. Your currency is ${currency}" }
closure.delegate = myMap
println closure()
I am taking a JSON input and I want it to convert it to uppercase. Can someone please help me with my code
int synchronizeSingleUnit(ApiResultDTO apiResultDTO, def inputJSON, int totalUpdates) {
def sql = synchronizationApiSqlHelperService.getUnitsSql()
String unit = getEmptyIfValueNull(inputJSON.unit)
def session = sessionFactory_apiDb.openSession() as SessionImpl
def connection = session.connection()
def sqlConnection = new Sql(connection)
try {
sqlConnection.execute(sql, [unit:unit])
} catch (Exception ex) {
// Preload result with statement to be executed
apiResultDTO.setJsonFailingPart(inputJSON)
apiResultDTO.setFailedSql(sql, [unit:unit])
throw new ExceptionWrapper(apiResultDTO, ex)
} finally {
session.close()
connection.close()
}
You can use java String.toUpperCase() as in:
String unit = getEmptyIfValueNull(inputJSON.unit)
String uCaseUnit = unit.toUpperCase()
< -- edit -- >
As a comment and addition, I don't know the specifics of method getEmptyIfValueNull but judging from the name you just want to return an empty string when the expression inputJSON.unit returns null.
Groovy has two special operators which make expressions like these easier to write.
the safe navigation operator ?. and
the elvis operator ?: (see how that looks like an Elvis smiley?)
using these two you could rewrite your code somewhat more concisely as:
String unit = inputJSON.unit?.toUpperCase() ?: ''
explanation:
inputJSON.unit?.toUpperCase() - evaluate inputJSON.unit and if that expression returns null, just return null from the entire expression (never executing the toUpperCase method). If inputJSON.unit returns a non-null value, things work as they would just by using inputJSON.unit.toUpperCase().
... ?: '' - take an expression and if it is not empty string or null,return it, otherwise return the empty string.
Where the first operator .? is specifically for handling null values and the second operator ?: uses groovy truth which includes, but is more inclusive than just null values.
There are a few ways of writing the above, for example:
String unit = (inputJSON.unit ?: '').toUpperCase()
but to my mind the first version "flows" better. To each his own.
im doing something stupid to try to send html email and not really understanding what im doing but I want to send a multiline string to a function and get the same string back with something appended to each line - what am i doing wrong?
def htmlizetext(intext: String) {
for(line <- intext.linesWithSeparators) {
<br>line<br/>
}
}
def htmlizetext(intext: String): String = {
for(line <- intext.linesWithSeparators) {
line + "<br/>"
}
}
Neither of the above work
You need yield, = (without = the method will still return Unit) and some form of concatenation:
def htmlizetext(intext: String) = {
for (line <- intext.linesWithSeparators) yield {
line + "<br/>
}
}.mkString
or the shorter equivalent:
def htmlizetext(intext: String) =
intext.linesWithSeparators.map(_ + "<br/>").mkString
Have a look at yield, that is probably what you are looking for.
def htmlizetext(intext: String) = {
for(line <- intext.linesWithSeparators) yield {
<br>line<br/>
}
}
You might additionally want to join all the elements from the returning list for returning a single String instead of a list of such strings
You are currently not returning a thing from your method as you do not return anything from your for statement which is the last method of your statement. Therefore, the Scala compiler infers that you are returning Unit.
Because for does't have a return value, unless you use yield...
A better solution would be to "map" your collection as follows:
intext.linesWithSeparators.map(line=> s"$line<br/>").mkString("")
this will turn your string in the desired format and then join all of them using mkString. If you need it, you can specify a separator instead of empty string
I have seen strange code for many times:
...
private currencyFormat = NumberFormat.currencyInstance
def convert = currencyFormat.&parse
...
By strange I mean this -> .&parse. Why logical AND operator is needed and who else it can be used?
That's a method pointer
convert is now effectively a Closure which delegates to the parse method
Example
It's defined here without an example, and mrhaki did a post about it here.
And as an example showing it handles overloading, consider a class with 2 static methods:
class Test {
static void printSomething( String thing ) {
println "A:$thing"
}
static void printSomething( String thing, String thing2 ) {
println "B:$thing$thing2"
}
}
We can get a reference to the printSomething methods:
def ref = Test.&printSomething
And then we can pass it to an each call on a list of single items:
// prints A:a and A:b
[ 'a', 'b' ].each ref
Or we can pass it two items and it will pick the correct overloaded method to call:
// prints B:ab and B:cd
[ [ 'a', 'b' ], [ 'c', 'd' ] ].each ref
It's not a bit manipulation operator. The ampersand was probably chosen because that's what C's address operator uses. The idea is that you can pass around references to a method on a specific instance.
Say you have some logic like:
def stuff = null
if (condition) {
stuff = foo.doThis(a, b, c)
} else {
stuff = bar.doOther(a, b, c)
}
You can rewrite that with a method pointer like this:
def myMethod = condition ? foo.&doThis : bar.&doOther
def stuff = myMethod(a, b, c)
It doesn't mean and. It's special syntax to reuse a method as a closure. Now you can use convert in places where you can pass a closure, like grep, find or similar methods.
I have a class
class A{
String name
String address
}
def a = new A()
a.address = "some address"
println "${a.name} ${a.address}" => "null some address"
Here a.name is null, so the string printed will contains "null", however I hope the result is "some address" which ignore the null value.
I know I can use println "${a.name ?: ''} ${a.address ?: ''}" when printing, is there any simpler solution?
You could redefine the toString method for Groovy's null object to return an empty string instead of null.
def a = [a:null, b:'foobar']
println "${a.a} ${a.b}"
org.codehaus.groovy.runtime.NullObject.metaClass.toString = {return ''}
println "${a.a} ${a.b}"
This will print:
null foobar
foobar
If you only want to redefine toString temporarily, add the following after your last print... to change it back:
org.codehaus.groovy.runtime.NullObject.metaClass.toString = {return 'null'}
You can also change null's toString behavior using a Groovy Category [1] [2]. For example:
#Category(org.codehaus.groovy.runtime.NullObject) class MyNullObjectCategory {def toString() {''}}
use (MyNullObjectCategory) {
println "${a.a} ${a.b}"
}
You could implement a toString method in your class like so:
class A{
String name
String address
String toString() {
"${name ?: ''} ${address ?: ''}".trim()
}
}
then do
def a = new A( address:'some address' )
println a
To get some address printed out, but this still used the Elvis operator as you had in your question...
Not sure there's much simpler you can do...
Not sure if simpler, but:
[a.name, a.address].findAll().join(' ')
You may of course combine it with Tim's toString suggestion.
Notice that if any of the values might be "falsy" (e.g. 0), it will filter it out. You can fix that doing:
[a.name, a.address].findAll {it != null}.join(' ')
I think, a rather simple way of achieving it, i.e. removing null, is to concatenate the string and the use replace method.
myString=""
myString=myString + "Bla Bla"
myString.replace("null", '')