15
15
*/
16
16
package org .springframework .data .mongodb .core .convert ;
17
17
18
- import java .util .*;
18
+ import java .lang .reflect .Constructor ;
19
+ import java .lang .reflect .Method ;
20
+ import java .util .ArrayList ;
21
+ import java .util .Arrays ;
22
+ import java .util .Collection ;
23
+ import java .util .Collections ;
24
+ import java .util .HashSet ;
25
+ import java .util .LinkedHashMap ;
26
+ import java .util .List ;
27
+ import java .util .Map ;
19
28
import java .util .Map .Entry ;
29
+ import java .util .Optional ;
30
+ import java .util .Set ;
20
31
21
32
import org .bson .Document ;
22
33
import org .bson .conversions .Bson ;
29
40
import org .springframework .core .CollectionFactory ;
30
41
import org .springframework .core .convert .ConversionService ;
31
42
import org .springframework .core .convert .support .DefaultConversionService ;
32
- import org .springframework .data .convert .CustomConversions ;
33
43
import org .springframework .data .convert .EntityInstantiator ;
34
- import org .springframework .data .convert .EntityInstantiators ;
35
44
import org .springframework .data .convert .TypeMapper ;
36
45
import org .springframework .data .mapping .Association ;
37
46
import org .springframework .data .mapping .MappingException ;
@@ -660,6 +669,10 @@ private static Collection<?> asCollection(Object source) {
660
669
protected List <Object > createCollection (Collection <?> collection , MongoPersistentProperty property ) {
661
670
662
671
if (!property .isDbReference ()) {
672
+
673
+ if (property .hasExplicitWriteTarget ()) {
674
+ return writeCollectionInternal (collection , new HijackedTypeInformation <>(property ), new ArrayList <>());
675
+ }
663
676
return writeCollectionInternal (collection , property .getTypeInformation (), new BasicDBList ());
664
677
}
665
678
@@ -739,7 +752,8 @@ private List<Object> writeCollectionInternal(Collection<?> source, @Nullable Typ
739
752
Class <?> elementType = element == null ? null : element .getClass ();
740
753
741
754
if (elementType == null || conversions .isSimpleType (elementType )) {
742
- collection .add (getPotentiallyConvertedSimpleWrite (element ));
755
+ collection .add (getPotentiallyConvertedSimpleWrite (element ,
756
+ componentType != null ? componentType .getType () : Object .class ));
743
757
} else if (element instanceof Collection || elementType .isArray ()) {
744
758
collection .add (writeCollectionInternal (asCollection (element ), componentType , new BasicDBList ()));
745
759
} else {
@@ -842,7 +856,7 @@ private String potentiallyConvertMapKey(Object key) {
842
856
}
843
857
844
858
return conversions .hasCustomWriteTarget (key .getClass (), String .class )
845
- ? (String ) getPotentiallyConvertedSimpleWrite (key )
859
+ ? (String ) getPotentiallyConvertedSimpleWrite (key , Object . class )
846
860
: key .toString ();
847
861
}
848
862
@@ -884,12 +898,13 @@ protected void addCustomTypeKeyIfNecessary(@Nullable TypeInformation<?> type, Ob
884
898
* @param key must not be {@literal null}.
885
899
*/
886
900
private void writeSimpleInternal (Object value , Bson bson , String key ) {
887
- addToMap (bson , key , getPotentiallyConvertedSimpleWrite (value ));
901
+ addToMap (bson , key , getPotentiallyConvertedSimpleWrite (value , Object . class ));
888
902
}
889
903
890
904
private void writeSimpleInternal (Object value , Bson bson , MongoPersistentProperty property ) {
891
905
DocumentAccessor accessor = new DocumentAccessor (bson );
892
- accessor .put (property , getPotentiallyConvertedSimpleWrite (value ));
906
+ accessor .put (property , getPotentiallyConvertedSimpleWrite (value ,
907
+ property .hasExplicitWriteTarget () ? property .getFieldType () : Object .class ));
893
908
}
894
909
895
910
/**
@@ -900,12 +915,19 @@ private void writeSimpleInternal(Object value, Bson bson, MongoPersistentPropert
900
915
* @return
901
916
*/
902
917
@ Nullable
903
- private Object getPotentiallyConvertedSimpleWrite (@ Nullable Object value ) {
918
+ private Object getPotentiallyConvertedSimpleWrite (@ Nullable Object value , @ Nullable Class <?> typeHint ) {
904
919
905
920
if (value == null ) {
906
921
return null ;
907
922
}
908
923
924
+ if (typeHint != null && Object .class != typeHint ) {
925
+
926
+ if (conversionService .canConvert (value .getClass (), typeHint )) {
927
+ value = conversionService .convert (value , typeHint );
928
+ }
929
+ }
930
+
909
931
Optional <Class <?>> customTarget = conversions .getCustomWriteTarget (value .getClass ());
910
932
911
933
if (customTarget .isPresent ()) {
@@ -1204,7 +1226,8 @@ public Object convertToMongoType(@Nullable Object obj, TypeInformation<?> typeIn
1204
1226
1205
1227
if (conversions .isSimpleType (obj .getClass ())) {
1206
1228
// Doesn't need conversion
1207
- return getPotentiallyConvertedSimpleWrite (obj );
1229
+ return getPotentiallyConvertedSimpleWrite (obj ,
1230
+ typeInformation != null ? typeInformation .getType () : Object .class );
1208
1231
}
1209
1232
1210
1233
if (obj instanceof List ) {
@@ -1599,7 +1622,6 @@ List<Document> bulkReadRefs(List<DBRef> references) {
1599
1622
return dbRefResolver .bulkFetch (references );
1600
1623
}
1601
1624
1602
-
1603
1625
/**
1604
1626
* Create a new {@link MappingMongoConverter} using the given {@link MongoDbFactory} when loading {@link DBRef}.
1605
1627
*
@@ -1667,4 +1689,91 @@ public <T> T getParameterValue(Parameter<T, MongoPersistentProperty> parameter)
1667
1689
return null ;
1668
1690
}
1669
1691
}
1692
+
1693
+ private static class HijackedTypeInformation <S > implements TypeInformation <S > {
1694
+
1695
+ private MongoPersistentProperty persistentProperty ;
1696
+ private TypeInformation <?> delegate ;
1697
+
1698
+ public HijackedTypeInformation (MongoPersistentProperty property ) {
1699
+
1700
+ this .persistentProperty = property ;
1701
+ this .delegate = property .getTypeInformation ();
1702
+ }
1703
+
1704
+ @ Override
1705
+ public List <org .springframework .data .util .TypeInformation <?>> getParameterTypes (Constructor constructor ) {
1706
+ return persistentProperty .getTypeInformation ().getParameterTypes (constructor );
1707
+ }
1708
+
1709
+ @ Override
1710
+ public org .springframework .data .util .TypeInformation <?> getProperty (String property ) {
1711
+ return delegate .getProperty (property );
1712
+ }
1713
+
1714
+ @ Override
1715
+ public boolean isCollectionLike () {
1716
+ return delegate .isCollectionLike ();
1717
+ }
1718
+
1719
+ @ Override
1720
+ public org .springframework .data .util .TypeInformation <?> getComponentType () {
1721
+ return ClassTypeInformation .from (persistentProperty .getFieldType ());
1722
+ }
1723
+
1724
+ @ Override
1725
+ public boolean isMap () {
1726
+ return delegate .isMap ();
1727
+ }
1728
+
1729
+ @ Override
1730
+ public org .springframework .data .util .TypeInformation <?> getMapValueType () {
1731
+ return ClassTypeInformation .from (persistentProperty .getFieldType ());
1732
+ }
1733
+
1734
+ @ Override
1735
+ public Class getType () {
1736
+ return delegate .getType ();
1737
+ }
1738
+
1739
+ @ Override
1740
+ public ClassTypeInformation <?> getRawTypeInformation () {
1741
+ return delegate .getRawTypeInformation ();
1742
+ }
1743
+
1744
+ @ Override
1745
+ public org .springframework .data .util .TypeInformation <?> getActualType () {
1746
+ return delegate .getActualType ();
1747
+ }
1748
+
1749
+ @ Override
1750
+ public org .springframework .data .util .TypeInformation <?> getReturnType (Method method ) {
1751
+ return delegate .getReturnType (method );
1752
+ }
1753
+
1754
+ @ Override
1755
+ public List <org .springframework .data .util .TypeInformation <?>> getParameterTypes (Method method ) {
1756
+ return delegate .getParameterTypes (method );
1757
+ }
1758
+
1759
+ @ Override
1760
+ public org .springframework .data .util .TypeInformation <?> getSuperTypeInformation (Class superType ) {
1761
+ return delegate .getSuperTypeInformation (superType );
1762
+ }
1763
+
1764
+ @ Override
1765
+ public boolean isAssignableFrom (org .springframework .data .util .TypeInformation target ) {
1766
+ return delegate .isAssignableFrom (target );
1767
+ }
1768
+
1769
+ @ Override
1770
+ public List <org .springframework .data .util .TypeInformation <?>> getTypeArguments () {
1771
+ return delegate .getTypeArguments ();
1772
+ }
1773
+
1774
+ @ Override
1775
+ public org .springframework .data .util .TypeInformation specialize (ClassTypeInformation type ) {
1776
+ return delegate .specialize (type );
1777
+ }
1778
+ }
1670
1779
}
0 commit comments