使用带有无效密钥的groovy map for DSL
我目前正在构建一个小型DSL,它需要在key=value对中指定一组属性,但是这些键可能包含破折号“-”或句点“.”,我似乎无法让它工作 归结起来,我基本上尝试将一个映射作为一个闭包的委托来传递,但是语法一直吸引着我使用带有无效密钥的groovy map for DSL,groovy,dsl,Groovy,Dsl,我目前正在构建一个小型DSL,它需要在key=value对中指定一组属性,但是这些键可能包含破折号“-”或句点“.”,我似乎无法让它工作 归结起来,我基本上尝试将一个映射作为一个闭包的委托来传递,但是语法一直吸引着我 作为一个例子,考虑如下: def map = [:] map.with { example1 = 123 //exam-ple2 = 123 //'exam-ple3' = 123 //(exam-ple4) = 123 exam.ple5
作为一个例子,考虑如下:
def map = [:]
map.with {
example1 = 123
//exam-ple2 = 123
//'exam-ple3' = 123
//(exam-ple4) = 123
exam.ple5 = 123
//'exam.ple6' = 123
}
示例1很好,键等于值,易于阅读。示例2和4根据编译器的要求是一个二进制表达式,不会编译。示例3和6是常量表达式,不会编译。示例5将编译,但在运行时生成NPE
我可以使用一些变通方法,比如将Map作为闭包的参数传递给闭包,这给了我示例3和6,但是它的冗长让我很恼火
有没有人知道如何巧妙地用DSL绘制一张房产地图
顺便说一句:我称DSL为java而非groovy,因此解析方面的技巧必须是java:)
更新1:在最初的评论和回答之后
因此,GroovyShell将脚本作为DelegatingScript进行计算,其中委托是Java对象。闭包包含.properties
文件中的属性,这些属性需要在不同的上下文中定义,例如
env {
server-name=someHost1
database.name=someHost2
clientName=someHost3
}
委派(Java)对象将此块读取为
public void env(Closure closure) {
Map map = new HashMap();
closure.setDelegate(map);
closure.setResolveStrategy(Closure.DELEGATE_ONLY);
closure.call();
... do something with map...
}
现在,用户(即不是我)可能会将原始属性文件复制到脚本中并更改名称,因此我希望他们不必进行太多编辑,因为这必然会导致打字错误
正如我所说的,我也讨论了示例3和6,但是是的,Tim,我忘记了隐含的含义:)
现在,我已经将格式更改为字符串,因此DSL编写如下内容
env '''
server-name=someHost1
database.name=someHost2
clientName=someHost3
'''
也就是说,使用多行字符串而不是闭包,然后读取字符串并使用标准java.util.Properties:
public void env(String envString) {
Properties properties = new Properties;
properties.load(new StringReader(envString))
....etc
}
尽管这是可行的,但闭包和多行字符串的混合是目前唯一的缺点。在映射声明中,Groovy将
example1
和example2
等标识符解析为映射的字符串键:
[ example1: 1, example2: 2 ]
在{}上下文中,它可能使用了一种机制
但是您的案例中有表达式
exam.ple
和exam-ple
。这些表达式具有优先级,因此Groovy将首先尝试解析它们(分别使用类似于exam.getProperty('ple')
和exam.减号(ple)
)
您有一些语法选择,但您必须向Groovy明确哪些应该是字符串键,哪些是其他表达式:
def map = [
'exam.ple4' : 4, // direct map declaration
example5 : 5 // unambiguous key declaration: no quotes needed
]
map.with {
example1 = 1
put 'exam.ple2', 2 // ambiguous, needs quotes
it.'exam-ple3' = 3 // as per @TimYates suggestion
}
assert map['exam-ple3'] == 3
assert map.'exam.ple2' == 2
assert map['exam.ple4'] == 4
assert map.example5 == 5 // again, no quotes needed for key
你能解释一下:‘解析端必须是java’吗?由于内部groovy DSL依赖于groovy语法解析器,比如这里的映射元素分配,您将如何用Java解析它???如果你调用groovy,这不是在groovy端完成的吗?
it.'exam-ple2'=123