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;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.util.ClassUtils;
......@@ -84,15 +83,8 @@ public class DataSourceBuilder {
}
private void bind(DataSource result) {
new RelaxedDataBinder(result).bind(getPropertyValues());
}
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);
MutablePropertyValues properties = new MutablePropertyValues(this.properties);
new RelaxedDataBinder(result).withAlias("url", "jdbcUrl").bind(properties);
}
public DataSourceBuilder type(Class<? extends DataSource> type) {
......
......@@ -19,6 +19,7 @@ package org.springframework.boot.bind;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
......@@ -29,6 +30,8 @@ import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.DataBinder;
......@@ -47,6 +50,8 @@ public class RelaxedDataBinder extends DataBinder {
private boolean ignoreNestedProperties;
private MultiValueMap<String, String> nameAliases = new LinkedMultiValueMap<String, String>();
/**
* Create a new {@link RelaxedDataBinder} instance.
* @param target the target into which properties are bound
......@@ -76,6 +81,27 @@ public class RelaxedDataBinder extends DataBinder {
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
public void initBeanPropertyAccess() {
super.initBeanPropertyAccess();
......@@ -262,19 +288,33 @@ public class RelaxedDataBinder extends DataBinder {
private String getActualPropertyName(BeanWrapper target, String prefix, String name) {
prefix = StringUtils.hasText(prefix) ? prefix + "." : "";
for (String candidate : new RelaxedNames(name)) {
try {
if (target.getPropertyType(prefix + candidate) != null) {
return candidate;
Iterable<String> names = getNameAndAliases(name);
for (String nameOrAlias : names) {
for (String candidate : new RelaxedNames(nameOrAlias)) {
try {
if (target.getPropertyType(prefix + candidate) != null) {
return candidate;
}
}
catch (InvalidPropertyException ex) {
// swallow and continue
}
}
catch (InvalidPropertyException ex) {
// swallow and continue
}
}
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) {
if (target instanceof Map) {
@SuppressWarnings("unchecked")
......
......@@ -53,6 +53,7 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
......@@ -444,6 +445,28 @@ public class RelaxedDataBinderTests {
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 {
BindingResult result = bind(target, "bingo: THIS");
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