suman j
suman j

Reputation: 6960

using gstring to access list property element

Using GStrings one can access the properties of the object, including nested properties. But how to access the n'th element inside a list property?

class Foo {
   List<Bar> elements
}
class Bar {
  String version
}

I need to access version property in Foo.elements object for a specific index using GString. Tried below code without success.

def property = "elements[0].version"
fooObject."$property" fails to identify the property

Upvotes: 3

Views: 211

Answers (2)

dmahapatro
dmahapatro

Reputation: 50245

Ideally, it could be:

def prop1 = "elements"
def prop2 = "version"

fooObject."$prop1"[0]."$prop2"

Lengthy and generic one would be using inject:

class Foo {
   List<Bar> elements
}
class Bar {
  String version
}

def fooObject = new Foo(elements: [new Bar(version: '1'), 
                                   new Bar(version: '2'), 
                                   new Bar(version: '3')])

def fetchVersion(property, fooObject) {
    property.tokenize(/./).inject(fooObject) {obj, elem -> 
        if(elem.contains(/[/)){
            def var = elem.tokenize(/[]/)
            obj?."${var[0]}".getAt("${var[1]}".toInteger()) 
        } else {
            obj?."$elem" 
        }
    }
}

assert fetchVersion("elements[0].version", fooObject) == '1'
assert fetchVersion("elements[1].version", fooObject) == '2'
assert fetchVersion("elements[2].version", fooObject) == '3'
assert fetchVersion("elements[7].version", fooObject) == null

Upvotes: 1

kdabir
kdabir

Reputation: 9868

So there are three ways in which I think this problem can be solved depending upon how much flexibility is allowed

class Foo {
   List<Bar> elements
}
class Bar {
  String version
}

Let's say fooObject is the object of Foo, e.g.:

def fooObject = new Foo(elements:[new Bar(version:1), new Bar(version:2)])
  1. If this is possible for you:

    println fooObject."elements"[1]."version"
    
  2. Otherwise, put everything in a string and then interpolate:

    println "${fooObject.elements[1].version}"
    
  3. Ultimately, if both of the above don't fly for you:

    def property='elements[1].version'
    def expr = 'fooObject.' + property
    println Eval.me('fooObject', fooObject, expr)
    

The last one makes the fooObject available as fooObject to the expression being evaluated and evaluates the expression.

Upvotes: 4

Related Questions