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
This commit is contained in:
parent
8d491f278b
commit
17f8a244de
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -17,11 +17,10 @@
|
|||
package org.springframework.boot.configurationprocessor.metadata;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
|
@ -38,7 +37,7 @@ import org.springframework.util.ObjectUtils;
|
|||
*/
|
||||
public class ConfigurationMetadata {
|
||||
|
||||
private static final Pattern CAMEL_CASE_PATTERN = Pattern.compile("([^A-Z-])([A-Z])");
|
||||
private static final List<Character> SEPARATORS = Arrays.asList('-', '_');
|
||||
|
||||
private final MultiValueMap<String, ItemMetadata> items;
|
||||
|
||||
|
|
@ -160,23 +159,23 @@ public class ConfigurationMetadata {
|
|||
}
|
||||
|
||||
static String toDashedCase(String name) {
|
||||
Matcher matcher = CAMEL_CASE_PATTERN.matcher(name);
|
||||
StringBuffer result = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(result, getDashed(matcher));
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
return result.toString().toLowerCase();
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Character previous = null;
|
||||
for (char current : name.toCharArray()) {
|
||||
if (SEPARATORS.contains(current)) {
|
||||
sb.append("-");
|
||||
}
|
||||
else if (Character.isUpperCase(current) && previous != null
|
||||
&& !SEPARATORS.contains(previous)) {
|
||||
sb.append("-").append(current);
|
||||
}
|
||||
else {
|
||||
sb.append(current);
|
||||
}
|
||||
previous = current;
|
||||
|
||||
private static String getDashed(Matcher matcher) {
|
||||
String first = matcher.group(1);
|
||||
String second = matcher.group(2);
|
||||
if (first.equals("_")) {
|
||||
// not a word for the binder
|
||||
return first + second;
|
||||
}
|
||||
return first + "-" + second;
|
||||
return sb.toString().toLowerCase();
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> List<T> flattenValues(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -33,35 +33,45 @@ public class ConfigurationMetadataTests {
|
|||
assertThat(toDashedCase("simpleCamelCase"), is("simple-camel-case"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseUpperCamelCaseSuffix() {
|
||||
assertThat(toDashedCase("myDLQ"), is("my-d-l-q"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseUpperCamelCaseMiddle() {
|
||||
assertThat(toDashedCase("someDLQKey"), is("some-d-l-q-key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseWordsUnderscore() {
|
||||
assertThat(toDashedCase("Word_With_underscore"), is("word_with_underscore"));
|
||||
assertThat(toDashedCase("Word_With_underscore"), is("word-with-underscore"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseWordsSeveralUnderscores() {
|
||||
assertThat(toDashedCase("Word___With__underscore"),
|
||||
is("word___with__underscore"));
|
||||
is("word---with--underscore"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseLowerCaseUnderscore() {
|
||||
assertThat(toDashedCase("lower_underscore"), is("lower_underscore"));
|
||||
assertThat(toDashedCase("lower_underscore"), is("lower-underscore"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseUpperUnderscore() {
|
||||
assertThat(toDashedCase("UPPER_UNDERSCORE"), is("upper_underscore"));
|
||||
public void toDashedCaseUpperUnderscoreSuffix() {
|
||||
assertThat(toDashedCase("my_DLQ"), is("my-d-l-q"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseUpperUnderscoreMiddle() {
|
||||
assertThat(toDashedCase("some_DLQ_key"), is("some-d-l-q-key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseMultipleUnderscores() {
|
||||
assertThat(toDashedCase("super___crazy"), is("super___crazy"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toDashedCaseUppercase() {
|
||||
assertThat(toDashedCase("UPPERCASE"), is("uppercase"));
|
||||
assertThat(toDashedCase("super___crazy"), is("super---crazy"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -170,6 +170,12 @@ public class PropertiesConfigurationFactoryTests {
|
|||
assertEquals("baz", foo.fooBarURI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyWithAllUpperCaseInTheMiddleCanBeBound() throws Exception {
|
||||
Foo foo = createFoo("foo-d-l-q-bar:baz");
|
||||
assertEquals("baz", foo.fooDLQBar);
|
||||
}
|
||||
|
||||
private Foo createFoo(final String values) throws Exception {
|
||||
setupFactory();
|
||||
return bindFoo(values);
|
||||
|
|
@ -203,6 +209,8 @@ public class PropertiesConfigurationFactoryTests {
|
|||
|
||||
private String fooBarURI;
|
||||
|
||||
private String fooDLQBar;
|
||||
|
||||
public String getSpringFooBaz() {
|
||||
return this.spring_foo_baz;
|
||||
}
|
||||
|
|
@ -243,6 +251,13 @@ public class PropertiesConfigurationFactoryTests {
|
|||
this.fooBarURI = fooBarURI;
|
||||
}
|
||||
|
||||
public String getFooDLQBar() {
|
||||
return this.fooDLQBar;
|
||||
}
|
||||
|
||||
public void setFooDLQBar(String fooDLQBar) {
|
||||
this.fooDLQBar = fooDLQBar;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue