5 changed files with 231 additions and 18 deletions
@ -0,0 +1,120 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2021 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 |
||||||
|
* |
||||||
|
* https://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.jdbc.core.convert; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import org.springframework.core.ResolvableType; |
||||||
|
import org.springframework.core.convert.ConversionService; |
||||||
|
import org.springframework.core.convert.TypeDescriptor; |
||||||
|
import org.springframework.core.convert.converter.GenericConverter; |
||||||
|
import org.springframework.data.convert.ReadingConverter; |
||||||
|
import org.springframework.data.convert.WritingConverter; |
||||||
|
import org.springframework.data.jdbc.core.mapping.AggregateReference; |
||||||
|
import org.springframework.lang.Nullable; |
||||||
|
|
||||||
|
/** |
||||||
|
* Converters for aggregate references. They need a {@link ConversionService} in order to delegate the conversion of the |
||||||
|
* content of the {@link AggregateReference}. |
||||||
|
* |
||||||
|
* @author Jens Schauder |
||||||
|
* @since 2.6 |
||||||
|
*/ |
||||||
|
class AggregateReferenceConverters { |
||||||
|
/** |
||||||
|
* Prevent instantiation. |
||||||
|
*/ |
||||||
|
private AggregateReferenceConverters() {} |
||||||
|
|
||||||
|
/** |
||||||
|
* Converts from an AggregateReference to its id, leaving the conversion of the id to the ultimate target type to the |
||||||
|
* delegate {@link ConversionService}. |
||||||
|
*/ |
||||||
|
@WritingConverter |
||||||
|
static class AggregateReferenceToSimpleTypeConverter implements GenericConverter { |
||||||
|
|
||||||
|
private final ConversionService delegate; |
||||||
|
|
||||||
|
AggregateReferenceToSimpleTypeConverter(ConversionService delegate) { |
||||||
|
this.delegate = delegate; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Set<ConvertiblePair> getConvertibleTypes() { |
||||||
|
return Collections.singleton(new ConvertiblePair(AggregateReference.class, Object.class)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object convert(@Nullable Object source, TypeDescriptor sourceDescriptor, TypeDescriptor targetDescriptor) { |
||||||
|
|
||||||
|
if (source == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
// if the target type is an AggregateReference we just going to assume it is of the correct type,
|
||||||
|
// because it was already converted.
|
||||||
|
Class<?> objectType = targetDescriptor.getObjectType(); |
||||||
|
if (objectType.isAssignableFrom(AggregateReference.class)) { |
||||||
|
return source; |
||||||
|
} |
||||||
|
|
||||||
|
Object id = ((AggregateReference<?, ?>) source).getId(); |
||||||
|
|
||||||
|
if (id == null) { |
||||||
|
throw new IllegalStateException( |
||||||
|
String.format("Aggregate references id must not be null when converting to %s from %s to %s", source, |
||||||
|
sourceDescriptor, targetDescriptor)); |
||||||
|
} |
||||||
|
|
||||||
|
return delegate.convert(id, TypeDescriptor.valueOf(id.getClass()), targetDescriptor); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convert any simple type to an {@link AggregateReference}. If the {@literal targetDescriptor} contains information |
||||||
|
* about the generic type id will properly get converted to the desired type by the delegate |
||||||
|
* {@link ConversionService}. |
||||||
|
*/ |
||||||
|
@ReadingConverter |
||||||
|
static class SimpleTypeToAggregateReferenceConverter implements GenericConverter { |
||||||
|
|
||||||
|
private final ConversionService delegate; |
||||||
|
|
||||||
|
SimpleTypeToAggregateReferenceConverter(ConversionService delegate) { |
||||||
|
this.delegate = delegate; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Set<ConvertiblePair> getConvertibleTypes() { |
||||||
|
return Collections.singleton(new ConvertiblePair(Object.class, AggregateReference.class)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object convert(@Nullable Object source, TypeDescriptor sourceDescriptor, TypeDescriptor targetDescriptor) { |
||||||
|
|
||||||
|
if (source == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
ResolvableType componentType = targetDescriptor.getResolvableType().getGenerics()[1]; |
||||||
|
TypeDescriptor targetType = TypeDescriptor.valueOf(componentType.resolve()); |
||||||
|
Object convertedId = delegate.convert(source, TypeDescriptor.valueOf(source.getClass()), targetType); |
||||||
|
|
||||||
|
return AggregateReference.to(convertedId); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2021 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 |
||||||
|
* |
||||||
|
* https://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.jdbc.core.convert; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.springframework.core.ResolvableType; |
||||||
|
import org.springframework.core.convert.TypeDescriptor; |
||||||
|
import org.springframework.core.convert.support.DefaultConversionService; |
||||||
|
import org.springframework.data.jdbc.core.mapping.AggregateReference; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for converters from an to {@link org.springframework.data.jdbc.core.mapping.AggregateReference}. |
||||||
|
* |
||||||
|
* @author Jens Schauder |
||||||
|
*/ |
||||||
|
class AggregateReferenceConvertersUnitTests { |
||||||
|
|
||||||
|
AggregateReferenceConverters.SimpleTypeToAggregateReferenceConverter simpleToAggregate = new AggregateReferenceConverters.SimpleTypeToAggregateReferenceConverter(DefaultConversionService.getSharedInstance()); |
||||||
|
AggregateReferenceConverters.AggregateReferenceToSimpleTypeConverter aggregateToSimple = new AggregateReferenceConverters.AggregateReferenceToSimpleTypeConverter(DefaultConversionService.getSharedInstance()); |
||||||
|
|
||||||
|
@Test // #992
|
||||||
|
void convertsFromSimpleValue() { |
||||||
|
|
||||||
|
ResolvableType aggregateReferenceWithIdTypeInteger = ResolvableType.forClassWithGenerics(AggregateReference.class, String.class, Integer.class); |
||||||
|
final Object converted = simpleToAggregate.convert(23, TypeDescriptor.forObject(23), new TypeDescriptor(aggregateReferenceWithIdTypeInteger, null, null)); |
||||||
|
|
||||||
|
assertThat(converted).isEqualTo(AggregateReference.to(23)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test // #992
|
||||||
|
void convertsFromSimpleValueThatNeedsSeparateConversion() { |
||||||
|
|
||||||
|
ResolvableType aggregateReferenceWithIdTypeInteger = ResolvableType.forClassWithGenerics(AggregateReference.class, String.class, Long.class); |
||||||
|
final Object converted = simpleToAggregate.convert(23, TypeDescriptor.forObject(23), new TypeDescriptor(aggregateReferenceWithIdTypeInteger, null, null)); |
||||||
|
|
||||||
|
assertThat(converted).isEqualTo(AggregateReference.to(23L)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test // #992
|
||||||
|
void convertsFromSimpleValueWithMissingTypeInformation() { |
||||||
|
|
||||||
|
final Object converted = simpleToAggregate.convert(23, TypeDescriptor.forObject(23), TypeDescriptor.valueOf(AggregateReference.class)); |
||||||
|
|
||||||
|
assertThat(converted).isEqualTo(AggregateReference.to(23)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test // #992
|
||||||
|
void convertsToSimpleValue() { |
||||||
|
|
||||||
|
final AggregateReference<Object, Integer> source = AggregateReference.to(23); |
||||||
|
|
||||||
|
final Object converted = aggregateToSimple.convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(Integer.class)); |
||||||
|
|
||||||
|
assertThat(converted).isEqualTo(23); |
||||||
|
} |
||||||
|
|
||||||
|
@Test // #992
|
||||||
|
void convertsToSimpleValueThatNeedsSeparateConversion() { |
||||||
|
|
||||||
|
final AggregateReference<Object, Integer> source = AggregateReference.to(23); |
||||||
|
|
||||||
|
final Object converted = aggregateToSimple.convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(Long.class)); |
||||||
|
|
||||||
|
assertThat(converted).isEqualTo(23L); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue