implements Elegance {

// Elwyn Malethan's musings on software development, mountain biking and general navel–gazing...

Humanise CamelCase in Java

In an effort to make my CRUD scaffolder for Seemore more friendly I embarked on the modest endeavour of implementing a utility method to convert camelCase variable or class names to something more human friendly.

A nice, easy little task to try and forget the hangover I managed to get myself last night (thanks Dave!). Here‘s the code.

/**
 * Converts a camelCase to a more human form, with spaces. E.g. 'Camel case'
 *
 */
public String humaniseCamelCase(String word) {
    Pattern pattern = Pattern.compile("([A-Z]|[a-z])[a-z]*");

    Vector<String> tokens = new Vector<String>();
    Matcher matcher = pattern.matcher(word);
    String acronym = "";
    while(matcher.find()) {
        String found = matcher.group();
        if(found.matches("^[A-Z]$")) {
            acronym += found;
        } else {
            if(acronym.length() > 0) {
                //we have an acronym to add before we continue
                tokens.add(acronym);
                acronym  = "";
            }
            tokens.add(found.toLowerCase());
        }
    }
    if(acronym.length() > 0) {
        tokens.add(acronym);
    }
    if (tokens.size() > 0) {
        String humanisedString = capitaliseFirstLetter(tokens.remove(0));
        for (String s : tokens) {
            humanisedString +=  " " + s;
        }
        return humanisedString;
    }

    return word;
}

The test case for this can be seen below.

import static org.junit.Assert.assertEquals;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

@RunWith(Parameterized.class)
public class StringUtilTest {

    private static StringUtils util;

    @BeforeClass
    public static void setUpBeforeClass() {
        util = new StringUtils();
    }

    @Parameterized.Parameters
    public static Collection regExValues() {
     return Arrays.asList(new String[][] {
         {"camel", "Camel"},
         {"Camel", "Camel"},
         {"camelCase", "Camel case"},
         {"CamelCase", "Camel case"},
         {"doubleCamelCase", "Double camel case"},
         {"DoubleCamelCase", "Double camel case"},
         {"somethingRandomInTheHouse", "Something random in the house"},
         {"aTLA", "A TLA"},
         {"aTLAAndSomeMore", "A TLA and some more"},
         {"NOTCAMELCASE", "NOTCAMELCASE"},
         {"Certainly not camel case", "Certainly not camel case"}
      });
    }

    String input;
    String expectedOutcome;

    public StringUtilTest(String input, String expectedOutcome) {
        this.input = input;
        this.expectedOutcome = expectedOutcome;
    }

    @Test
    public void humaniseShouldHandleCamelCase() {
        assertEquals(expectedOutcome, util.humaniseCamelCase(input));
    }
}

I‘m not sure I like the way JUnit does the parameterised tests. It‘s certainly an improvement on having to write each test out individually (who‘d do that!?) and it‘s probably better than lumping all scenarios/criteria into one test. However, the reporting of each scenario/run isn‘t any more detailed than doing just that. The only difference is that the array index of the failing parameters is given – hardly useful when the failed assert already tells us what‘s wrong.

When you compare the above to something like how it would look implemented in Rspec, it looks just plain ugly. I don't like ugly. I must look into TestNG, to see if it has a more elegant approach. Failing that, I'll have a look at how the JtestR project is coming along and start thinking about writing some tests using Rspec again.

Update: There's a better, more considered implementation of this here.

First published on Feb 8, 2009. Last updated on: Dec 30, 2009.

Comments (7)

Leave a reply »

 
 

Stumbled on your solution while Googling for “java convert camel case”. I also found an very interesting implementation in Javascript. It would be interesting to see if Java could produce such a succinct implementation.

 

... Yesterday, I posted a hangover–inspired camel–case humaniser. Today – with the benefit of a clearer mind …

 

Was looking at Apache Commons StringUtils but did not find ‘humanise‘. Thanks a lot

 

download commons.lang 2.4 above
i guess you can manipulate through the StringUtils.splitByCharacterTypeCamelCase(String)

e.g.

//Split the word
String[] strArray = StringUtils.splitByCharacterTypeCamelCase(String);

//separate the tokens by spaces
StringUtils.join(strArray, “ ”);

Hope this helps :-)

 

Nice! What about capitaliseFirstLetter?

 

@Dan

capitaliseFirstLetter can be found in the refactored code here. It‘s actually fairly trivial.

return str.substring(0, 1).toUpperCase() + str.substring(1);

Edit 17th-Feb-2010: Though you should use a StringBuffer or StringBuilder for better efficiency.

 

Hey Its great!!

Leave a Reply

Your name
 
Email
 
Website
 
Comment

You may use Textile notation here
 
 

Please perform this simple arithmetic test to prove you are human