Is it possible to build a grails config property key programmatically? - grails

When accessing a Config.groovy property using grailsApplication.config.myapp.something
Is it possible to build the property key programmatically somehow? e.g. grailsApplication.config.myapp. + somethingVar.toString()

Groovy allows you to use GString expressions for property accesses, so
grailsApplication.config.myapp."${somethingVar}"
will do what you want as long as somethingVar doesn't contain any dots. If you have a variable that contains the whole config key including the dots then you can use flatConfig:
def key = "myapp.something"
def value = grailsApplication.flatConfig."${key}"
or if the variable is part of the "path" but not the whole:
def key = "some.thing"
def value = grailsApplication.flatConfig."myapp.${key}" // gives myapp.some.thing
or you can avoid the flatConfig by using a trick with inject
def key = "some.thing"
def value = key.split(/\./).inject(grailsApplication.config.myapp) { co, part ->
co."${part}"
}
The inject method calls the closure once for each item in the array we're iterating over, each time passing in the value that the last iteration returned (I've called it co as it will be a ConfigObject) and the value for this iteration (part). The overall result of inject is the value returned by the last iteration.

Related

How to access map keys through index? Dart

dartques = {'Color':[], 'Fruits':[], 'Hobbies':[]};
How to access the values using index in map?
I need to access only key or value using index.
Just like we do in list
=>list[1]
you can get it like this
var element = dartques.values.elementAt(0);
also for Dart 2.7+ you can write extension function
extension GetByKeyIndex on Map {
elementAt(int index) => this.values.elementAt(index);
}
var element = dartques.elementAt(1);
For accessing the values by index, there are two approaches:
Get Key by index and value using the key:
final key = dartques.keys.elementAt(index);
final value = dartques[key];
Get value by index:
final value = dartques.values.elementAt(index);
You may choose the approach based on how and what data are stored on the map.
For example if your map consists of data in which there are duplicate values, I would recommend using the first approach as it allows you to get key at the index first and then the value so you can know if the value is the wanted one or not.
But if you do not care about duplication and only want to find a value based on Index then you should use the second approach, as it gives you the value directly.
Note: As per this Answer By Genchi Genbutsu, you can also use Extension methods for your convenience.
Important:
Since the default implementation for Map in dart is LinkedHashmap you are in great luck. Otherwise Generic Map is known for not maintaining order in many programming languages.
If this was asked for any other language for which the default was HashMap, it might have been impossible to answer.
You can convert it to two lists using keys and values methods:
var ques = {'Color':['a'], 'Fruits':['b'], 'Hobbies':['c']};
List keys = ques.keys.toList();
List values = ques.values.toList();
print (keys);
print (values);
The output:
[Color, Fruits, Hobbies]
[[a], [b], [c]]
So you can access it normally by using keys[0], for example.

Not able to read parameters from properties file in jenkins

Here is what I am trying to achieve. - I have two 'Choice Parameters' in my Jenkins job. The values of the first Choice Parameter are hard coded. The second choice list should be populated based on the first choice list selection. I have one properties file saved in Jenkins, which has key-value pairs. The values in first choice list and the Keys in the file are same. On selecting a value in first choice list i want a code to read the properties file and populate the second choice parameter with the values from file corresponding to that key.
For second choice list i am trying with 'Active Choice Reactive Parameter' , Referenced parameters= first_choice and below groovy script. But this is not returning any values. Please help!
def firstChoice = [first_choice]
Properties props = new Properties()
def stream = new FileInputStream('C:/Jenkins/books.properties')
try{
props.load(stream)
}
catch (Exception ex){
println "Exception"
}
finally {
stream.close()
}
def values = props.getProperty(firstChoice).split(",")
return values
Are the parameters defined in your job? if you're trying to inject parameters that are not defined in the job you need to either define them or add exception in Jenkins when you're loading the master service.
More reading:
https://wiki.jenkins-ci.org/display/JENKINS/Plugins+affected+by+fix+for+SECURITY-170
Follow this answer and use active choices parameter. This will help you achieve what you want to
https://stackoverflow.com/a/73742809/4781673

Grails - Bind parameter to command object field of a different name

If I have a command object SomeClassCommand with a String field someField but want to bind data from a parameter params.otherField, how do I go about doing that? Is there an annotation I can put in the command object?
Actually there is a horrendous work around which defies the purpose of auto binding in your case.
def map = [:]
map.someField = params.otherField
//plus set all the other params to map
map << params
def commandObj = new SomeCommandObj()
//Explicitly bind map to command object
bindData(commandObj, map)
It really is horrendous, because you are doing extra work only to bind data. You could have directly set values to Command Object.
I would suggest either to change the command object field name or the parameter field name, which ever is controllable. AFAIK there is no annotation available unless you have your own utility to do such.

Way to deep traverse a Groovy object with dot in string using GPath

The situation I have is that I'm querying MongoDB with a string for a field that is more than one level deep in the object hierarchy. This query must be a string. So for example I'm querying for something like this in Groovy:
def queryField = 'a.b.c' //this is variable and can be different every time
def result = mongodb.collection.findOne([queryField:5])
The problem no arises that in the result I want to find the value of the nested field. With GPath I could go one level deep and get a's value doing this
def aObj = result."a" //or result["a"]
However I want to go deeper than that by doing something like this:
def queryField = "a.b.c" //this can change every time and is not always 'a.b.c'
def cObj = result[queryField] //since field is variable, can't just assume result.a.b.c
This does not work in Groovy right now. There is a bug logged here, but I was wondering if there is a better work around to use for this scenario that is a bit cleaner than me parsing the string by splitting on the dot and then building the object traversal. Note that "a.b.c" is variable and unknown at runtime (e.g. it could be "a.b.d").
Based on the bug/thread it would appear there are some ambiguity problems with supporting a dotted property accessor. Based on the mailing list thread it would seem that evaluating the queryField string would be your best bet:
def result = [a: [b: [c: 42]]]
def queryString = 'a.b.c'
def evalResult = Eval.x(result, 'x.' + queryString)
assert evalResult == 42
Script on Groovy Web Console
The mailing list thread is a little old, so there's a new-ish (since at least 1.7.2) Eval class that can help out with running small snippets that don't have a large binding.
Otherwise, you can split the string and recursively do property evaluations on the object, effectively reproducing a subset of GPath traversal behavior.

Ascii to Int function in Groovy

I'm trying to pass the value "1" into a Grails tag. However, it turns out to be an integer value of 49 - the ascii value for "1". How do I convert this to the proper value in Groovy?
Actually, there's a "toInteger()" function on a String.
To add to Jack BeNimble's comment, if you are using 1.2 (release of which is imminent), you also have null-safe converters to int (i.e. params.int('value'), which will do
From Release Notes.
Convenient, null safe converters in params and tag attributes
New convenience methods have been added to the params object and tag attrs objects that allow the easy, exception safe and null safe conversion of parameters to common types:
def total = params.int('total')
There are methods for all the common base types such as int#, #long#, #boolean and so on. There is a special converter called list that always returns a list for cases when dealing with one or many parameters of the same name:
def names = params.list('names')

Resources