4141import org .junit .jupiter .api .Disabled ;
4242import org .junit .jupiter .api .Test ;
4343import org .junit .jupiter .api .extension .ExtendWith ;
44+ import org .junit .jupiter .params .ParameterizedTest ;
45+ import org .junit .jupiter .params .provider .ValueSource ;
4446import org .mockito .Mock ;
4547import org .mockito .Mockito ;
4648import org .mockito .junit .jupiter .MockitoExtension ;
8284import org .springframework .data .mongodb .core .mapping .Document ;
8385import org .springframework .data .mongodb .core .mapping .Field ;
8486import org .springframework .data .mongodb .core .mapping .FieldType ;
87+ import org .springframework .data .mongodb .core .mapping .MongoId ;
8588import org .springframework .data .mongodb .core .mapping .MongoMappingContext ;
8689import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
8790import org .springframework .data .mongodb .core .mapping .PersonPojoStringId ;
@@ -2866,7 +2869,7 @@ public org.bson.Document write(@Nullable String domainValue, MongoConversionCont
28662869
28672870 @ Test // GH-4371
28682871 void shouldConvertTypesToStringTargetType () {
2869-
2872+
28702873 org .bson .Document source = org .bson .Document .parse ("""
28712874 {
28722875 city : ["Gotham", "Metropolis"]
@@ -2876,6 +2879,35 @@ void shouldConvertTypesToStringTargetType() {
28762879 assertThat (converter .read (Address .class , source ).city ).isEqualTo ("Gotham,Metropolis" );
28772880 }
28782881
2882+ @ ValueSource (classes = { ComplexIdAndNoAnnotation .class , ComplexIdAndIdAnnotation .class ,
2883+ ComplexIdAndMongoIdAnnotation .class , ComplexIdAndFieldAnnotation .class })
2884+ @ ParameterizedTest // GH-4524
2885+ void projectShouldReadComplexIdType (Class <?> projectionTargetType ) {
2886+
2887+ EntityProjectionIntrospector introspector = EntityProjectionIntrospector .create (converter .getProjectionFactory (),
2888+ EntityProjectionIntrospector .ProjectionPredicate .typeHierarchy ()
2889+ .and ((target , underlyingType ) -> !converter .conversions .isSimpleType (target )),
2890+ mappingContext );
2891+
2892+ ComplexId idValue = ComplexId .of (101L );
2893+ org .bson .Document source = new org .bson .Document ("_id" , new org .bson .Document ("innerId" , idValue .innerId ))
2894+ .append ("value" , "abc" ).append ("_class" , ComplexIdAndNoAnnotation .class .getName ());
2895+
2896+ EntityProjection <?, ComplexIdAndNoAnnotation > projection = introspector .introspect (projectionTargetType ,
2897+ ComplexIdAndNoAnnotation .class );
2898+
2899+ assertThat (converter .project (projection , source )) //
2900+ .isInstanceOf (projectionTargetType ) //
2901+ .extracting ("id" ).isEqualTo (idValue );
2902+ }
2903+
2904+ org .bson .Document write (Object source ) {
2905+
2906+ org .bson .Document target = new org .bson .Document ();
2907+ converter .write (source , target );
2908+ return target ;
2909+ }
2910+
28792911 static class GenericType <T > {
28802912 T content ;
28812913 }
@@ -3092,7 +3124,33 @@ static class ClassWithComplexId {
30923124 }
30933125
30943126 static class ComplexId {
3127+
30953128 Long innerId ;
3129+
3130+ static ComplexId of (Long value ) {
3131+
3132+ ComplexId id = new ComplexId ();
3133+ id .innerId = value ;
3134+ return id ;
3135+ }
3136+
3137+ @ Override
3138+ public boolean equals (Object o ) {
3139+
3140+ if (o == this ) {
3141+ return true ;
3142+ }
3143+ if (o == null || getClass () != o .getClass ()) {
3144+ return false ;
3145+ }
3146+ ComplexId complexId = (ComplexId ) o ;
3147+ return Objects .equals (innerId , complexId .innerId );
3148+ }
3149+
3150+ @ Override
3151+ public int hashCode () {
3152+ return Objects .hash (innerId );
3153+ }
30963154 }
30973155
30983156 static class TypWithCollectionConstructor {
@@ -3611,10 +3669,12 @@ static class WithFieldWrite {
36113669 @ org .springframework .data .mongodb .core .mapping .Field (
36123670 write = org .springframework .data .mongodb .core .mapping .Field .Write .ALWAYS ) Integer writeAlways ;
36133671
3614- @ org .springframework .data .mongodb .core .mapping .DBRef @ org .springframework .data .mongodb .core .mapping .Field (
3672+ @ org .springframework .data .mongodb .core .mapping .DBRef
3673+ @ org .springframework .data .mongodb .core .mapping .Field (
36153674 write = org .springframework .data .mongodb .core .mapping .Field .Write .NON_NULL ) Person writeNonNullPerson ;
36163675
3617- @ org .springframework .data .mongodb .core .mapping .DBRef @ org .springframework .data .mongodb .core .mapping .Field (
3676+ @ org .springframework .data .mongodb .core .mapping .DBRef
3677+ @ org .springframework .data .mongodb .core .mapping .Field (
36183678 write = org .springframework .data .mongodb .core .mapping .Field .Write .ALWAYS ) Person writeAlwaysPerson ;
36193679
36203680 }
@@ -3728,12 +3788,79 @@ static class Author {
37283788
37293789 }
37303790
3731- @ Data
37323791 static class Cyclic {
37333792
37343793 @ Id String id ;
37353794 String value ;
37363795 Cyclic cycle ;
3796+
3797+ public String getId () {
3798+ return id ;
3799+ }
3800+
3801+ public void setId (String id ) {
3802+ this .id = id ;
3803+ }
3804+
3805+ public String getValue () {
3806+ return value ;
3807+ }
3808+
3809+ public void setValue (String value ) {
3810+ this .value = value ;
3811+ }
3812+
3813+ public Cyclic getCycle () {
3814+ return cycle ;
3815+ }
3816+
3817+ public void setCycle (Cyclic cycle ) {
3818+ this .cycle = cycle ;
3819+ }
3820+
3821+ @ Override
3822+ public boolean equals (Object o ) {
3823+ if (o == this ) {
3824+ return true ;
3825+ }
3826+ if (o == null || getClass () != o .getClass ()) {
3827+ return false ;
3828+ }
3829+ Cyclic cyclic = (Cyclic ) o ;
3830+ return Objects .equals (id , cyclic .id ) && Objects .equals (value , cyclic .value )
3831+ && Objects .equals (cycle , cyclic .cycle );
3832+ }
3833+
3834+ @ Override
3835+ public int hashCode () {
3836+ return Objects .hash (id , value , cycle );
3837+ }
3838+ }
3839+
3840+ static class ComplexIdAndFieldAnnotation {
3841+
3842+ @ Field ("_id" ) //
3843+ ComplexId id ;
3844+ String value ;
3845+ }
3846+
3847+ static class ComplexIdAndMongoIdAnnotation {
3848+
3849+ @ MongoId //
3850+ ComplexId id ;
3851+ String value ;
37373852 }
37383853
3854+ static class ComplexIdAndIdAnnotation {
3855+
3856+ @ Id //
3857+ ComplexId id ;
3858+ String value ;
3859+ }
3860+
3861+ static class ComplexIdAndNoAnnotation {
3862+
3863+ ComplexId id ;
3864+ String value ;
3865+ }
37393866}
0 commit comments