38
38
39
39
import org .apiguardian .api .API ;
40
40
import org .neo4j .cypherdsl .core .Statement ;
41
- import org .neo4j .driver .internal .types .InternalTypeSystem ;
42
41
import org .neo4j .driver .types .TypeSystem ;
43
42
import org .springframework .beans .BeanUtils ;
44
43
import org .springframework .beans .BeansException ;
66
65
import org .springframework .data .neo4j .core .schema .IdGenerator ;
67
66
import org .springframework .data .neo4j .core .schema .Node ;
68
67
import org .springframework .data .neo4j .core .schema .PostLoad ;
68
+ import org .springframework .data .util .Lazy ;
69
69
import org .springframework .data .util .TypeInformation ;
70
70
import org .springframework .lang .Nullable ;
71
71
import org .springframework .util .ReflectionUtils ;
@@ -117,26 +117,67 @@ public final class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersi
117
117
118
118
private boolean strict = false ;
119
119
120
- public Neo4jMappingContext () {
120
+ private final Lazy <PersistentPropertyCharacteristicsProvider > propertyCharacteristicsProvider ;
121
+
122
+ /**
123
+ * A builder for creating custom instances of a {@link Neo4jMappingContext}.
124
+ * @since 6.3.7
125
+ */
126
+ public static class Builder {
127
+
128
+ private Neo4jConversions neo4jConversions ;
129
+
130
+ @ Nullable
131
+ private TypeSystem typeSystem ;
121
132
122
- this (new Neo4jConversions ());
133
+ @ Nullable
134
+ private PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider ;
135
+
136
+ private Builder () {
137
+ this (new Neo4jConversions (), null , null );
138
+ }
139
+
140
+ private Builder (Neo4jConversions neo4jConversions , @ Nullable TypeSystem typeSystem , @ Nullable PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider ) {
141
+ this .neo4jConversions = neo4jConversions ;
142
+ this .typeSystem = typeSystem ;
143
+ this .persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider ;
144
+ }
145
+
146
+ @ SuppressWarnings ("HiddenField" )
147
+ public Builder withNeo4jConversions (@ Nullable Neo4jConversions neo4jConversions ) {
148
+ this .neo4jConversions = neo4jConversions ;
149
+ return this ;
150
+ }
151
+
152
+ @ SuppressWarnings ("HiddenField" )
153
+ public Builder withPersistentPropertyCharacteristicsProvider (@ Nullable PersistentPropertyCharacteristicsProvider persistentPropertyCharacteristicsProvider ) {
154
+ this .persistentPropertyCharacteristicsProvider = persistentPropertyCharacteristicsProvider ;
155
+ return this ;
156
+ }
157
+
158
+ @ SuppressWarnings ("HiddenField" )
159
+ public Builder withTypeSystem (@ Nullable TypeSystem typeSystem ) {
160
+ this .typeSystem = typeSystem ;
161
+ return this ;
162
+ }
163
+
164
+ public Neo4jMappingContext build () {
165
+ return new Neo4jMappingContext (this );
166
+ }
123
167
}
124
168
125
- public Neo4jMappingContext (Neo4jConversions neo4jConversions ) {
169
+ public static Builder builder () {
170
+ return new Builder ();
171
+ }
172
+
173
+ public Neo4jMappingContext () {
126
174
127
- this (neo4jConversions , null );
175
+ this (new Builder () );
128
176
}
129
177
130
- /**
131
- * We need to set the context to non-strict in case we must dynamically add parent classes. As there is no
132
- * way to access the original value without reflection, we track its change.
133
- *
134
- * @param strict The new value for the strict setting.
135
- */
136
- @ Override
137
- public void setStrict (boolean strict ) {
138
- super .setStrict (strict );
139
- this .strict = strict ;
178
+ public Neo4jMappingContext (Neo4jConversions neo4jConversions ) {
179
+
180
+ this (new Builder (neo4jConversions , null , null ));
140
181
}
141
182
142
183
/**
@@ -145,17 +186,40 @@ public void setStrict(boolean strict) {
145
186
*
146
187
* @param neo4jConversions The conversions to be used
147
188
* @param typeSystem The current drivers type system. If this is null, we use the default one without accessing the driver.
189
+ * @deprecated Use {@link Neo4jMappingContext#builder()}
148
190
*/
149
191
@ API (status = API .Status .INTERNAL , since = "6.0" )
192
+ @ Deprecated (since = "6.3.7" , forRemoval = true )
150
193
public Neo4jMappingContext (Neo4jConversions neo4jConversions , @ Nullable TypeSystem typeSystem ) {
194
+ this (new Builder (neo4jConversions , typeSystem , null ));
195
+ }
196
+
197
+ private Neo4jMappingContext (Builder builder ) {
151
198
152
- this .conversionService = new DefaultNeo4jConversionService (neo4jConversions );
153
- this .typeSystem = typeSystem == null ? InternalTypeSystem . TYPE_SYSTEM : typeSystem ;
199
+ this .conversionService = new DefaultNeo4jConversionService (builder . neo4jConversions );
200
+ this .typeSystem = builder . typeSystem == null ? TypeSystem . getDefault () : builder . typeSystem ;
154
201
this .eventSupport = EventSupport .useExistingCallbacks (this , EntityCallbacks .create ());
155
202
156
- super .setSimpleTypeHolder (neo4jConversions .getSimpleTypeHolder ());
203
+ super .setSimpleTypeHolder (builder .neo4jConversions .getSimpleTypeHolder ());
204
+
205
+ PersistentPropertyCharacteristicsProvider characteristicsProvider = builder .persistentPropertyCharacteristicsProvider ;
206
+ this .propertyCharacteristicsProvider = Lazy .of (() -> characteristicsProvider != null || this .beanFactory == null ?
207
+ characteristicsProvider : this .beanFactory .getBeanProvider (PersistentPropertyCharacteristicsProvider .class ).getIfUnique ());
157
208
}
158
209
210
+ /**
211
+ * We need to set the context to non-strict in case we must dynamically add parent classes. As there is no
212
+ * way to access the original value without reflection, we track its change.
213
+ *
214
+ * @param strict The new value for the strict setting.
215
+ */
216
+ @ Override
217
+ public void setStrict (boolean strict ) {
218
+ super .setStrict (strict );
219
+ this .strict = strict ;
220
+ }
221
+
222
+
159
223
public Neo4jEntityConverter getEntityConverter () {
160
224
return new DefaultNeo4jEntityConverter (INSTANTIATORS , nodeDescriptionStore , conversionService , eventSupport ,
161
225
typeSystem );
@@ -260,7 +324,12 @@ private static boolean isValidParentNode(@Nullable Class<?> parentClass) {
260
324
protected Neo4jPersistentProperty createPersistentProperty (Property property , Neo4jPersistentEntity <?> owner ,
261
325
SimpleTypeHolder simpleTypeHolder ) {
262
326
263
- return new DefaultNeo4jPersistentProperty (property , owner , this , simpleTypeHolder );
327
+ PersistentPropertyCharacteristics optionalCharacteristics = this .propertyCharacteristicsProvider
328
+ .getOptional ()
329
+ .flatMap (provider -> Optional .ofNullable (provider .apply (property , owner )))
330
+ .orElse (null );
331
+
332
+ return new DefaultNeo4jPersistentProperty (property , owner , this , simpleTypeHolder , optionalCharacteristics );
264
333
}
265
334
266
335
@ Override
@@ -278,9 +347,9 @@ public NodeDescription<?> getNodeDescription(Class<?> underlyingClass) {
278
347
@ Nullable
279
348
public Neo4jPersistentEntity <?> getPersistentEntity (TypeInformation <?> typeInformation ) {
280
349
281
- NodeDescription <?> existingDescription = this .doGetPersistentEntity (typeInformation );
350
+ Neo4jPersistentEntity <?> existingDescription = this .doGetPersistentEntity (typeInformation );
282
351
if (existingDescription != null ) {
283
- return ( Neo4jPersistentEntity <?>) existingDescription ;
352
+ return existingDescription ;
284
353
}
285
354
return super .getPersistentEntity (typeInformation );
286
355
}
0 commit comments