I am trying to overwrite method Call on the groovy sql class and i am able to do it.But i need to have different implementations based on order.
Sql.metaClass.call = {String sql, List params, Closure c -> c(mockResultSet)} //first time should call this method
Sql.metaClass.call = {String sql, List params, Closure c -> c(expectedLookupId)} //second time should call this method.
One way to implement it would be using an internal flag in the class.
Then call the different implementations based on the flag.
Sql.metaClass.first = true
Sql.metaClass.call = {String sql, List params, Closure c ->
if (first){
c(mockResultSet)
first = false
}else{
c(expectedLookupId)
}
}
Thanks #Joachim for the suggestion.This worked for me.
def counter = 1
Sql.metaClass.call = {String sql, List params, Closure c ->
if(counter ==1 ) {
c(mockResultSet)
counter++;
}else{
c(expectedLookupId)
}
}
Related
I'm making a project with many functions, each named prx, x being a number up to 200, is it possible to create a call from a string like this
var ="pr" + x
You can do this using reflection
class MyTestClass {
fun pr1(): Int = 5
fun pr2(value: Int) = value.toString()
}
class SomeOtherClass{
fun main(){
val myTestClassObj = MyTestClass()
// Find pr1 by name (function without arguments)
val pr1 = myTestClassObj::class.java.getMethod("pr1").kotlinFunction
// call pr1, pass class object as argument, used to call the function
val pr1Result = pr1?.call(myTestClassObj)
// Find function with arguments, pass function name and type of arguments
val pr2 = MyTestClass::class.java.getMethod("pr2", Int::class.java).kotlinFunction
// Call pr2, pass class reference and the function parameter
val pr2Result = pr2?.call(myTestClassObj, 100)
}
}
Be carefull when working with reflection, its easy to create untraceable bugs using it and often it is only a workaround for bad design.
This is my simple groovy script;
def fourtify(String str) {
def clsr = {
str*4
}
return clsr
}
def c = fourtify("aa")
println("binding variables: ${c.getBinding().getVariables()}")
...
All I'm trying to do here is being able to access the free variable "str" using the closure instance to understand how closure works behind the scenes a bit more better. Like, perhaps, Python's locals() method.
Is there a way to do this?
The closure you have defined does not store anything in binding object - it simply returns String passed as str variable, repeated 4 times.
This binding object stores all variables that were defined without specifying their types or using def keyword. It is done via Groovy metaprogramming feature (getProperty and setProperty methods to be more specific). So when you define a variable s like:
def clsr = {
s = str*4
return s
}
then this closure will create a binding with key s and value evaluated from expression str * 4. This binding object is nothing else than a map that is accessed via getProperty and setProperty method. So when Groovy executes s = str * 4 it calls setProperty('s', str * 4) because variable/property s is not defined. If we make a slightly simple change like:
def clsr = {
def s = str*4 // or String s = str * 4
return s
}
then binding s won't be created, because setProperty method does not get executed.
Another comment to your example. If you want to see anything in binding object, you need to call returned closure. In example you have shown above the closure gets returned, but it never gets called. If you do:
def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")
then your closure gets called and binding object will contain bindings (if any set). Now, if you modify your example to something like this:
def fourtify(String str) {
def clsr = {
def n = 4 // it does not get stored as binding
s = str * n
return s
}
return clsr
}
def c = fourtify("aa")
c.call()
println("binding variables: ${c.getBinding().getVariables()}")
you will see following output in return:
binding variables: [args:[], s:aaaaaaaa]
Hope it helps.
in your example str is a parameter of the method/function fortify
however maybe following example will give you better Closure understanding:
def c={ String s,int x-> return s*x }
println( c.getClass().getSuperclass() ) // groovy.lang.Closure
println( c.getMaximumNumberOfParameters() ) // 2
println( c.getParameterTypes() ) // [class java.lang.String, int]
the locals() Python's function better matches groovy.lang.Script.getBinding()
and here is a simple example with script:
Script scr = new GroovyShell().parse('''
println this.getBinding().getVariables() // print "s" and "x"
z = s*(x+1) // declare a new script-level var "z"
println this.getBinding().getVariables() // print "s", "x", and "z"
return s*x
''')
scr.setBinding( new Binding([
"s":"ab",
"x":4
]) )
println scr.run() // abababab
println scr.getBinding().getVariables() // print "s", "x", and "z"
Please help with a metaprogramming configuration such that I can add collections methods called collectWithIndex and injectWithIndex that work in a similar manner to eachWithIndex but of course include the base functionality of collect and inject. The new methods would accept a two (three with maps) argument closure just like eachWithIndex. I would like to have the capability to utilize these methods across many different scripts.
Use case:
List one = [1, 2, 3]
List two = [10, 20, 30]
assert [10, 40, 90] == one.collectWithIndex { value, index ->
value * two [index]
}
Once the method is developed then how would it be made available to scripts? I suspect that a jar file would be created with special extension information and then added to the classpath.
Many thanks in advance
I'm still sure, it's not a proper SO question, but I'll give you an example, how you can enrich metaclass for your multiple scripts.
Idea is based on basescript, adding required method to List's metaClass in it's constructor. You have to implement collect logic yourself, through it's pretty easy. You can use wrapping
import org.codehaus.groovy.control.CompilerConfiguration
class WithIndexInjector extends Script {
WithIndexInjector() {
println("Adding collectWithIndex to List")
List.metaClass.collectWithIndex {
int i = 0
def result = []
for (o in delegate) // delegate is a ref holding initial list.
result << it(o, i++) // it is closure given to method
result
}
}
#Override Object run() {
return null
}
}
def configuration = new CompilerConfiguration()
configuration.scriptBaseClass = WithIndexInjector.name
new GroovyShell(configuration).evaluate('''
println(['a', 'b'].collectWithIndex { it, id -> "[$id]:$it" })
''')
// will print [[0]:a, [1]:b]
If you like to do it in more functional way, without repeating collect logic, you may use wrapping proxy closure. I expect it to be slower, but maybe it's not a deal. Just replace collectWithIndex with following implementation.
List.metaClass.collectWithIndex {
def wrappingProxyClosure = { Closure collectClosure, int startIndex = 0 ->
int i = startIndex
return {
collectClosure(it, i++) // here we keep hold on outer collectClosure and i, and use call former with one extra argument. "it" is list element, provided by default collect method.
}
}
delegate.collect(wrappingProxyClosure(it))
}
offtopic: In SO community your current question will only attract minuses, not answers.
I'am trying to understand how this code example works. Unfortunately isn't commented at all.
HSSFRow.metaClass.getAt = { int idx ->
def cell = delegate.getCell(idx)
if(!cell) {
return null
}
def value
switch(cell.cellType) {
case HSSFCell.CELL_TYPE_NUMERIC:
if(HSSFDateUtil.isCellDateFormatted(cell)) {
value = cell.dateCellValue
} else {
value = cell.numericCellValue
}
break
case HSSFCell.CELL_TYPE_BOOLEAN:
value = cell.booleanCellValue
break
default:
value = cell.stringCellValue
break
}
return value
}
}
Can some one please explain me
Why need to override the MetaClass.getAt() method? It's not used directly. How does it work?
What's the cellType, dateCellValue, numericCellValue etc (methods or variables)? Where are they defined?
You don't need to override getAt method but it's overridden to make coding easier. When getAt is overridden it enables using [] syntax when You refer to object as in this line of code return row[idx] (taken from the example). It's operator overloading, see here. Summing up it's not used directly via getAt but with [] syntax.
In groovy when getXXX() method is provided (no arguments) on object x You can just refer to it omitting get so: x.getXXX() is the same as x.XXX. cell is just invocation of getCell() on HSSFRow object, the other methods are invoked on HSSFCell object and exactly the same rule applies.
I'd like to call a closure with a delegate parameter to override or shadow the calling context. But the following example prints prints "outside" where I expect "inside".
What am I doing wrong?
def f(String a){
def v = { return a }
v.delegate = [a:"inside"]
// Makes no difference:
// v.resolveStrategy = Closure.DELEGATE_FIRST
println(v.call())
}
f("outside")
I believe the issue is that when the closure is declared inside the function, it 'closes' round the known values in the method (a), so that value becomes effectively hard-coded into the closure (it never hits the delegate to find the unknown value as it is known to the Closure).
If you move the closure v definition outside of the function f, then it works:
v = { return a }
def f(String a){
v.delegate = [a:"inside"]
println(v.call())
}
f("outside")
Other option is to use getProperty('a') instead of directly using a as this forces the use of the delegate to retrieve the value of a.
Can also be done by referring the delegate in the closure. For v as a closure, a does not make any sense (equivalent to use of ExpandoMetaClass)
def f(String a){
def v = { delegate.a }
v.delegate = [a:"inside"]
println v()
}
f("outside")