将字符串添加到属性

时间:2011-08-31 08:30:04

标签: groovy gradle

我有一个与此类似的字符串哈希:

Map map = ['a.b.c': 'Hi']

...我需要在gradle中使用以扩展这样的表达式:

This is a greeting: ${a.b.c}

如果我使用展开的gradle复制任务,我将收到一条错误消息'No such property:a'。

有没有办法让gradle / groovy将该地图转换为我需要解析的属性?

3 个答案:

答案 0 :(得分:2)

我找不到内置的答案,但它是一个完整的,自包含的方法,可以在Map上用作元方法来做你想要的:

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"]]]

它还允许使用与.不同的分隔符,只需将分隔符传递到expandKeys方法

如果你想像普通函数一样使用它,那么你可以这样做:

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"]]]

除了合并地图之外,主要技巧是拆分然后反转每个键。然后可以向后构建最终层次结构。此外,可能有更好的方法来处理合并,因为我不喜欢最后挂a

答案 1 :(得分:1)

我对Gradle一无所知,但也许这会有所帮助......

如果您有地图

Map map = ['a.b.c': 'Hi']

然后您无法使用

检索值“Hi”
map.a.b.c

相反,您必须使用:

map.'a.b.c'

map['a.b.c']

答案 2 :(得分:0)

我不确定您的需求是什么,但是如果您只需要替换类似属性的令牌并且不需要Groovy模板的全部功能,那么filter()方法与Ant的ReplaceTokens方法相结合1}}类比expand()更安全(也更快)。请参阅Gradle用户指南中的Filtering files