15
15
*/
16
16
package org .springframework .data .jdbc .core .convert ;
17
17
18
+ import java .util .ArrayList ;
19
+ import java .util .Arrays ;
18
20
import java .util .Collection ;
19
21
import java .util .Collections ;
20
22
import java .util .List ;
23
+ import java .util .function .Consumer ;
21
24
25
+ import org .springframework .core .convert .converter .Converter ;
26
+ import org .springframework .core .convert .converter .ConverterFactory ;
27
+ import org .springframework .core .convert .converter .GenericConverter ;
22
28
import org .springframework .core .convert .converter .GenericConverter .ConvertiblePair ;
29
+ import org .springframework .data .convert .ConverterBuilder ;
23
30
import org .springframework .data .convert .CustomConversions ;
24
31
import org .springframework .data .jdbc .core .mapping .JdbcSimpleTypes ;
32
+ import org .springframework .data .relational .core .dialect .Dialect ;
33
+ import org .springframework .lang .Contract ;
34
+ import org .springframework .util .Assert ;
25
35
26
36
/**
27
37
* Value object to capture custom conversion. {@link JdbcCustomConversions} also act as factory for
@@ -50,10 +60,10 @@ public JdbcCustomConversions() {
50
60
* Create a new {@link JdbcCustomConversions} instance registering the given converters and the default store
51
61
* converters.
52
62
*
53
- * @param converters must not be {@literal null}.
63
+ * @param userConverters must not be {@literal null}.
54
64
*/
55
- public JdbcCustomConversions (List <?> converters ) {
56
- super ( constructConverterConfiguration ( converters ) );
65
+ public JdbcCustomConversions (List <?> userConverters ) {
66
+ this ( StoreConversions . of ( JdbcSimpleTypes . HOLDER , STORE_CONVERTERS ), userConverters );
57
67
}
58
68
59
69
/**
@@ -63,12 +73,7 @@ public JdbcCustomConversions(List<?> converters) {
63
73
* @since 2.3
64
74
*/
65
75
public JdbcCustomConversions (StoreConversions storeConversions , List <?> userConverters ) {
66
-
67
- super (new ConverterConfiguration ( //
68
- storeConversions , //
69
- userConverters , //
70
- JdbcCustomConversions ::excludeConversionsBetweenDateAndJsr310Types //
71
- ));
76
+ super (JdbcConverterConfigurer .from (storeConversions ).registerConverters (userConverters ).createConfiguration ());
72
77
}
73
78
74
79
/**
@@ -82,15 +87,40 @@ public JdbcCustomConversions(ConverterConfiguration converterConfiguration) {
82
87
super (converterConfiguration );
83
88
}
84
89
85
- private static ConverterConfiguration constructConverterConfiguration (List <?> converters ) {
90
+ /**
91
+ * Create a new {@link JdbcCustomConversions} from the given {@link Dialect} and {@code converters}.
92
+ *
93
+ * @param dialect must not be {@literal null}.
94
+ * @param converters must not be {@literal null}.
95
+ * @return a new {@link JdbcCustomConversions} instance configured from the given dialect and configured converters.
96
+ * @since 4.0
97
+ */
98
+ public static JdbcCustomConversions of (Dialect dialect , Collection <?> converters ) {
99
+
100
+ Assert .notNull (dialect , "Dialect must not be null" );
101
+ Assert .notNull (converters , "Converters must not be null" );
86
102
87
- return new ConverterConfiguration ( //
88
- StoreConversions .of (JdbcSimpleTypes .HOLDER , STORE_CONVERTERS ), //
89
- converters , //
90
- JdbcCustomConversions ::excludeConversionsBetweenDateAndJsr310Types //
91
- );
103
+ return create (dialect , configurer -> configurer .registerConverters (converters ));
92
104
}
93
105
106
+ /**
107
+ * Create a new {@link JdbcCustomConversions} instance using the given {@link Dialect} and
108
+ * {@link JdbcConverterConfigurer} callback to configure converters.
109
+ *
110
+ * @param dialect the {@link Dialect} to use, must not be {@literal null}.
111
+ * @param configurer the configurer callback to configure converters, must not be {@literal null}.
112
+ * @return a new {@link JdbcCustomConversions} instance configured from the given dialect and configured converters.
113
+ */
114
+ public static JdbcCustomConversions create (Dialect dialect , Consumer <JdbcConverterConfigurer > configurer ) {
115
+
116
+ Assert .notNull (dialect , "Dialect must not be null" );
117
+ Assert .notNull (configurer , "JdbcConverterConfigurer Consumer must not be null" );
118
+
119
+ JdbcConverterConfigurer converterConfigurer = JdbcConverterConfigurer .from (dialect );
120
+ configurer .accept (converterConfigurer );
121
+
122
+ return new JdbcCustomConversions (converterConfigurer .createConfiguration ());
123
+ }
94
124
95
125
/**
96
126
* Obtain a read only copy of default store converters.
@@ -118,4 +148,112 @@ private static boolean isDateTimeApiConversion(ConvertiblePair cp) {
118
148
private static boolean excludeConversionsBetweenDateAndJsr310Types (ConvertiblePair cp ) {
119
149
return !isDateTimeApiConversion (cp );
120
150
}
151
+
152
+ /**
153
+ * {@link JdbcConverterConfigurer} encapsulates creation of
154
+ * {@link org.springframework.data.convert.CustomConversions.ConverterConfiguration} with JDBC specifics.
155
+ *
156
+ * @author Mark Paluch
157
+ * @since 4.0
158
+ */
159
+ public static class JdbcConverterConfigurer {
160
+
161
+ private final StoreConversions storeConversions ;
162
+ private final List <Object > customConverters = new ArrayList <>();
163
+
164
+ private JdbcConverterConfigurer (StoreConversions storeConversions ) {
165
+ this .storeConversions = storeConversions ;
166
+ }
167
+
168
+ /**
169
+ * Create a {@link JdbcConverterConfigurer} using the provided {@code dialect} and our own codecs for JSR-310 types.
170
+ *
171
+ * @param dialect must not be {@literal null}.
172
+ * @return
173
+ */
174
+ static JdbcConverterConfigurer from (Dialect dialect ) {
175
+
176
+ List <Object > converters = new ArrayList <>();
177
+ converters .addAll (dialect .getConverters ());
178
+ converters .addAll (JdbcCustomConversions .storeConverters ());
179
+
180
+ StoreConversions storeConversions = StoreConversions .of (JdbcSimpleTypes .HOLDER , converters );
181
+
182
+ return new JdbcConverterConfigurer (storeConversions );
183
+ }
184
+
185
+ /**
186
+ * Create a {@link JdbcConverterConfigurer} using the provided {@code storeConversions}.
187
+ *
188
+ * @param storeConversions must not be {@literal null}.
189
+ * @return
190
+ */
191
+ static JdbcConverterConfigurer from (StoreConversions storeConversions ) {
192
+ return new JdbcConverterConfigurer (storeConversions );
193
+ }
194
+
195
+ /**
196
+ * Add a custom {@link Converter} implementation.
197
+ *
198
+ * @param converter must not be {@literal null}.
199
+ * @return this.
200
+ */
201
+ @ Contract ("_ -> this" )
202
+ public JdbcConverterConfigurer registerConverter (Converter <?, ?> converter ) {
203
+
204
+ Assert .notNull (converter , "Converter must not be null" );
205
+ customConverters .add (converter );
206
+ return this ;
207
+ }
208
+
209
+ /**
210
+ * Add {@link Converter converters}, {@link ConverterFactory factories}, {@link ConverterBuilder.ConverterAware
211
+ * converter-aware objects}, and {@link GenericConverter generic converters}.
212
+ *
213
+ * @param converters must not be {@literal null} nor contain {@literal null} values.
214
+ * @return this.
215
+ */
216
+ @ Contract ("_ -> this" )
217
+ public JdbcConverterConfigurer registerConverters (Object ... converters ) {
218
+ return registerConverters (Arrays .asList (converters ));
219
+ }
220
+
221
+ /**
222
+ * Add {@link Converter converters}, {@link ConverterFactory factories}, {@link ConverterBuilder.ConverterAware
223
+ * converter-aware objects}, and {@link GenericConverter generic converters}.
224
+ *
225
+ * @param converters must not be {@literal null} nor contain {@literal null} values.
226
+ * @return this.
227
+ */
228
+ @ Contract ("_ -> this" )
229
+ public JdbcConverterConfigurer registerConverters (Collection <?> converters ) {
230
+
231
+ Assert .notNull (converters , "Converters must not be null" );
232
+ Assert .noNullElements (converters , "Converters must not be null nor contain null values" );
233
+
234
+ customConverters .addAll (converters );
235
+ return this ;
236
+ }
237
+
238
+ /**
239
+ * Add a custom {@link ConverterFactory} implementation.
240
+ *
241
+ * @param converterFactory must not be {@literal null}.
242
+ * @return this.
243
+ */
244
+ @ Contract ("_ -> this" )
245
+ public JdbcConverterConfigurer registerConverterFactory (ConverterFactory <?, ?> converterFactory ) {
246
+
247
+ Assert .notNull (converterFactory , "ConverterFactory must not be null" );
248
+ customConverters .add (converterFactory );
249
+ return this ;
250
+ }
251
+
252
+ ConverterConfiguration createConfiguration () {
253
+ return new ConverterConfiguration (storeConversions , this .customConverters ,
254
+ JdbcCustomConversions ::excludeConversionsBetweenDateAndJsr310Types );
255
+ }
256
+
257
+ }
258
+
121
259
}
0 commit comments