Skip to content

Commit 17f8a24

Browse files
committed
Fix property names with successive capital letters
Previously, if a property name had successive capital letters, the generated meta-data would clean it in such a way it is defined as a regular word. For instance a `myFOO` property would be written as `my-foo` in the meta-data. It turns out this decision is wrong as the binder has no way to compute back the name of the property and therefore `my-foo` wouldn't bind to `setMyFOO` as it should. This commit updates the meta-data name generation algorithm to properly identify such cases: `myFOO` now translates to `my-f-o-o`. While the generated name is a bit ugly, it now provides a consistent binding experience. Closes gh-5330
1 parent 8d491f2 commit 17f8a24

File tree

3 files changed

+54
-30
lines changed

3 files changed

+54
-30
lines changed

spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadata.java

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2015 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,11 +17,10 @@
1717
package org.springframework.boot.configurationprocessor.metadata;
1818

1919
import java.util.ArrayList;
20+
import java.util.Arrays;
2021
import java.util.Collections;
2122
import java.util.List;
2223
import java.util.ListIterator;
23-
import java.util.regex.Matcher;
24-
import java.util.regex.Pattern;
2524

2625
import org.springframework.util.CollectionUtils;
2726
import org.springframework.util.LinkedMultiValueMap;
@@ -38,7 +37,7 @@
3837
*/
3938
public class ConfigurationMetadata {
4039

41-
private static final Pattern CAMEL_CASE_PATTERN = Pattern.compile("([^A-Z-])([A-Z])");
40+
private static final List<Character> SEPARATORS = Arrays.asList('-', '_');
4241

4342
private final MultiValueMap<String, ItemMetadata> items;
4443

@@ -160,23 +159,23 @@ public static String nestedPrefix(String prefix, String name) {
160159
}
161160

162161
static String toDashedCase(String name) {
163-
Matcher matcher = CAMEL_CASE_PATTERN.matcher(name);
164-
StringBuffer result = new StringBuffer();
165-
while (matcher.find()) {
166-
matcher.appendReplacement(result, getDashed(matcher));
167-
}
168-
matcher.appendTail(result);
169-
return result.toString().toLowerCase();
170-
}
162+
StringBuilder sb = new StringBuilder();
163+
Character previous = null;
164+
for (char current : name.toCharArray()) {
165+
if (SEPARATORS.contains(current)) {
166+
sb.append("-");
167+
}
168+
else if (Character.isUpperCase(current) && previous != null
169+
&& !SEPARATORS.contains(previous)) {
170+
sb.append("-").append(current);
171+
}
172+
else {
173+
sb.append(current);
174+
}
175+
previous = current;
171176

172-
private static String getDashed(Matcher matcher) {
173-
String first = matcher.group(1);
174-
String second = matcher.group(2);
175-
if (first.equals("_")) {
176-
// not a word for the binder
177-
return first + second;
178177
}
179-
return first + "-" + second;
178+
return sb.toString().toLowerCase();
180179
}
181180

182181
private static <T extends Comparable<T>> List<T> flattenValues(

spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadataTests.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,35 +33,45 @@ public void toDashedCaseCamelCase() {
3333
assertThat(toDashedCase("simpleCamelCase"), is("simple-camel-case"));
3434
}
3535

36+
@Test
37+
public void toDashedCaseUpperCamelCaseSuffix() {
38+
assertThat(toDashedCase("myDLQ"), is("my-d-l-q"));
39+
}
40+
41+
@Test
42+
public void toDashedCaseUpperCamelCaseMiddle() {
43+
assertThat(toDashedCase("someDLQKey"), is("some-d-l-q-key"));
44+
}
45+
3646
@Test
3747
public void toDashedCaseWordsUnderscore() {
38-
assertThat(toDashedCase("Word_With_underscore"), is("word_with_underscore"));
48+
assertThat(toDashedCase("Word_With_underscore"), is("word-with-underscore"));
3949
}
4050

4151
@Test
4252
public void toDashedCaseWordsSeveralUnderscores() {
4353
assertThat(toDashedCase("Word___With__underscore"),
44-
is("word___with__underscore"));
54+
is("word---with--underscore"));
4555
}
4656

4757
@Test
4858
public void toDashedCaseLowerCaseUnderscore() {
49-
assertThat(toDashedCase("lower_underscore"), is("lower_underscore"));
59+
assertThat(toDashedCase("lower_underscore"), is("lower-underscore"));
5060
}
5161

5262
@Test
53-
public void toDashedCaseUpperUnderscore() {
54-
assertThat(toDashedCase("UPPER_UNDERSCORE"), is("upper_underscore"));
63+
public void toDashedCaseUpperUnderscoreSuffix() {
64+
assertThat(toDashedCase("my_DLQ"), is("my-d-l-q"));
5565
}
5666

5767
@Test
58-
public void toDashedCaseMultipleUnderscores() {
59-
assertThat(toDashedCase("super___crazy"), is("super___crazy"));
68+
public void toDashedCaseUpperUnderscoreMiddle() {
69+
assertThat(toDashedCase("some_DLQ_key"), is("some-d-l-q-key"));
6070
}
6171

6272
@Test
63-
public void toDashedCaseUppercase() {
64-
assertThat(toDashedCase("UPPERCASE"), is("uppercase"));
73+
public void toDashedCaseMultipleUnderscores() {
74+
assertThat(toDashedCase("super___crazy"), is("super---crazy"));
6575
}
6676

6777
@Test

spring-boot/src/test/java/org/springframework/boot/bind/PropertiesConfigurationFactoryTests.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2015 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -170,6 +170,12 @@ public void propertyWithAllUpperCaseSuffixCanBeBound() throws Exception {
170170
assertEquals("baz", foo.fooBarURI);
171171
}
172172

173+
@Test
174+
public void propertyWithAllUpperCaseInTheMiddleCanBeBound() throws Exception {
175+
Foo foo = createFoo("foo-d-l-q-bar:baz");
176+
assertEquals("baz", foo.fooDLQBar);
177+
}
178+
173179
private Foo createFoo(final String values) throws Exception {
174180
setupFactory();
175181
return bindFoo(values);
@@ -203,6 +209,8 @@ public static class Foo {
203209

204210
private String fooBarURI;
205211

212+
private String fooDLQBar;
213+
206214
public String getSpringFooBaz() {
207215
return this.spring_foo_baz;
208216
}
@@ -243,6 +251,13 @@ public void setFooBarURI(String fooBarURI) {
243251
this.fooBarURI = fooBarURI;
244252
}
245253

254+
public String getFooDLQBar() {
255+
return this.fooDLQBar;
256+
}
257+
258+
public void setFooDLQBar(String fooDLQBar) {
259+
this.fooDLQBar = fooDLQBar;
260+
}
246261
}
247262

248263
}

0 commit comments

Comments
 (0)