J'essaie d'utiliser la récursivité dans groovy pour traverser une relation d'arbre. Le code ci-dessous exécute un cycle, jusqu'à childNodes & & recurClosure (childNodes), mais n'appelle pas la fermeture recurClosure à nouveau. A ce moment, childNodes avait deux objets (liste de tableaux) du même type que root.récursivité dans groovy (grails)
Dans le code, recurClosure est défini et appelle avec une liste d'objets (root). Il parcourt ensuite chaque élément et infléchit les nœuds enfants (utilise grails dsl pour cela). Si childNodes n'est pas nul, il appelle récursivement la méthode parent.
Dois-je le casser, ou quel est le problème?
def parentval
def root = Domain.list()
def recurClosure
recurClosure = {inroot ->
inroot.each {
returnList << it
parentval = it
childNodes = Domain.withCriteria {
eq('parent', parentval)
}
}
childNodes && recurClosure(childNodes)
}(root)
return returnList
}
merci à l'avance.
Mise à jour: L'exception suivante est notée
ERROR [2010-06-24 08:20:04,742] [groovy.grails.web.errors.GrailsExceptionResolver] Cannot invoke method call() on null object
java.lang.NullPointerException: Cannot invoke method call() on null object
at com.bsr.test.DomainService$_closure2_closure7.doCall(com.bsr.test.DomainService:68)
at com.bsr.test.DomainService$_closure2.doCall(com.bsr.test.DomainService:58)
at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy:45)
at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy)
at org.apache.shiro.web.servlet.ShiroFilter.executeChain(ShiroFilter.java:687)
at org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:616)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
at java.lang.Thread.run(Thread.java:619)
Mise à jour 2: Maintenant, essayer la suggestion de Daniel.
{ inroot ->
inroot.each {
returnList << it
parentval = it
childNodes = Domain.withCriteria {
eq('parent', parentval)
}
if(childNodes)
call(childNodes)
}
/*if(childNodes)
call(childNodes)*/
}(root)
Dans la mise en œuvre ci-dessus, la racine est un arraylist, la fermeture intérieure prend chaque élément sur et appelle récursivement la fermeture anonyme. Lorsque j'ai déplacé le 'call' à l'intérieur de chaque fermeture, il n'appelle pas la fermeture anonyme externe, mais inroot.each {} lui-même. Donc, je reçois une erreur
ERROR [2010-06-24 08:47:46,438] [groovy.grails.web.errors.GrailsExceptionResolver] instance not of expected entity type: java.util.ArrayList is not a: com.bsr.test.Domain
Je vois un billet de blog sur la façon de nommer la fermeture par 'this'> Je vais mettre à jour ma conclusion .. merci
Mise à jour 3: La façon d'appeler la fermeture extérieure est owner.call (childNodes)
Daniel .. heureux de voir votre réponse, car il attrape toutes les erreurs dans le code .. Eh bien, j'ai adapté ma liste de code pour le rendre plus simple pour la question. Donc, 1. J'ai défini returnList comme une liste de tableaux. 2. Je suis d'accord 3. Vous avez raison, ce que je voulais (j'ai essayé de déplacer la déclaration dans et hors de cette fermeture pour voir l'effet). Je n'étais certainement pas en train de faire un list() sur la classe du domaine, en effet, je l'ai obtenu d'une autre table. Je n'ai jamais eu l'intention de tromper un expert comme vous (à la fois dans groovy et grails: - |) .. J'essaie votre mise en œuvre de fermeture anonyme .. mettra à jour dans un peu .. merci beaucoup – bsr
Wow, excellente réponse +1 – codeporn
Daniel , J'ai mis à jour la question avec plus de détails .. maintenant la question est, comment invoquer la fermeture anonyme externe par «appel». Merci encore. – bsr