57
57
import org .springframework .data .mongodb .core .aggregation .RelaxedTypeBasedAggregationOperationContext ;
58
58
import org .springframework .data .mongodb .core .convert .MappingMongoConverter .NestedDocument ;
59
59
import org .springframework .data .mongodb .core .mapping .FieldName ;
60
+ import org .springframework .data .mongodb .core .mapping .MongoPath .MappedMongoPath ;
61
+ import org .springframework .data .mongodb .core .mapping .MongoPath .MappedMongoPath .MappedSegment ;
60
62
import org .springframework .data .mongodb .core .mapping .MongoPath ;
63
+ import org .springframework .data .mongodb .core .mapping .MongoPath .PathSegment ;
64
+ import org .springframework .data .mongodb .core .mapping .MongoPaths ;
65
+ import org .springframework .data .mongodb .core .mapping .MongoPath .RawMongoPath ;
66
+ import org .springframework .data .mongodb .core .mapping .MongoPath .RawMongoPath .Segment ;
67
+ import org .springframework .data .mongodb .core .mapping .MongoPath .RawMongoPath .TargetType ;
61
68
import org .springframework .data .mongodb .core .mapping .MongoPersistentEntity ;
62
69
import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
63
70
import org .springframework .data .mongodb .core .query .Query ;
@@ -104,6 +111,7 @@ private enum MetaMapping {
104
111
private final MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > mappingContext ;
105
112
private final MongoExampleMapper exampleMapper ;
106
113
private final MongoJsonSchemaMapper schemaMapper ;
114
+ protected final MongoPaths paths ;
107
115
108
116
/**
109
117
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
@@ -119,6 +127,7 @@ public QueryMapper(MongoConverter converter) {
119
127
this .mappingContext = converter .getMappingContext ();
120
128
this .exampleMapper = new MongoExampleMapper (converter );
121
129
this .schemaMapper = new MongoJsonSchemaMapper (converter );
130
+ this .paths = new MongoPaths (mappingContext );
122
131
}
123
132
124
133
public Document getMappedObject (Bson query , Optional <? extends MongoPersistentEntity <?>> entity ) {
@@ -381,10 +390,10 @@ protected Field createPropertyField(@Nullable MongoPersistentEntity<?> entity, S
381
390
}
382
391
383
392
if (FieldName .ID .name ().equals (key )) {
384
- return new MetadataBackedField (key , entity , mappingContext , entity .getIdProperty ());
393
+ return new MetadataBackedField (paths . create ( key ) , entity , mappingContext , entity .getIdProperty ());
385
394
}
386
395
387
- return new MetadataBackedField (key , entity , mappingContext );
396
+ return new MetadataBackedField (paths . create ( key ) , entity , mappingContext );
388
397
}
389
398
390
399
/**
@@ -1123,67 +1132,120 @@ public Class<?> getFieldType() {
1123
1132
}
1124
1133
}
1125
1134
1135
+ /**
1136
+ * Create a {@link PropertyPath} starting at {@link MongoPersistentEntity}.
1137
+ * <p>
1138
+ * Can return {@code null} if the property path contains named segments that are not mapped to the entity.
1139
+ *
1140
+ * @param persistentEntity
1141
+ * @return
1142
+ */
1143
+ @ Nullable
1144
+ public PropertyPath toPropertyPath (
1145
+ MongoPath mongoPath , MongoPersistentEntity <?> persistentEntity ) {
1146
+
1147
+ StringBuilder path = new StringBuilder ();
1148
+ MongoPersistentEntity <?> entity = persistentEntity ;
1149
+
1150
+ for (PathSegment segment : mongoPath .segments ()) {
1151
+
1152
+ if (segment .isKeyword ()) {
1153
+ continue ;
1154
+ }
1155
+
1156
+ if (entity == null ) {
1157
+ return null ;
1158
+ }
1159
+
1160
+ MongoPersistentProperty persistentProperty = entity .getPersistentProperty (segment .segment ());
1161
+
1162
+ if (persistentProperty == null ) {
1163
+
1164
+ if (segment .isNumeric ()) {
1165
+ continue ;
1166
+
1167
+ }
1168
+
1169
+ return null ;
1170
+ }
1171
+
1172
+ entity = mappingContext .getPersistentEntity (persistentProperty );
1173
+
1174
+ String name = segment .segment ();
1175
+
1176
+ if (!path .isEmpty ()) {
1177
+ path .append ("." );
1178
+ }
1179
+ path .append (Pattern .quote (name ));
1180
+ }
1181
+
1182
+ if (path .isEmpty ()) {
1183
+ return null ;
1184
+ }
1185
+
1186
+ return PropertyPath .from (path .toString (), persistentEntity .getType ());
1187
+ }
1188
+
1189
+
1126
1190
/**
1127
1191
* Extension of {@link Field} to be backed with mapping metadata.
1128
1192
*
1129
1193
* @author Oliver Gierke
1130
1194
* @author Thomas Darimont
1131
1195
*/
1132
- protected static class MetadataBackedField extends Field {
1196
+ protected class MetadataBackedField extends Field {
1133
1197
1134
- private static final Pattern POSITIONAL_PARAMETER_PATTERN = Pattern .compile ("\\ .\\ $(\\ [.*?\\ ])?" );
1135
- private static final Pattern NUMERIC_SEGMENT = Pattern .compile ("\\ d+" );
1136
1198
private static final String INVALID_ASSOCIATION_REFERENCE = "Invalid path reference %s; Associations can only be pointed to directly or via their id property" ;
1137
1199
1138
1200
private final MongoPersistentEntity <?> entity ;
1139
1201
private final MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > mappingContext ;
1140
1202
private final MongoPersistentProperty property ;
1141
- private final @ Nullable PersistentPropertyPath <MongoPersistentProperty > path ;
1203
+ private final @ Nullable PersistentPropertyPath <MongoPersistentProperty > propertyPath ;
1142
1204
private final @ Nullable Association <MongoPersistentProperty > association ;
1143
1205
private final MongoPath mongoPath ;
1144
1206
1145
1207
/**
1146
1208
* Creates a new {@link MetadataBackedField} with the given name, {@link MongoPersistentEntity} and
1147
1209
* {@link MappingContext}.
1148
1210
*
1149
- * @param name must not be {@literal null} or empty.
1211
+ * @param path must not be {@literal null} or empty.
1150
1212
* @param entity must not be {@literal null}.
1151
1213
* @param context must not be {@literal null}.
1152
1214
*/
1153
- public MetadataBackedField (String name , MongoPersistentEntity <?> entity ,
1215
+ public MetadataBackedField (MongoPath path , MongoPersistentEntity <?> entity ,
1154
1216
MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > context ) {
1155
- this (name , entity , context , null );
1217
+ this (path , entity , context , null );
1156
1218
}
1157
1219
1158
1220
/**
1159
1221
* Creates a new {@link MetadataBackedField} with the given name, {@link MongoPersistentEntity} and
1160
1222
* {@link MappingContext} with the given {@link MongoPersistentProperty}.
1161
1223
*
1162
- * @param name must not be {@literal null} or empty.
1224
+ * @param path must not be {@literal null} or empty.
1163
1225
* @param entity must not be {@literal null}.
1164
1226
* @param context must not be {@literal null}.
1165
1227
* @param property may be {@literal null}.
1166
1228
*/
1167
- public MetadataBackedField (String name , MongoPersistentEntity <?> entity ,
1229
+ public MetadataBackedField (MongoPath path , MongoPersistentEntity <?> entity ,
1168
1230
MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > context ,
1169
1231
@ Nullable MongoPersistentProperty property ) {
1170
1232
1171
- super (name );
1233
+ super (path . path () );
1172
1234
1173
1235
Assert .notNull (entity , "MongoPersistentEntity must not be null" );
1174
1236
1175
1237
this .entity = entity ;
1176
1238
this .mappingContext = context ;
1177
1239
1178
- this .mongoPath = MongoPath . parse ( name ) ;
1179
- this .path = getPath (mongoPath , property );
1180
- this .property = path == null ? property : path .getLeafProperty ();
1240
+ this .mongoPath = path ;
1241
+ this .propertyPath = getPath (mongoPath , property );
1242
+ this .property = this . propertyPath == null ? property : this . propertyPath .getLeafProperty ();
1181
1243
this .association = findAssociation ();
1182
1244
}
1183
1245
1184
1246
@ Override
1185
1247
public MetadataBackedField with (String name ) {
1186
- return new MetadataBackedField (name , entity , mappingContext , property );
1248
+ return new MetadataBackedField (mongoPath , entity , mappingContext , property );
1187
1249
}
1188
1250
1189
1251
@ Override
@@ -1237,8 +1299,8 @@ public Association<MongoPersistentProperty> getAssociation() {
1237
1299
@ Nullable
1238
1300
private Association <MongoPersistentProperty > findAssociation () {
1239
1301
1240
- if (this .path != null ) {
1241
- for (MongoPersistentProperty p : this .path ) {
1302
+ if (this .propertyPath != null ) {
1303
+ for (MongoPersistentProperty p : this .propertyPath ) {
1242
1304
1243
1305
Association <MongoPersistentProperty > association = p .getAssociation ();
1244
1306
@@ -1261,19 +1323,20 @@ public String getMappedKey() {
1261
1323
1262
1324
// TODO: Switch to MongoPath?!
1263
1325
if (isAssociation ()) {
1264
- return path == null ? name : path .toDotPath (getAssociationConverter ());
1326
+ return propertyPath == null ? name : propertyPath .toDotPath (getAssociationConverter ());
1265
1327
}
1266
1328
1267
1329
if (entity != null ) {
1268
- return mongoPath . applyFieldNames ( mappingContext , entity ).toString ();
1330
+ return paths . mappedPath ( mongoPath , entity . getTypeInformation () ).toString ();
1269
1331
}
1270
1332
1271
1333
return name ;
1272
1334
}
1273
1335
1336
+
1274
1337
@ Nullable
1275
1338
protected PersistentPropertyPath <MongoPersistentProperty > getPath () {
1276
- return path ;
1339
+ return propertyPath ;
1277
1340
}
1278
1341
1279
1342
/**
@@ -1290,7 +1353,7 @@ private PersistentPropertyPath<MongoPersistentProperty> getPath(MongoPath mongoP
1290
1353
PropertyPath .from (Pattern .quote (sourceProperty .getName ()), entity .getTypeInformation ()));
1291
1354
}
1292
1355
1293
- PropertyPath path = mongoPath . toPropertyPath (mappingContext , entity );
1356
+ PropertyPath path = toPropertyPath (mongoPath , entity );
1294
1357
1295
1358
if (path == null || isPathToJavaLangClassProperty (path )) {
1296
1359
return null ;
0 commit comments