Based on the original description, I'd use this:
// Define classes
class1 = getPathClass('class1')
class2 = getPathClass('class2')
// Get all the class1 annotations that don't contain a class2 object as a direct child
toRemove = getAnnotationObjects().findAll {
if (it.getPathClass() != class1)
return false
children = it.getChildObjects()
return !children.any {it.getPathClass() == class2}
}
// Remove annotations meaning that criteria
removeObjects(toRemove, true)
But yes, if 'emptiness' is the criteria then just checking the getChildObjects() is empty is probably better.
I'd just recommend bringing together all the objects you want to remove in one single list first (as I did with findAll) and removing them all in one go.
Removing the objects one at a time will involve triggering hierarchy (and user interface) updates for every object that is removed. At best, this could reduce performance a bit unnecessarily. At worst, it might result in concurrent modification exceptions if you end up removing objects from a list that is currently being used elsewhere... at least when running interactively (because the GUI will be handling the updates on a different thread). I haven't tested it so don't know for sure if it happens... but better avoid it anyway.
In general it's better to modify the object hierarchy fewer times in bigger ways, both for performance and stability.