Reputation: 12601
I've got a hash of strings similar to this:
Map map = ['a.b.c': 'Hi']
... that I need to use in gradle to expand an expression like this:
This is a greeting: ${a.b.c}
If I use the gradle copy task with expand I will get an error message 'No such property: a'.
Is there any way to get gradle/groovy to convert that map into the properties I need to resolve?
Upvotes: 3
Views: 1089
Reputation: 123920
I'm not exactly sure what your needs are, but if you just need to replace property-like tokens and don't need the full power of Groovy templates, the filter()
method in combination with Ant's ReplaceTokens
class is a safer (and faster) bet than expand()
. See Filtering files in the Gradle User Guide.
Upvotes: 0
Reputation: 39570
I couldn't find a built-in answer, but it here is a complete, self-contained method that can be used as a meta method on Map to do what you want:
Map map = ['a.b.c': 'Hi', 'a.b.d': 'Yo', 'f.g.h': 'Howdy']
Map.metaClass.expandKeys = { separator = '.' ->
def mergeMaps = { a, b ->
b.each{ k, v ->
if(a[k] && (v instanceof Map)) {
mergeMaps(a[k], v)
} else {
a[k] = v
}
}
a
}
delegate.inject([:]){ result, k, v ->
mergeMaps(result, k.tokenize(separator).reverse().inject(v){last, subkey -> [(subkey):last] })
}
}
assert map.expandKeys() == [a:[b:[c:"Hi", d:"Yo"]], f:[g:[h:"Howdy"]]]
It also allows for different separators than .
, just pass the separator into the expandKeys
method
If you want to use it like a normal function, then you can do this instead:
Map map = ['a.b.c': 'Hi', 'a.b.d': 'Yo', 'f.g.h': 'Howdy']
def expandKeys = { Map input, separator = '.' ->
def mergeMaps = { a, b ->
b.each{ k, v ->
if(a[k] && (v instanceof Map)) {
mergeMaps(a[k], v)
} else {
a[k] = v
}
}
a
}
input.inject([:]){ result, k, v ->
mergeMaps(result, k.tokenize(separator).reverse().inject(v){last, subkey -> [(subkey):last] })
}
}
assert expandKeys(map) == [a:[b:[c:"Hi", d:"Yo"]], f:[g:[h:"Howdy"]]]
The main trick, besides merging the maps, is to split then reverse each key. Then the final hierarchy can be built up backwards. Also, there may be a better way to handle the merge, because I don't like the hanging a
at the end.
Upvotes: 2
Reputation: 187537
I don't know anything about Gradle but maybe this will help....
If you have a Map
Map map = ['a.b.c': 'Hi']
Then you can't retrieve the value 'Hi' using
map.a.b.c
Instead, you must use:
map.'a.b.c'
or
map['a.b.c']
Upvotes: 1