0

Using Groovy 2.0

Is it possible with the GPath property expressions to uses predicate to filter:

class HandShaker {
String title
}

class AussieGreeter implements Greeter {
String name
List<HandShaker> handshaker
    ....
}

AussieGreeter greeter = new AussieGreeter()
greeter.setName("hello")
greeter.setHandshaker([new Handshaker().setTitle("butler")].asList()])

println Eval.x(greeter,"x[name=='hello'].handshaker[0].title")

To filter a Greeter if the name property is equal to "hello"? Haven't seen an examples like this and Groovy bails with MissingPropertyException.

tim_yates
  • 167,322
  • 27
  • 342
  • 338
Matthew Campbell
  • 1,864
  • 3
  • 24
  • 51

1 Answers1

1

I think you need to do:

println Eval.x(greeter,"x.find { it.name == 'hello' }.handshaker[0].title")

You can hack the getAt method for AussieGreeter to take a Closure, and return the element if that returns true or null otherwise like so:

class HandShaker {
  String title
}

interface Greeter {}

class AussieGreeter implements Greeter {
  String name
  List<HandShaker> handshaker

  def getAt( Closure o ) {
    o.delegate = this
    o.resolveStrategy = Closure.DELEGATE_FIRST
    o() ? this : null
  }
}

AussieGreeter greeter = new AussieGreeter( name:'hello',
                                           handshaker:[new HandShaker( title:'butler' )] )

greeter[ { name == 'hello' } ]?.handshaker[0].title

Which is closer to your original requirement (but has braces round the comparison and a ? after the square braces)

But the find is much easier to read imho :-/

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • That is what is in my comment. Wanted a shorthand more compact way of doing it like predicate filters in XPath. If this exists. Or if people opt for another alternative like JXPath instead? – Matthew Campbell Jul 02 '12 at 12:00
  • @MatthewYoung Yeah, you added your second comment just after I added this answer. There's nothing I can think of that matches your requirement – tim_yates Jul 02 '12 at 12:11
  • The getAt operator is what is being applied so maybe an override with the right typing might do it: greeter.metaClass.getAt = { String predicate -> return Eval.x(delegate,"x.find { $predicate }") } – Matthew Campbell Jul 02 '12 at 13:05
  • @MatthewYoung Added the best I can think of for hacking around with `getAt` to my answer... – tim_yates Jul 02 '12 at 14:13