Commit 8476a79d authored by Phillip Webb's avatar Phillip Webb

Add support for RelaxedDataBinder aliases

Update RelaxedDataBinder to support property aliases and change
DataSourceBuilder to use them.

Fixes gh-1384
parent a6e6e1e0
...@@ -23,7 +23,6 @@ import javax.sql.DataSource; ...@@ -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 { ...@@ -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; ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 { ...@@ -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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment