1515 */
1616package org .springframework .data .mongodb .core .convert ;
1717
18- import java .util .*;
18+ import java .util .AbstractMap ;
19+ import java .util .ArrayList ;
20+ import java .util .Arrays ;
21+ import java .util .Collection ;
22+ import java .util .Iterator ;
23+ import java .util .LinkedHashMap ;
24+ import java .util .List ;
25+ import java .util .Map ;
1926import java .util .Map .Entry ;
27+ import java .util .Optional ;
28+ import java .util .Set ;
2029import java .util .regex .Matcher ;
2130import java .util .regex .Pattern ;
2231import java .util .stream .Collectors ;
2736import org .bson .Document ;
2837import org .bson .conversions .Bson ;
2938import org .bson .types .ObjectId ;
39+
3040import org .springframework .core .convert .ConversionService ;
3141import org .springframework .core .convert .converter .Converter ;
3242import org .springframework .data .annotation .Reference ;
@@ -496,7 +506,7 @@ protected boolean isAssociationConversionNecessary(Field documentField, @Nullabl
496506
497507 Assert .notNull (documentField , "Document field must not be null" );
498508
499- if (value == null ) {
509+ if (value == null || documentField . getProperty () == null ) {
500510 return false ;
501511 }
502512
@@ -552,10 +562,6 @@ protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersisten
552562 return getMappedObject ((Document ) source , entity );
553563 }
554564
555- if (source instanceof BasicDBList ) {
556- return delegateConvertToMongoType (source , entity );
557- }
558-
559565 if (isDBObject (source )) {
560566 return getMappedObject ((BasicDBObject ) source , entity );
561567 }
@@ -564,20 +570,20 @@ protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersisten
564570 return source ;
565571 }
566572
567- if (source instanceof Map <?,?> sourceMap ) {
573+ if (source instanceof Map <?, ?> sourceMap ) {
568574
569575 Map <String , Object > map = new LinkedHashMap <>(sourceMap .size (), 1F );
570576
571- sourceMap .entrySet (). forEach ( it -> {
577+ for ( Entry <?, ?> entry : sourceMap .entrySet ()) {
572578
573- String key = ObjectUtils .nullSafeToString (converter .convertToMongoType (it .getKey ()));
579+ String key = ObjectUtils .nullSafeToString (converter .convertToMongoType (entry .getKey ()));
574580
575- if (it .getValue () instanceof Document document ) {
581+ if (entry .getValue () instanceof Document document ) {
576582 map .put (key , getMappedObject (document , entity ));
577583 } else {
578- map .put (key , delegateConvertToMongoType (it .getValue (), entity ));
584+ map .put (key , delegateConvertToMongoType (entry .getValue (), entity ));
579585 }
580- });
586+ }
581587
582588 return map ;
583589 }
@@ -603,6 +609,7 @@ protected Object delegateConvertToMongoType(Object source, @Nullable MongoPersis
603609 return converter .convertToMongoType (source , entity == null ? null : entity .getTypeInformation ());
604610 }
605611
612+ @ Nullable
606613 protected Object convertAssociation (Object source , Field field ) {
607614 Object value = convertAssociation (source , field .getProperty ());
608615 if (value != null && field .isIdField () && field .getFieldType () != value .getClass ()) {
@@ -627,8 +634,7 @@ protected Object convertAssociation(@Nullable Object source, @Nullable MongoPers
627634
628635 if (source instanceof DBRef ref ) {
629636
630- Object id = convertId (ref .getId (),
631- property != null && property .isIdProperty () ? property .getFieldType () : ObjectId .class );
637+ Object id = convertId (ref .getId (), property .isIdProperty () ? property .getFieldType () : ObjectId .class );
632638
633639 if (StringUtils .hasText (ref .getDatabaseName ())) {
634640 return new DBRef (ref .getDatabaseName (), ref .getCollectionName (), id );
@@ -645,9 +651,8 @@ protected Object convertAssociation(@Nullable Object source, @Nullable MongoPers
645651 return result ;
646652 }
647653
648- if (property .isMap ()) {
654+ if (property .isMap () && source instanceof Document dbObject ) {
649655 Document result = new Document ();
650- Document dbObject = (Document ) source ;
651656 for (String key : dbObject .keySet ()) {
652657 result .put (key , createReferenceFor (dbObject .get (key ), property ));
653658 }
@@ -661,19 +666,26 @@ protected Object convertAssociation(@Nullable Object source, @Nullable MongoPers
661666 private Object convertValue (Field documentField , Object sourceValue , Object value ,
662667 PropertyValueConverter <Object , Object , ValueConversionContext <MongoPersistentProperty >> valueConverter ) {
663668
664- MongoConversionContext conversionContext = new MongoConversionContext (new PropertyValueProvider <>() {
665- @ Override
666- public <T > T getPropertyValue (MongoPersistentProperty property ) {
667- throw new IllegalStateException ("No enclosing property available" );
668- }
669- }, documentField .getProperty (), converter );
669+ MongoPersistentProperty property = documentField .getProperty ();
670+ MongoConversionContext conversionContext = new MongoConversionContext (NoPropertyPropertyValueProvider .INSTANCE ,
671+ property , converter );
670672
671673 /* might be an $in clause with multiple entries */
672- if (!documentField .getProperty ().isCollectionLike () && sourceValue instanceof Collection <?> collection ) {
673- return collection .stream ().map (it -> valueConverter .write (it , conversionContext )).collect (Collectors .toList ());
674+ if (property != null && !property .isCollectionLike () && sourceValue instanceof Collection <?> collection ) {
675+
676+ if (collection .isEmpty ()) {
677+ return collection ;
678+ }
679+
680+ List <Object > converted = new ArrayList <>(collection .size ());
681+ for (Object o : collection ) {
682+ converted .add (valueConverter .write (o , conversionContext ));
683+ }
684+
685+ return converted ;
674686 }
675687
676- if (!documentField .getProperty ().isMap () && sourceValue instanceof Document document ) {
688+ if (property != null && !documentField .getProperty ().isMap () && sourceValue instanceof Document document ) {
677689
678690 return BsonUtils .mapValues (document , (key , val ) -> {
679691 if (isKeyword (key )) {
@@ -687,6 +699,7 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
687699 }
688700
689701 @ Nullable
702+ @ SuppressWarnings ("unchecked" )
690703 private Object convertIdField (Field documentField , Object source ) {
691704
692705 Object value = source ;
@@ -714,8 +727,8 @@ private Object convertIdField(Field documentField, Object source) {
714727 } else {
715728 return getMappedObject (resultDbo , Optional .empty ());
716729 }
717- return resultDbo ;
718730
731+ return resultDbo ;
719732 }
720733
721734 /**
@@ -1454,15 +1467,13 @@ static class KeyMapper {
14541467
14551468 private final Iterator <String > iterator ;
14561469 private int currentIndex ;
1457- private String currentPropertyRoot ;
14581470 private final List <String > pathParts ;
14591471
14601472 public KeyMapper (String key ,
14611473 MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > mappingContext ) {
14621474
14631475 this .pathParts = Arrays .asList (key .split ("\\ ." ));
14641476 this .iterator = pathParts .iterator ();
1465- this .currentPropertyRoot = iterator .next ();
14661477 this .currentIndex = 0 ;
14671478 }
14681479
@@ -1578,4 +1589,14 @@ public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentPropert
15781589 public MongoConverter getConverter () {
15791590 return converter ;
15801591 }
1592+
1593+ private enum NoPropertyPropertyValueProvider implements PropertyValueProvider <MongoPersistentProperty > {
1594+
1595+ INSTANCE ;
1596+
1597+ @ Override
1598+ public <T > T getPropertyValue (MongoPersistentProperty property ) {
1599+ throw new IllegalStateException ("No enclosing property source available" );
1600+ }
1601+ }
15811602}
0 commit comments