78
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2007, 2008 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Matt Carter - Character support completed (bug 197679)
|
|
11 * Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
|
|
12 *******************************************************************************/
|
|
13
|
|
14 module org.eclipse.core.databinding.UpdateValueStrategy;
|
81
|
15 import org.eclipse.core.databinding.UpdateStrategy;
|
78
|
16
|
|
17 import java.lang.all;
|
|
18
|
|
19 import java.util.Date;
|
|
20 import java.util.HashMap;
|
|
21
|
|
22 import org.eclipse.core.databinding.conversion.IConverter;
|
|
23 import org.eclipse.core.databinding.observable.value.IObservableValue;
|
|
24 import org.eclipse.core.databinding.validation.IValidator;
|
|
25 import org.eclipse.core.databinding.validation.ValidationStatus;
|
|
26 import org.eclipse.core.internal.databinding.BindingMessages;
|
|
27 import org.eclipse.core.internal.databinding.Pair;
|
|
28 import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
|
|
29 import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
|
|
30 import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter;
|
|
31 import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter;
|
|
32 import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter;
|
|
33 import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
|
|
34 import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
|
|
35 import org.eclipse.core.internal.databinding.conversion.NumberToNumberConverter;
|
|
36 import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
|
|
37 import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter;
|
|
38 import org.eclipse.core.internal.databinding.conversion.StringToDateConverter;
|
|
39 import org.eclipse.core.internal.databinding.validation.NumberFormatConverter;
|
|
40 import org.eclipse.core.internal.databinding.validation.NumberToByteValidator;
|
|
41 import org.eclipse.core.internal.databinding.validation.NumberToDoubleValidator;
|
|
42 import org.eclipse.core.internal.databinding.validation.NumberToFloatValidator;
|
|
43 import org.eclipse.core.internal.databinding.validation.NumberToIntegerValidator;
|
|
44 import org.eclipse.core.internal.databinding.validation.NumberToLongValidator;
|
|
45 import org.eclipse.core.internal.databinding.validation.NumberToShortValidator;
|
|
46 import org.eclipse.core.internal.databinding.validation.NumberToUnboundedNumberValidator;
|
|
47 import org.eclipse.core.internal.databinding.validation.ObjectToPrimitiveValidator;
|
|
48 import org.eclipse.core.internal.databinding.validation.StringToByteValidator;
|
|
49 import org.eclipse.core.internal.databinding.validation.StringToCharacterValidator;
|
|
50 import org.eclipse.core.internal.databinding.validation.StringToDateValidator;
|
|
51 import org.eclipse.core.internal.databinding.validation.StringToDoubleValidator;
|
|
52 import org.eclipse.core.internal.databinding.validation.StringToFloatValidator;
|
|
53 import org.eclipse.core.internal.databinding.validation.StringToIntegerValidator;
|
|
54 import org.eclipse.core.internal.databinding.validation.StringToLongValidator;
|
|
55 import org.eclipse.core.internal.databinding.validation.StringToShortValidator;
|
|
56 import org.eclipse.core.runtime.IStatus;
|
|
57 import org.eclipse.core.runtime.Status;
|
|
58
|
|
59 /**
|
|
60 * Customizes a {@link Binding} between two
|
|
61 * {@link IObservableValue observable values}. The following behaviors can be
|
|
62 * customized via the strategy:
|
|
63 * <ul>
|
|
64 * <li>Validation</li>
|
|
65 * <li>Conversion</li>
|
|
66 * <li>Automatic processing</li>
|
|
67 * </ul>
|
|
68 * <p>
|
|
69 * The update phases are:
|
|
70 * <ol>
|
|
71 * <li>Validate after get - {@link #validateAfterGetcast(Object)}</li>
|
|
72 * <li>Conversion - {@link #convertcast(Object)}</li>
|
|
73 * <li>Validate after conversion - {@link #validateAfterConvertcast(Object)}</li>
|
|
74 * <li>Validate before set - {@link #validateBeforeSetcast(Object)}</li>
|
|
75 * <li>Value set - {@link #doSet(IObservableValue, Object)}</li>
|
|
76 * </ol>
|
|
77 * </p>
|
|
78 * <p>
|
|
79 * Validation:<br/> {@link IValidator Validators} validate the value at
|
|
80 * multiple phases in the update process. Statuses returned from validators are
|
|
81 * aggregated into a <code>MultiStatus</code> until a status of
|
|
82 * <code>ERROR</code> or <code>CANCEL</code> is encountered. Either of these
|
|
83 * statuses will abort the update process. These statuses are available as the
|
|
84 * {@link Binding#getValidationStatus() binding validation status}.
|
|
85 * </p>
|
|
86 * <p>
|
|
87 * Conversion:<br/> A {@link IConverter converter} will convert the value from
|
|
88 * the type of the source observable into the type of the destination. The
|
|
89 * strategy has the ability to default converters for common scenarios.
|
|
90 * </p>
|
|
91 * <p>
|
|
92 * Automatic processing:<br/> The processing to perform when the source
|
|
93 * observable changes. This behavior is configured via policies provided on
|
|
94 * construction of the strategy (e.g. {@link #POLICY_NEVER},
|
|
95 * {@link #POLICY_CONVERT}, {@link #POLICY_ON_REQUEST}, {@link #POLICY_UPDATE}).
|
|
96 * </p>
|
|
97 *
|
|
98 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
|
|
99 * UpdateValueStrategy, UpdateValueStrategy)
|
|
100 * @see Binding#getValidationStatus()
|
|
101 * @see IValidator
|
|
102 * @see IConverter
|
|
103 * @since 1.0
|
|
104 */
|
|
105 public class UpdateValueStrategy : UpdateStrategy {
|
|
106
|
|
107 /**
|
|
108 * Policy constant denoting that the source observable's state should not be
|
|
109 * tracked and that the destination observable's value should never be
|
|
110 * updated.
|
|
111 */
|
|
112 public static int POLICY_NEVER = notInlined(1);
|
|
113
|
|
114 /**
|
|
115 * Policy constant denoting that the source observable's state should not be
|
|
116 * tracked, but that validation, conversion and updating the destination
|
|
117 * observable's value should be performed when explicitly requested.
|
|
118 */
|
|
119 public static int POLICY_ON_REQUEST = notInlined(2);
|
|
120
|
|
121 /**
|
|
122 * Policy constant denoting that the source observable's state should be
|
|
123 * tracked, including validating changes except for
|
|
124 * {@link #validateBeforeSetcast(Object)}, but that the destination
|
|
125 * observable's value should only be updated on request.
|
|
126 */
|
|
127 public static int POLICY_CONVERT = notInlined(4);
|
|
128
|
|
129 /**
|
|
130 * Policy constant denoting that the source observable's state should be
|
|
131 * tracked, and that validation, conversion and updating the destination
|
|
132 * observable's value should be performed automaticlly on every change of
|
|
133 * the source observable value.
|
|
134 */
|
|
135 public static int POLICY_UPDATE = notInlined(8);
|
|
136
|
|
137 /**
|
|
138 * Helper method allowing API evolution of the above constant values. The
|
|
139 * compiler will not inline constant values into client code if values are
|
|
140 * "computed" using this helper.
|
|
141 *
|
|
142 * @param i
|
|
143 * an integer
|
|
144 * @return the same integer
|
|
145 */
|
|
146 private static int notInlined(int i) {
|
|
147 return i;
|
|
148 }
|
|
149
|
|
150 protected IValidator afterGetValidator;
|
|
151 protected IValidator afterConvertValidator;
|
|
152 protected IValidator beforeSetValidator;
|
|
153 protected IConverter converter;
|
|
154
|
|
155 private int updatePolicy;
|
|
156
|
|
157 private static ValidatorRegistry validatorRegistry = new ValidatorRegistry();
|
|
158 private static HashMap validatorsByConverter = new HashMap();
|
|
159
|
|
160 protected bool provideDefaults;
|
|
161
|
|
162 /**
|
|
163 * <code>true</code> if we defaulted the converter
|
|
164 */
|
|
165 private bool defaultedConverter = false;
|
|
166
|
|
167 /**
|
|
168 * Creates a new update value strategy for automatically updating the
|
|
169 * destination observable value whenever the source observable value
|
|
170 * changes. Default validators and a default converter will be provided. The
|
|
171 * defaults can be changed by calling one of the setter methods.
|
|
172 */
|
|
173 public this() {
|
|
174 this(true, POLICY_UPDATE);
|
|
175 }
|
|
176
|
|
177 /**
|
|
178 * Creates a new update value strategy with a configurable update policy.
|
|
179 * Default validators and a default converter will be provided. The defaults
|
|
180 * can be changed by calling one of the setter methods.
|
|
181 *
|
|
182 * @param updatePolicy
|
|
183 * one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST},
|
|
184 * {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE}
|
|
185 */
|
|
186 public this(int updatePolicy) {
|
|
187 this(true, updatePolicy);
|
|
188 }
|
|
189
|
|
190 /**
|
|
191 * Creates a new update value strategy with a configurable update policy.
|
|
192 * Default validators and a default converter will be provided if
|
|
193 * <code>provideDefaults</code> is <code>true</code>. The defaults can
|
|
194 * be changed by calling one of the setter methods.
|
|
195 *
|
|
196 * @param provideDefaults
|
|
197 * if <code>true</code>, default validators and a default
|
|
198 * converter will be provided based on the observable value's
|
|
199 * type.
|
|
200 * @param updatePolicy
|
|
201 * one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST},
|
|
202 * {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE}
|
|
203 */
|
|
204 public this(bool provideDefaults, int updatePolicy) {
|
|
205 this.provideDefaults = provideDefaults;
|
|
206 this.updatePolicy = updatePolicy;
|
|
207 }
|
|
208
|
|
209 /**
|
|
210 * Converts the value from the source type to the destination type.
|
|
211 * <p>
|
|
212 * Default implementation will use the
|
|
213 * {@link #setConvertercast(IConverter) converter} if one exists. If no
|
|
214 * converter exists no conversion occurs.
|
|
215 * </p>
|
|
216 *
|
|
217 * @param value
|
|
218 * @return the converted value
|
|
219 */
|
|
220 public Object convert(Object value) {
|
|
221 return converter is null ? value : converter.convert(value);
|
|
222 }
|
|
223
|
|
224 /**
|
|
225 * Tries to create a validator that can validate values of type fromType.
|
|
226 * Returns <code>null</code> if no validator could be created. Either
|
|
227 * toType or modelDescription can be <code>null</code>, but not both.
|
|
228 *
|
|
229 * @param fromType
|
|
230 * @param toType
|
|
231 * @return an IValidator, or <code>null</code> if unsuccessful
|
|
232 */
|
|
233 protected IValidator createValidator(Object fromType, Object toType) {
|
|
234 if (fromType is null || toType is null) {
|
|
235 return new class() IValidator {
|
|
236
|
|
237 public IStatus validate(Object value) {
|
|
238 return Status.OK_STATUS;
|
|
239 }
|
|
240 };
|
|
241 }
|
|
242
|
|
243 return findValidator(fromType, toType);
|
|
244 }
|
|
245
|
|
246 /**
|
|
247 * Fills out default values based upon the provided <code>source</code>
|
|
248 * and <code>destination</code>. If the strategy is to default values it
|
|
249 * will attempt to default a converter. If the converter can be defaulted an
|
|
250 * attempt is made to default the
|
|
251 * {@link #validateAfterGetcast(Object) after get validator}. If a validator
|
|
252 * cannot be defaulted it will be <code>null</code>.
|
|
253 *
|
|
254 * @param source
|
|
255 * @param destination
|
|
256 */
|
|
257 protected void fillDefaults(IObservableValue source,
|
|
258 IObservableValue destination) {
|
|
259 Object sourceType = source.getValueType();
|
|
260 Object destinationType = destination.getValueType();
|
|
261 if (provideDefaults && sourceType !is null && destinationType !is null) {
|
|
262 if (converter is null) {
|
|
263 IConverter converter = createConverter(sourceType,
|
|
264 destinationType);
|
|
265 defaultedConverter = (converter !is null);
|
|
266 setConverter(converter);
|
|
267 }
|
|
268
|
|
269 if (afterGetValidator is null) {
|
|
270 afterGetValidator = createValidator(sourceType, destinationType);
|
|
271 }
|
|
272 }
|
|
273 if (converter !is null) {
|
|
274 if (sourceType !is null) {
|
|
275 checkAssignable(converter.getFromType(), sourceType,
|
|
276 "converter does not convert from type " + sourceType); //$NON-NLS-1$
|
|
277 }
|
|
278 if (destinationType !is null) {
|
|
279 checkAssignable(converter.getToType(), destinationType,
|
|
280 "converter does not convert to type " + destinationType); //$NON-NLS-1$
|
|
281 }
|
|
282 }
|
|
283 }
|
|
284
|
|
285 private IValidator findValidator(Object fromType, Object toType) {
|
|
286 IValidator result = null;
|
|
287
|
|
288 // We only default the validator if we defaulted the converter since the
|
|
289 // two are tightly coupled.
|
|
290 if (defaultedConverter) {
|
|
291 if (String.classinfo.equals(fromType)) {
|
|
292 result = cast(IValidator) validatorsByConverter.get(converter);
|
|
293
|
|
294 if (result is null) {
|
|
295 // TODO sring based lookup
|
|
296 if (Integer.classinfo.equals(toType)
|
|
297 || Integer.TYPE.equals(toType)) {
|
|
298 result = new StringToIntegerValidator(
|
|
299 cast(NumberFormatConverter) converter);
|
|
300 } else if (Long.classinfo.equals(toType)
|
|
301 || Long.TYPE.equals(toType)) {
|
|
302 result = new StringToLongValidator(
|
|
303 cast(NumberFormatConverter) converter);
|
|
304 } else if (Float.classinfo.equals(toType)
|
|
305 || Float.TYPE.equals(toType)) {
|
|
306 result = new StringToFloatValidator(
|
|
307 cast(NumberFormatConverter) converter);
|
|
308 } else if (Double.classinfo.equals(toType)
|
|
309 || Double.TYPE.equals(toType)) {
|
|
310 result = new StringToDoubleValidator(
|
|
311 cast(NumberFormatConverter) converter);
|
|
312 } else if (Byte.classinfo.equals(toType)
|
|
313 || Byte.TYPE.equals(toType)) {
|
|
314 result = new StringToByteValidator(
|
|
315 cast(NumberFormatConverter) converter);
|
|
316 } else if (Short.classinfo.equals(toType)
|
|
317 || Short.TYPE.equals(toType)) {
|
|
318 result = new StringToShortValidator(
|
|
319 cast(NumberFormatConverter) converter);
|
|
320 } else if (Character.classinfo.equals(toType)
|
|
321 || Character.TYPE.equals(toType)
|
|
322 && null !is cast(StringToCharacterConverter)converter ) {
|
|
323 result = new StringToCharacterValidator(
|
|
324 cast(StringToCharacterConverter) converter);
|
|
325 } else if (Date.classinfo.equals(toType)
|
|
326 && null !is cast(StringToDateConverter)converter ) {
|
|
327 result = new StringToDateValidator(
|
|
328 cast(StringToDateConverter) converter);
|
|
329 }
|
|
330
|
|
331 if (result !is null) {
|
|
332 validatorsByConverter.put(converter, result);
|
|
333 }
|
|
334 }
|
|
335 } else if ( null !is cast(NumberToNumberConverter)converter ) {
|
|
336 result = cast(IValidator) validatorsByConverter.get(converter);
|
|
337
|
|
338 if (result is null) {
|
|
339 if ( null !is cast(NumberToByteConverter)converter ) {
|
|
340 result = new NumberToByteValidator(
|
|
341 cast(NumberToByteConverter) converter);
|
|
342 } else if ( null !is cast(NumberToShortConverter)converter ) {
|
|
343 result = new NumberToShortValidator(
|
|
344 cast(NumberToShortConverter) converter);
|
|
345 } else if ( null !is cast(NumberToIntegerConverter)converter ) {
|
|
346 result = new NumberToIntegerValidator(
|
|
347 cast(NumberToIntegerConverter) converter);
|
|
348 } else if ( null !is cast(NumberToLongConverter)converter ) {
|
|
349 result = new NumberToLongValidator(
|
|
350 cast(NumberToLongConverter) converter);
|
|
351 } else if ( null !is cast(NumberToFloatConverter)converter ) {
|
|
352 result = new NumberToFloatValidator(
|
|
353 cast(NumberToFloatConverter) converter);
|
|
354 } else if ( null !is cast(NumberToDoubleConverter)converter ) {
|
|
355 result = new NumberToDoubleValidator(
|
|
356 cast(NumberToDoubleConverter) converter);
|
|
357 } else if ( null !is cast(NumberToBigIntegerConverter)converter
|
|
358 || null !is cast(NumberToBigDecimalConverter)converter ) {
|
|
359 result = new NumberToUnboundedNumberValidator(
|
|
360 cast(NumberToNumberConverter) converter);
|
|
361 }
|
|
362 }
|
|
363 }
|
|
364
|
|
365 if (result is null) {
|
|
366 // TODO string based lookup
|
|
367 result = validatorRegistry.get(fromType, toType);
|
|
368 }
|
|
369 }
|
|
370
|
|
371 return result;
|
|
372 }
|
|
373
|
|
374 /**
|
|
375 * @return the update policy
|
|
376 */
|
|
377 public int getUpdatePolicy() {
|
|
378 return updatePolicy;
|
|
379 }
|
|
380
|
|
381 /**
|
|
382 * Sets the validator to be invoked after the source value is converted to
|
|
383 * the type of the destination observable.
|
|
384 *
|
|
385 * @param validator
|
|
386 * @return the receiver, to enable method call chaining
|
|
387 */
|
|
388 public UpdateValueStrategy setAfterConvertValidator(IValidator validator) {
|
|
389 this.afterConvertValidator = validator;
|
|
390 return this;
|
|
391 }
|
|
392
|
|
393 /**
|
|
394 * Sets the validator to be invoked after the source value is retrieved at
|
|
395 * the beginning of the synchronization process.
|
|
396 *
|
|
397 * @param validator
|
|
398 * @return the receiver, to enable method call chaining
|
|
399 */
|
|
400 public UpdateValueStrategy setAfterGetValidator(IValidator validator) {
|
|
401 this.afterGetValidator = validator;
|
|
402 return this;
|
|
403 }
|
|
404
|
|
405 /**
|
|
406 * Sets the validator to be invoked before the value is to be set on the
|
|
407 * destination at the end of the synchronization process.
|
|
408 *
|
|
409 * @param validator
|
|
410 * @return the receiver, to enable method call chaining
|
|
411 */
|
|
412 public UpdateValueStrategy setBeforeSetValidator(IValidator validator) {
|
|
413 this.beforeSetValidator = validator;
|
|
414 return this;
|
|
415 }
|
|
416
|
|
417 /**
|
|
418 * Sets the converter to be invoked when converting from the source type to
|
|
419 * the destination type.
|
|
420 *
|
|
421 * @param converter
|
|
422 * @return the receiver, to enable method call chaining
|
|
423 */
|
|
424 public UpdateValueStrategy setConverter(IConverter converter) {
|
|
425 this.converter = converter;
|
|
426 return this;
|
|
427 }
|
|
428
|
|
429 /**
|
|
430 * Validates the value after it is converted.
|
|
431 * <p>
|
|
432 * Default implementation will use the
|
|
433 * {@link #setAfterConvertValidatorcast(IValidator) validator} if one exists. If
|
|
434 * one does not exist no validation will occur.
|
|
435 * </p>
|
|
436 *
|
|
437 * @param value
|
|
438 * @return an ok status
|
|
439 */
|
|
440 public IStatus validateAfterConvert(Object value) {
|
|
441 return afterConvertValidator is null ? Status.OK_STATUS
|
|
442 : afterConvertValidator.validate(value);
|
|
443 }
|
|
444
|
|
445 /**
|
|
446 * Validates the value after it is retrieved from the source.
|
|
447 * <p>
|
|
448 * Default implementation will use the
|
|
449 * {@link #setAfterGetValidatorcast(IValidator) validator} if one exists. If one
|
|
450 * does not exist no validation will occur.
|
|
451 * </p>
|
|
452 *
|
|
453 * @param value
|
|
454 * @return an ok status
|
|
455 */
|
|
456 public IStatus validateAfterGet(Object value) {
|
|
457 return afterGetValidator is null ? Status.OK_STATUS : afterGetValidator
|
|
458 .validate(value);
|
|
459 }
|
|
460
|
|
461 /**
|
|
462 * Validates the value before it is set on the destination.
|
|
463 * <p>
|
|
464 * Default implementation will use the
|
|
465 * {@link #setBeforeSetValidatorcast(IValidator) validator} if one exists. If
|
|
466 * one does not exist no validation will occur.
|
|
467 * </p>
|
|
468 *
|
|
469 * @param value
|
|
470 * @return an ok status
|
|
471 */
|
|
472 public IStatus validateBeforeSet(Object value) {
|
|
473 return beforeSetValidator is null ? Status.OK_STATUS
|
|
474 : beforeSetValidator.validate(value);
|
|
475 }
|
|
476
|
|
477 /**
|
|
478 * Sets the current value of the given observable to the given value.
|
|
479 * Clients may extend but must call the super implementation.
|
|
480 *
|
|
481 * @param observableValue
|
|
482 * @param value
|
|
483 * @return status
|
|
484 */
|
|
485 protected IStatus doSet(IObservableValue observableValue, Object value) {
|
|
486 try {
|
|
487 observableValue.setValue(value);
|
|
488 } catch (Exception ex) {
|
|
489 return ValidationStatus.error(BindingMessages
|
|
490 .getStringcast(BindingMessages.VALUEBINDING_ERROR_WHILE_SETTING_VALUE),
|
|
491 ex);
|
|
492 }
|
|
493 return Status.OK_STATUS;
|
|
494 }
|
|
495
|
|
496 private static class ValidatorRegistry {
|
|
497
|
|
498 private HashMap validators = new HashMap();
|
|
499
|
|
500 /**
|
|
501 * Adds the system-provided validators to the current validator
|
|
502 * registry. This is done automatically for the validator registry
|
|
503 * singleton.
|
|
504 */
|
|
505 private this() {
|
|
506 // Standalone validators here...
|
|
507 associate(Integer.classinfo, Integer.TYPE,
|
|
508 new ObjectToPrimitiveValidatorcast(Integer.TYPE));
|
|
509 associate(Byte.classinfo, Byte.TYPE, new ObjectToPrimitiveValidator(
|
|
510 Byte.TYPE));
|
|
511 associate(Short.classinfo, Short.TYPE, new ObjectToPrimitiveValidator(
|
|
512 Short.TYPE));
|
|
513 associate(Long.classinfo, Long.TYPE, new ObjectToPrimitiveValidator(
|
|
514 Long.TYPE));
|
|
515 associate(Float.classinfo, Float.TYPE, new ObjectToPrimitiveValidator(
|
|
516 Float.TYPE));
|
|
517 associate(Double.classinfo, Double.TYPE,
|
|
518 new ObjectToPrimitiveValidatorcast(Double.TYPE));
|
|
519 associate(Boolean.classinfo, Boolean.TYPE,
|
|
520 new ObjectToPrimitiveValidatorcast(Boolean.TYPE));
|
|
521
|
|
522 associate(Object.classinfo, Integer.TYPE,
|
|
523 new ObjectToPrimitiveValidatorcast(Integer.TYPE));
|
|
524 associate(Object.classinfo, Byte.TYPE, new ObjectToPrimitiveValidator(
|
|
525 Byte.TYPE));
|
|
526 associate(Object.classinfo, Short.TYPE, new ObjectToPrimitiveValidator(
|
|
527 Short.TYPE));
|
|
528 associate(Object.classinfo, Long.TYPE, new ObjectToPrimitiveValidator(
|
|
529 Long.TYPE));
|
|
530 associate(Object.classinfo, Float.TYPE, new ObjectToPrimitiveValidator(
|
|
531 Float.TYPE));
|
|
532 associate(Object.classinfo, Double.TYPE,
|
|
533 new ObjectToPrimitiveValidatorcast(Double.TYPE));
|
|
534 associate(Object.classinfo, Boolean.TYPE,
|
|
535 new ObjectToPrimitiveValidatorcast(Boolean.TYPE));
|
|
536 }
|
|
537
|
|
538 /**
|
|
539 * Associate a particular validator that can validate the conversion
|
|
540 * (fromClass, toClass)
|
|
541 *
|
|
542 * @param fromClass
|
|
543 * The Class to convert from
|
|
544 * @param toClass
|
|
545 * The Class to convert to
|
|
546 * @param validator
|
|
547 * The IValidator
|
|
548 */
|
|
549 private void associate(Object fromClass, Object toClass,
|
|
550 IValidator validator) {
|
|
551 validators.put(new Pair(fromClass, toClass), validator);
|
|
552 }
|
|
553
|
|
554 /**
|
|
555 * Return an IValidator for a specific fromClass and toClass.
|
|
556 *
|
|
557 * @param fromClass
|
|
558 * The Class to convert from
|
|
559 * @param toClass
|
|
560 * The Class to convert to
|
|
561 * @return An appropriate IValidator
|
|
562 */
|
|
563 private IValidator get(Object fromClass, Object toClass) {
|
|
564 IValidator result = cast(IValidator) validators.get(new Pair(fromClass,
|
|
565 toClass));
|
|
566 if (result !is null)
|
|
567 return result;
|
|
568 if (fromClass !is null && toClass !is null && fromClass is toClass) {
|
|
569 return new class() IValidator {
|
|
570 public IStatus validate(Object value) {
|
|
571 return Status.OK_STATUS;
|
|
572 }
|
|
573 };
|
|
574 }
|
|
575 return new class() IValidator {
|
|
576 public IStatus validate(Object value) {
|
|
577 return Status.OK_STATUS;
|
|
578 }
|
|
579 };
|
|
580 }
|
|
581 }
|
|
582
|
|
583 }
|