Search code examples
groovyfindallcollect

How to use the collect function in Groovy to find all objects by the name of a field?


I know the question is confusing, let me explain. I have an object like this

scmStage: {
"execute": true,
"parallel": true,
"integrationPoints": [
    {
        "method": "checkout",
        "checkout": {
            "credentials": {
                "type": "credentialsId",
                "id": "bitB1"
            },
            "type": "GIT",
            "url": "...",
            "branch": "feature",
            "component": true
        }
    },
    {
        "method": "scm",
        "scm": {
            "credentials": {
                "type": "credentialsId",
                "id": "bitB1"
            },
            "type": "GIT",
            "url": "...",
            "branch": "master"
        }
    },
    {
        "method": "scm",
        "scm": {
            "credentials": {
                "type": "credentialsId",
                "id": "bitB1"
            },
            "type": "GIT",
            "url": "...",
            "branch": "dev"
        }
    }
]
}

I need to check each of the integration points, until I find the one with the property

"component": true

In this case, it's the first one. If the integration points had all the same method (lets say METHOD_SCM), I would do something like this:

integrationPointComponent = (Map) (((List<Map>) scmStage.integrationPoints)?.findAll {
      it.method == Constants.METHOD_SCM
  })?.collect {
      (Map) it.scm
  }?.findAll {
      it.component
  }?.size() == 1

And I would have my integration point with the component property, but, the reality is that the integration points can have three different names (METHOD_SCM, METHOD_CHECKOUT and METHOD_GIT)

And I would need to do something like this

integrationPointComponent = (Map) (((List<Map>) scmStage.integrationPoints)?.findAll {
    (it.method == Constants.METHOD_SCM || it.method == Constants.METHOD_CHECKOUT || it.method == Constants.METHOD_GIT)
    })?.collect {
        (Map) it.scm  <-------PROBLEM
    }?.findAll {
        it.component
    }?.size() == 1

I need for each method to write its name in the collect function depending on the method if its METHOD_SCM, then it should be it.scm, if its METHOD_CHECKOUT then it should be it.checkout, and similar with git.

Is there any way to write it up in one go, instead of writing 3 different cases for each one, something like using the method property as a field within the collection, something like this:

?.collect {
    (Map) it.[it.method]   or ${it.method} or  something else...need help
}?.findAll {
    it.component
}?.size() == 1

Or another way of asking this question is, what would be the best way of getting the integration point with the component property?

Edit 1: @daggett I tried the first variant as @dagget suggested, like this:

(((List<Map>) scmStage.integrationPoints)?.find{
it.method in ['checkout', 'git', 'scm'] && it[it.method]?.component==true })

And the first part: it.method in ['checkout', 'git', 'scm'] throws an error:

'ArrayList<String>' cannot contain 'Object'

I solved it by converting the it.method to string, like this:

(String)it.method in ['checkout','scm', 'git']

But one issue remains in the second part: it[it.method]?.component==true

That is the following: No candidates found for method call it[it.method]?.component

But, the funny part is, it's working! Thanks man, have an upvote.


Solution

  • def scmStage = new groovy.json.JsonSlurper().parseText(''' {
    "execute": true,
    "parallel": true,
    "integrationPoints": [
        {
            "method": "scm",
            "scm": {
                "credentials": {
                    "type": "credentialsId",
                    "id": "scm-bitbucket"
                },
                "type": "GIT",
                "url": "...",
                "branch": "master"
            }
        },
        {
            "method": "checkout",
            "checkout": {
                "credentials": {
                    "type": "credentialsId",
                    "id": "scm-bitbucket"
                },
                "type": "GIT",
                "url": "...",
                "branch": "feature",
                "component": true
            }
        },
        {
            "method": "scm",
            "scm": {
                "credentials": {
                    "type": "credentialsId",
                    "id": "scm-bitbucket"
                },
                "type": "GIT",
                "url": "...",
                "branch": "dev"
            }
        }
    ]
    }''')
    
    
    def p = scmStage.integrationPoints.find{ it.method in ['checkout'] && it[it.method]?.component==true }
    assert p