@@ -124,7 +124,7 @@ <T> Entity<T> forEntity(T entity) {
124124 return new SimpleMappedEntity ((Map <String , Object >) entity );
125125 }
126126
127- return MappedEntity .of (entity , context );
127+ return MappedEntity .of (entity , context , this );
128128 }
129129
130130 /**
@@ -148,7 +148,7 @@ <T> AdaptibleEntity<T> forEntity(T entity, ConversionService conversionService)
148148 return new SimpleMappedEntity ((Map <String , Object >) entity );
149149 }
150150
151- return AdaptibleMappedEntity .of (entity , context , conversionService );
151+ return AdaptibleMappedEntity .of (entity , context , conversionService , this );
152152 }
153153
154154 /**
@@ -386,6 +386,16 @@ interface Entity<T> {
386386 */
387387 Object getId ();
388388
389+ /**
390+ * Returns the property value for {@code key}.
391+ *
392+ * @param key
393+ * @return
394+ * @since 4.1
395+ */
396+ @ Nullable
397+ Object getPropertyValue (String key );
398+
389399 /**
390400 * Returns the {@link Query} to find the entity by its identifier.
391401 *
@@ -457,6 +467,11 @@ default boolean isVersionedEntity() {
457467 */
458468 boolean isNew ();
459469
470+ /**
471+ * @param sortObject
472+ * @return
473+ * @since 3.1
474+ */
460475 Map <String , Object > extractKeys (Document sortObject );
461476
462477 }
@@ -518,7 +533,12 @@ public String getIdFieldName() {
518533
519534 @ Override
520535 public Object getId () {
521- return map .get (ID_FIELD );
536+ return getPropertyValue (ID_FIELD );
537+ }
538+
539+ @ Override
540+ public Object getPropertyValue (String key ) {
541+ return map .get (key );
522542 }
523543
524544 @ Override
@@ -613,23 +633,26 @@ private static class MappedEntity<T> implements Entity<T> {
613633 private final MongoPersistentEntity <?> entity ;
614634 private final IdentifierAccessor idAccessor ;
615635 private final PersistentPropertyAccessor <T > propertyAccessor ;
636+ private final EntityOperations entityOperations ;
616637
617638 protected MappedEntity (MongoPersistentEntity <?> entity , IdentifierAccessor idAccessor ,
618- PersistentPropertyAccessor <T > propertyAccessor ) {
639+ PersistentPropertyAccessor <T > propertyAccessor , EntityOperations entityOperations ) {
619640
620641 this .entity = entity ;
621642 this .idAccessor = idAccessor ;
622643 this .propertyAccessor = propertyAccessor ;
644+ this .entityOperations = entityOperations ;
623645 }
624646
625647 private static <T > MappedEntity <T > of (T bean ,
626- MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > context ) {
648+ MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > context ,
649+ EntityOperations entityOperations ) {
627650
628651 MongoPersistentEntity <?> entity = context .getRequiredPersistentEntity (bean .getClass ());
629652 IdentifierAccessor identifierAccessor = entity .getIdentifierAccessor (bean );
630653 PersistentPropertyAccessor <T > propertyAccessor = entity .getPropertyAccessor (bean );
631654
632- return new MappedEntity <>(entity , identifierAccessor , propertyAccessor );
655+ return new MappedEntity <>(entity , identifierAccessor , propertyAccessor , entityOperations );
633656 }
634657
635658 @ Override
@@ -642,6 +665,11 @@ public Object getId() {
642665 return idAccessor .getRequiredIdentifier ();
643666 }
644667
668+ @ Override
669+ public Object getPropertyValue (String key ) {
670+ return propertyAccessor .getProperty (entity .getRequiredPersistentProperty (key ));
671+ }
672+
645673 @ Override
646674 public Query getByIdQuery () {
647675
@@ -728,13 +756,38 @@ public Map<String, Object> extractKeys(Document sortObject) {
728756
729757 for (String key : sortObject .keySet ()) {
730758
731- // TODO: make this work for nested properties
732- MongoPersistentProperty persistentProperty = entity .getRequiredPersistentProperty (key );
733- keyset .put (key , propertyAccessor .getProperty (persistentProperty ));
759+ if (key .indexOf ('.' ) != -1 ) {
760+
761+ // follow the path across nested levels.
762+ // TODO: We should have a MongoDB-specific property path abstraction to allow diving into Document.
763+ keyset .put (key , getNestedPropertyValue (key ));
764+ } else {
765+ keyset .put (key , getPropertyValue (key ));
766+ }
734767 }
735768
736769 return keyset ;
737770 }
771+
772+ @ Nullable
773+ private Object getNestedPropertyValue (String key ) {
774+
775+ String [] segments = key .split ("\\ ." );
776+ Entity <?> currentEntity = this ;
777+ Object currentValue = null ;
778+
779+ for (int i = 0 ; i < segments .length ; i ++) {
780+
781+ String segment = segments [i ];
782+ currentValue = currentEntity .getPropertyValue (segment );
783+
784+ if (i < segments .length - 1 ) {
785+ currentEntity = entityOperations .forEntity (currentValue );
786+ }
787+ }
788+
789+ return currentValue ;
790+ }
738791 }
739792
740793 private static class AdaptibleMappedEntity <T > extends MappedEntity <T > implements AdaptibleEntity <T > {
@@ -744,9 +797,9 @@ private static class AdaptibleMappedEntity<T> extends MappedEntity<T> implements
744797 private final IdentifierAccessor identifierAccessor ;
745798
746799 private AdaptibleMappedEntity (MongoPersistentEntity <?> entity , IdentifierAccessor identifierAccessor ,
747- ConvertingPropertyAccessor <T > propertyAccessor ) {
800+ ConvertingPropertyAccessor <T > propertyAccessor , EntityOperations entityOperations ) {
748801
749- super (entity , identifierAccessor , propertyAccessor );
802+ super (entity , identifierAccessor , propertyAccessor , entityOperations );
750803
751804 this .entity = entity ;
752805 this .propertyAccessor = propertyAccessor ;
@@ -755,14 +808,14 @@ private AdaptibleMappedEntity(MongoPersistentEntity<?> entity, IdentifierAccesso
755808
756809 private static <T > AdaptibleEntity <T > of (T bean ,
757810 MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > context ,
758- ConversionService conversionService ) {
811+ ConversionService conversionService , EntityOperations entityOperations ) {
759812
760813 MongoPersistentEntity <?> entity = context .getRequiredPersistentEntity (bean .getClass ());
761814 IdentifierAccessor identifierAccessor = entity .getIdentifierAccessor (bean );
762815 PersistentPropertyAccessor <T > propertyAccessor = entity .getPropertyAccessor (bean );
763816
764817 return new AdaptibleMappedEntity <>(entity , identifierAccessor ,
765- new ConvertingPropertyAccessor <>(propertyAccessor , conversionService ));
818+ new ConvertingPropertyAccessor <>(propertyAccessor , conversionService ), entityOperations );
766819 }
767820
768821 @ Nullable
0 commit comments