问题描述
file1: select file
file2: select file
file3: select file
....
我不想拥有
Meta('JSON') {
// JSON content using JSON Builder in this case
}
content('HTML') {
// HTML content using MarkupTemplateEngine in this case
}
或
JsonBuilder builder = new JsonBuilder()
builder.author {
}
如何设置初始构建器和嵌套构建器?
我将DSL通用元素定义为:
def builder = new groovy.xml.MarkupBuilder()
builder.html {
}
我定义为以下元素:
import groovy.transform.CompileStatic
import org.eclipse.collections.impl.map.mutable.UnifiedMap
@CompileStatic
abstract class DSLElement extends UnifiedMap {
DSLElement(Map attributes) {
putAll(attributes)
}
getAt(Object key) {
get(key)
}
putAt(Object key,Object value) {
put(key,value)
}
}
@CompileStatic
class BaseFactoryBuilder extends FactoryBuilderSupport {
BaseFactoryBuilder(boolean init = true) {
super(init)
}
}
@CompileStatic
class DSLFactoryBuilder
extends BaseFactoryBuilder
implements MetaRegistration,ContentRegistration,TemplateRegistration {
}
和
import groovy.transform.CompileStatic
import groovy.transform.InheritConstructors
import groovy.transform.SelfType
@CompileStatic
@InheritConstructors
class Meta extends DSLElement {}
@CompileStatic
class MetaFactory extends AbstractFactory {
boolean isLeaf() {
return false
}
Object newInstance(FactoryBuilderSupport builder,Object name,Object value,Map attributes)
throws InstantiationException,illegalaccessexception {
return new Meta(attributes)
}
}
@SelfType(DSLFactoryBuilder)
@CompileStatic
trait MetaRegistration {
registerMeta() {
registerFactory("Meta",new MetaFactory())
}
}
我还没想过如何嵌套另一个构建器和参数import groovy.transform.CompileStatic
import groovy.transform.InheritConstructors
import groovy.transform.SelfType
@CompileStatic
@InheritConstructors
class Content extends DSLElement {
}
@CompileStatic
class ContentFactory extends AbstractFactory {
boolean isLeaf() {
return false
}
Object newInstance(FactoryBuilderSupport builder,illegalaccessexception {
return new Content(attributes)
}
}
@SelfType(DSLFactoryBuilder)
@CompileStatic
trait ContentRegistration {
registerMeta() {
registerFactory("content",new ContentFactory())
}
}
或'JSON'
。
我正在遵循Groovy for Domain-Specific Languages
中给出的FactoryBuilderSupport示例解决方法
也许我没有完全理解这个问题-太长了,以至于您提供的代码无法运行(或不完整)
我假设您想实现这一目标:
def html = meta('HTML'){
person(name:'foo')
}
def json = meta('JSON'){
person(name:'bar')
}
如果是的话,这是实现它的代码
String meta(String ctxName,Closure builderBody){
def builder = null
def writer = null
if(ctxName=='HTML'){
writer=new StringWriter()
builder=new groovy.xml.MarkupBuilder(writer)
}else if(ctxName=='JSON'){
builder=new groovy.json.JsonBuilder()
}
else throw new RuntimeException("unsupported meta=`$ctxName`")
def result = builder.with(builderBody)
if(ctxName=='HTML'){
return writer.toString()
}else if(ctxName=='JSON'){
return builder.toPrettyString()
}
}
println meta('HTML'){
person(name:'foo')
}
println meta('JSON'){
person(name:'bar')
}
结果:
<person name='foo' />
{
"person": {
"name": "bar"
}
}