具有Groovy BuilderSupport的外部内容

具有Groovy BuilderSupport的外部内容,groovy,builder,Groovy,Builder,通过扩展BuilderSupport,我在Groovy中构建了一个自定义生成器。与几乎所有的构建器代码示例一样,它在配置时工作良好: def builder = new MyBuilder() builder.foo { "Some Entry" (property1:value1, property2: value2) } 当然,这是完美的。问题是我不希望我正在构建的信息出现在代码中。我希望将这些信息保存在一个文件中,该文件由生成器读入并内置到对象中。我不知道怎么做 我甚至不能通过在

通过扩展BuilderSupport,我在Groovy中构建了一个自定义生成器。与几乎所有的构建器代码示例一样,它在配置时工作良好:

def builder = new MyBuilder()
builder.foo {
    "Some Entry" (property1:value1, property2: value2)
}
当然,这是完美的。问题是我不希望我正在构建的信息出现在代码中。我希望将这些信息保存在一个文件中,该文件由生成器读入并内置到对象中。我不知道怎么做

我甚至不能通过在代码中移动简单的条目来实现这一点。 这项工作:

def textClosure = { "Some Entry" (property1:value1, property2: value2) }
builder.foo(textClosure)
因为textClosure是一个闭包

如果我这样做:

def text = '"Some Entry" (property1:value1, property2: value2)'
def textClosure = { text }
builder.foo(textClosure)
生成器只为“foo”节点调用。我已经尝试了许多变体,包括直接将文本块传递到构建器中,而不将其包装在闭包中。它们都产生相同的结果


有没有什么方法可以将一段任意文本传递到我的生成器中,以便它能够正确地解析和构建它?

我认为使用slurper或解析器可以更好地解决您描述的问题

见:

用于基于XML的示例

就你而言。给定XML文件:

<foo>
    <entry name='Some Entry' property1="value1" property2="value2"/>
</foo>

最初,我希望能够指定

"Some Entry" (property1:value1, property2: value2)
在外部文件中。我特别尝试避免使用XML和类似XML的语法,以便普通用户更容易创建和修改这些文件。我当前的解决方案使用
ConfigSlurper
,该文件现在看起来像:

"Some Entry"
{ 
   property1 = value1 
   property2 = value2 
}
ConfigSlurper
为我提供了如下映射:

["Some Entry":[property1:value1,property2:value2]]

使用这些值创建对象非常简单,特别是因为我可以将属性/值映射传递到构造函数中。

您的问题是字符串不是Groovy代码。
ConfigSlurper
处理此问题的方法是使用
GroovyClassLoader\parseClass
将文本编译成
Script
的实例。e、 g

// create a Binding subclass that delegates to the builder
class MyBinding extends Binding {
    def builder
    Object getVariable(String name) {
        return { Object... args ->  builder.invokeMethod(name,args) }
    }   
}

// parse the script and run it against the builder
new File("foo.groovy").withInputStream { input ->
    Script s = new GroovyClassLoader().parseClass(input).newInstance()
    s.binding = new MyBinding(builder:builder)
    s.run()
}
的子类只返回所有变量的闭包,这些变量将调用委托给生成器。因此,假设foo.groovy包含:

foo {
    "Some Entry" (property1:value1, property2: value2)
}

这与上面的代码相当。

这些示例仍然假设要解析/slurped的内容在类路径中,而我的应用程序则不这样。我不想在配置中使用XML—我查看了XmlSlurper和XmlParser的源代码,它们都非常特定于XML。我必须从头开始编写我的slurper/解析器,因为没有像BuilderSupport那样的公共基础。我加了一个例子来说明我的意思。也许你可以指出这个解决方案的问题所在。
foo {
    "Some Entry" (property1:value1, property2: value2)
}