What's wrong with this Groovy construct? - groovy

This is a short Groovy script:
import org.apache.commons.io.FileUtils;
def dir = new File("/mydir")
def files = FileUtils.listFiles(dir, new String[] { "java" }, false)
It says:
No expression for the array constructor call at line: 2
What's wrong?

The call should be:
def files = FileUtils.listFiles(dir, [ "java" ] as String[], false)
Groovy uses Lists by default, and the as operator can be used to coerce these lists into arrays of a specified type (often for interacting with the java api as in this example)
[edit]
As an aside, you can do this with pure Groovy like so:
def files = dir.listFiles().findAll { it.name ==~ /.*\.java/ }
Then, you don't need Commons FileUtils

Related

Object Array Declaration in Groovy

How come I cannot declare an array of People in Groovy as shown.
Maybe I'm lacking the deeper understanding of classes
class People {
Integer id
}
class Job {
def func() {
People[] p = new People[10]
}
}
I get an error of People[] cannot be applied to app.People[]
The code sample you have shown does not reproduce the error you mentioned in the question above. It's broken actually and does not compile - method func() is missing its body. If you correct the code to e.g.
class People {
Integer id
}
class Job {
def func() {
People[] p = new People[10]
assert p.size() == 10
println p
}
}
new Job().func()​
you will see it produces the expected result - check it out in the Groovy web console here. When you run it you will see following output to the console:
[null, null, null, null, null, null, null, null, null, null]
The difference between Groovy and Java
When it comes to array initialization there is one significant difference between Groovy and Java. In Java you can initialize an array of People[] like this:
People[] p = new People[] { new People(), new People(), /* ... */ new People() };
It wont work in Groovy, because Groovy reserves {} for closures. In Groovy you can initialize such array as:
People[] p = [new People(), new People(), new People()] as People[]
While Szymon Stepniak's answer is correct for Groovy 2.5 and below, Java-style array initialization are part of the enhancements of Groovy 3.0 and 2.6 made possible by the new parrot parser.
Example from the release notes:
def primes = new int[] {2, 3, 5, 7, 11}
assert primes.size() == 5 && primes.sum() == 28
assert primes.class.name == '[I'
def pets = new String[] {'cat', 'dog'}
assert pets.size() == 2 && pets.sum() == 'catdog'
assert pets.class.name == '[Ljava.lang.String;'
// traditional Groovy alternative still supported
String[] groovyBooks = [ 'Groovy in Action', 'Making Java Groovy' ]
assert groovyBooks.every{ it.contains('Groovy') }
Szymon Stepniak's answer is correct. I'll point another example of a real case in some unit test that I've worked (general Object type):
Object[] o = [YourModel] as Object[]
This is sufficient to mock a general Object with your model properties.

Groovy Spock unit tests with closures

How can I do this in Spock/groovy?
package org.jenkinsci.plugins
import hudson.matrix.*
import spock.lang.*
import org.junit.Rule
import org.jvnet.hudson.test.JenkinsRule
class xxxx extends Specification {
#Rule JenkinsRule rule = new JenkinsRule()
def 'matrix'() {
given:
def matrixProject = rule.createMatrixProject()
AxisList axl = new AxisList();
def axis = new TextAxis('TEST', "1", "2", "3")
axl.add(axis)
matrixProject.setAxes(axl)
expect: matrixProject.scheduleBuild2(0).get().logFile.text.contains("Some String!")
matrixProject.scheduleBuild2(0).get().getRuns().each(){
expect: it.logFile.text.contains("Another String")
}
}
}
specifically, how can I run a closure with a nested test? The "Another String" test doesn't work
Does this work?
def 'matrix'() {
given:
def matrixProject = rule.createMatrixProject()
def axis = new TextAxis('TEST', "1", "2", "3")
matrixProject.axes.add(axis)
expect:
with( matrixProject.scheduleBuild2(0).get() ) {
logFile.text.contains("Some String!")
runs.every { it.logFile.text.contains("Another String") }
}
}
}
Either use every instead of each, or use a nested assert.
I'm not sure if I understand your question well. However if by nested test you mean evaluating statement inside of each closure, why not just use assert
expect:
matrixProject.scheduleBuild2(0).get().logFile.text.contains("Some String!")
matrixProject.scheduleBuild2(0).get().getRuns().each() {
assert it.logFile.text.contains("Another String")
}
#tim_yates's approach also seems fine and it's more like Spock's way. I haven't tested it though.
EDIT
If you want be sure that all logFiles contain test string then use 'every' method as Peter suggested.
expect:
...
matrixProject.scheduleBuild2(0).get().getRuns().every {
it.text.contains('Another String')
}
Other approach, if you prefer to know how many logFiles don't contain test string on test fail count them and compare result size to zero:
expect:
...
matrixProject.scheduleBuild2(0).get().getRuns().count {
!it.text.contains('Another String')
} == 0
Yet another, if you like to know which files caused test to fail, get names of those which don't contain test string and compare that to an empty list:
expect:
...
matrixProject.scheduleBuild2(0).get().getRuns().findAll {
!it.text.contains('Another String')
}*.name == []

Convert camelCase string to dash-separated in Gradle (i.e. Groovy)

I have a bunch of string properties in a gradle build script, which is in camelCase (for example "jmxConsoleWeb"), and I'd like to split each into a dash-separated (e.g. jmx-console-web) string instead.
Is there a "non-hackish" way to do this?
I've solved it like this:
public static String dashSeparated(String s) {
return s.replaceAll(/\B[A-Z]/) { '-' + it }.toLowerCase()
}
Also take a look here
You can use Guava if you don't mind the extra dependancy. Here's a Groovy script that demonstrates its use:
#Grab( 'com.google.guava:guava:13.0.1' )
import static com.google.common.base.CaseFormat.*
String.metaClass.caseFormat = { from, to ->
from.to( to, delegate )
}
assert 'varName'.caseFormat( LOWER_CAMEL, UPPER_UNDERSCORE ) == 'VAR_NAME'
assert 'var-name'.caseFormat( LOWER_HYPHEN, UPPER_CAMEL ) == 'VarName'
assert 'var_name'.caseFormat( LOWER_UNDERSCORE, LOWER_CAMEL ) == 'varName'
assert 'VAR_NAME'.caseFormat( UPPER_UNDERSCORE, LOWER_UNDERSCORE ) == 'var_name'
assert 'VarName'.caseFormat( UPPER_CAMEL, LOWER_HYPHEN ) == 'var-name'
Of course, in a Gradle script, you'd need to import guava into the buildScript dependencies if you want its methods available to the build itself

Need Groovy syntax help for generating a Closure from a String

I'm trying to generate a closure from a string. The code inside the closure references a DSL function build(). The errors I'm getting imply that Groovy is trying to execute the closure instead of just declaring it. What is the correct syntax for this? Here are some of the constructs I have already tried.
sh = new GroovyShell()
cl = sh.evaluate( '{ build("my job") }' }
=> Ambiguous expression could be either a parameterless closure expression or an isolated open code block;
sh = new GroovyShell()
cl = sh.evaluate( 'L: { build("my job") }' }
=> No signature of method: Script1.build() is applicable ...
cl = Eval.me( 'L: { build("my job") }' }
=> No signature of method: Script1.build() is applicable ...
cl = Eval.me( 'L: { com.flow.FlowDelegate.build("my job") }' }
=> No such property: com for class: Script1
The example I'm trying to follow comes from:
Load closure code from string in Groovy
What about returning the closure from the script?
Eval.me("return { build('my job') } ")
What do you intend using that L:? Returning a map? If is that so, you can use square brackets:
groovy:000> a = Eval.me("[L: { build('test for') }]")
===> {L=Script1$_run_closure1#958d49}
groovy:000> a.L
===> Script1$_run_closure1#958d49
Consider the example below. The key is to specify, explicitly, a closure without parameters.
def build = { def jobName ->
println "executing ${jobName}"
}
// we initialize the shell to complete the example
def sh = new GroovyShell()
sh.setVariable("build", build)
// note "->" to specify the closure
def cl = sh.evaluate(' { -> build("my job") }')
println cl.class
cl.call()
In addition to Michael Easter's answer, you could also pass the script's binding through to the GroovyShell
def build = { ->
"BUILD $it"
}
def shell = new GroovyShell( this.binding )
def c = shell.evaluate( "{ -> build( 'tim_yates' ) }" )
c()
If you are evaluating the String from your DSL configuration script, you do not need to create a GroovyShell object.
Your script will be run as a subclass of Script which provides a convenience method for evaluating a string with the current binding.
public Object evaluate(String expression)
throws CompilationFailedException
A helper method to allow the dynamic evaluation of groovy expressions using this scripts binding as the variable scope
So in this case, you'd just need to call evaluate('{ -> build("my job") }').

how to create xml document with special node names with groovy markupbuilder

I am building an ant script with groovy markupbuilder. Unfortunately markupbuilder doesn't allow me to create nodes with name 'target' (no problem with targetee),
becauase it throws me
Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.String.call() is applicable for argument types: (java.util.LinkedHashMap, BuildGen$_main_closure1_closure5) values: [[name:clean], BuildGen$_main_closure1_closure5#18efaea]
Possible solutions: wait(), any(), trim(), split(), dump(), next()
so inside my markupbuilder this snippet works:
targete(name: 'clean') {
delete(dir: rootProj.compilerOutput)
}
but I would like to achieve the same with a 'target' node..
I managed to create an empty 'target' node this way:
builder.invokeMethod('target', [name: 'clean'])
but how can I go on and put more nodes inside this 'target' node?
Example of working code:
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)
builder.project(name: projectName, basedir:'.') {
// works with 'target2' but not with 'target'
'target2'(name: 'build-subprojects') {
rootProj.getAllDependentProjects().each { p->
echo(message: "Compiling project: ${p.projectName}")
// some real stuff
}
}
If I guess right, your problem is you want to create nodes with names that are Groovy keywords?
If so, then you can simply put the name in quotes, like so:
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder( writer )
builder.project {
'for'(name: 'clean') {
delete(dir: '.')
}
}
println writer
That snippet will print out:
<project>
<for name='clean'>
<delete dir='.' />
</for>
</project>
For me, this works:
def projects = [ 'pro_one', 'pro_two' ]
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)
builder.project( name: 'test', basedir:'.' ) {
'target'( name: 'build-subprojects' ) {
projects.each { p ->
echo( message: "Compiling project: ${p}" )
}
}
}
println writer.toString()
Have you got target set to anything in your code before calling this?
You could try:
builder.target( name: 'build-subprojects' ) {
That might work better?
I've tried Groovy 1.7.5, and 1.8 beta 2 and can't get it to fail :-/

Resources