20
20
import java .util .HashMap ;
21
21
import java .util .Objects ;
22
22
23
+ import com .fasterxml .jackson .databind .JsonNode ;
24
+ import com .fasterxml .jackson .databind .node .BaseJsonNode ;
25
+ import com .fasterxml .jackson .databind .node .NullNode ;
23
26
import org .slf4j .LoggerFactory ;
24
27
25
28
import com .vaadin .flow .component .Component ;
26
29
import com .vaadin .flow .component .webcomponent .WebComponentConfiguration ;
27
30
import com .vaadin .flow .function .SerializableBiConsumer ;
28
31
import com .vaadin .flow .function .SerializableConsumer ;
32
+ import com .vaadin .flow .internal .JacksonCodec ;
29
33
import com .vaadin .flow .internal .JsonCodec ;
30
34
35
+ import elemental .json .Json ;
31
36
import elemental .json .JsonValue ;
32
37
33
38
/**
@@ -54,7 +59,7 @@ public final class WebComponentBinding<C extends Component>
54
59
* Constructs a new {@code WebComponentBinding}. The bound {@link Component}
55
60
* is given via {@code component} parameter. The web component properties
56
61
* are bound by calling
57
- * {@link #bindProperty(PropertyConfigurationImpl, boolean, elemental.json.JsonValue )};
62
+ * {@link #bindProperty(PropertyConfigurationImpl, boolean, JsonNode )};
58
63
*
59
64
* @param component
60
65
* component which exposes {@code properties} as web component.
@@ -116,6 +121,7 @@ public void updateProperty(String propertyName, Serializable value) {
116
121
* if the {@code jsonValue} cannot be converted to the type of
117
122
* the property identified by {@code propertyName}.
118
123
*/
124
+ @ Deprecated
119
125
public void updateProperty (String propertyName , JsonValue jsonValue ) {
120
126
Objects .requireNonNull (propertyName ,
121
127
"Parameter 'propertyName' must not be null!" );
@@ -127,6 +133,34 @@ public void updateProperty(String propertyName, JsonValue jsonValue) {
127
133
updateProperty (propertyName , value );
128
134
}
129
135
136
+ /**
137
+ * Updates a property bound to the {@code component}. Converts the {@code
138
+ * jsonValue} into the correct type if able and then calls
139
+ * {@link #updateProperty(String, java.io.Serializable)}.
140
+ *
141
+ * @param propertyName
142
+ * name of the property, not {@code null}
143
+ * @param jsonValue
144
+ * new value to set for the property
145
+ * @throws NullPointerException
146
+ * if {@code propertyName} is {@code null}
147
+ * @throws IllegalArgumentException
148
+ * if no bound property can be found for {@code propertyName}
149
+ * @throws IllegalArgumentException
150
+ * if the {@code jsonValue} cannot be converted to the type of
151
+ * the property identified by {@code propertyName}.
152
+ */
153
+ public void updateProperty (String propertyName , BaseJsonNode jsonValue ) {
154
+ Objects .requireNonNull (propertyName ,
155
+ "Parameter 'propertyName' must not be null!" );
156
+
157
+ Class <? extends Serializable > propertyType = getPropertyType (
158
+ propertyName );
159
+
160
+ Serializable value = jsonValueToConcreteType (jsonValue , propertyType );
161
+ updateProperty (propertyName , value );
162
+ }
163
+
130
164
/**
131
165
* Retrieves the bound {@link Component} instance.
132
166
*
@@ -170,6 +204,69 @@ public void updatePropertiesToComponent() {
170
204
properties .forEach ((key , value ) -> value .notifyValueChange ());
171
205
}
172
206
207
+ /**
208
+ * Adds a property to {@code this} web component binding based on the {@code
209
+ * propertyConfiguration}. If a property with an existing name is bound, the
210
+ * previous binding is removed. Starting value for the property is set to
211
+ * {@code null}.
212
+ *
213
+ * @param propertyConfiguration
214
+ * property configuration, not {@code null}
215
+ * @param overrideDefault
216
+ * set to {@code true} if the property should be initialized with
217
+ * {@literal null} instead of default value found in
218
+ * {@link PropertyData}
219
+ * @throws NullPointerException
220
+ * if {@code propertyConfiguration} is {@code null}
221
+ */
222
+ public void bindProperty (
223
+ PropertyConfigurationImpl <C , ? extends Serializable > propertyConfiguration ,
224
+ boolean overrideDefault ) {
225
+ bindProperty (propertyConfiguration , overrideDefault , (JsonNode ) null );
226
+ }
227
+
228
+ /**
229
+ * Adds a property to {@code this} web component binding based on the {@code
230
+ * propertyConfiguration}. If a property with an existing name is bound, the
231
+ * previous binding is removed.
232
+ *
233
+ * @param propertyConfiguration
234
+ * property configuration, not {@code null}
235
+ * @param overrideDefault
236
+ * set to {@code true} if the property should be initialized with
237
+ * {@code startingValue} instead of default value found in
238
+ * {@link PropertyData}
239
+ * @param startingValue
240
+ * starting value for the property. Can be {@code null}.
241
+ * {@code overrideDefault} must be {@code true} for this value to
242
+ * have any effect
243
+ * @throws NullPointerException
244
+ * if {@code propertyConfiguration} is {@code null}
245
+ */
246
+ public void bindProperty (
247
+ PropertyConfigurationImpl <C , ? extends Serializable > propertyConfiguration ,
248
+ boolean overrideDefault , JsonNode startingValue ) {
249
+ Objects .requireNonNull (propertyConfiguration ,
250
+ "Parameter 'propertyConfiguration' cannot be null!" );
251
+
252
+ final SerializableBiConsumer <C , Serializable > consumer = propertyConfiguration
253
+ .getOnChangeHandler ();
254
+
255
+ final Serializable selectedStartingValue = !overrideDefault
256
+ ? propertyConfiguration .getPropertyData ().getDefaultValue ()
257
+ : jsonValueToConcreteType (startingValue ,
258
+ propertyConfiguration .getPropertyData ().getType ());
259
+
260
+ final PropertyBinding <? extends Serializable > binding = new PropertyBinding <>(
261
+ propertyConfiguration .getPropertyData (),
262
+ consumer == null ? null
263
+ : value -> consumer .accept (component , value ),
264
+ selectedStartingValue );
265
+
266
+ properties .put (propertyConfiguration .getPropertyData ().getName (),
267
+ binding );
268
+ }
269
+
173
270
/**
174
271
* Adds a property to {@code this} web component binding based on the {@code
175
272
* propertyConfiguration}. If a property with an existing name is bound, the
@@ -188,6 +285,7 @@ public void updatePropertiesToComponent() {
188
285
* @throws NullPointerException
189
286
* if {@code propertyConfiguration} is {@code null}
190
287
*/
288
+ @ Deprecated
191
289
public void bindProperty (
192
290
PropertyConfigurationImpl <C , ? extends Serializable > propertyConfiguration ,
193
291
boolean overrideDefault , JsonValue startingValue ) {
@@ -212,6 +310,7 @@ public void bindProperty(
212
310
binding );
213
311
}
214
312
313
+ @ Deprecated
215
314
private Serializable jsonValueToConcreteType (JsonValue jsonValue ,
216
315
Class <? extends Serializable > type ) {
217
316
Objects .requireNonNull (type , "Parameter 'type' must not be null!" );
@@ -229,6 +328,31 @@ private Serializable jsonValueToConcreteType(JsonValue jsonValue,
229
328
}
230
329
}
231
330
331
+ private Serializable jsonValueToConcreteType (JsonNode jsonValue ,
332
+ Class <? extends Serializable > type ) {
333
+ Objects .requireNonNull (type , "Parameter 'type' must not be null!" );
334
+
335
+ if (JacksonCodec .canEncodeWithoutTypeInfo (type )) {
336
+ Serializable value = null ;
337
+ if (jsonValue != null ) {
338
+ value = JacksonCodec .decodeAs (jsonValue , type );
339
+ }
340
+ return value ;
341
+ } else if (JsonCodec .canEncodeWithoutTypeInfo (type )) {
342
+ // TODO: Remove when ClientCallable works with jackson types only.
343
+ Serializable value = null ;
344
+ if (jsonValue != null && !(jsonValue instanceof NullNode )) {
345
+ value = JsonCodec .decodeAs (Json .parse (jsonValue .toString ()),
346
+ type );
347
+ }
348
+ return value ;
349
+ } else {
350
+ throw new IllegalArgumentException (
351
+ String .format ("Received '%s' was not convertible to '%s'" ,
352
+ jsonValue .getClass ().getName (), type .getName ()));
353
+ }
354
+ }
355
+
232
356
private static class PropertyBinding <P extends Serializable >
233
357
implements Serializable {
234
358
private PropertyData <P > data ;
0 commit comments