aShadowOnTheSun
aShadowOnTheSun

Reputation: 3

Switching on String Value Yields Unexpected Results in Groovy

I am working in a groovy/grails set up and am having some trouble trying to execute a switch statement on a String value.

Basically, I am looping through the attribute names in a webservice response to see if they match pre-defined mappings that are configured on a per user basis. If they have established a mapping on that field, I pull the value out of the response and use it elsewhere.

The code looks something like this:

switch(attributeName)
{
    case {attributeName} :
        log.info("Currently switching on value... ${attributeName}")

    case user.getFirstNameMapping():
        model.user.userInfo.firstName = attributeValue
        break
    case user.getLastNameMapping():
        model.user.userInfo.lastName = attributeValue
        break
    case user.getAuthenticationKeyMapping():
        model.authenticationValue = attributeValue
        break
    case user.getEmailMapping():
        model.email = attributeValue.toLowerCase()
        break
}

The value being switched on (attributeName) is of type String, and the getter methods for the user instance also return type String.

Based on my research and understanding of the Groovy language, switching on an Object such as a String should end up using String.equals() to make the comparison. The result, however, is that it is matching on the user.getFirstNameMapping() case every time, and repeatedly overwriting the value in the model; therefore, the last value that comes back in the response is what ends up saved, and none of the other values are saved.

What's interesting is that if I use an if/else structure and do something like this:

if(attributeName.equals(user.getFirstNameMapping())
{
    ...
}

It works fine every time. I've verified through logging that it's not something silly like extra whitespace or a capitalization issue. I've also tried changing things around to run the switch by default and explicitly compare the attributeName in the case like this:

switch(true)
{
    case {attributeName} :
        log.info("Currently switching on value... ${attributeName}")
    case {user.getFirstNameMapping().equals(attributeName)}:
        model.user.userInfo.firstName = attributeValue
        break
    case {user.getLastNameMapping().equals(attributeName)}:
        model.user.userInfo.lastName = attributeValue
        break
    case {user.getAuthenticationKeyMapping().equals(attributeName)}:
        model.authenticationValue = attributeValue
        break
    case {user.getEmailMapping().equals(attributeName)}:
        model.email = attributeValue.toLowerCase()
        break
}

And it still fails to meet my expectations in the exact same way. So, I'm wondering why this is the behavior when the switch statement should simply be using .equals() to compare the strings, and when I explicitly compare them in an if/else using .equals(), it works as expected.

Upvotes: 0

Views: 426

Answers (2)

Chetan Hallan
Chetan Hallan

Reputation: 279

The issue is in your switch case.

Have a look here :-

case {attributeName} :
        log.info("Currently switching on value... ${attributeName}")

case user.getFirstNameMapping():
        model.user.userInfo.firstName = attributeValue
        break

As you can see your these two cases will run every time because the switch condition is :-

switch(attributeName)

So the first one will get match and will run until it encounters break; which is at after case 2 i.e. case user.getFirstNameMapping(): so i would suggest you to print the value of {attributeName} before the swtich starts.

Hope that will help you.

Thanks

Upvotes: 1

user800014
user800014

Reputation:

I don't know exactly what's your issue, but the case statement works just fine, even with methods. See my example

String something = "Foo"

class User {
  String firstName
  String lastName
}

User u = new User(firstName: 'Something', lastName:'Foo')

switch(something) {
  case u.getFirstName(): 
    println "firstName: ${u.firstName}"
    break;
  case u.getLastName():
    println "lastName: ${u.lastName}"
    break;
  default:
    println "nothing..."
}

This code will print lastName as expected. ​

Upvotes: 0

Related Questions