5 changed files with 231 additions and 18 deletions
@ -0,0 +1,120 @@
@@ -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 @@
@@ -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