Grails - access data within Config.groovy whilst using variable in path - grails

I know that to access a variable from within the Config.groovy file,
grailsApplication.config.someValue.anotherValue
I want to use a variable within this path because I want to get a URL from the config file. The value foo is passed in as a parameter to the method which will be called a number of times using different variables based on other factors.
def foo = "anothervalue"
grailsApplication.config.someValue.${ foo }.
The actual path to the value I want in the config stays the same as in the first instance.
I have tried:
grailsApplication.config.someValue.${ foo }
grailsApplication.config.someValue${ foo }
grailsApplication.config.someValue + "${ foo }"
grailsApplication.config.someValue + ".${ foo }"
grailsApplication.config.someValue + ${ foo }

grailsApplication.config.someValue."${ foo }" must works.
grailsApplication.config returns a groovy.util.ConfigObject like groovy.util.ConfigSlurper.parse() so you can see how it works in the follow example:
import groovy.util.ConfigSlurper
def configTxt = '''
prop1 {
prop2 {
person.name = 'paco'
}
}
'''
def config = new ConfigSlurper().parse(configTxt)
def foo = "prop2"
println config.prop1."${foo}" // prints [person:[name:paco]]
Hope this helps,

more natural would be grailsApplication.config.someValue[ foo ]

Related

How can I handle un object via its reference groovy?

def c = Service1.search(params)
String filename = 'FILE.csv'
def lines = c.collect {
String k = it[1]
[k[0..10], it[0]].join(',')
} as List<String>
each Item 'it' is an object like com.pakage1#123fgdg.. so it shows me an error that i can't get it[1], how i can get the value from this objects thank you .
it is an object . Suppose your class has a property named email.so can get value by using it.email. when you iterate over list it works like this .

Groovy: Dynamic nested properties [duplicate]

I am wondering if I can pass variable to be evaluated as String inside gstring evaluation.
simplest example will be some thing like
def var ='person.lName'
def value = "${var}"
println(value)
I am looking to get output the value of lastName in the person instance. As a last resort I can use reflection, but wondering there should be some thing simpler in groovy, that I am not aware of.
Can you try:
def var = Eval.me( 'new Date()' )
In place of the first line in your example.
The Eval class is documented here
edit
I am guessing (from your updated question) that you have a person variable, and then people are passing in a String like person.lName , and you want to return the lName property of that class?
Can you try something like this using GroovyShell?
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
GroovyShell shell = new GroovyShell( binding )
def result = shell.evaluate( commandString )
Or this, using direct string parsing and property access
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
// Split the command string into a list based on '.', and inject starting with null
def result = commandString.split( /\./ ).inject( null ) { curr, prop ->
// if curr is null, then return the property from the binding
// Otherwise try to get the given property from the curr object
curr?."$prop" ?: binding[ prop ]
}

Groovy - Append values to variables in a string

Lets assume I have a domain class called Template that looks somewhat like this:
class Template{
String subject
...
}
I save an instance of this class:
Template t=new Template(subject:'Hello ${name}').save()
Now, I fetch this instance inside a method as follows:
def render(Long id){
String name='foo'
Template t= Template.get(id)
println t.subject
}
I want the "println t.subject" to be printed as "Hello foo". What I get is "Hello ${name}".
I want t.subject to dynamically replace the value of variable name - "foo" in place of ${name}.
Can this be achieved in groovy?
I cannot find any documentation of how to do this, or why this cannot be done.
Update:
I tried this on my GroovyConsole.
class Entity{
String name
}
class Template{
String name
String subject
}
String renderTemplate(Template template, Entity entity){
return template.subject
}
Entity e = new Entity(name:'product')
Template template=new Template(name:'emailTemplate',subject:'Product ${e.name}')
renderTemplate(template,e)
The Output I got was:
Result: Product product
class Template {
String subject
// ...
}
Template t = new Template(subject: 'Hello, ${name}').save()
Important: Use single quotes in 'Hello, ${name}' or you will get an error.
def render(Long id) {
String name = "world"
Template t = Template.get(id)
​def engine = new groovy.text.GStringTemplateEngine()
def subject = engine
.createTemplate(t.subject)
.make(name: name)​
println subject
}
There are a couple of things wrong with the code shown. You have this:
class Template{
String subject
...
}
Then you have this:
Template t=new Template(subject:"Hello ${name}").save()
The Groovy String assigned to the subject property will be evaluated as soon as you assign it to subject because subject is a String. The actual value will depend on the value of the name property that is in scope when that code executes.
Later you have this:
def render(Long id){
String name="foo"
Template t= Template.get(id)
println t.subject
}
It looks like you are wanting that local name property to be substituted into a Groovy String that has been assigned to t.subject, but that isn't how Groovy works. t.subject is not a Groovy String. It is a String.
Separate from that you comment that when you println t.subject that the output is "Hello ${name}". I don't think that is possible, but if that is what you are seeing, then I guess it is.
You can use a transient property to emulate the required behavior:
class Template{
String subject
String getSubjectPretty(){ "Hello $subject" }
static transients = ['subjectPretty']
}
Then you can use:
println Template.get(1).subjectPretty

How can you store a specific line from a file in an array in Groovy?

I am interested if there is a easy way to store a specific line from a file into an array in Groovy (i need it for GroovyAxis in Jenkins). The file would look like this:
var1="value1 value2 etc"
var2="a b etc"
var3="test1 test2 test3 etc"
I would need test1 test2 test3 etc from var3 to be stored in an array. Right now i use this:
def words = []
new File( '/home/workstation/jenkins/params' ).eachLine { line ->
words << line
}
But it stores each line i have into an array, so i have to heavily workaround the config file to get the job done.
Thank you very much
You are very close!
def words = [:]
new File( '/home/workstation/jenkins/params' ).eachLine { line ->
(var, value) = line.split('=')
words << [(var): value.split(' ')]
}
The result is a map of arrays. The key is the variable name and the value is an array.
update
Oh, it's a property file...
Properties properties = new Properties()
File propertiesFile = new. File('/home/workstation/jenkins/params')
propertiesFile.withInputStream { properties.load(it) }
def result = properties.var3.split(' ').collect { item.minus('"') }
return result
ConfigSlurper can be useful to load properties/configurations :
def config = new ConfigSlurper(new File("my.conf").toURL())
assert config.var2 == "a b etc"
//cat /tmp/words.txt
//It's must be file Format
//SOME_DETAILS:1234-A0;1456-B1;2456-B0;3436-D0;4467-C0
stage("test"){
def testArray=[]
new File('/tmp/words.txt').splitEachLine("[:;]"){line->
if(line[0]=='SOME_DETAILS')testArray=line[1..-1]
}
println testArray
}
After Run it's Output you get

Groovy - with closure with multiple references

I'm trying to parse a JSON data and assign it to a POJO in Grails.
I started with
obj.param=jsonRequest.jsonWrap.attrib.something.jsonParam
After some experimenting and refactoring, it looks like this now.
jsonRequest.jsonWrap.attrib.something.with {
obj.param1=jsonParam1
obj.param2=jsonParam2
//...
}
}
Now, can I avoid the repeated use of obj reference?
I'm imagining that your actual starting point is something like the following. On the JSON side:
import groovy.json.JsonSlurper
String jsonText = '''{
"jsonWrap":{
"attrib":{
"something":{
"jsonParam1": "value1",
"jsonParam2": "value2",
"jsonParam3": "value3",
"jsonParam4": "value4",
"jsonParam5": "value5"
}
}
}
}'''
def jsonRequest = new JsonSlurper().parseText(jsonText)
On the Groovy side:
class ObjectType {
def param1, param2, param3, param4, param5
}
def obj = new ObjectType()
Now, if I had any control over how either the JSON side or the Groovy side are defined then I would do my darnedest to ensure that the property names of the JSON "something" object are exactly the same as the property names in the Groovy "ObjectType" class. For example, like this:
class ObjectType {
def jsonParam1, jsonParam2, jsonParam3, jsonParam4, jsonParam5
}
Then, unmarshalling the "something" object into Groovy is as simple as this:
def obj = new ObjectType(jsonRequest.jsonWrap.attrib.something)
Only one reference to the JSON object. Only one reference to the Groovy object. And the former is used to instantiate the latter. And furthermore, notice that there is no need to reference the properties at all. That is, JSON objects from the slurper are instances of Map, so if the property names match up, you can use the default "Map constructor" syntax.
If, however, you do not control property naming in either set of objects, I would still recommend a different Map-based short-cut. First define a constant Map from one set of property names to the other, like so:
def map = [param1:"jsonParam1", param2:"jsonParam2", param3:"jsonParam3",
param4:"jsonParam4", param5:"jsonParam5"]
Then I would use something like this for the object unmarshalling:
def obj = new ObjectType().with { o ->
jsonRequest.jsonWrap.attrib.something.with { j ->
map.each { oParam, jParam -> o[oParam] = j[jParam] }
}
o
}
i don't think there is a trivial way to trick groovy into "use objectA, if getting is needed and objectB for setting". If obj above is a map or you can apply a map to this object, then you could produce a map in your with block and use this. If you have to have nested structures then more work is needed.
def jsonParam = new Expando([ p1: 'p1', p2: 'p2', p3: 'p3', ])
def obj = new Expando(
jsonParam.with{
[
param1: p1,
param3: p3,
] // `with` will return this map
})
assert obj.param1==jsonParam.p1
assert obj.param3==jsonParam.p3
I use expandos for simple code.

Resources