Puede haber una mejor manera, pero un truco es llamar directamente invokeMethod
:
String buildCatalog(Catalog catalog) {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.catalog(xmlns:'http://www.sybrium.com/XMLSchema/NodeCatalog') {
delegate.invokeMethod('identity', [{
groupId(catalog.groupId)
artifactId(catalog.artifactId)
version(catalog.version)
}])
}
return writer.toString();
}
Esto es efectivamente lo maravilloso está haciendo detrás de las escenas. No pude hacer funcionar delegate.identity
o owner.identity
, que son los trucos habituales.
Editar: me di cuenta de lo que está pasando.
Groovy adds a method con una firma de identity(Closure c)
para cada objeto.
Esto significa que cuando se trató de invocar dinámicamente el elemento identity
en el constructor de XML, mientras que pasa en un solo argumento de cierre, se llama al método identity()
, que es como decir que delegate({...})
en el cierre exterior.
Usando las fuerzas invokeMethod
truco maravilloso para eludir el Protocolo Meta Object y tratar el método como un método dinámico, a pesar de que el método identity
ya existe en el meta objeto.
Sabiendo esto, podemos armar una solución mejor y más legible. Todo lo que tenemos que hacer es cambiar la firma del método, así:
String buildCatalog(Catalog catalog) {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.catalog(xmlns:'http://www.sybrium.com/XMLSchema/NodeCatalog') {
// NOTE: LEAVE the empty map here to prevent calling the identity method!
identity([:]) {
groupId(catalog.groupId)
artifactId(catalog.artifactId)
version(catalog.version)
}
}
return writer.toString();
}
Esto es mucho más fácil de leer, es más clara la intención, y el comentario debe (con suerte) evitar que cualquier persona la eliminación de la "innecesaria" vacía mapa.
Eso funcionó, pero ¿puedes explicar esto? ¿Qué es delegado y por qué es delegate.identity diferente de delegate.invokeMethod ('identity')? –
Lo descubrí, actualizaré mi respuesta. – OverZealous
FYI: rastreé esto utilizando GroovyConsole para inspeccionar el objeto XML. Esto me permite saber que el método 'identity' ya existía con un solo' Closure' como argumento. – OverZealous