elyon
elyon

Reputation: 181

Get method for maps in groovy

In Config.groovy:

Query {
    parameterMap {
        time.'1328' =  ['T1']
        time.'1329' =  ['T2']
        templates.'T1'   =  ['X','Y','Z']
        templates.'T2'   =  ['Z']
    }
}

In QuartzSchedulerJob I want to use T1 and T2 which are templateId as key to get the corresponding values in parameterMap but it returns me null and [:] respectively, parameterMap.templates.get("${v}") but I want to get ['X','Y','Z'] and ['Z'] respectively for T1 and T2

def execute() {
    def currentTime = new Date().format('HHmm')
    grailsApplication.config.Query.parameterMap.time.each { k, v ->
        if (currentTime=="${k}") {
            println "${k} " + currentTime
            String templateId = "${v}".replaceAll("\\[", "").replaceAll("\\]","")
            println grailsApplication.config.Query.parameterMap.templates.get("${v}") //this prints null
            println grailsApplication.config.Query.parameterMap.templates.getAt("${v}") //this prints [:]
        }
    }
}

Upvotes: 0

Views: 288

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75671

"${k}" is a weird expression, and I see it a lot in Groovy code. I would love to know who and/or what (book/blog/???) somehow got people using that syntax. I see it quite often in toString methods that intend to return a class field as the value, e.g.

private String name
...
String toString() {
   "${name}"
}

Why not just return the variable?

String toString() {
   name
}

You're doing this here, making a GString "${k}" with only a single embedded variable and no other characters, and then implicitly converting it to a String when comparing it to currentTime (which works, but is far from optimal or sensible) and using this GString to generate (in a very funky way) to a potential key in a Map when calling get and getAt, and wondering why the value inside this weird little GString, which is very close to being a map key (as Tim points out the values of the time map are single-element Lists, and the keys of the templates map are Strings which are the single elements of these Lists) isn't also automagically converted into what you wanted it to have been.

Groovy does lots of implicit conversions, but the signature of the get method in Map is Object get(Object key) (technically it's got a generic return type, but that's not relevant here) so Groovy isn't going to do any conversion for you - you're passing an Object as a parameter to a method that takes Object. There's no reason at all to expect that it would be converted to a String, or to any of the types of any of the keys, or to anything at all.

This loc hurts my brain:

String templateId = "${v}".replaceAll("\\[", "").replaceAll("\\]","")

You're taking the list v, converting it to a String by embedding it with nothing else in a GString, coercing Groovy to convert the GString to a String so it can call replaceAll on it, to remove the brackets that are at the beginning and end of the toString form of AbstractCollection, to extract the single String element in v.

How about something a bit more direct:

String templateId = v[0]

and its use in a cleaned up version of execute:

def execute() {
    String currentTime = new Date().format('HHmm')
    grailsApplication.config.Query.parameterMap.time.each { k, v ->
        if (currentTime == k) {
            println "$k $currentTime"
            String templateId = v[0]
            println config.Query.parameterMap.templates[templateId] // get and getAt would also work
        }
    }
}

Upvotes: 1

Related Questions