1616
1717package org .springframework .data .couchbase .core .convert ;
1818
19- import static org .springframework .data .couchbase .core .mapping .id .GenerationStrategy .UNIQUE ;
20- import static org .springframework .data .couchbase .core .mapping .id .GenerationStrategy .USE_ATTRIBUTES ;
19+ import static org .springframework .data .couchbase .core .mapping .id .GenerationStrategy .*;
2120
2221import java .beans .Transient ;
2322import java .lang .reflect .InaccessibleObjectException ;
3433import org .springframework .beans .factory .BeanClassLoaderAware ;
3534import org .springframework .context .ApplicationContext ;
3635import org .springframework .context .ApplicationContextAware ;
36+ import org .springframework .context .EnvironmentAware ;
3737import org .springframework .core .CollectionFactory ;
3838import org .springframework .core .convert .ConversionService ;
3939import org .springframework .core .convert .TypeDescriptor ;
4040import org .springframework .core .convert .support .DefaultConversionService ;
41+ import org .springframework .core .env .Environment ;
42+ import org .springframework .core .env .EnvironmentCapable ;
43+ import org .springframework .core .env .StandardEnvironment ;
4144import org .springframework .data .convert .CustomConversions ;
4245import org .springframework .data .convert .PropertyValueConverter ;
4346import org .springframework .data .couchbase .core .mapping .CouchbaseDocument ;
6265import org .springframework .data .mapping .PropertyHandler ;
6366import org .springframework .data .mapping .callback .EntityCallbacks ;
6467import org .springframework .data .mapping .context .MappingContext ;
68+ import org .springframework .data .mapping .model .CachingValueExpressionEvaluatorFactory ;
6569import org .springframework .data .mapping .model .ConvertingPropertyAccessor ;
66- import org .springframework .data .mapping .model .DefaultSpELExpressionEvaluator ;
6770import org .springframework .data .mapping .model .EntityInstantiator ;
6871import org .springframework .data .mapping .model .ParameterValueProvider ;
6972import org .springframework .data .mapping .model .PersistentEntityParameterValueProvider ;
7073import org .springframework .data .mapping .model .PropertyValueProvider ;
7174import org .springframework .data .mapping .model .SpELContext ;
72- import org .springframework .data .mapping .model .SpELExpressionEvaluator ;
73- import org .springframework .data .mapping .model .SpELExpressionParameterValueProvider ;
75+ import org .springframework .data .mapping .model .ValueExpressionEvaluator ;
76+ import org .springframework .data .mapping .model .ValueExpressionParameterValueProvider ;
7477import org .springframework .data .util .TypeInformation ;
78+ import org .springframework .expression .spel .standard .SpelExpressionParser ;
7579import org .springframework .lang .Nullable ;
7680import org .springframework .util .Assert ;
7781import org .springframework .util .CollectionUtils ;
9296 * @author Remi Bleuse
9397 * @author Vipul Gupta
9498 */
95- public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implements ApplicationContextAware {
99+ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implements ApplicationContextAware , EnvironmentCapable , EnvironmentAware {
96100
97101 /**
98102 * The default "type key", the name of the field that will hold type information.
@@ -113,6 +117,10 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
113117 * Spring Expression Language context.
114118 */
115119 private final SpELContext spELContext ;
120+
121+ private final SpelExpressionParser expressionParser = new SpelExpressionParser ();
122+
123+ private final CachingValueExpressionEvaluatorFactory expressionEvaluatorFactory ;
116124 /**
117125 * The overall application context.
118126 */
@@ -127,6 +135,8 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
127135 */
128136 private @ Nullable EntityCallbacks entityCallbacks ;
129137
138+ private @ Nullable Environment environment ;
139+
130140 public MappingCouchbaseConverter () {
131141 this (new CouchbaseMappingContext (), null );
132142 }
@@ -173,6 +183,9 @@ public MappingCouchbaseConverter(
173183 ((CouchbaseMappingContext ) mappingContext ).setSimpleTypeHolder (customConversions .getSimpleTypeHolder ());
174184 typeMapper = new DefaultCouchbaseTypeMapper (typeKey != null ? typeKey : TYPEKEY_DEFAULT );
175185 spELContext = new SpELContext (CouchbaseDocumentPropertyAccessor .INSTANCE );
186+
187+ expressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory (
188+ expressionParser , this , o -> spELContext .getEvaluationContext (o ));
176189 }
177190
178191 /**
@@ -200,6 +213,21 @@ private static boolean isSubtype(final Class<?> left, final Class<?> right) {
200213 return left .isAssignableFrom (right ) && !left .equals (right );
201214 }
202215
216+ @ Override
217+ public void setEnvironment (Environment environment ) {
218+ this .environment = environment ;
219+ }
220+
221+ @ Override
222+ public Environment getEnvironment () {
223+
224+ if (this .environment == null ) {
225+ this .environment = new StandardEnvironment ();
226+ }
227+
228+ return environment ;
229+ }
230+
203231 @ Override
204232 public MappingContext <? extends CouchbasePersistentEntity <?>, CouchbasePersistentProperty > getMappingContext () {
205233 return mappingContext ;
@@ -273,7 +301,8 @@ protected <R> R read(final TypeInformation<R> type, final CouchbaseDocument sour
273301 * @return the converted entity.
274302 */
275303 protected <R > R read (final CouchbasePersistentEntity <R > entity , final CouchbaseDocument source , final Object parent ) {
276- final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (source , spELContext );
304+
305+ ValueExpressionEvaluator evaluator = expressionEvaluatorFactory .create (source );
277306 ParameterValueProvider <CouchbasePersistentProperty > provider = getParameterProvider (entity , source , evaluator ,
278307 parent );
279308 EntityInstantiator instantiator = instantiators .getInstantiatorFor (entity );
@@ -284,7 +313,7 @@ protected <R> R read(final CouchbasePersistentEntity<R> entity, final CouchbaseD
284313 entity .doWithProperties (new PropertyHandler <>() {
285314 @ Override
286315 public void doWithPersistentProperty (final CouchbasePersistentProperty prop ) {
287- if (!doesPropertyExistInSource (prop ) || entity .isConstructorArgument (prop ) || isIdConstructionProperty (prop )
316+ if (!doesPropertyExistInSource (prop ) || entity .isCreatorArgument (prop ) || isIdConstructionProperty (prop )
288317 || prop .isAnnotationPresent (N1qlJoin .class )) {
289318 return ;
290319 }
@@ -330,7 +359,7 @@ private boolean isIdConstructionProperty(final CouchbasePersistentProperty prope
330359 */
331360 protected Object getValueInternal (final CouchbasePersistentProperty property , final CouchbaseDocument source ,
332361 final Object parent , PersistentEntity entity ) {
333- return new CouchbasePropertyValueProvider (source , spELContext , parent , entity ).getPropertyValue (property );
362+ return new CouchbasePropertyValueProvider (source , expressionEvaluatorFactory . create ( source ) , parent , entity ).getPropertyValue (property );
334363 }
335364
336365 /**
@@ -344,7 +373,7 @@ protected Object getValueInternal(final CouchbasePersistentProperty property, fi
344373 */
345374 private ParameterValueProvider <CouchbasePersistentProperty > getParameterProvider (
346375 final CouchbasePersistentEntity <?> entity , final CouchbaseDocument source ,
347- final DefaultSpELExpressionEvaluator evaluator , final Object parent ) {
376+ final ValueExpressionEvaluator evaluator , final Object parent ) {
348377 CouchbasePropertyValueProvider provider = new CouchbasePropertyValueProvider (source , evaluator , parent , entity );
349378 PersistentEntityParameterValueProvider <CouchbasePersistentProperty > parameterProvider = new PersistentEntityParameterValueProvider <>(
350379 entity , provider , parent );
@@ -1070,7 +1099,7 @@ private class CouchbasePropertyValueProvider implements PropertyValueProvider<Co
10701099 /**
10711100 * The expression evaluator.
10721101 */
1073- private final SpELExpressionEvaluator evaluator ;
1102+ private final ValueExpressionEvaluator evaluator ;
10741103
10751104 /**
10761105 * The optional parent object.
@@ -1082,15 +1111,10 @@ private class CouchbasePropertyValueProvider implements PropertyValueProvider<Co
10821111 */
10831112 private final PersistentEntity entity ;
10841113
1085- public CouchbasePropertyValueProvider (final CouchbaseDocument source , final SpELContext factory ,
1086- final Object parent , final PersistentEntity entity ) {
1087- this (source , new DefaultSpELExpressionEvaluator (source , factory ), parent , entity );
1088- }
1089-
10901114 public CouchbasePropertyValueProvider (final CouchbaseDocument source ,
1091- final DefaultSpELExpressionEvaluator evaluator , final Object parent , final PersistentEntity entity ) {
1115+ final ValueExpressionEvaluator evaluator , final Object parent , final PersistentEntity entity ) {
10921116 Assert .notNull (source , "CouchbaseDocument must not be null!" );
1093- Assert .notNull (evaluator , "DefaultSpELExpressionEvaluator must not be null!" );
1117+ Assert .notNull (evaluator , "ValueExpressionEvaluator must not be null!" );
10941118
10951119 this .source = source ;
10961120 this .evaluator = evaluator ;
@@ -1148,20 +1172,19 @@ String maybeMangle(PersistentProperty<?> property) {
11481172 * A expression parameter value provider.
11491173 */
11501174 private class ConverterAwareSpELExpressionParameterValueProvider
1151- extends SpELExpressionParameterValueProvider <CouchbasePersistentProperty > {
1175+ extends ValueExpressionParameterValueProvider <CouchbasePersistentProperty > {
11521176
11531177 private final Object parent ;
11541178
1155- public ConverterAwareSpELExpressionParameterValueProvider (final SpELExpressionEvaluator evaluator ,
1179+ public ConverterAwareSpELExpressionParameterValueProvider (final ValueExpressionEvaluator evaluator ,
11561180 final ConversionService conversionService , final ParameterValueProvider <CouchbasePersistentProperty > delegate ,
11571181 final Object parent ) {
11581182 super (evaluator , conversionService , delegate );
11591183 this .parent = parent ;
11601184 }
11611185
11621186 @ Override
1163- protected <T > T potentiallyConvertSpelValue (final Object object ,
1164- final Parameter <T , CouchbasePersistentProperty > parameter ) {
1187+ protected <T > T potentiallyConvertExpressionValue (Object object , Parameter <T , CouchbasePersistentProperty > parameter ) {
11651188 return readValue (object , parameter .getType (), parent );
11661189 }
11671190 }
0 commit comments