I am creating a criteria depending on several factors. Currently I'm using nested closures in the following way:
Utils.groovy
static def statusAndOrderCriteria = { x ->
...
Utils.commonOrderCriteria.delegate = delegate
Utils.commonOrderCriteria(x)
}
static def commonOrderCriteria = { x ->
...
}
Usage:
Alert.createCriteria().list({
Utils.statusAndOrderCriteria.delegate = delegate
Utils.statusAndOrderCriteria(x)
})
I want to use several closures, such as:
Alert.createCriteria().list({
Utils.firstCriteria(a)
Utils.secondCriteria(b)
Utils.statusAndOrderCriteria(x)
})
I don't know how to achieve that. I know that I can't be overwriting the delegate object several times on the same closure.
When you build a GORM criteria query, the delegate of the closure is an instance of HibernateCriteriaBuilder
. What you can do is modify your Util
closures to accept this builder as a parameter. Then, delegate the method calls to the builder. Here's an example:
class Utils {
static def statusAndOrderCriteria = { criteriaBuilder, x ->
criteriaBuilder.eq('foo', x)
Utils.commonOrderCriteria(criteriaBuilder, x)
}
static def commonOrderCriteria = { criteriaBuilder, x ->
criteriaBuilder.lt('bar', x)
}
}
Then you can use the static closures in Util
like this:
Alert.createCriteria().list({
Utils.firstCriteria(delegate, a)
Utils.secondCriteria(delegate, b)
Utils.statusAndOrderCriteria(delegate, x)
})
Hint: If the closures were not static properties you'd be able to avoid constantly having to pass the delegate, like this:
@groovy.transform.TupleConstructor
class Utils {
HibernateCriteriaBuilder criteriaBuilder
def statusAndOrderCriteria = { x ->
criteriaBuilder.foo()
Utils.commonOrderCriteria(x)
}
def commonOrderCriteria = { x ->
criteriaBuilder.bar()
}
}
Alert.createCriteria().list({
def utils = new Utils(delegate)
utils.firstCriteria(a)
utils.secondCriteria(b)
utils.statusAndOrderCriteria(x)
})