Add support for RelaxedDataBinder aliases
Update RelaxedDataBinder to support property aliases and change DataSourceBuilder to use them. Fixes gh-1384
This commit is contained in:
@@ -23,7 +23,6 @@ import javax.sql.DataSource;
|
|||||||
|
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.PropertyValues;
|
|
||||||
import org.springframework.boot.bind.RelaxedDataBinder;
|
import org.springframework.boot.bind.RelaxedDataBinder;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
@@ -84,15 +83,8 @@ public class DataSourceBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void bind(DataSource result) {
|
private void bind(DataSource result) {
|
||||||
new RelaxedDataBinder(result).bind(getPropertyValues());
|
MutablePropertyValues properties = new MutablePropertyValues(this.properties);
|
||||||
}
|
new RelaxedDataBinder(result).withAlias("url", "jdbcUrl").bind(properties);
|
||||||
|
|
||||||
private PropertyValues getPropertyValues() {
|
|
||||||
if (getType().getName().contains("Hikari") && this.properties.containsKey("url")) {
|
|
||||||
this.properties.put("jdbcUrl", this.properties.get("url"));
|
|
||||||
this.properties.remove("url");
|
|
||||||
}
|
|
||||||
return new MutablePropertyValues(this.properties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataSourceBuilder type(Class<? extends DataSource> type) {
|
public DataSourceBuilder type(Class<? extends DataSource> type) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.springframework.boot.bind;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -29,6 +30,8 @@ import org.springframework.beans.InvalidPropertyException;
|
|||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.PropertyValue;
|
import org.springframework.beans.PropertyValue;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.validation.DataBinder;
|
import org.springframework.validation.DataBinder;
|
||||||
|
|
||||||
@@ -47,6 +50,8 @@ public class RelaxedDataBinder extends DataBinder {
|
|||||||
|
|
||||||
private boolean ignoreNestedProperties;
|
private boolean ignoreNestedProperties;
|
||||||
|
|
||||||
|
private MultiValueMap<String, String> nameAliases = new LinkedMultiValueMap<String, String>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link RelaxedDataBinder} instance.
|
* Create a new {@link RelaxedDataBinder} instance.
|
||||||
* @param target the target into which properties are bound
|
* @param target the target into which properties are bound
|
||||||
@@ -76,6 +81,27 @@ public class RelaxedDataBinder extends DataBinder {
|
|||||||
this.ignoreNestedProperties = ignoreNestedProperties;
|
this.ignoreNestedProperties = ignoreNestedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set name aliases.
|
||||||
|
* @param aliases a map of property name to aliases
|
||||||
|
*/
|
||||||
|
public void setNameAliases(Map<String, List<String>> aliases) {
|
||||||
|
this.nameAliases = new LinkedMultiValueMap<String, String>(aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add aliases to the {@link DataBinder}.
|
||||||
|
* @param name the property name to alias
|
||||||
|
* @param alias aliases for the property names
|
||||||
|
* @return this instance
|
||||||
|
*/
|
||||||
|
public RelaxedDataBinder withAlias(String name, String... alias) {
|
||||||
|
for (String value : alias) {
|
||||||
|
this.nameAliases.add(name, value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initBeanPropertyAccess() {
|
public void initBeanPropertyAccess() {
|
||||||
super.initBeanPropertyAccess();
|
super.initBeanPropertyAccess();
|
||||||
@@ -262,19 +288,33 @@ public class RelaxedDataBinder extends DataBinder {
|
|||||||
|
|
||||||
private String getActualPropertyName(BeanWrapper target, String prefix, String name) {
|
private String getActualPropertyName(BeanWrapper target, String prefix, String name) {
|
||||||
prefix = StringUtils.hasText(prefix) ? prefix + "." : "";
|
prefix = StringUtils.hasText(prefix) ? prefix + "." : "";
|
||||||
for (String candidate : new RelaxedNames(name)) {
|
Iterable<String> names = getNameAndAliases(name);
|
||||||
try {
|
for (String nameOrAlias : names) {
|
||||||
if (target.getPropertyType(prefix + candidate) != null) {
|
for (String candidate : new RelaxedNames(nameOrAlias)) {
|
||||||
return candidate;
|
try {
|
||||||
|
if (target.getPropertyType(prefix + candidate) != null) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidPropertyException ex) {
|
||||||
|
// swallow and continue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (InvalidPropertyException ex) {
|
|
||||||
// swallow and continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Iterable<String> getNameAndAliases(String name) {
|
||||||
|
List<String> aliases = this.nameAliases.get(name);
|
||||||
|
if (aliases == null) {
|
||||||
|
return Collections.singleton(name);
|
||||||
|
}
|
||||||
|
List<String> nameAndAliases = new ArrayList<String>(aliases.size() + 1);
|
||||||
|
nameAndAliases.add(name);
|
||||||
|
nameAndAliases.addAll(aliases);
|
||||||
|
return nameAndAliases;
|
||||||
|
}
|
||||||
|
|
||||||
private static Object wrapTarget(Object target) {
|
private static Object wrapTarget(Object target) {
|
||||||
if (target instanceof Map) {
|
if (target instanceof Map) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
|||||||
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
@@ -444,6 +445,28 @@ public class RelaxedDataBinderTests {
|
|||||||
doTestBindCaseInsensitiveEnums(target);
|
doTestBindCaseInsensitiveEnums(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBindWithoutAlais() throws Exception {
|
||||||
|
VanillaTarget target = new VanillaTarget();
|
||||||
|
MutablePropertyValues properties = new MutablePropertyValues();
|
||||||
|
properties.add("flub", "a");
|
||||||
|
properties.add("foo", "b");
|
||||||
|
new RelaxedDataBinder(target).bind(properties);
|
||||||
|
assertThat(target.getFooBaz(), nullValue());
|
||||||
|
assertThat(target.getFoo(), equalTo("b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBindWithAlias() throws Exception {
|
||||||
|
VanillaTarget target = new VanillaTarget();
|
||||||
|
MutablePropertyValues properties = new MutablePropertyValues();
|
||||||
|
properties.add("flub", "a");
|
||||||
|
properties.add("foo", "b");
|
||||||
|
new RelaxedDataBinder(target).withAlias("flub", "fooBaz").bind(properties);
|
||||||
|
assertThat(target.getFooBaz(), equalTo("a"));
|
||||||
|
assertThat(target.getFoo(), equalTo("b"));
|
||||||
|
}
|
||||||
|
|
||||||
private void doTestBindCaseInsensitiveEnums(VanillaTarget target) throws Exception {
|
private void doTestBindCaseInsensitiveEnums(VanillaTarget target) throws Exception {
|
||||||
BindingResult result = bind(target, "bingo: THIS");
|
BindingResult result = bind(target, "bingo: THIS");
|
||||||
assertThat(result.getErrorCount(), equalTo(0));
|
assertThat(result.getErrorCount(), equalTo(0));
|
||||||
|
|||||||
Reference in New Issue
Block a user