I have the following groovy code:
def script
String credentials_id
String repository_path
String relative_directory
String repository_url
CredentialsWrapper(script, credentials_id, repository_name, repository_group, relative_directory=null) {
this(script, credentials_id, 'git#gitlab.foo.com:' + repository_group +'/' + repository_name + '.git', relative_directory);
}
CredentialsWrapper(script, credentials_id, repository_url, relative_directory=null) {
this.script = script;
this.credentials_id = credentials_id;
this.repository_url = repository_url;
if (null == relative_directory) {
int lastSeparatorIndex = repository_url.lastIndexOf("/");
int indexOfExt = repository_url.indexOf(".git");
this.relative_directory = repository_url.substring(lastSeparatorIndex+1, indexOfExt);
}
}
Jenkins gives me the following:
Unable to compile class com.foo.CredentialsWrapper due to hash collision in constructors # line 30, column 7.
I do not understand why, the constructors are different, they do not have the same number of arguments.
Also, "script" is an instance from "WorkflowScript", but I do not know what I should import to access this class, which would allow me to declare script explicitly instead of using "def"
Any idea ?
When you call the Constructor with four parameters, would you like to call the first or the second one?
If you write an constructor/method with default values, groovy will actually generate two or more versions.
So
Test(String x, String y ="test")
will result in
Test(String x, String y) {...}
and
Test(String x) {new Test(x, "test")}
So your code would like to compile to 4 constructors, but it contains the constructor with the signature
CredentialsWrapper(def, def, def, def)
two times.
If I understand your code correctly, you can omit one or both of the =null. The result will be the same, but you will get only two or three signatures. Then you can choose between both versions by calling calling them with the right parameter count.
Related
I am new to Groovy so I am a bit confused by the run time binding, typed and not typed attributes of the language. Personally I prefer types to be declared.
However, I have a question.
I have a small method that takes some variable from maps, input, whatever, that I know are numbers. Let's say that I don't know what the initial type was (it's somewhere deep in the code or comes from an external source), other that it was a number. Now I have a method that takes two of these arguments and I have to do a modulo operation on them. Because they might be decimal or not, I wrote a small method using the remainder of BigDecimal so to enforce the type I used the type BigDecimal on the method signature.
def callerMethod(Map map) {
...
map.each{
calledMethod(it.val1, it.val2)
...
}
...
}
def calledMethod(BigDecimal val1, BigDecimal val2) {
...
vl1.remainder(val2)
...
}
Is this correct? If the incoming argument is Integer (most of the time the primitives are boxed if I understand it correctly), will it be implicitly cast or turned into a BigDecimal?
How does this work in Groovy.
I still think that since I have the option to use types, I want to use them rather than declaring everything def. It also makes it easier to read code or see what something is if you reading already existing code
The problem in this methods are not the type of variables, is the each of your map
In a groovy Map, the each have two signatures.
One receive a Map.Entry of parameter and other receive key and value
Ex.:
Map map = [key1:'value1',key2:'value2']
map.each{ Map.Entry entryMap ->
println "The value of key: ${entryMap.key} is ${entryMap.value}"
}
The result of this each will be:
The value of key: key1 is value1
The value of key: key2 is value2
Or could be like this
Map map = [key1:'value1',key2:'value2']
map.each{ def key, def value ->
println "The value of key: ${key} is ${value}"
}
And the result of this second will be the same of the first.
If you want to pass two specific arguments to you calledMethod, pass both outside of the each like this:
def callerMethod(Map map) {
calledMethod(map.val1, map.val2)
}
I don't understand perfectly what you want.. I hope that's help you to do you code.
My current work project allows user-provided expressions to be evaluated in specific contexts, as a way for them to extend and influence the workflow. These expressions the usual logical ones f. To make it a bit palatable for non-programmers, I'd like to give them the option of using literal operators (e.g. and, or, not instead of &, |, !).
A simple search & replace is not sufficient, as the data might contains those words within quotes and building a parser, while doable, may not be the most elegant and efficient solution.
To make the question clear: is there a way in Groovy to allow the users to write
x > 10 and y = 20 or not z
but have Groovy evaluate it as if it were:
x > 10 && y == 20 || !z
Thank you.
Recent versions of Groovy support Command chains, so it's indeed possible to write this:
compute x > 10 and y == 20 or not(z)
The word "compute" here is arbitrary, but it cannot be omitted, because it's the first "verb" in the command chain. Everything that follows alternates between verb and noun:
compute x > 10 and y == 20 or not(z)
───┬─── ──┬─── ─┬─ ───┬─── ─┬─ ──┬───
verb noun verb noun verb noun
A command chain is compiled like this:
verb(noun).verb(noun).verb(noun)...
so the example above is compiled to:
compute(x > 10).and(y == 20).or(not(z))
There are many ways to implement this. Here is just a quick & dirty proof of concept, that doesn't implement operator precedence, among other things:
class Compute {
private value
Compute(boolean v) { value = v }
def or (boolean w) { value = value || w; this }
def and(boolean w) { value = value && w; this }
String toString() { value }
}
def compute(v) { new Compute(v) }
def not(boolean v) { !v }
You can use command chains by themselves (as top-level statements) or to the right-hand side of an assignment operator (local variable or property assignment), but not inside other expressions.
If you can swap operators like > and = for the facelets-like gt and eq, respectively, i THINK your case may be doable, though it will require a lot of effort:
x gt 10 and y eq 20 or not z
resolves to:
x(gt).10(and).y(eq).20(or).not(z)
And this will be hell to parse.
The way #Brian Henry suggested is the easiest way, though not user-friendly, since it needs the parens and dots.
Well, considering we can swap the operators, you could try to intercept the Integer.call to start expressions. Having the missing properties in a script being resolved to operations can solve your new keywords problem. Then you can build expressions and save them to a list, executing them in the end of the script. It's not finished, but i came along with this:
// the operators that can be used in the script
enum Operation { eq, and, gt, not }
// every unresolved variable here will try to be resolved as an Operation
def propertyMissing(String property) { Operation.find { it.name() == property} }
// a class to contain what should be executed in the end of the script
#groovy.transform.ToString
class Instruction { def left; Operation operation; def right }
// a class to handle the next allowed tokens
class Expression {
Closure handler; Instruction instruction
def methodMissing(String method, args) {
println "method=$method, args=$args"
handler method, args
}
}
// a list to contain the instructions that will need to be parsed
def instructions = []
// the start of the whole mess: an integer will get this called
Integer.metaClass {
call = { Operation op ->
instruction = new Instruction(operation: op, left: delegate)
instructions << instruction
new Expression(
instruction: instruction,
handler:{ String method, args ->
instruction.right = method.toInteger()
println instructions
this
})
}
}
x = 12
y = 19
z = false
x gt 10 and y eq 20 or not z
Which will give an exception, due the not() part not being implemented, but it can build two Instruction objects before failing:
[Instruction(12, gt, 10), Instruction(19, eq, 20)]
Not sure if it is worth it.
The GDK tacks on and() and or() methods to Boolean. If you supplied a method like
Boolean not(Boolean b) {return !b}
you could write something like
(x > 10).and(y == 20).or(not(4 == 1))
I'm not sure that's particularly easy to write, though.
I'm trying to write a mini DSL for some specific task. For this purpose I've been trying to solve a problem like this below (without using parantheses):
give me 5 like romanLetter
give me 5 like word
where the first line would return "V" and the second "five"
My definitions for the first part give me 5 look like this
def give = { clos -> clos() }
def me = { clos -> [:].withDefault { it
println it}
}
and then give me 5 prints 5
The problem is how to add more metaclass methods on the right. E.g.
give me 5 like romanLetter -> prints V OR
give me 5 like word -> prints five
my intuition is that I define like as
Object.metaClass.like = {orth -> if (orth.equals("roman")){ println "V"}
else {println "five"} }
this metaClass method like works only if there is a returned value from the left to be applied to, right? I tried adding a return statement in all of the closures which are on the left side but I always receive
groovy.lang.MissingPropertyException: No such property: like
for class: com.ontotext.paces.rules.FERulesScriptTest ...
do you have an idea how shall I do?
========================================
Here is the application of what I'm asking for.
I want to make a rule as follows
add FEATURE of X opts A,B,C named Y
where add is a closure, of, opts and named are MetaClass methods (at least that's how i imagine it), X, A, B, C, Y are parameters most probably strings and FEATURE is either a MetaClass property, or a closure without arguments or a closure with arguments.
If FEATURE does not take arguments then it is enough that add takes FEATURE as argument and returns a value on which
Object.metaClass.of will be executed with parameter X
Object.metaClass.opts will be executed on the returned by OF value with parameters A, B, C
Object.metaClass.named will be executed on the returned by opts value with parameter Y
each one of these metaclass methods sets its parameter as a value in a map, which is passed to a JAVA method when named is called.
I'm not sure this is the best solution for such a problem, but it seems to me such for the moment. The problem is if FEATURE is not a property itself but a closure which takes argument (e.g. feature1 ARG1). Then
add feature1 ARG1 of X opts A,B,C named Y
and this is the case which I'm stuck with. add feature1 ARG1 is the give me 5 part and I'm trying to add the rest to it.
========================================================
EXAMPLES:
I need to have both of the following working:
add contextFeature "text" of 1,2,3 opts "upperCase" named "TO_UPPER"
add length named "LENGTH"
where in the first case by parsing the rule, whenever each metaclass method of, opts, named is called I fill in the corresponding value in the following map:
params = [feature: "text",
of: 1,2,3,
opts: "upperCase",
named: "TO_UPPER"]
ones this map is filled in, which happens when named is parsed, I call a java method
setFeature(params.of, params.named, params.opts, params.feature)
In the second case length is predefined as length = "length", params values will be only
params = [feature : length,
of: null,
opts: null,
named: "LENGTH"]
and since of is null another java method will be called which is addSurfaceFeature(params.feature, params.named). The second case is more or less streight forward, but the first one is the one I can't manage.
Thanks in advance! Iv
You can do this sort of thing... Does that get you close?
def contextFeature( type ) {
"FEATURE_$type"
}
// Testing
new IvitaParser().parse {
a = add text of 1,2,3 opts "upperCase" named "TO_UPPER"
b = add length named "LENGTH"
c = add contextFeature( "text" ) of 1,2,3 opts "upperCase" named "TO_UPPER"
}
assert a == [feature:'text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
assert b == [feature:'length', of:null, opts:null, named:'LENGTH']
assert c == [feature:'FEATURE_text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
// Implementation
class IvitaParser {
Map result
def parse( Closure c ) {
c.delegate = this
c.resolveMethod = Closure.DELEGATE_FIRST
c()
}
def propertyMissing( String name ) {
name
}
def add( String param ) {
result = [ feature:param, of:null, opts:null, named:null ]
this
}
def of( Object... values ) {
result.of = values
this
}
def named( String name ) {
result.named = name
result
}
def opts( String opt ) {
result.opts = opt
this
}
}
You can even get rid of the quotes on the definition:
a = add text of 1,2,3 opts upperCase named TO_UPPER
b = add length named LENGTH
As the propertyMissing method just converts unknown properties into a String of their name
Groovy supports both default, and named arguments. I just dont see them working together.
I need some classes to support construction using simple non named arguments, and using named arguments like below:
def a1 = new A(2)
def a2 = new A(a: 200, b: "non default")
class A extends SomeBase {
def props
A(a=1, b="str") {
_init(a, b)
}
A(args) {
// use the values in the args map:
_init(args.a, args.b)
props = args
}
private _init(a, b) {
}
}
Is it generally good practice to support both at the same time? Is the above code the only way to it?
The given code will cause some problems. In particular, it'll generate two constructors with a single Object parameter. The first constructor generates bytecode equivalent to:
A() // a,b both default
A(Object) // a set, b default
A(Object, Object) // pass in both
The second generates this:
A(Object) // accepts any object
You can get around this problem by adding some types. Even though groovy has dynamic typing, the type declarations in methods and constructors still matter. For example:
A(int a = 1, String b = "str") { ... }
A(Map args) { ... }
As for good practices, I'd simply use one of the groovy.transform.Canonical or groovy.transform.TupleConstructor annotations. They will provide correct property map and positional parameter constructors automatically. TupleConstructor provides the constructors only, Canonical applies some other best practices with regards to equals, hashCode, and toString.
I am new to groovy and I've been facing some issues understanding the each{} and eachwithindex{} statements in groovy.
Are each and eachWithIndex actually methods? If so what are the arguments that they take?
In the groovy documentation there is this certain example:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" } //prints each index and number
Well, I see that numbers is an array. What are num and idx in the above statement? What does the -> operator do?
I do know that $idx and $num prints the value, but how is it that idx and num are automatically being associated with the index and contents of the array? What is the logic behind this? Please help.
These are plain methods but they follow quite a specific pattern - they take a Closure as their last argument. A Closure is a piece of functionality that you can pass around and call when applicable.
For example, method eachWithIndex might look like this (roughly):
void eachWithIndex(Closure operation) {
for (int i = 0; this.hasNext(); i++) {
operation(this.next(), i); // Here closure passed as parameter is being called
}
}
This approach allows one to build generic algorithms (like iteration over items) and change the concrete processing logic at runtime by passing different closures.
Regarding the parameters part, as you see in the example above we call the closure (operation) with two parameters - the current element and current index. This means that the eachWithIndex method expects to receive not just any closure but one which would accept these two parameters. From a syntax prospective one defines the parameters during closure definition like this:
{ elem, index ->
// logic
}
So -> is used to separate arguments part of closure definition from its logic. When a closure takes only one argument, its parameter definition can be omitted and then the parameter will be accessible within the closure's scope with the name it (implicit name for the first argument). For example:
[1,2,3].each {
println it
}
It could be rewritten like this:
[1,2,3].each({ elem ->
println elem
})
As you see the Groovy language adds some syntax sugar to make such constructions look prettier.
each and eachWithIndex are, amongst many others, taking so called Closure as an argument. The closure is just a piece of Groovy code wrapped in {} braces. In the code with array:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" }
there is only one argument (closure, or more precisely: function), please note that in Groovy () braces are sometime optional. num and idx are just an optional aliases for closure (function) arguments, when we need just one argument, this is equivalent (it is implicit name of the first closure argument, very convenient):
def numbers = [ 5, 7, 9, 12 ]
numbers.each {println "$it" }
References:
http://groovy.codehaus.org/Closures
http://en.wikipedia.org/wiki/First-class_function
Normally, if you are using a functional programing language such as Groovy, you would want to avoid using each and eachWithIndex since they encourage you to modify state within the closure or do things that have side effects.
If possible, you may want to do your operations using other groovy collection methods such as .collect or .inject or findResult etc.
However, to use these for your problem, i.e print the list elements with their index, you will need to use the withIndex method on the original collection which will transform the collection to a collection of pairs of [element, index]
For example,
println(['a', 'b', 'c'].withIndex())
EachWithIndex can be used as follows:
package json
import groovy.json.*
import com.eviware.soapui.support.XmlHolder
def project = testRunner.testCase.testSuite.project
def testCase = testRunner.testCase;
def strArray = new String[200]
//Response for a step you want the json from
def response = context.expand('${Offers#Response#$[\'Data\']}').toString()
def json = new JsonSlurper().parseText(response)
//Value you want to compare with in your array
def offername = project.getPropertyValue("Offername")
log.info(offername)
Boolean flagpresent = false
Boolean flagnotpresent = false
strArray = json.Name
def id = 0;
//To find the offername in the array of offers displayed
strArray.eachWithIndex
{
name, index ->
if("${name}" != offername)
{
flagnotpresent= false;
}
else
{
id = "${index}";
flagpresent = true;
log.info("${index}.${name}")
log.info(id)
}
}