3939import org .bson .conversions .Bson ;
4040import org .bson .json .JsonReader ;
4141import org .bson .types .ObjectId ;
42+
4243import org .springframework .beans .BeansException ;
4344import org .springframework .beans .factory .BeanClassLoaderAware ;
4445import org .springframework .context .ApplicationContext ;
4748import org .springframework .core .convert .ConversionService ;
4849import org .springframework .core .convert .TypeDescriptor ;
4950import org .springframework .core .convert .support .DefaultConversionService ;
51+ import org .springframework .core .env .Environment ;
52+ import org .springframework .core .env .EnvironmentCapable ;
53+ import org .springframework .core .env .StandardEnvironment ;
5054import org .springframework .data .annotation .Reference ;
5155import org .springframework .data .convert .CustomConversions ;
5256import org .springframework .data .convert .TypeMapper ;
5963import org .springframework .data .mapping .PersistentPropertyAccessor ;
6064import org .springframework .data .mapping .callback .EntityCallbacks ;
6165import org .springframework .data .mapping .context .MappingContext ;
66+ import org .springframework .data .mapping .model .CachingValueExpressionEvaluatorFactory ;
6267import org .springframework .data .mapping .model .ConvertingPropertyAccessor ;
63- import org .springframework .data .mapping .model .DefaultSpELExpressionEvaluator ;
6468import org .springframework .data .mapping .model .EntityInstantiator ;
6569import org .springframework .data .mapping .model .ParameterValueProvider ;
6670import org .springframework .data .mapping .model .PersistentEntityParameterValueProvider ;
6771import org .springframework .data .mapping .model .PropertyValueProvider ;
6872import org .springframework .data .mapping .model .SpELContext ;
69- import org .springframework .data .mapping .model .SpELExpressionEvaluator ;
7073import org .springframework .data .mapping .model .SpELExpressionParameterValueProvider ;
74+ import org .springframework .data .mapping .model .ValueExpressionEvaluator ;
75+ import org .springframework .data .mapping .model .ValueExpressionParameterValueProvider ;
7176import org .springframework .data .mongodb .CodecRegistryProvider ;
7277import org .springframework .data .mongodb .MongoDatabaseFactory ;
7378import org .springframework .data .mongodb .core .mapping .BasicMongoPersistentProperty ;
8893import org .springframework .data .projection .SpelAwareProxyProjectionFactory ;
8994import org .springframework .data .util .Predicates ;
9095import org .springframework .data .util .TypeInformation ;
96+ import org .springframework .expression .spel .standard .SpelExpressionParser ;
9197import org .springframework .lang .Nullable ;
9298import org .springframework .util .Assert ;
9399import org .springframework .util .ClassUtils ;
116122 * @author Divya Srivastava
117123 * @author Julia Lee
118124 */
119- public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
125+ public class MappingMongoConverter extends AbstractMongoConverter
126+ implements ApplicationContextAware , EnvironmentCapable {
120127
121128 private static final String INCOMPATIBLE_TYPES = "Cannot convert %1$s of type %2$s into an instance of %3$s; Implement a custom Converter<%2$s, %3$s> and register it with the CustomConversions; Parent object was: %4$s" ;
122129 private static final String INVALID_TYPE_TO_READ = "Expected to read Document %s into type %s but didn't find a PersistentEntity for the latter" ;
@@ -132,15 +139,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
132139 protected final ReferenceLookupDelegate referenceLookupDelegate ;
133140
134141 protected @ Nullable ApplicationContext applicationContext ;
142+ protected @ Nullable Environment environment ;
135143 protected MongoTypeMapper typeMapper ;
136144 protected @ Nullable String mapKeyDotReplacement = null ;
137145 protected @ Nullable CodecRegistryProvider codecRegistryProvider ;
138146
139147 private MongoTypeMapper defaultTypeMapper ;
140148 private SpELContext spELContext ;
141149 private @ Nullable EntityCallbacks entityCallbacks ;
150+ private final SpelExpressionParser expressionParser = new SpelExpressionParser ();
142151 private final DocumentPointerFactory documentPointerFactory ;
143- private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory ();
152+ private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory (
153+ expressionParser );
154+ private final CachingValueExpressionEvaluatorFactory expressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory (
155+ expressionParser , this , o -> spELContext .getEvaluationContext (o ));
144156
145157 /**
146158 * Creates a new {@link MappingMongoConverter} given the new {@link DbRefResolver} and {@link MappingContext}.
@@ -169,7 +181,7 @@ public MappingMongoConverter(DbRefResolver dbRefResolver,
169181
170182 ConversionContext context = getConversionContext (path );
171183 return MappingMongoConverter .this .getValueInternal (context , prop , bson , evaluator );
172- });
184+ }, expressionEvaluatorFactory :: create );
173185
174186 this .referenceLookupDelegate = new ReferenceLookupDelegate (mappingContext , spELContext );
175187 this .documentPointerFactory = new DocumentPointerFactory (conversionService , mappingContext );
@@ -271,9 +283,11 @@ public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentPropert
271283 return mappingContext ;
272284 }
273285
286+ @ Override
274287 public void setApplicationContext (ApplicationContext applicationContext ) throws BeansException {
275288
276289 this .applicationContext = applicationContext ;
290+ this .environment = applicationContext .getEnvironment ();
277291 this .spELContext = new SpELContext (this .spELContext , applicationContext );
278292 this .projectionFactory .setBeanFactory (applicationContext );
279293 this .projectionFactory .setBeanClassLoader (applicationContext .getClassLoader ());
@@ -288,6 +302,15 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
288302 }
289303 }
290304
305+ @ Override
306+ public Environment getEnvironment () {
307+
308+ if (environment == null ) {
309+ environment = new StandardEnvironment ();
310+ }
311+ return environment ;
312+ }
313+
291314 /**
292315 * Set the {@link EntityCallbacks} instance to use when invoking
293316 * {@link org.springframework.data.mapping.callback.EntityCallback callbacks} like the {@link AfterConvertCallback}.
@@ -328,7 +351,7 @@ private <R> R doReadProjection(ConversionContext context, Bson bson, EntityProje
328351 TypeInformation <?> mappedType = projection .getActualMappedType ();
329352 MongoPersistentEntity <R > mappedEntity = (MongoPersistentEntity <R >) getMappingContext ()
330353 .getPersistentEntity (mappedType );
331- SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (bson , spELContext );
354+ ValueExpressionEvaluator evaluator = expressionEvaluatorFactory . create (bson );
332355
333356 boolean isInterfaceProjection = mappedType .getType ().isInterface ();
334357 if (isInterfaceProjection ) {
@@ -481,14 +504,14 @@ protected <S extends Object> S readDocument(ConversionContext context, Bson bson
481504 }
482505
483506 private ParameterValueProvider <MongoPersistentProperty > getParameterProvider (ConversionContext context ,
484- MongoPersistentEntity <?> entity , DocumentAccessor source , SpELExpressionEvaluator evaluator ) {
507+ MongoPersistentEntity <?> entity , DocumentAccessor source , ValueExpressionEvaluator evaluator ) {
485508
486509 AssociationAwareMongoDbPropertyValueProvider provider = new AssociationAwareMongoDbPropertyValueProvider (context ,
487510 source , evaluator );
488511 PersistentEntityParameterValueProvider <MongoPersistentProperty > parameterProvider = new PersistentEntityParameterValueProvider <>(
489512 entity , provider , context .getPath ().getCurrentObject ());
490513
491- return new ConverterAwareSpELExpressionParameterValueProvider (context , evaluator , conversionService ,
514+ return new ConverterAwareValueExpressionParameterValueProvider (context , evaluator , conversionService ,
492515 parameterProvider );
493516 }
494517
@@ -499,7 +522,7 @@ private <S> S read(ConversionContext context, MongoPersistentEntity<S> entity, D
499522 return existing ;
500523 }
501524
502- SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (bson , spELContext );
525+ ValueExpressionEvaluator evaluator = expressionEvaluatorFactory . create (bson );
503526 DocumentAccessor documentAccessor = new DocumentAccessor (bson );
504527
505528 InstanceCreatorMetadata <MongoPersistentProperty > instanceCreatorMetadata = entity .getInstanceCreatorMetadata ();
@@ -515,7 +538,7 @@ private <S> S read(ConversionContext context, MongoPersistentEntity<S> entity, D
515538 }
516539
517540 private <S > S populateProperties (ConversionContext context , MongoPersistentEntity <S > entity ,
518- DocumentAccessor documentAccessor , SpELExpressionEvaluator evaluator , S instance ) {
541+ DocumentAccessor documentAccessor , ValueExpressionEvaluator evaluator , S instance ) {
519542
520543 if (!entity .requiresPropertyPopulation ()) {
521544 return instance ;
@@ -545,7 +568,7 @@ private <S> S populateProperties(ConversionContext context, MongoPersistentEntit
545568 */
546569 @ Nullable
547570 private Object readAndPopulateIdentifier (ConversionContext context , PersistentPropertyAccessor <?> accessor ,
548- DocumentAccessor document , MongoPersistentEntity <?> entity , SpELExpressionEvaluator evaluator ) {
571+ DocumentAccessor document , MongoPersistentEntity <?> entity , ValueExpressionEvaluator evaluator ) {
549572
550573 Object rawId = document .getRawId (entity );
551574
@@ -565,7 +588,7 @@ private Object readAndPopulateIdentifier(ConversionContext context, PersistentPr
565588 }
566589
567590 @ Nullable
568- private Object readIdValue (ConversionContext context , SpELExpressionEvaluator evaluator ,
591+ private Object readIdValue (ConversionContext context , ValueExpressionEvaluator evaluator ,
569592 MongoPersistentProperty idProperty , Object rawId ) {
570593
571594 String expression = idProperty .getSpelExpression ();
@@ -578,7 +601,7 @@ private Object readIdValue(ConversionContext context, SpELExpressionEvaluator ev
578601
579602 private void readProperties (ConversionContext context , MongoPersistentEntity <?> entity ,
580603 PersistentPropertyAccessor <?> accessor , DocumentAccessor documentAccessor ,
581- MongoDbPropertyValueProvider valueProvider , SpELExpressionEvaluator evaluator ,
604+ MongoDbPropertyValueProvider valueProvider , ValueExpressionEvaluator evaluator ,
582605 Predicate <MongoPersistentProperty > propertyFilter ) {
583606
584607 DbRefResolverCallback callback = null ;
@@ -622,7 +645,7 @@ private void readProperties(ConversionContext context, MongoPersistentEntity<?>
622645 }
623646
624647 private DbRefResolverCallback getDbRefResolverCallback (ConversionContext context , DocumentAccessor documentAccessor ,
625- SpELExpressionEvaluator evaluator ) {
648+ ValueExpressionEvaluator evaluator ) {
626649
627650 return new DefaultDbRefResolverCallback (documentAccessor .getDocument (), context .getPath (), evaluator ,
628651 (prop , bson , e , path ) -> MappingMongoConverter .this .getValueInternal (context , prop , bson , e ));
@@ -1387,7 +1410,7 @@ protected DBRef createDBRef(Object target, @Nullable MongoPersistentProperty pro
13871410
13881411 @ Nullable
13891412 private Object getValueInternal (ConversionContext context , MongoPersistentProperty prop , Bson bson ,
1390- SpELExpressionEvaluator evaluator ) {
1413+ ValueExpressionEvaluator evaluator ) {
13911414 return new MongoDbPropertyValueProvider (context , bson , evaluator ).getPropertyValue (prop );
13921415 }
13931416
@@ -1876,35 +1899,35 @@ static class MongoDbPropertyValueProvider implements PropertyValueProvider<Mongo
18761899
18771900 final ConversionContext context ;
18781901 final DocumentAccessor accessor ;
1879- final SpELExpressionEvaluator evaluator ;
1902+ final ValueExpressionEvaluator evaluator ;
18801903 final SpELContext spELContext ;
18811904
18821905 /**
1883- * Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link SpELExpressionEvaluator } and
1906+ * Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link ValueExpressionEvaluator } and
18841907 * {@link ObjectPath}.
18851908 *
18861909 * @param context must not be {@literal null}.
18871910 * @param source must not be {@literal null}.
18881911 * @param evaluator must not be {@literal null}.
18891912 */
1890- MongoDbPropertyValueProvider (ConversionContext context , Bson source , SpELExpressionEvaluator evaluator ) {
1913+ MongoDbPropertyValueProvider (ConversionContext context , Bson source , ValueExpressionEvaluator evaluator ) {
18911914 this (context , new DocumentAccessor (source ), evaluator , null );
18921915 }
18931916
18941917 /**
1895- * Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link SpELExpressionEvaluator } and
1918+ * Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link ValueExpressionEvaluator } and
18961919 * {@link ObjectPath}.
18971920 *
18981921 * @param context must not be {@literal null}.
18991922 * @param accessor must not be {@literal null}.
19001923 * @param evaluator must not be {@literal null}.
19011924 */
19021925 MongoDbPropertyValueProvider (ConversionContext context , DocumentAccessor accessor ,
1903- SpELExpressionEvaluator evaluator , SpELContext spELContext ) {
1926+ ValueExpressionEvaluator evaluator , SpELContext spELContext ) {
19041927
19051928 Assert .notNull (context , "ConversionContext must no be null" );
19061929 Assert .notNull (accessor , "DocumentAccessor must no be null" );
1907- Assert .notNull (evaluator , "SpELExpressionEvaluator must not be null" );
1930+ Assert .notNull (evaluator , "ValueExpressionEvaluator must not be null" );
19081931
19091932 this .context = context ;
19101933 this .accessor = accessor ;
@@ -1953,13 +1976,13 @@ class AssociationAwareMongoDbPropertyValueProvider extends MongoDbPropertyValueP
19531976
19541977 /**
19551978 * Creates a new {@link AssociationAwareMongoDbPropertyValueProvider} for the given source,
1956- * {@link SpELExpressionEvaluator } and {@link ObjectPath}.
1979+ * {@link ValueExpressionEvaluator } and {@link ObjectPath}.
19571980 *
19581981 * @param source must not be {@literal null}.
19591982 * @param evaluator must not be {@literal null}.
19601983 */
19611984 AssociationAwareMongoDbPropertyValueProvider (ConversionContext context , DocumentAccessor source ,
1962- SpELExpressionEvaluator evaluator ) {
1985+ ValueExpressionEvaluator evaluator ) {
19631986 super (context , source , evaluator , MappingMongoConverter .this .spELContext );
19641987 }
19651988
@@ -2000,21 +2023,21 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
20002023 *
20012024 * @author Oliver Gierke
20022025 */
2003- private static class ConverterAwareSpELExpressionParameterValueProvider
2004- extends SpELExpressionParameterValueProvider <MongoPersistentProperty > {
2026+ private static class ConverterAwareValueExpressionParameterValueProvider
2027+ extends ValueExpressionParameterValueProvider <MongoPersistentProperty > {
20052028
20062029 private final ConversionContext context ;
20072030
20082031 /**
2009- * Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider }.
2032+ * Creates a new {@link ConverterAwareValueExpressionParameterValueProvider }.
20102033 *
20112034 * @param context must not be {@literal null}.
20122035 * @param evaluator must not be {@literal null}.
20132036 * @param conversionService must not be {@literal null}.
20142037 * @param delegate must not be {@literal null}.
20152038 */
2016- public ConverterAwareSpELExpressionParameterValueProvider (ConversionContext context ,
2017- SpELExpressionEvaluator evaluator , ConversionService conversionService ,
2039+ public ConverterAwareValueExpressionParameterValueProvider (ConversionContext context ,
2040+ ValueExpressionEvaluator evaluator , ConversionService conversionService ,
20182041 ParameterValueProvider <MongoPersistentProperty > delegate ) {
20192042
20202043 super (evaluator , conversionService , delegate );
@@ -2025,7 +2048,7 @@ public ConverterAwareSpELExpressionParameterValueProvider(ConversionContext cont
20252048 }
20262049
20272050 @ Override
2028- protected <T > T potentiallyConvertSpelValue (Object object , Parameter <T , MongoPersistentProperty > parameter ) {
2051+ protected <T > T potentiallyConvertExpressionValue (Object object , Parameter <T , MongoPersistentProperty > parameter ) {
20292052 return context .convert (object , parameter .getType ());
20302053 }
20312054 }
0 commit comments