DATACMNS-1034 - Introduced API to easily register converters using Java 8 lambdas.
Introduced ConverterBuilder which exposes API to register Spring GenericConverters for the use with a store module's CustomConversions. This allows simple registration of such converters using Java 8 lambdas. ConverterAware converters = ConverterBuilder.reading(String.class, Long.class, it -> Long.valueOf(it)).andWriting(it -> Object::toString); The setup can also be done from the reading side which would just need the method invocations inverted. The resulting ConverterAware will expose the registered converters so that they can be easily handed to a CustomConversions instance. Partial creation of either reading or writing converters is possible, too with the returned instance then only exposing one of the two converters. CustomConversions now considers ConverterAware and treats them appropriately for ConvertiblePair registration as well as during the registration in the ConversionService. Tweaked parameter types in CustomConversions to rather accept a Collection<?> for the converters (previously List<?>). Also, registerConverterIn(…) now takes a ConverterRegistry over a GenericConversionService. Polished Javadoc and non-null assertions. Original pull request: #209.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.convert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.Supplier;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.data.convert.ConverterBuilder.ConverterAware;
|
||||
import org.springframework.data.convert.ConverterBuilder.ReadingConverterBuilder;
|
||||
import org.springframework.data.convert.ConverterBuilder.WritingConverterBuilder;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultConverterBuilder}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 2.0
|
||||
* @soundtrack John Mayer - In the Blood (The Search for Everything)
|
||||
*/
|
||||
public class ConverterBuilderUnitTests {
|
||||
|
||||
@Test // DATACMNS-1034
|
||||
public void setsUpBidirectionalConvertersFromReading() {
|
||||
|
||||
ConverterAware builder = ConverterBuilder.reading(String.class, Long.class, it -> Long.valueOf(it))
|
||||
.andWriting(Object::toString);
|
||||
|
||||
assertConverter(builder.getReadingConverter(), "1", 1L);
|
||||
assertConverter(builder.getWritingConverter(), 1L, "1");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1034
|
||||
public void setsUpBidirectionalConvertersFromWriting() {
|
||||
|
||||
ConverterAware builder = ConverterBuilder.writing(Long.class, String.class, Object::toString)
|
||||
.andReading(it -> Long.valueOf(it));
|
||||
|
||||
assertConverter(builder.getReadingConverter(), "1", 1L);
|
||||
assertConverter(builder.getWritingConverter(), 1L, "1");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1034
|
||||
public void setsUpReadingConverter() {
|
||||
|
||||
ReadingConverterBuilder<String, Long> builder = ConverterBuilder.reading(String.class, Long.class,
|
||||
string -> Long.valueOf(string));
|
||||
|
||||
assertConverter(builder.getReadingConverter(), "1", 1L);
|
||||
assertOnlyConverter(builder, builder::getReadingConverter);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1034
|
||||
public void setsUpWritingConverter() {
|
||||
|
||||
WritingConverterBuilder<Long, String> builder = ConverterBuilder.writing(Long.class, String.class,
|
||||
Object::toString);
|
||||
|
||||
assertConverter(builder.getWritingConverter(), 1L, "1");
|
||||
assertOnlyConverter(builder, builder::getWritingConverter);
|
||||
}
|
||||
|
||||
private static void assertConverter(GenericConverter converter, Object source, Object target) {
|
||||
|
||||
assertThat(converter.getConvertibleTypes())
|
||||
.containsExactly(new ConvertiblePair(source.getClass(), target.getClass()));
|
||||
assertThat(converter.convert(source, TypeDescriptor.forObject(source), TypeDescriptor.forObject(target)))
|
||||
.isEqualTo(target);
|
||||
}
|
||||
|
||||
private static void assertOnlyConverter(ConverterBuilder builder, Supplier<GenericConverter> supplier) {
|
||||
assertThat(builder.getConverters()).containsExactly(supplier.get());
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,10 @@ import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.ConverterBuilder.ConverterAware;
|
||||
import org.springframework.data.convert.CustomConversions.StoreConversions;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
|
||||
@@ -158,6 +160,24 @@ public class CustomConversionsUnitTests {
|
||||
assertThat(customConversions.getCustomWriteTarget(String.class, SimpleDateFormat.class)).isPresent();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1034
|
||||
public void registersConverterFromConverterAware() {
|
||||
|
||||
ConverterAware converters = ConverterBuilder.reading(Left.class, Right.class, left -> new Right())
|
||||
.andWriting(right -> new Left());
|
||||
|
||||
CustomConversions conversions = new CustomConversions(StoreConversions.NONE, Collections.singletonList(converters));
|
||||
|
||||
assertThat(conversions.hasCustomWriteTarget(Right.class)).isTrue();
|
||||
assertThat(conversions.hasCustomReadTarget(Left.class, Right.class)).isTrue();
|
||||
|
||||
ConfigurableConversionService conversionService = new GenericConversionService();
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
|
||||
assertThat(conversionService.canConvert(Left.class, Right.class)).isTrue();
|
||||
assertThat(conversionService.canConvert(Right.class, Left.class)).isTrue();
|
||||
}
|
||||
|
||||
private static Class<?> createProxyTypeFor(Class<?> type) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
@@ -274,4 +294,8 @@ public class CustomConversionsUnitTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Left {}
|
||||
|
||||
static class Right {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user