Accessing an object property with a $class definition



Let’s have an object:

def scm = [
            $class: 'GitSCM', 
            branches: branches,
            userRemoteConfigs: 
                [ [ credentialsId: credentialsId, url: repoUrl, name: remote, refspec: refspecs ] ],
            extensions: [
                [$class: 'RelativeTargetDirectory', relativeTargetDir: (args.path ? args.path : args.repository.name) ],
                [$class: 'CloneOption', honorRefspec: true, noTags: true, reference: '', shallow: false, timeout: 30],
                [$class: 'ScmName', name: args.repository.name]
            ]
        ]

I want to check the value of timeout from CloneOption.

I unsuccessfully tried things like:

script.println(scm.extensions[[CloneOption.timeout]])
...

Answer

A way to do it is this:




scm.extensions.find { it.'$class' ==  'CloneOption' }?.timeout

Because scm.extensions is a List, we use find to take one element out of it that matches the condition inside the closure… in the closure, we ask which element has a property $class whose value is CloneOption.

find returns either one element that matches the condition, or null, so to access timeout we use the null-safe operator: ?.timeout.

You can go further and add a helper method to Maps (the type of your “object”) which lets you access property from it or its “extensions” more easily:




Map.metaClass.getProp = { String name ->
    if (containsKey(name)) return get(name)
    extensions.find { e -> e."$name" != null }?."$name"
}

Now, you can use getProp to achieve that:

println "Class of scm is ${scm.getProp('$class')}"
println "Timeout value is ${scm.getProp('timeout')}"

Which will print:

Class of scm is GitSCM
Timeout value is 30


Source: stackoverflow