diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java index be3287722f..72299b1cfa 100644 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java +++ b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedNames.java @@ -19,6 +19,8 @@ package org.springframework.boot.bind; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.springframework.util.StringUtils; @@ -32,6 +34,8 @@ import org.springframework.util.StringUtils; */ public final class RelaxedNames implements Iterable { + private static final Pattern CAMEL_CASE_PATTERN = Pattern.compile("([^A-Z-])([A-Z])"); + private final String name; private final Set values = new LinkedHashSet(); @@ -126,17 +130,28 @@ public final class RelaxedNames implements Iterable { CAMELCASE_TO_UNDERSCORE { @Override public String apply(String value) { - value = value.replaceAll("([^A-Z-])([A-Z])", "$1_$2"); - StringBuilder builder = new StringBuilder(); - for (String field : value.split("_")) { - if (builder.length() == 0) { - builder.append(field); - } - else { - builder.append("_").append(StringUtils.uncapitalize(field)); - } + Matcher matcher = CAMEL_CASE_PATTERN.matcher(value); + StringBuffer result = new StringBuffer(); + while (matcher.find()) { + matcher.appendReplacement(result, matcher.group(1) + '_' + + StringUtils.uncapitalize(matcher.group(2))); } - return builder.toString(); + matcher.appendTail(result); + return result.toString(); + } + }, + + CAMELCASE_TO_HYPHEN { + @Override + public String apply(String value) { + Matcher matcher = CAMEL_CASE_PATTERN.matcher(value); + StringBuffer result = new StringBuffer(); + while (matcher.find()) { + matcher.appendReplacement(result, matcher.group(1) + '-' + + StringUtils.uncapitalize(matcher.group(2))); + } + matcher.appendTail(result); + return result.toString(); } }, diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedNamesTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedNamesTests.java index d1b6bf2be8..37acee80ff 100644 --- a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedNamesTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedNamesTests.java @@ -72,9 +72,24 @@ public class RelaxedNamesTests { Iterator iterator = new RelaxedNames("caMel").iterator(); assertThat(iterator.next(), equalTo("caMel")); assertThat(iterator.next(), equalTo("ca_mel")); + assertThat(iterator.next(), equalTo("ca-mel")); assertThat(iterator.next(), equalTo("camel")); assertThat(iterator.next(), equalTo("CAMEL")); assertThat(iterator.next(), equalTo("CA_MEL")); + assertThat(iterator.next(), equalTo("CA-MEL")); + assertThat(iterator.hasNext(), equalTo(false)); + } + + @Test + public void fromCompoundCamelCase() throws Exception { + Iterator iterator = new RelaxedNames("caMelCase").iterator(); + assertThat(iterator.next(), equalTo("caMelCase")); + assertThat(iterator.next(), equalTo("ca_mel_case")); + assertThat(iterator.next(), equalTo("ca-mel-case")); + assertThat(iterator.next(), equalTo("camelcase")); + assertThat(iterator.next(), equalTo("CAMELCASE")); + assertThat(iterator.next(), equalTo("CA_MEL_CASE")); + assertThat(iterator.next(), equalTo("CA-MEL-CASE")); assertThat(iterator.hasNext(), equalTo(false)); }