View | Details | Raw Unified | Return to bug 183055 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/internal/databinding/conversion/StringToNumberParser.java (-4 / +21 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Ovidio Mallo - bug 183055
10
 *******************************************************************************/
11
 *******************************************************************************/
11
12
12
package org.eclipse.core.internal.databinding.conversion;
13
package org.eclipse.core.internal.databinding.conversion;
Lines 115-125 Link Here
115
				.getErrorIndex() : position.getIndex();
116
				.getErrorIndex() : position.getIndex();
116
117
117
		if (errorIndex < value.length()) {
118
		if (errorIndex < value.length()) {
118
			return BindingMessages.formatString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR,
119
			return BindingMessages.getFormattedString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR,
119
					new Object[] { value, new Integer(errorIndex + 1),
120
					new Object[] { value, new Integer(errorIndex + 1),
120
							new Character(value.charAt(errorIndex)) });
121
							new Character(value.charAt(errorIndex)) });
121
		}
122
		}
122
		return BindingMessages.formatString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER,
123
		return BindingMessages.getFormattedString(BindingMessages.VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER,
123
				new Object[] { value, new Integer(errorIndex + 1) });
124
				new Object[] { value, new Integer(errorIndex + 1) });
124
	}
125
	}
125
126
Lines 133-138 Link Here
133
	 */
134
	 */
134
	public static String createOutOfRangeMessage(Number minValue,
135
	public static String createOutOfRangeMessage(Number minValue,
135
			Number maxValue, NumberFormat numberFormat) {
136
			Number maxValue, NumberFormat numberFormat) {
137
		return createOutOfRangeMessage(
138
				BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_OUT_OF_RANGE_ERROR), minValue, maxValue, numberFormat);
139
	}
140
141
	/**
142
	 * Formats an appropriate message for an out of range error.
143
	 * 
144
	 * @param message
145
	 * @param minValue
146
	 * @param maxValue
147
	 * @param numberFormat
148
	 *            when accessed method synchronizes on instance
149
	 * @return message
150
	 */
151
	public static String createOutOfRangeMessage(String message,
152
			Number minValue, Number maxValue, NumberFormat numberFormat) {
136
		String min = null;
153
		String min = null;
137
		String max = null;
154
		String max = null;
138
155
Lines 141-148 Link Here
141
			max = numberFormat.format(maxValue);
158
			max = numberFormat.format(maxValue);
142
		}
159
		}
143
160
144
		return BindingMessages.formatString(
161
		return BindingMessages.formatMessage(message, new Object[] { min,
145
				"Validate_NumberOutOfRangeError", new Object[] { min, max }); //$NON-NLS-1$
162
				max });
146
	}
163
	}
147
164
148
	/**
165
	/**
(-)src/org/eclipse/core/internal/databinding/conversion/StringToBooleanPrimitiveConverter.java (-4 / +35 lines)
Lines 9-14 Link Here
9
 * Contributors:
9
 * Contributors:
10
 *     db4objects - Initial API and implementation
10
 *     db4objects - Initial API and implementation
11
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
11
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
12
 *     Ovidio Mallo - bug 183055
12
 */
13
 */
13
package org.eclipse.core.internal.databinding.conversion;
14
package org.eclipse.core.internal.databinding.conversion;
14
15
Lines 24-42 Link Here
24
 * StringToBooleanPrimitiveConverter.
25
 * StringToBooleanPrimitiveConverter.
25
 */
26
 */
26
public class StringToBooleanPrimitiveConverter implements IConverter {
27
public class StringToBooleanPrimitiveConverter implements IConverter {
27
	private static final String[] trueValues;
28
28
29
	private static final String[] falseValues;
29
	private static final String[] DEFAULT_TRUE_VALUES;
30
	private static final String[] DEFAULT_FALSE_VALUES;
30
31
31
	static {
32
	static {
32
		String delimiter = BindingMessages.getString(BindingMessages.VALUE_DELIMITER);
33
		String delimiter = BindingMessages.getString(BindingMessages.VALUE_DELIMITER);
33
		String values = BindingMessages.getString(BindingMessages.TRUE_STRING_VALUES);
34
		String values = BindingMessages.getString(BindingMessages.TRUE_STRING_VALUES);
34
		trueValues = valuesToSortedArray(delimiter, values);
35
		DEFAULT_TRUE_VALUES = valuesToSortedArray(delimiter, values);
35
36
36
		values = BindingMessages.getString(BindingMessages.FALSE_STRING_VALUES);
37
		values = BindingMessages.getString(BindingMessages.FALSE_STRING_VALUES);
37
		falseValues = valuesToSortedArray(delimiter, values);
38
		DEFAULT_FALSE_VALUES = valuesToSortedArray(delimiter, values);
38
	}
39
	}
39
40
41
	private String[] trueValues = DEFAULT_TRUE_VALUES;
42
	private String[] falseValues = DEFAULT_FALSE_VALUES;
43
40
	/**
44
	/**
41
	 * Returns a sorted array with all values converted to upper case.
45
	 * Returns a sorted array with all values converted to upper case.
42
	 *
46
	 *
Lines 57-62 Link Here
57
		return array;
61
		return array;
58
	}
62
	}
59
63
64
	/**
65
	 * Sets the string values which are considered to represent a
66
	 * <code>true</code> and <code>false</code> value, respectively.
67
	 * 
68
	 * <p>
69
	 * Note that the capitalization of the provided strings is ignored.
70
	 * </p>
71
	 * 
72
	 * @param trueValues
73
	 *            The set of strings representing a <code>true</code> value.
74
	 * @param falseValues
75
	 *            The set of strings representing a <code>false</code> value.
76
	 */
77
	public final void setSourceStrings(String[] trueValues, String[] falseValues) {
78
		this.trueValues = new String[trueValues.length];
79
		for (int i = 0; i < trueValues.length; i++) {
80
			this.trueValues[i] = trueValues[i].toUpperCase();
81
		}
82
		Arrays.sort(this.trueValues); // for binary search
83
84
		this.falseValues = new String[falseValues.length];
85
		for (int i = 0; i < falseValues.length; i++) {
86
			this.falseValues[i] = falseValues[i].toUpperCase();
87
		}
88
		Arrays.sort(this.falseValues); // for binary search
89
	}
90
60
	/*
91
	/*
61
	 * (non-Javadoc)
92
	 * (non-Javadoc)
62
	 *
93
	 *
(-)src/org/eclipse/core/internal/databinding/conversion/DateConversionSupport.java (+15 lines)
Lines 10-15 Link Here
10
 *     db4objects - Initial API and implementation
10
 *     db4objects - Initial API and implementation
11
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
11
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
12
 *     Matthew Hall - bug 121110
12
 *     Matthew Hall - bug 121110
13
 *     Ovidio Mallo - bug 183055
13
 ******************************************************************************/
14
 ******************************************************************************/
14
package org.eclipse.core.internal.databinding.conversion;
15
package org.eclipse.core.internal.databinding.conversion;
15
16
Lines 52-57 Link Here
52
	};
53
	};
53
54
54
	/**
55
	/**
56
	 * Sets the {@link DateFormat}s to be used for parsing/formatting dates. Any
57
	 * of the supplied formats will be used for {@link #parse(String) parsing} a
58
	 * date from a string while the first format in the array will be used for
59
	 * {@link #format(Date) formatting} a date as a string.
60
	 * 
61
	 * @param formatters
62
	 *            The {@link DateFormat}s to be used for parsing/formatting
63
	 *            dates.
64
	 */
65
	public final void setFormatters(DateFormat[] formatters) {
66
		this.formatters = formatters;
67
	}
68
69
	/**
55
	 * Tries all available formatters to parse the given string according to the
70
	 * Tries all available formatters to parse the given string according to the
56
	 * default locale or as a raw millisecond value and returns the result of the
71
	 * default locale or as a raw millisecond value and returns the result of the
57
	 * first successful run.
72
	 * first successful run.
(-).settings/org.eclipse.jdt.ui.prefs (-3 / +3 lines)
Lines 1-4 Link Here
1
#Tue Feb 10 16:05:48 MST 2009
1
#Thu Jan 07 19:10:54 CET 2010
2
cleanup.add_default_serial_version_id=true
2
cleanup.add_default_serial_version_id=true
3
cleanup.add_generated_serial_version_id=false
3
cleanup.add_generated_serial_version_id=false
4
cleanup.add_missing_annotations=true
4
cleanup.add_missing_annotations=true
Lines 51-57 Link Here
51
cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
51
cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
52
cleanup_settings_version=2
52
cleanup_settings_version=2
53
eclipse.preferences.version=1
53
eclipse.preferences.version=1
54
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
54
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false
55
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
55
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
56
formatter_settings_version=11
56
formatter_settings_version=11
57
org.eclipse.jdt.ui.exception.name=e
57
org.eclipse.jdt.ui.exception.name=e
Lines 78-84 Link Here
78
sp_cleanup.always_use_this_for_non_static_method_access=false
78
sp_cleanup.always_use_this_for_non_static_method_access=false
79
sp_cleanup.convert_to_enhanced_for_loop=false
79
sp_cleanup.convert_to_enhanced_for_loop=false
80
sp_cleanup.correct_indentation=false
80
sp_cleanup.correct_indentation=false
81
sp_cleanup.format_source_code=true
81
sp_cleanup.format_source_code=false
82
sp_cleanup.format_source_code_changes_only=false
82
sp_cleanup.format_source_code_changes_only=false
83
sp_cleanup.make_local_variable_final=false
83
sp_cleanup.make_local_variable_final=false
84
sp_cleanup.make_parameters_final=false
84
sp_cleanup.make_parameters_final=false
(-)src/org/eclipse/core/internal/databinding/validation/NumberToNumberValidator.java (-8 / +27 lines)
Lines 13-18 Link Here
13
13
14
import org.eclipse.core.databinding.validation.IValidator;
14
import org.eclipse.core.databinding.validation.IValidator;
15
import org.eclipse.core.databinding.validation.ValidationStatus;
15
import org.eclipse.core.databinding.validation.ValidationStatus;
16
import org.eclipse.core.internal.databinding.BindingMessages;
16
import org.eclipse.core.internal.databinding.conversion.NumberToNumberConverter;
17
import org.eclipse.core.internal.databinding.conversion.NumberToNumberConverter;
17
import org.eclipse.core.internal.databinding.conversion.StringToNumberParser;
18
import org.eclipse.core.internal.databinding.conversion.StringToNumberParser;
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.core.runtime.IStatus;
Lines 33-39 Link Here
33
34
34
	private final Number max;
35
	private final Number max;
35
36
36
	private String outOfRangeMessage;
37
	private String outOfRangeMessage = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_OUT_OF_RANGE_ERROR);
38
	private String formattedOutOfRangeMessage;
37
39
38
	private final boolean primitive;
40
	private final boolean primitive;
39
41
Lines 53-58 Link Here
53
		primitive = ((Class) converter.getToType()).isPrimitive();
55
		primitive = ((Class) converter.getToType()).isPrimitive();
54
	}
56
	}
55
57
58
	/**
59
	 * Sets the validation message pattern to be used in case the input number
60
	 * lies outside the value range supported by the target number type
61
	 * associated to this validator.
62
	 * 
63
	 * @param message
64
	 *            The validation message pattern to be used in case the input
65
	 *            number lies outside the supported value range supported by the
66
	 *            target number type. Can be parameterized with the <i>min</i>
67
	 *            and <i>max</i> value supported by the target number type.
68
	 */
69
	public final void setOutOfRangeMessage(String message) {
70
		this.outOfRangeMessage = message;
71
		this.formattedOutOfRangeMessage = null;
72
	}
73
56
	/*
74
	/*
57
	 * (non-Javadoc)
75
	 * (non-Javadoc)
58
	 * 
76
	 * 
Lines 78-92 Link Here
78
			return Status.OK_STATUS;
96
			return Status.OK_STATUS;
79
		}
97
		}
80
98
81
		synchronized (this) {
99
		return ValidationStatus.error(getFormattedOutOfRangeMessage());
82
			if (outOfRangeMessage == null && min != null && max != null) {
100
	}
83
				outOfRangeMessage = StringToNumberParser
84
						.createOutOfRangeMessage(min, max, converter
85
								.getNumberFormat());
86
			}
87
101
88
			return ValidationStatus.error(outOfRangeMessage);
102
	private synchronized String getFormattedOutOfRangeMessage() {
103
		if (formattedOutOfRangeMessage == null && min != null && max != null) {
104
			formattedOutOfRangeMessage = StringToNumberParser
105
					.createOutOfRangeMessage(outOfRangeMessage, min, max,
106
							converter.getNumberFormat());
89
		}
107
		}
108
		return formattedOutOfRangeMessage;
90
	}
109
	}
91
110
92
	/**
111
	/**
(-)src/org/eclipse/core/internal/databinding/validation/StringToCharacterValidator.java (-3 / +16 lines)
Lines 8-13 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Matt Carter - initial API and implementation
9
 *     Matt Carter - initial API and implementation
10
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
10
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
11
 *     Ovidio Mallo - bug 183055
11
 ******************************************************************************/
12
 ******************************************************************************/
12
13
13
package org.eclipse.core.internal.databinding.validation;
14
package org.eclipse.core.internal.databinding.validation;
Lines 26-31 Link Here
26
27
27
	private final StringToCharacterConverter converter;
28
	private final StringToCharacterConverter converter;
28
29
30
	private String parseErrorMessage = BindingMessages.getString(BindingMessages.VALIDATE_CHARACTER_HELP);
31
29
	/**
32
	/**
30
	 * @param converter
33
	 * @param converter
31
	 */
34
	 */
Lines 33-38 Link Here
33
		this.converter = converter;
36
		this.converter = converter;
34
	}
37
	}
35
38
39
	/**
40
	 * Sets the validation message to be used in case the source string does not
41
	 * represent a valid character.
42
	 * 
43
	 * @param message
44
	 *            The validation message to be used in case the source string
45
	 *            does not represent a valid character.
46
	 */
47
	public final void setParseErrorMessage(String message) {
48
		this.parseErrorMessage  = message;
49
	}
50
36
	/*
51
	/*
37
	 * (non-Javadoc)
52
	 * (non-Javadoc)
38
	 *
53
	 *
Lines 44-53 Link Here
44
		} catch (IllegalArgumentException e) {
59
		} catch (IllegalArgumentException e) {
45
			// The StringToCharacterConverter throws an IllegalArgumentException
60
			// The StringToCharacterConverter throws an IllegalArgumentException
46
			// if it cannot convert.
61
			// if it cannot convert.
47
			return ValidationStatus.error(BindingMessages
62
			return ValidationStatus.error(parseErrorMessage);
48
					.getString(BindingMessages.VALIDATE_CHARACTER_HELP));
49
		}
63
		}
50
		return Status.OK_STATUS;
64
		return Status.OK_STATUS;
51
	}
65
	}
52
53
}
66
}
(-)src/org/eclipse/core/internal/databinding/validation/StringToDateValidator.java (-8 / +24 lines)
Lines 8-13 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
10
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
11
 *     Ovidio Mallo - bug 183055
11
 *******************************************************************************/
12
 *******************************************************************************/
12
13
13
package org.eclipse.core.internal.databinding.validation;
14
package org.eclipse.core.internal.databinding.validation;
Lines 28-33 Link Here
28
public class StringToDateValidator implements IValidator {
29
public class StringToDateValidator implements IValidator {
29
	private final StringToDateConverter converter;
30
	private final StringToDateConverter converter;
30
31
32
	private String parseErrorMessage = null;
33
31
	/**
34
	/**
32
	 * @param converter
35
	 * @param converter
33
	 */
36
	 */
Lines 35-40 Link Here
35
		this.converter = converter;
38
		this.converter = converter;
36
	}
39
	}
37
40
41
	/**
42
	 * Sets the validation message to be used in case the source string does not
43
	 * represent a valid date.
44
	 * 
45
	 * @param message
46
	 *            The validation message to be used in case the source string
47
	 *            does not represent a valid date.
48
	 */
49
	public final void setParseErrorMessage(String message) {
50
		this.parseErrorMessage = message;
51
	}
52
38
	/*
53
	/*
39
	 * (non-Javadoc)
54
	 * (non-Javadoc)
40
	 *
55
	 *
Lines 47-64 Link Here
47
		Object convertedValue = converter.convert(value);
62
		Object convertedValue = converter.convert(value);
48
		//The StringToDateConverter returns null if it can't parse the date.
63
		//The StringToDateConverter returns null if it can't parse the date.
49
		if (convertedValue == null) {
64
		if (convertedValue == null) {
50
			return ValidationStatus.error(getErrorMessage());
65
			return ValidationStatus.error(getParseErrorMessage());
51
		}
66
		}
52
67
53
		return Status.OK_STATUS;
68
		return Status.OK_STATUS;
54
	}
69
	}
55
70
56
	/*
71
	private String getParseErrorMessage() {
57
	 * (non-Javadoc)
72
		if (parseErrorMessage != null) {
58
	 *
73
			return parseErrorMessage;
59
	 * @see org.eclipse.core.internal.databinding.validation.WrappedConverterValidator#getErrorMessage()
74
		}
60
	 */
75
61
	protected String getErrorMessage() {
62
		Date sampleDate = new Date();
76
		Date sampleDate = new Date();
63
77
64
		// FIXME We need to use the information from the
78
		// FIXME We need to use the information from the
Lines 73-79 Link Here
73
		samples.append('\'');
87
		samples.append('\'');
74
		samples.append(util.format(sampleDate, 0));
88
		samples.append(util.format(sampleDate, 0));
75
		samples.append('\'');
89
		samples.append('\'');
76
		return BindingMessages.getString(BindingMessages.EXAMPLES) + ": " + samples + ",..."; //$NON-NLS-1$//$NON-NLS-2$
90
		parseErrorMessage = BindingMessages.getString(BindingMessages.EXAMPLES) + ": " + samples + ",..."; //$NON-NLS-1$//$NON-NLS-2$
91
92
		return parseErrorMessage;
77
	}
93
	}
78
94
79
	private static class FormatUtil extends DateConversionSupport {
95
	private static class FormatUtil extends DateConversionSupport {
(-)src/org/eclipse/core/internal/databinding/validation/AbstractStringToNumberValidator.java (-9 / +56 lines)
Lines 7-18 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Ovidio Mallo - bug 183055
10
 ******************************************************************************/
11
 ******************************************************************************/
11
12
12
package org.eclipse.core.internal.databinding.validation;
13
package org.eclipse.core.internal.databinding.validation;
13
14
15
import java.text.ParsePosition;
16
14
import org.eclipse.core.databinding.validation.IValidator;
17
import org.eclipse.core.databinding.validation.IValidator;
15
import org.eclipse.core.databinding.validation.ValidationStatus;
18
import org.eclipse.core.databinding.validation.ValidationStatus;
19
import org.eclipse.core.internal.databinding.BindingMessages;
16
import org.eclipse.core.internal.databinding.conversion.StringToNumberParser;
20
import org.eclipse.core.internal.databinding.conversion.StringToNumberParser;
17
import org.eclipse.core.internal.databinding.conversion.StringToNumberParser.ParseResult;
21
import org.eclipse.core.internal.databinding.conversion.StringToNumberParser.ParseResult;
18
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.IStatus;
Lines 31-37 Link Here
31
	private final Number min;
35
	private final Number min;
32
	private final Number max;
36
	private final Number max;
33
37
34
	private String outOfRangeMessage;
38
	private String parseErrorMessage;
39
40
	private String outOfRangeMessage = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_OUT_OF_RANGE_ERROR);
41
	private String formattedOutOfRangeMessage;
35
42
36
	/**
43
	/**
37
	 * Constructs a new instance.
44
	 * Constructs a new instance.
Lines 55-60 Link Here
55
	}
62
	}
56
63
57
	/**
64
	/**
65
	 * Sets the validation message pattern to be used in case the source string
66
	 * does not represent a valid number.
67
	 * 
68
	 * @param message
69
	 *            The validation message pattern to be used in case the source
70
	 *            string does not represent a valid number.
71
	 */
72
	public final void setParseErrorMessage(String message) {
73
		this.parseErrorMessage = message;
74
	}
75
76
	/**
77
	 * Sets the validation message pattern to be used in case the parsed number
78
	 * lies outside the value range supported by the number type associated to
79
	 * this validator.
80
	 * 
81
	 * @param message
82
	 *            The validation message pattern to be used in case the parsed
83
	 *            number lies outside the supported value range. Can be
84
	 *            parameterized by the <code>Integer.MIN_VALUE</code> and
85
	 *            <code>Integer.MAX_VALUE</code> values.
86
	 */
87
	public final void setOutOfRangeMessage(String message) {
88
		this.outOfRangeMessage = message;
89
		this.formattedOutOfRangeMessage = null;
90
	}
91
92
	/**
58
	 * Validates the provided <code>value</code>.  An error status is returned if:
93
	 * Validates the provided <code>value</code>.  An error status is returned if:
59
	 * <ul>
94
	 * <ul>
60
	 * <li>The value cannot be parsed.</li>
95
	 * <li>The value cannot be parsed.</li>
Lines 69-84 Link Here
69
104
70
		if (result.getNumber() != null) {
105
		if (result.getNumber() != null) {
71
			if (!isInRange(result.getNumber())) {
106
			if (!isInRange(result.getNumber())) {
72
				if (outOfRangeMessage == null) {
107
				return ValidationStatus.error(getFormattedOutOfRangeMessage());
73
					outOfRangeMessage = StringToNumberParser
74
							.createOutOfRangeMessage(min, max, converter
75
									.getNumberFormat());
76
				}
77
78
				return ValidationStatus.error(outOfRangeMessage);
79
			}
108
			}
80
		} else if (result.getPosition() != null) {
109
		} else if (result.getPosition() != null) {
81
			String parseErrorMessage = StringToNumberParser.createParseErrorMessage(
110
			String parseErrorMessage = createParseErrorMessage(
82
					(String) value, result.getPosition());
111
					(String) value, result.getPosition());
83
112
84
			return ValidationStatus.error(parseErrorMessage);
113
			return ValidationStatus.error(parseErrorMessage);
Lines 94-97 Link Here
94
	 * @return <code>true</code> if in range
123
	 * @return <code>true</code> if in range
95
	 */
124
	 */
96
	protected abstract boolean isInRange(Number number);
125
	protected abstract boolean isInRange(Number number);
126
127
	private String createParseErrorMessage(String input,
128
			ParsePosition parsePosition) {
129
		if (parseErrorMessage == null) {
130
			return StringToNumberParser.createParseErrorMessage(input,
131
					parsePosition);
132
		}
133
		return parseErrorMessage;
134
	}
135
136
	private String getFormattedOutOfRangeMessage() {
137
		if (formattedOutOfRangeMessage == null) {
138
			formattedOutOfRangeMessage = StringToNumberParser
139
					.createOutOfRangeMessage(outOfRangeMessage, min, max,
140
							converter.getNumberFormat());
141
		}
142
		return formattedOutOfRangeMessage;
143
	}
97
}
144
}
(-)src/org/eclipse/core/databinding/UpdateStrategy.java (-2 / +3 lines)
Lines 9-14 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matt Carter - bug 180392
10
 *     Matt Carter - bug 180392
11
 *                 - bug 197679 (Character support completed)
11
 *                 - bug 197679 (Character support completed)
12
 *     Ovidio Mallo - bug 183055
12
 *******************************************************************************/
13
 *******************************************************************************/
13
14
14
package org.eclipse.core.databinding;
15
package org.eclipse.core.databinding;
Lines 24-29 Link Here
24
import org.eclipse.core.databinding.util.Policy;
25
import org.eclipse.core.databinding.util.Policy;
25
import org.eclipse.core.internal.databinding.ClassLookupSupport;
26
import org.eclipse.core.internal.databinding.ClassLookupSupport;
26
import org.eclipse.core.internal.databinding.Pair;
27
import org.eclipse.core.internal.databinding.Pair;
28
import org.eclipse.core.internal.databinding.conversion.BooleanToStringConverter;
27
import org.eclipse.core.internal.databinding.conversion.CharacterToStringConverter;
29
import org.eclipse.core.internal.databinding.conversion.CharacterToStringConverter;
28
import org.eclipse.core.internal.databinding.conversion.IdentityConverter;
30
import org.eclipse.core.internal.databinding.conversion.IdentityConverter;
29
import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter;
31
import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter;
Lines 35-41 Link Here
35
import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
37
import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
36
import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
38
import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
37
import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
39
import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
38
import org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter;
39
import org.eclipse.core.internal.databinding.conversion.StringToByteConverter;
40
import org.eclipse.core.internal.databinding.conversion.StringToByteConverter;
40
import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter;
41
import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter;
41
import org.eclipse.core.internal.databinding.conversion.StringToShortConverter;
42
import org.eclipse.core.internal.databinding.conversion.StringToShortConverter;
Lines 307-313 Link Here
307
							new Pair(BOOLEAN_CLASS, "java.lang.Boolean"), new IdentityConverter(Boolean.class, Boolean.class)); //$NON-NLS-1$
308
							new Pair(BOOLEAN_CLASS, "java.lang.Boolean"), new IdentityConverter(Boolean.class, Boolean.class)); //$NON-NLS-1$
308
			converterMap
309
			converterMap
309
					.put(
310
					.put(
310
							new Pair(BOOLEAN_CLASS, "java.lang.String"), new ObjectToStringConverter(Boolean.class)); //$NON-NLS-1$
311
							new Pair(BOOLEAN_CLASS, "java.lang.String"), new BooleanToStringConverter(Boolean.class)); //$NON-NLS-1$
311
			converterMap
312
			converterMap
312
					.put(
313
					.put(
313
							new Pair(BOOLEAN_CLASS, "java.lang.Object"), new IdentityConverter(Boolean.class, Object.class)); //$NON-NLS-1$
314
							new Pair(BOOLEAN_CLASS, "java.lang.Object"), new IdentityConverter(Boolean.class, Object.class)); //$NON-NLS-1$
(-)META-INF/MANIFEST.MF (+2 lines)
Lines 8-14 Link Here
8
Bundle-Localization: plugin
8
Bundle-Localization: plugin
9
Export-Package: org.eclipse.core.databinding,
9
Export-Package: org.eclipse.core.databinding,
10
 org.eclipse.core.databinding.conversion;x-internal:=false,
10
 org.eclipse.core.databinding.conversion;x-internal:=false,
11
 org.eclipse.core.databinding.editing,
11
 org.eclipse.core.databinding.validation;x-internal:=false,
12
 org.eclipse.core.databinding.validation;x-internal:=false,
13
 org.eclipse.core.databinding.validation.constraint,
12
 org.eclipse.core.internal.databinding;x-friends:="org.eclipse.core.databinding.beans",
14
 org.eclipse.core.internal.databinding;x-friends:="org.eclipse.core.databinding.beans",
13
 org.eclipse.core.internal.databinding.conversion;x-friends:="org.eclipse.jface.tests.databinding",
15
 org.eclipse.core.internal.databinding.conversion;x-friends:="org.eclipse.jface.tests.databinding",
14
 org.eclipse.core.internal.databinding.validation;x-friends:="org.eclipse.jface.tests.databinding"
16
 org.eclipse.core.internal.databinding.validation;x-friends:="org.eclipse.jface.tests.databinding"
(-)src/org/eclipse/core/internal/databinding/BindingMessages.java (-4 / +141 lines)
Lines 8-13 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
10
 *     Tom Schindl<tom.schindl@bestsolution.at> - bugfix for 217940
11
 *     Ovidio Mallo - bug 183055
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.core.internal.databinding;
13
package org.eclipse.core.internal.databinding;
13
14
Lines 69-74 Link Here
69
	public static final String FALSE_STRING_VALUES = "FalseStringValues"; //$NON-NLS-1$
70
	public static final String FALSE_STRING_VALUES = "FalseStringValues"; //$NON-NLS-1$
70
71
71
	/**
72
	/**
73
	 * Key to be used for a "Validate_InvalidBooleanString" message
74
	 */
75
	public static final String VALIDATE_INVALID_BOOLEAN_STRING = "Validate_InvalidBooleanString"; //$NON-NLS-1$
76
77
	/**
72
	 * Key to be used for a "Validate_NumberOutOfRangeError" message
78
	 * Key to be used for a "Validate_NumberOutOfRangeError" message
73
	 */
79
	 */
74
	public static final String VALIDATE_NUMBER_OUT_OF_RANGE_ERROR = "Validate_NumberOutOfRangeError"; //$NON-NLS-1$
80
	public static final String VALIDATE_NUMBER_OUT_OF_RANGE_ERROR = "Validate_NumberOutOfRangeError"; //$NON-NLS-1$
Lines 99-104 Link Here
99
	public static final String VALIDATE_CHARACTER_HELP = "Validate_CharacterHelp"; //$NON-NLS-1$
105
	public static final String VALIDATE_CHARACTER_HELP = "Validate_CharacterHelp"; //$NON-NLS-1$
100
106
101
	/**
107
	/**
108
	 * Key to be used for a "Validate_CharacterNoWhitespace" message
109
	 */
110
	public static final String VALIDATE_CHARACTER_NO_WHITESPACE = "Validate_CharacterNoWhitespace"; //$NON-NLS-1$
111
112
	/**
113
	 * Key to be used for a "Validate_CharacterNoSpace" message
114
	 */
115
	public static final String VALIDATE_CHARACTER_NO_SPACE = "Validate_CharacterNoSpace"; //$NON-NLS-1$
116
117
	/**
118
	 * Key to be used for a "Validate_CharacterLetter" message
119
	 */
120
	public static final String VALIDATE_CHARACTER_LETTER = "Validate_CharacterLetter"; //$NON-NLS-1$
121
122
	/**
123
	 * Key to be used for a "Validate_CharacterDigit" message
124
	 */
125
	public static final String VALIDATE_CHARACTER_DIGIT = "Validate_CharacterDigit"; //$NON-NLS-1$
126
127
	/**
128
	 * Key to be used for a "Validate_CharacterLetterOrDigit" message
129
	 */
130
	public static final String VALIDATE_CHARACTER_LETTER_OR_DIGIT = "Validate_CharacterLetterOrDigit"; //$NON-NLS-1$
131
132
	/**
102
	 * Key to be used for a "Examples" message
133
	 * Key to be used for a "Examples" message
103
	 */
134
	 */
104
	public static final String EXAMPLES = "Examples"; //$NON-NLS-1$
135
	public static final String EXAMPLES = "Examples"; //$NON-NLS-1$
Lines 109-118 Link Here
109
	public static final String VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER = "Validate_NumberParseErrorNoCharacter"; //$NON-NLS-1$
140
	public static final String VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER = "Validate_NumberParseErrorNoCharacter"; //$NON-NLS-1$
110
141
111
	/**
142
	/**
143
	 * Key to be used for a "Validate_NonNull" message
144
	 */
145
	public static final String VALIDATE_NON_NULL = "Validate_NonNull"; //$NON-NLS-1$
146
147
	/**
148
	 * Key to be used for a "Validate_NonEmptyString" message
149
	 */
150
	public static final String VALIDATE_NON_EMPTY_STRING = "Validate_NonEmptyString"; //$NON-NLS-1$
151
152
	/**
153
	 * Key to be used for a "Validate_NonStringRegex" message
154
	 */
155
	public static final String VALIDATE_STRING_REGEX = "Validate_NonStringRegex"; //$NON-NLS-1$
156
157
	/**
158
	 * Key to be used for a "Validate_NumberRangeGreater" message
159
	 */
160
	public static final String VALIDATE_NUMBER_RANGE_GREATER = "Validate_NumberRangeGreater"; //$NON-NLS-1$
161
162
	/**
163
	 * Key to be used for a "Validate_NumberRangeGreaterEqual" message
164
	 */
165
	public static final String VALIDATE_NUMBER_RANGE_GREATER_EQUAL = "Validate_NumberRangeGreaterEqual"; //$NON-NLS-1$
166
167
	/**
168
	 * Key to be used for a "Validate_NumberRangeLess" message
169
	 */
170
	public static final String VALIDATE_NUMBER_RANGE_LESS = "Validate_NumberRangeLess"; //$NON-NLS-1$
171
172
	/**
173
	 * Key to be used for a "Validate_NumberRangeLessEqual" message
174
	 */
175
	public static final String VALIDATE_NUMBER_RANGE_LESS_EQUAL = "Validate_NumberRangeLessEqual"; //$NON-NLS-1$
176
177
	/**
178
	 * Key to be used for a "Validate_NumberRangeWithinRange" message
179
	 */
180
	public static final String VALIDATE_NUMBER_RANGE_WITHIN_RANGE = "Validate_NumberRangeWithinRange"; //$NON-NLS-1$
181
182
	/**
183
	 * Key to be used for a "Validate_NumberRangePositive" message
184
	 */
185
	public static final String VALIDATE_NUMBER_RANGE_POSITIVE = "Validate_NumberRangePositive"; //$NON-NLS-1$
186
187
	/**
188
	 * Key to be used for a "Validate_NumberRangeNonNegative" message
189
	 */
190
	public static final String VALIDATE_NUMBER_RANGE_NON_NEGATIVE = "Validate_NumberRangeNonNegative"; //$NON-NLS-1$
191
192
	/**
193
	 * Key to be used for a "Validate_DateRangeAfter" message
194
	 */
195
	public static final String VALIDATE_DATE_RANGE_AFTER = "Validate_DateRangeAfter"; //$NON-NLS-1$
196
197
	/**
198
	 * Key to be used for a "Validate_DateRangeAfterEqual" message
199
	 */
200
	public static final String VALIDATE_DATE_RANGE_AFTER_EQUAL = "Validate_DateRangeAfterEqual"; //$NON-NLS-1$
201
202
	/**
203
	 * Key to be used for a "Validate_DateRangeBefore" message
204
	 */
205
	public static final String VALIDATE_DATE_RANGE_BEFORE = "Validate_DateRangeBefore"; //$NON-NLS-1$
206
207
	/**
208
	 * Key to be used for a "Validate_DateRangeBeforeEqual" message
209
	 */
210
	public static final String VALIDATE_DATE_RANGE_BEFORE_EQUAL = "Validate_DateRangeBeforeEqual"; //$NON-NLS-1$
211
212
	/**
213
	 * Key to be used for a "Validate_DateRangeWithinRange" message
214
	 */
215
	public static final String VALIDATE_DATE_RANGE_WITHIN_RANGE = "Validate_DateRangeWithinRange"; //$NON-NLS-1$
216
217
	/**
218
	 * Key to be used for a "Validate_StringLengthMin" message
219
	 */
220
	public static final String VALIDATE_STRING_LENGTH_MIN = "Validate_StringLengthMin"; //$NON-NLS-1$
221
222
	/**
223
	 * Key to be used for a "Validate_StringLengthMax" message
224
	 */
225
	public static final String VALIDATE_STRING_LENGTH_MAX = "Validate_StringLengthMax"; //$NON-NLS-1$
226
227
	/**
228
	 * Key to be used for a "Validate_StringLengthRange" message
229
	 */
230
	public static final String VALIDATE_STRING_LENGTH_RANGE = "Validate_StringLengthRange"; //$NON-NLS-1$
231
232
	/**
233
	 * Key to be used for a "Validate_DecimalMaxScale" message
234
	 */
235
	public static final String VALIDATE_DECIMAL_MAX_SCALE = "Validate_DecimalMaxScale"; //$NON-NLS-1$
236
237
	/**
112
	 * Returns the resource object with the given key in the resource bundle for
238
	 * Returns the resource object with the given key in the resource bundle for
113
	 * JFace Data Binding. If there isn't any value under the given key, the key
239
	 * JFace Data Binding. If there isn't any value under the given key, the key
114
	 * is returned.
240
	 * is returned.
115
	 *
241
	 * 
116
	 * @param key
242
	 * @param key
117
	 *            the resource name
243
	 *            the resource name
118
	 * @return the string
244
	 * @return the string
Lines 128-143 Link Here
128
	/**
254
	/**
129
	 * Returns a formatted string with the given key in the resource bundle for
255
	 * Returns a formatted string with the given key in the resource bundle for
130
	 * JFace Data Binding.
256
	 * JFace Data Binding.
131
	 *
257
	 * 
132
	 * @param key
258
	 * @param key
133
	 * @param arguments
259
	 * @param arguments
134
	 * @return formatted string, the key if the key is invalid
260
	 * @return formatted string, the key if the key is invalid
135
	 */
261
	 */
136
	public static String formatString(String key, Object[] arguments) {
262
	public static String getFormattedString(String key, Object[] arguments) {
137
		try {
263
		try {
138
			return MessageFormat.format(bundle.getString(key), arguments);
264
			return formatMessage(getString(key), arguments);
139
		} catch (MissingResourceException e) {
265
		} catch (MissingResourceException e) {
140
			return key;
266
			return key;
141
		}
267
		}
142
	}
268
	}
269
270
	/**
271
	 * Formats the given message pattern with the provided arguments.
272
	 * 
273
	 * @param pattern
274
	 * @param arguments
275
	 * @return formatted string
276
	 */
277
	public static String formatMessage(String pattern, Object[] arguments) {
278
		return MessageFormat.format(pattern, arguments);
279
	}
143
}
280
}
(-)src/org/eclipse/core/internal/databinding/messages.properties (+42 lines)
Lines 43-48 Link Here
43
TrueStringValues=yes,true
43
TrueStringValues=yes,true
44
FalseStringValues=no,false
44
FalseStringValues=no,false
45
45
46
Validate_InvalidBooleanString=The boolean string is invalid.
47
46
Validate_NumberOutOfRangeError=Please enter a value between [{0}] and [{1}] and with a similar format.
48
Validate_NumberOutOfRangeError=Please enter a value between [{0}] and [{1}] and with a similar format.
47
Validate_NumberParseError=Invalid character for value [{0}] at position [{1}] character [{2}].
49
Validate_NumberParseError=Invalid character for value [{0}] at position [{1}] character [{2}].
48
Validate_NumberParseErrorNoCharacter=Missing character for value [{0}] at position [{1}].
50
Validate_NumberParseErrorNoCharacter=Missing character for value [{0}] at position [{1}].
Lines 53-56 Link Here
53
Validate_NoChangeAllowedHelp=Changes are not allowed in this field
55
Validate_NoChangeAllowedHelp=Changes are not allowed in this field
54
Validate_CharacterHelp=Please type a character
56
Validate_CharacterHelp=Please type a character
55
57
58
#CharacterValidator
59
Validate_CharacterNoWhitespace=The character must be no whitespace.
60
Validate_CharacterNoSpace=The character must be no space.
61
Validate_CharacterLetter=The character must be a letter.
62
Validate_CharacterDigit=The character must be a digit.
63
Validate_CharacterLetterOrDigit=The character must be a letter or digit.
64
65
#NonNullValidator
66
Validate_NonNull=The value must not be empty.
67
68
#NonEmptyStringValidator
69
Validate_NonEmptyString=The string must not be empty.
70
71
#StringRegexValidator
72
Validate_NonStringRegex=The string must match the following pattern: {0}.
73
74
#NumberRangeValidator
75
Validate_NumberRangeGreater=The value must be greater than {0}.
76
Validate_NumberRangeGreaterEqual=The value must be greater than or equal to {0}.
77
Validate_NumberRangeLess=The value must be less than {0}.
78
Validate_NumberRangeLessEqual=The value must be less than or equal to {0}.
79
Validate_NumberRangeWithinRange=The value must lie between {0} and {1}.
80
Validate_NumberRangePositive=The value must be positive.
81
Validate_NumberRangeNonNegative=The value must not be negative.
82
83
#DateRangeValidator
84
Validate_DateRangeAfter=The date must be after {0}.
85
Validate_DateRangeAfterEqual=The date must be after or on {0}.
86
Validate_DateRangeBefore=The date must be before {0}.
87
Validate_DateRangeBeforeEqual=The date must be before or on {0}.
88
Validate_DateRangeWithinRange=The date must lie between {0} and {1}.
89
90
#StringLengthValidator
91
Validate_StringLengthMin=The string must have at least {0} characters.
92
Validate_StringLengthMax=The string must not have more than {0} characters.
93
Validate_StringLengthRange=The string must have between {0} and {1} characters.
94
95
#DecimalScaleValidator
96
Validate_DecimalMaxScale=The decimal must not have more than {0} fractional digits.
97
56
Examples=Examples
98
Examples=Examples
(-)src/org/eclipse/core/databinding/editing/StringEditing.java (+251 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import java.util.regex.Pattern;
15
16
import org.eclipse.core.databinding.conversion.IConverter;
17
import org.eclipse.core.databinding.validation.constraint.Constraints;
18
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
19
import org.eclipse.core.internal.databinding.conversion.StringStripConverter;
20
import org.eclipse.core.internal.databinding.conversion.StringTrimConverter;
21
22
/**
23
 * @since 1.4
24
 */
25
public final class StringEditing extends Editing {
26
27
	private StringEditing(IConverter targetConverter) {
28
		setTargetConverter(targetConverter);
29
	}
30
31
	/**
32
	 * Creates a new editing object for strings which performs no validation or
33
	 * conversion.
34
	 * 
35
	 * @return The new editing object which performs no validation or
36
	 *         conversion.
37
	 */
38
	public static StringEditing withDefaults() {
39
		return new StringEditing(null);
40
	}
41
42
	/**
43
	 * Creates a new editing object which strips whitespace from both ends of
44
	 * the input string.
45
	 * 
46
	 * @param stripToNull
47
	 *            Whether to convert the input string to <code>null</code> in
48
	 *            case stripping the input string results in an empty string.
49
	 * @return The new editing object which strips whitespace from both ends of
50
	 *         the input string.
51
	 * 
52
	 * @see Character#isWhitespace(char)
53
	 */
54
	public static StringEditing stripped(boolean stripToNull) {
55
		return new StringEditing(new StringStripConverter(stripToNull));
56
	}
57
58
	/**
59
	 * Creates a new editing object which {@link String#trim()}s the input
60
	 * string.
61
	 * 
62
	 * @param trimToNull
63
	 *            Whether to convert the input string to <code>null</code> in
64
	 *            case trimming the input string results in an empty string.
65
	 * @return The new editing object which trims whitespace from both ends of
66
	 *         the input string.
67
	 * 
68
	 * @see String#trim()
69
	 */
70
	public static StringEditing trimmed(boolean trimToNull) {
71
		return new StringEditing(new StringTrimConverter(trimToNull));
72
	}
73
74
	/**
75
	 * Returns the target constraints to apply.
76
	 * 
77
	 * <p>
78
	 * This method provides a typesafe access to the {@link StringConstraints
79
	 * string target constraints} of this editing object and is equivalent to
80
	 * {@code (StringConstraints) targetConstraints()}.
81
	 * </p>
82
	 * 
83
	 * @return The target constraints to apply.
84
	 * 
85
	 * @see #targetConstraints()
86
	 * @see StringConstraints
87
	 */
88
	public StringConstraints targetStringConstraints() {
89
		return (StringConstraints) targetConstraints();
90
	}
91
92
	/**
93
	 * Returns the model constraints to apply.
94
	 * 
95
	 * <p>
96
	 * This method provides a typesafe access to the {@link StringConstraints
97
	 * string model constraints} of this editing object and is equivalent to
98
	 * {@code (StringConstraints) modelConstraints()}.
99
	 * </p>
100
	 * 
101
	 * @return The model constraints to apply.
102
	 * 
103
	 * @see #modelConstraints()
104
	 * @see StringConstraints
105
	 */
106
	public StringConstraints modelStringConstraints() {
107
		return (StringConstraints) modelConstraints();
108
	}
109
110
	/**
111
	 * Returns the before-set model constraints to apply.
112
	 * 
113
	 * <p>
114
	 * This method provides a typesafe access to the {@link StringConstraints
115
	 * string before-set model constraints} of this editing object and is
116
	 * equivalent to {@code (StringConstraints) beforeSetModelConstraints()}.
117
	 * </p>
118
	 * 
119
	 * @return The before-set model constraints to apply.
120
	 * 
121
	 * @see #beforeSetModelConstraints()
122
	 * @see StringConstraints
123
	 */
124
	public StringConstraints beforeSetModelStringConstraints() {
125
		return (StringConstraints) beforeSetModelConstraints();
126
	}
127
128
	protected Constraints createTargetConstraints() {
129
		return new StringConstraints();
130
	}
131
132
	protected Constraints createModelConstraints() {
133
		return new StringConstraints();
134
	}
135
136
	protected Constraints createBeforeSetModelConstraints() {
137
		return new StringConstraints();
138
	}
139
140
	/**
141
	 * Convenience method which adds a {@link StringConstraints#required()
142
	 * required constraint} to the set of {@link #modelStringConstraints()}.
143
	 * 
144
	 * @return This editing instance for method chaining.
145
	 * 
146
	 * @see StringConstraints#required()
147
	 * @see #modelStringConstraints()
148
	 */
149
	public StringEditing required() {
150
		modelStringConstraints().required();
151
		return this;
152
	}
153
154
	/**
155
	 * Convenience method which adds a {@link StringConstraints#nonEmpty()
156
	 * non-empty constraint} to the set of {@link #modelStringConstraints()}.
157
	 * 
158
	 * @return This editing instance for method chaining.
159
	 * 
160
	 * @see StringConstraints#nonEmpty()
161
	 * @see #modelStringConstraints()
162
	 */
163
	public StringEditing nonEmpty() {
164
		modelStringConstraints().nonEmpty();
165
		return this;
166
	}
167
168
	/**
169
	 * Convenience method which adds a {@link StringConstraints#minLength(int)
170
	 * min-length constraint} to the set of {@link #modelStringConstraints()}.
171
	 * 
172
	 * @param minLength
173
	 *            The min length of the min-length constraint.
174
	 * @return This editing instance for method chaining.
175
	 * 
176
	 * @see StringConstraints#minLength(int)
177
	 * @see #modelStringConstraints()
178
	 */
179
	public StringEditing minLength(int minLength) {
180
		modelStringConstraints().minLength(minLength);
181
		return this;
182
	}
183
184
	/**
185
	 * Convenience method which adds a {@link StringConstraints#maxLength(int)
186
	 * max-length constraint} to the set of {@link #modelStringConstraints()}.
187
	 * 
188
	 * @param maxLength
189
	 *            The max length of the max-length constraint.
190
	 * @return This editing instance for method chaining.
191
	 * 
192
	 * @see StringConstraints#maxLength(int)
193
	 * @see #modelStringConstraints()
194
	 */
195
	public StringEditing maxLength(int maxLength) {
196
		modelStringConstraints().maxLength(maxLength);
197
		return this;
198
	}
199
200
	/**
201
	 * Convenience method which adds a
202
	 * {@link StringConstraints#lengthRange(int, int) length-range constraint}
203
	 * to the set of {@link #modelStringConstraints()}.
204
	 * 
205
	 * @param minLength
206
	 *            The min length of the length-range constraint.
207
	 * @param maxLength
208
	 *            The max length of the length-range constraint.
209
	 * @return This editing instance for method chaining.
210
	 * 
211
	 * @see StringConstraints#lengthRange(int, int)
212
	 * @see #modelStringConstraints()
213
	 */
214
	public StringEditing lengthRange(int minLength, int maxLength) {
215
		modelStringConstraints().lengthRange(minLength, maxLength);
216
		return this;
217
	}
218
219
	/**
220
	 * Convenience method which adds a {@link StringConstraints#matches(String)
221
	 * matches constraint} to the set of {@link #modelStringConstraints()}.
222
	 * 
223
	 * @param regex
224
	 *            The regular expression of the matches constraint.
225
	 * @return This editing instance for method chaining.
226
	 * 
227
	 * @see StringConstraints#matches(String)
228
	 * @see #modelStringConstraints()
229
	 */
230
	public StringEditing matches(String regex) {
231
		modelStringConstraints().matches(regex);
232
		return this;
233
	}
234
235
	/**
236
	 * Convenience method which adds a
237
	 * {@link StringConstraints#matches(Pattern) matches constraint} to the set
238
	 * of {@link #modelStringConstraints()}.
239
	 * 
240
	 * @param pattern
241
	 *            The pattern of the matches constraint.
242
	 * @return This editing instance for method chaining.
243
	 * 
244
	 * @see StringConstraints#matches(Pattern)
245
	 * @see #modelStringConstraints()
246
	 */
247
	public StringEditing matches(Pattern pattern) {
248
		modelStringConstraints().matches(pattern);
249
		return this;
250
	}
251
}
(-)src/org/eclipse/core/internal/databinding/validation/DateRangeValidator.java (+238 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.text.MessageFormat;
15
import java.util.Date;
16
17
import org.eclipse.core.databinding.validation.IValidator;
18
import org.eclipse.core.databinding.validation.ValidationStatus;
19
import org.eclipse.core.internal.databinding.BindingMessages;
20
import org.eclipse.core.runtime.IStatus;
21
22
import com.ibm.icu.text.DateFormat;
23
24
/**
25
 * Provides validations for date which must lie within an open/closed range.
26
 * 
27
 * @since 1.4
28
 */
29
public class DateRangeValidator implements IValidator {
30
31
	// The set of constraint types for the lower/upper bound of the date range.
32
	private static final int UNDEFINED = -1;
33
	private static final int AFTER = 0;
34
	private static final int AFTER_EQUAL = 1;
35
	private static final int BEFORE = 2;
36
	private static final int BEFORE_EQUAL = 3;
37
38
	// The default validation messages.
39
	private static final String AFTER_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_DATE_RANGE_AFTER);
40
	private static final String AFTER_EQUAL_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_DATE_RANGE_AFTER_EQUAL);
41
	private static final String BEFORE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_DATE_RANGE_BEFORE);
42
	private static final String BEFORE_EQUAL_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_DATE_RANGE_BEFORE_EQUAL);
43
	private static final String WITHIN_RANGE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_DATE_RANGE_WITHIN_RANGE);
44
45
	private final Date min;
46
	private final Date max;
47
	private final int minConstraint;
48
	private final int maxConstraint;
49
	private final String validationMessage;
50
	private String formattedValidationMessage;
51
	private final DateFormat format;
52
53
	/**
54
	 * Single constructor which supports the individual date range types.
55
	 * 
56
	 * @param min
57
	 *            The min date of the range or <code>null</code> in case no
58
	 *            lower bound is defined.
59
	 * @param max
60
	 *            The max date of the range or <code>null</code> in case no
61
	 *            upper bound is defined.
62
	 * @param minConstraint
63
	 *            The type of constraint imposed by the lower bound of the
64
	 *            range.
65
	 * @param maxConstraint
66
	 *            The type of constraint imposed by the upper bound of the
67
	 *            range.
68
	 * @param validationMessage
69
	 *            The validation message pattern to use. Can be parameterized by
70
	 *            the lower and upper bound of the range, if defined.
71
	 * @param format
72
	 *            The date format to use for formatting dates in the validation
73
	 *            message.
74
	 */
75
	private DateRangeValidator(Date min, Date max, int minConstraint,
76
			int maxConstraint, String validationMessage, DateFormat format) {
77
		this.min = min;
78
		this.max = max;
79
		this.minConstraint = minConstraint;
80
		this.maxConstraint = maxConstraint;
81
		this.validationMessage = validationMessage;
82
		this.format = format;
83
	}
84
85
	/**
86
	 * Creates a validator which checks that an input date is after the given
87
	 * date.
88
	 * 
89
	 * @param date
90
	 *            The reference date of the after constraint.
91
	 * @param validationMessage
92
	 *            The validation message pattern to use. Can be parameterized
93
	 *            with the given reference date.
94
	 * @param format
95
	 *            The display format to use for formatting dates in the
96
	 *            validation message.
97
	 * @return The validator instance.
98
	 */
99
	public static DateRangeValidator after(Date date, String validationMessage,
100
			DateFormat format) {
101
		return new DateRangeValidator(date, null, AFTER, UNDEFINED,
102
				defaultIfNull(validationMessage, AFTER_MESSAGE), format);
103
	}
104
105
	/**
106
	 * Creates a validator which checks that an input date is after or on the
107
	 * given date.
108
	 * 
109
	 * @param date
110
	 *            The reference date of the after-equal constraint.
111
	 * @param validationMessage
112
	 *            The validation message pattern to use. Can be parameterized
113
	 *            with the given reference date.
114
	 * @param format
115
	 *            The display format to use for formatting dates in the
116
	 *            validation message.
117
	 * @return The validator instance.
118
	 */
119
	public static DateRangeValidator afterEqual(Date date,
120
			String validationMessage, DateFormat format) {
121
		return new DateRangeValidator(date, null, AFTER_EQUAL, UNDEFINED,
122
				defaultIfNull(validationMessage, AFTER_EQUAL_MESSAGE), format);
123
	}
124
125
	/**
126
	 * Creates a validator which checks that an input date is before the given
127
	 * date.
128
	 * 
129
	 * @param date
130
	 *            The reference date of the before constraint.
131
	 * @param validationMessage
132
	 *            The validation message pattern to use. Can be parameterized
133
	 *            with the given reference date.
134
	 * @param format
135
	 *            The display format to use for formatting dates in the
136
	 *            validation message.
137
	 * @return The validator instance.
138
	 */
139
	public static DateRangeValidator before(Date date, String validationMessage,
140
			DateFormat format) {
141
		return new DateRangeValidator(null, date, UNDEFINED, BEFORE,
142
				defaultIfNull(validationMessage, BEFORE_MESSAGE), format);
143
	}
144
145
	/**
146
	 * Creates a validator which checks that an input date is before or on the
147
	 * given date.
148
	 * 
149
	 * @param date
150
	 *            The reference date of the before-equal constraint.
151
	 * @param validationMessage
152
	 *            The validation message pattern to use. Can be parameterized
153
	 *            with the given reference date.
154
	 * @param format
155
	 *            The display format to use for formatting dates in the
156
	 *            validation message.
157
	 * @return The validator instance.
158
	 */
159
	public static DateRangeValidator beforeEqual(Date date,
160
			String validationMessage, DateFormat format) {
161
		return new DateRangeValidator(null, date, UNDEFINED, BEFORE_EQUAL,
162
				defaultIfNull(validationMessage, BEFORE_EQUAL_MESSAGE), format);
163
	}
164
165
	/**
166
	 * Creates a validator which checks that an input date is within the given
167
	 * range.
168
	 * 
169
	 * @param min
170
	 *            The lower bound of the range (inclusive).
171
	 * @param max
172
	 *            The upper bound of the range (inclusive).
173
	 * @param validationMessage
174
	 *            The validation message pattern to use. Can be parameterized
175
	 *            with the range's lower and upper bound.
176
	 * @param format
177
	 *            The display format to use for formatting dates in the
178
	 *            validation message.
179
	 * @return The validator instance.
180
	 */
181
	public static DateRangeValidator range(Date min, Date max,
182
			String validationMessage, DateFormat format) {
183
		return new DateRangeValidator(min, max, AFTER_EQUAL, BEFORE_EQUAL,
184
				defaultIfNull(validationMessage, WITHIN_RANGE_MESSAGE), format);
185
	}
186
187
	public IStatus validate(Object value) {
188
		if (value != null) {
189
			Date date = (Date) value;
190
			if ((min != null && !fulfillsConstraint(date, min, minConstraint))
191
					|| (max != null && !fulfillsConstraint(date, max,
192
							maxConstraint))) {
193
				return ValidationStatus.error(getFormattedValidationMessage());
194
			}
195
		}
196
		return ValidationStatus.ok();
197
	}
198
199
	private boolean fulfillsConstraint(Date date1, Date date2, int constraint) {
200
		switch (constraint) {
201
		case AFTER:
202
			return date1.after(date2);
203
		case AFTER_EQUAL:
204
			return date1.after(date2) || date1.equals(date2);
205
		case BEFORE:
206
			return date1.before(date2);
207
		case BEFORE_EQUAL:
208
			return date1.before(date2) || date1.equals(date2);
209
		case UNDEFINED:
210
		default:
211
			throw new IllegalArgumentException(
212
					"Unsupported constraint: " + constraint); //$NON-NLS-1$
213
		}
214
	}
215
216
	private synchronized String getFormattedValidationMessage() {
217
		if (formattedValidationMessage == null) {
218
			formattedValidationMessage = MessageFormat.format(
219
					validationMessage, getValidationMessageArguments());
220
		}
221
		return formattedValidationMessage;
222
	}
223
224
	private String[] getValidationMessageArguments() {
225
		synchronized (format) {
226
			if (min == null) {
227
				return new String[] { format.format(max) };
228
			} else if (max == null) {
229
				return new String[] { format.format(min) };
230
			}
231
			return new String[] { format.format(min), format.format(max) };
232
		}
233
	}
234
235
	private static String defaultIfNull(String string, String defaultString) {
236
		return (string != null) ? string : defaultString;
237
	}
238
}
(-)src/org/eclipse/core/internal/databinding/validation/NumberRangeValidator.java (+149 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.text.MessageFormat;
15
16
import org.eclipse.core.databinding.validation.IValidator;
17
import org.eclipse.core.databinding.validation.ValidationStatus;
18
import org.eclipse.core.internal.databinding.BindingMessages;
19
import org.eclipse.core.runtime.IStatus;
20
21
import com.ibm.icu.text.NumberFormat;
22
23
/**
24
 * Provides validations for numbers which must lie within an open/closed range.
25
 * 
26
 * @since 1.4
27
 */
28
public abstract class NumberRangeValidator implements IValidator {
29
30
	// The set of constraint types for the lower/upper bound of the date range.
31
	protected static final int UNDEFINED = -1;
32
	protected static final int GREATER = 0;
33
	protected static final int GREATER_EQUAL = 1;
34
	protected static final int LESS = 2;
35
	protected static final int LESS_EQUAL = 3;
36
37
	// The default validation messages.
38
	protected static final String GREATER_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_GREATER);
39
	protected static final String GREATER_EQUAL_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_GREATER_EQUAL);
40
	protected static final String LESS_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_LESS);
41
	protected static final String LESS_EQUAL_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_LESS_EQUAL);
42
	protected static final String WITHIN_RANGE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_WITHIN_RANGE);
43
	protected static final String POSITIVE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_POSITIVE);
44
	protected static final String NON_NEGATIVE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NUMBER_RANGE_NON_NEGATIVE);
45
46
	private final Number min;
47
	private final Number max;
48
	private final int minConstraint;
49
	private final int maxConstraint;
50
	private final String validationMessage;
51
	private String formattedValidationMessage;
52
	private final NumberFormat format;
53
54
	/**
55
	 * Single constructor which supports the individual number range types.
56
	 * 
57
	 * @param min
58
	 *            The min number of the range or <code>null</code> in case no
59
	 *            lower bound is defined.
60
	 * @param max
61
	 *            The max number of the range or <code>null</code> in case no
62
	 *            upper bound is defined.
63
	 * @param minConstraint
64
	 *            The type of constraint imposed by the lower bound of the
65
	 *            range.
66
	 * @param maxConstraint
67
	 *            The type of constraint imposed by the upper bound of the
68
	 *            range.
69
	 * @param validationMessage
70
	 *            The validation message pattern to use. Can be parameterized by
71
	 *            the lower and upper bound of the range, if defined.
72
	 * @param format
73
	 *            The integer format to use for formatting numbers in the
74
	 *            validation message.
75
	 */
76
	protected NumberRangeValidator(Number min, Number max, int minConstraint,
77
			int maxConstraint, String validationMessage, NumberFormat format) {
78
		this.min = min;
79
		this.max = max;
80
		this.minConstraint = minConstraint;
81
		this.maxConstraint = maxConstraint;
82
		this.validationMessage = validationMessage;
83
		this.format = format;
84
	}
85
86
	public IStatus validate(Object value) {
87
		if (value != null) {
88
			Number number = (Number) value;
89
			if ((min != null && !fulfillsConstraint(number, min, minConstraint))
90
					|| (max != null && !fulfillsConstraint(number, max,
91
							maxConstraint))) {
92
				return ValidationStatus.error(getFormattedValidationMessage());
93
			}
94
		}
95
		return ValidationStatus.ok();
96
	}
97
98
	private boolean fulfillsConstraint(Number number1, Number number2,
99
			int constraint) {
100
		int compareResult = compare(number1, number2);
101
		switch (constraint) {
102
		case GREATER:
103
			return compareResult > 0;
104
		case GREATER_EQUAL:
105
			return compareResult >= 0;
106
		case LESS:
107
			return compareResult < 0;
108
		case LESS_EQUAL:
109
			return compareResult <= 0;
110
		case UNDEFINED:
111
		default:
112
			throw new IllegalArgumentException(
113
					"Unsupported constraint: " + constraint); //$NON-NLS-1$
114
		}
115
	}
116
117
	/**
118
	 * Comparator method to be implemented by subclasses in order to compare two
119
	 * instances of the concrete number type.
120
	 * 
121
	 * @param number1
122
	 *            The first number to compare.
123
	 * @param number2
124
	 *            The second number to compare.
125
	 * @return A negative number, zero, or a positive number in case the first
126
	 *         number is smaller than, equal to, or greater than the second
127
	 *         number, respectively.
128
	 */
129
	protected abstract int compare(Number number1, Number number2);
130
131
	private synchronized String getFormattedValidationMessage() {
132
		if (formattedValidationMessage == null) {
133
			formattedValidationMessage = MessageFormat.format(
134
					validationMessage, getValidationMessageArguments());
135
		}
136
		return formattedValidationMessage;
137
	}
138
139
	private String[] getValidationMessageArguments() {
140
		synchronized (format) {
141
			if (min == null) {
142
				return new String[] { format.format(max) };
143
			} else if (max == null) {
144
				return new String[] { format.format(min) };
145
			}
146
			return new String[] { format.format(min), format.format(max) };
147
		}
148
	}
149
}
(-)src/org/eclipse/core/databinding/validation/constraint/CharacterConstraints.java (+190 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import org.eclipse.core.internal.databinding.validation.CharacterValidator;
15
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
16
17
/**
18
 * @since 1.4
19
 */
20
public final class CharacterConstraints extends Constraints {
21
22
	private String requiredMessage = null;
23
24
	private String noWhitespaceMessage = null;
25
26
	private String noSpaceMessage = null;
27
28
	private String letterMessage = null;
29
30
	private String digitMessage = null;
31
32
	private String letterOrDigitMessage = null;
33
34
	/**
35
	 * Adds a validator ensuring that the character is not <code>null</code> .
36
	 * Uses the current {@link #requiredMessage(String) validation message}.
37
	 * 
38
	 * @return This constraints instance for method chaining.
39
	 */
40
	public CharacterConstraints required() {
41
		addValidator(new NonNullValidator(requiredMessage));
42
		return this;
43
	}
44
45
	/**
46
	 * Sets the validation message for the {@link #required()} constraint.
47
	 * 
48
	 * @param message
49
	 *            The validation message for the {@link #required()} constraint.
50
	 * @return This constraints instance for method chaining.
51
	 * 
52
	 * @see #required()
53
	 */
54
	public CharacterConstraints requiredMessage(String message) {
55
		this.requiredMessage = message;
56
		return this;
57
	}
58
59
	/**
60
	 * Adds a validator ensuring that the character is no
61
	 * {@link Character#isWhitespace(char) whitespace}. Uses the current
62
	 * {@link #noWhitespaceMessage(String) validation message}.
63
	 * 
64
	 * @return This constraints instance for method chaining.
65
	 */
66
	public CharacterConstraints noWhitespace() {
67
		addValidator(CharacterValidator.noWhitespace(noWhitespaceMessage));
68
		return this;
69
	}
70
71
	/**
72
	 * Sets the validation message for the {@link #noWhitespace()} constraint.
73
	 * 
74
	 * @param message
75
	 *            The validation message for the {@link #noWhitespace()}
76
	 *            constraint.
77
	 * @return This constraints instance for method chaining.
78
	 * 
79
	 * @see #noWhitespace()
80
	 */
81
	public CharacterConstraints noWhitespaceMessage(String message) {
82
		this.noWhitespaceMessage = message;
83
		return this;
84
	}
85
86
	/**
87
	 * Adds a validator ensuring that the character is no
88
	 * {@link Character#isSpaceChar(char) space}. Uses the current
89
	 * {@link #noSpaceMessage(String) validation message}.
90
	 * 
91
	 * @return This constraints instance for method chaining.
92
	 */
93
	public CharacterConstraints noSpace() {
94
		addValidator(CharacterValidator.noSpace(noSpaceMessage));
95
		return this;
96
	}
97
98
	/**
99
	 * Sets the validation message for the {@link #noSpace()} constraint.
100
	 * 
101
	 * @param message
102
	 *            The validation message for the {@link #noSpace()} constraint.
103
	 * @return This constraints instance for method chaining.
104
	 * 
105
	 * @see #noSpace()
106
	 */
107
	public CharacterConstraints noSpaceMessage(String message) {
108
		this.noSpaceMessage = message;
109
		return this;
110
	}
111
112
	/**
113
	 * Adds a validator ensuring that the character is a
114
	 * {@link Character#isLetter(char) letter}. Uses the current
115
	 * {@link #letterMessage(String) validation message}.
116
	 * 
117
	 * @return This constraints instance for method chaining.
118
	 */
119
	public CharacterConstraints letter() {
120
		addValidator(CharacterValidator.letter(letterMessage));
121
		return this;
122
	}
123
124
	/**
125
	 * Sets the validation message for the {@link #letter()} constraint.
126
	 * 
127
	 * @param message
128
	 *            The validation message for the {@link #letter()} constraint.
129
	 * @return This constraints instance for method chaining.
130
	 * 
131
	 * @see #letter()
132
	 */
133
	public CharacterConstraints letterMessage(String message) {
134
		this.letterMessage = message;
135
		return this;
136
	}
137
138
	/**
139
	 * Adds a validator ensuring that the character is a
140
	 * {@link Character#isDigit(char) digit}. Uses the current
141
	 * {@link #digitMessage(String) validation message}.
142
	 * 
143
	 * @return This constraints instance for method chaining.
144
	 */
145
	public CharacterConstraints digit() {
146
		addValidator(CharacterValidator.digit(digitMessage));
147
		return this;
148
	}
149
150
	/**
151
	 * Sets the validation message for the {@link #digit()} constraint.
152
	 * 
153
	 * @param message
154
	 *            The validation message for the {@link #digit()} constraint.
155
	 * @return This constraints instance for method chaining.
156
	 * 
157
	 * @see #digit()
158
	 */
159
	public CharacterConstraints digitMessage(String message) {
160
		this.digitMessage = message;
161
		return this;
162
	}
163
164
	/**
165
	 * Adds a validator ensuring that the character is a
166
	 * {@link Character#isLetterOrDigit(char) letter or digit}. Uses the current
167
	 * {@link #letterOrDigitMessage(String) validation message}.
168
	 * 
169
	 * @return This constraints instance for method chaining.
170
	 */
171
	public CharacterConstraints letterOrDigit() {
172
		addValidator(CharacterValidator.letterOrDigit(letterOrDigitMessage));
173
		return this;
174
	}
175
176
	/**
177
	 * Sets the validation message for the {@link #letterOrDigit()} constraint.
178
	 * 
179
	 * @param message
180
	 *            The validation message for the {@link #letterOrDigit()}
181
	 *            constraint.
182
	 * @return This constraints instance for method chaining.
183
	 * 
184
	 * @see #letterOrDigit()
185
	 */
186
	public CharacterConstraints letterOrDigitMessage(String message) {
187
		this.letterOrDigitMessage = message;
188
		return this;
189
	}
190
}
(-)src/org/eclipse/core/internal/databinding/validation/StringLengthValidator.java (+164 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.text.MessageFormat;
15
16
import org.eclipse.core.databinding.validation.IValidator;
17
import org.eclipse.core.databinding.validation.ValidationStatus;
18
import org.eclipse.core.internal.databinding.BindingMessages;
19
import org.eclipse.core.runtime.IStatus;
20
21
import com.ibm.icu.text.NumberFormat;
22
23
/**
24
 * Provides validations for strings which must have a specified length.
25
 * 
26
 * @since 1.4
27
 */
28
public class StringLengthValidator implements IValidator {
29
30
	// The default validation messages.
31
	private static final String MIN_LENGTH_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_STRING_LENGTH_MIN);
32
	private static final String MAX_LENGTH_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_STRING_LENGTH_MAX);
33
	private static final String LENGTH_RANGE_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_STRING_LENGTH_RANGE);
34
35
	private final Integer minLength;
36
	private final Integer maxLength;
37
	private final String validationMessage;
38
	private String formattedValidationMessage;
39
	private final NumberFormat format;
40
41
	/**
42
	 * Creates a string length validator defining a minimum and/or maximum
43
	 * length for a string.
44
	 * 
45
	 * @param minLength
46
	 *            The minimum length of the string or <code>null</code> in case
47
	 *            no minimum length is defined.
48
	 * @param maxLength
49
	 *            The maximum length of the string or <code>null</code> in case
50
	 *            no maximum length is defined.
51
	 * @param validationMessage
52
	 *            The validation message pattern to use. Can be parameterized by
53
	 *            the lower and upper bound of the range, if defined.
54
	 * @param format
55
	 *            The number format to use for formatting integers (the length
56
	 *            bounds) in the validation message.
57
	 */
58
	private StringLengthValidator(Integer minLength, Integer maxLength,
59
			String validationMessage, NumberFormat format) {
60
		this.minLength = minLength;
61
		this.maxLength = maxLength;
62
		this.validationMessage = validationMessage;
63
		this.format = format;
64
	}
65
66
	/**
67
	 * Creates a validator which checks that an input string has the given
68
	 * minimum length.
69
	 * 
70
	 * @param minLength
71
	 *            The minimum length which the input string must have.
72
	 * @param validationMessage
73
	 *            The validation message pattern to use. Can be parameterized
74
	 *            with the given minimum length.
75
	 * @param format
76
	 *            The display format to use for formatting integers (the minimum
77
	 *            length) in the validation message.
78
	 * @return The validator instance.
79
	 */
80
	public static StringLengthValidator min(int minLength,
81
			String validationMessage, NumberFormat format) {
82
		return new StringLengthValidator(new Integer(minLength), null,
83
				defaultIfNull(validationMessage, MIN_LENGTH_MESSAGE), format);
84
	}
85
86
	/**
87
	 * Creates a validator which checks that an input string has the given
88
	 * maximum length.
89
	 * 
90
	 * @param maxLength
91
	 *            The maximum length which the input string must have.
92
	 * @param validationMessage
93
	 *            The validation message pattern to use. Can be parameterized
94
	 *            with the given maximum length.
95
	 * @param format
96
	 *            The display format to use for formatting integers (the maximum
97
	 *            length) in the validation message.
98
	 * @return The validator instance.
99
	 */
100
	public static StringLengthValidator max(int maxLength,
101
			String validationMessage, NumberFormat format) {
102
		return new StringLengthValidator(null, new Integer(maxLength),
103
				defaultIfNull(validationMessage, MAX_LENGTH_MESSAGE), format);
104
	}
105
106
	/**
107
	 * Creates a validator which checks that the length of an input string lies
108
	 * in the given range.
109
	 * 
110
	 * @param minLength
111
	 *            The minimum length which the input string must have.
112
	 * @param maxLength
113
	 *            The maximum length which the input string must have.
114
	 * @param validationMessage
115
	 *            The validation message pattern to use. Can be parameterized
116
	 *            with the given minimum and maximum lengths.
117
	 * @param format
118
	 *            The display format to use for formatting integers (the
119
	 *            minimum/maximum length) in the validation message.
120
	 * @return The validator instance.
121
	 */
122
	public static StringLengthValidator range(int minLength,
123
			int maxLength, String validationMessage, NumberFormat format) {
124
		return new StringLengthValidator(new Integer(minLength), new Integer(
125
				maxLength), defaultIfNull(validationMessage,
126
				LENGTH_RANGE_MESSAGE), format);
127
	}
128
129
	public IStatus validate(Object value) {
130
		String input = (String) value;
131
		if (input != null) {
132
			int inputLength = input.length();
133
			if ((minLength != null && inputLength < minLength.intValue())
134
					|| maxLength != null && inputLength > maxLength.intValue()) {
135
				return ValidationStatus.error(getFormattedValidationMessage());
136
			}
137
		}
138
		return ValidationStatus.ok();
139
	}
140
141
	private synchronized String getFormattedValidationMessage() {
142
		if (formattedValidationMessage == null) {
143
			formattedValidationMessage = MessageFormat.format(
144
					validationMessage, getValidationMessageArguments());
145
		}
146
		return formattedValidationMessage;
147
	}
148
149
	private String[] getValidationMessageArguments() {
150
		synchronized (format) {
151
			if (minLength == null) {
152
				return new String[] { format.format(maxLength) };
153
			} else if (maxLength == null) {
154
				return new String[] { format.format(minLength) };
155
			}
156
			return new String[] { format.format(minLength),
157
					format.format(maxLength) };
158
		}
159
	}
160
161
	private static String defaultIfNull(String string, String defaultString) {
162
		return (string != null) ? string : defaultString;
163
	}
164
}
(-)src/org/eclipse/core/databinding/validation/constraint/DecimalConstraints.java (+362 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import org.eclipse.core.internal.databinding.validation.DecimalRangeValidator;
15
import org.eclipse.core.internal.databinding.validation.DecimalScaleValidator;
16
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
17
18
import com.ibm.icu.text.NumberFormat;
19
20
/**
21
 * @since 1.4
22
 */
23
public final class DecimalConstraints extends Constraints {
24
25
	private NumberFormat decimalFormat = NumberFormat.getNumberInstance();
26
27
	private NumberFormat integerFormat = NumberFormat.getIntegerInstance();
28
29
	private String requiredMessage = null;
30
31
	private String greaterMessage = null;
32
33
	private String greaterEqualMessage = null;
34
35
	private String lessMessage = null;
36
37
	private String lessEqualMessage = null;
38
39
	private String rangeMessage = null;
40
41
	private String positiveMessage = null;
42
43
	private String nonNegativeMessage = null;
44
45
	private String maxScaleMessage = null;
46
47
	/**
48
	 * Sets the format to use when formatting a decimal to be included in any of
49
	 * the validation messages.
50
	 * 
51
	 * <p>
52
	 * This decimal format will be used for any subsequent constraints which are
53
	 * applied.
54
	 * </p>
55
	 * 
56
	 * @param format
57
	 *            The format to use for displaying decimals in validation
58
	 *            messages.
59
	 * @return This constraints instance for method chaining.
60
	 */
61
	public DecimalConstraints decimalFormat(NumberFormat format) {
62
		this.decimalFormat = format;
63
		return this;
64
	}
65
66
	/**
67
	 * Sets the format to use when formatting an integer to be included in any
68
	 * of the validation messages.
69
	 * 
70
	 * <p>
71
	 * This integer format will be used for any subsequent constraints which are
72
	 * applied.
73
	 * </p>
74
	 * 
75
	 * @param format
76
	 *            The format to use for displaying integers in validation
77
	 *            messages.
78
	 * @return This constraints instance for method chaining.
79
	 * 
80
	 * @see #maxScale(int)
81
	 */
82
	public DecimalConstraints integerFormat(NumberFormat format) {
83
		this.integerFormat = format;
84
		return this;
85
	}
86
87
	/**
88
	 * Adds a validator ensuring that the parsed decimal is not
89
	 * <code>null</code>. Uses the current {@link #requiredMessage(String)
90
	 * validation message}.
91
	 * 
92
	 * @return This constraints instance for method chaining.
93
	 */
94
	public DecimalConstraints required() {
95
		addValidator(new NonNullValidator(requiredMessage));
96
		return this;
97
	}
98
99
	/**
100
	 * Sets the validation message for the {@link #required()} constraint.
101
	 * 
102
	 * @param message
103
	 *            The validation message for the {@link #required()} constraint.
104
	 * @return This constraints instance for method chaining.
105
	 * 
106
	 * @see #required()
107
	 */
108
	public DecimalConstraints requiredMessage(String message) {
109
		this.requiredMessage = message;
110
		return this;
111
	}
112
113
	/**
114
	 * Adds a validator ensuring that the parsed decimal is greater than the
115
	 * given number. Uses the current {@link #greaterMessage(String) validation
116
	 * message}.
117
	 * 
118
	 * @param number
119
	 *            The number which the parsed decimal must be greater than.
120
	 * @return This constraints instance for method chaining.
121
	 */
122
	public DecimalConstraints greater(double number) {
123
		addValidator(DecimalRangeValidator.greater(number, greaterMessage,
124
				decimalFormat));
125
		return this;
126
	}
127
128
	/**
129
	 * Sets the validation message pattern for the {@link #greater(double)}
130
	 * constraint.
131
	 * 
132
	 * @param message
133
	 *            The validation message pattern for the
134
	 *            {@link #greater(double)} constraint. Can be parameterized with
135
	 *            the number which the parsed decimal must be greater than.
136
	 * @return This constraints instance for method chaining.
137
	 * 
138
	 * @see #greater(double)
139
	 */
140
	public DecimalConstraints greaterMessage(String message) {
141
		this.greaterMessage = message;
142
		return this;
143
	}
144
145
	/**
146
	 * Adds a validator ensuring that the parsed decimal is greater than or
147
	 * equal to the given number. Uses the current
148
	 * {@link #greaterEqualMessage(String) validation message}.
149
	 * 
150
	 * @param number
151
	 *            The number which the parsed decimal must be greater than or
152
	 *            equal to.
153
	 * @return This constraints instance for method chaining.
154
	 */
155
	public DecimalConstraints greaterEqual(double number) {
156
		addValidator(DecimalRangeValidator.greaterEqual(number,
157
				greaterEqualMessage, decimalFormat));
158
		return this;
159
	}
160
161
	/**
162
	 * Sets the validation message pattern for the {@link #greaterEqual(double)}
163
	 * constraint.
164
	 * 
165
	 * @param message
166
	 *            The validation message pattern for the
167
	 *            {@link #greaterEqual(double)} constraint. Can be parameterized
168
	 *            with the number which the parsed decimal must be greater than
169
	 *            or equal to.
170
	 * @return This constraints instance for method chaining.
171
	 * 
172
	 * @see #greaterEqual(double)
173
	 */
174
	public DecimalConstraints greaterEqualMessage(String message) {
175
		this.greaterEqualMessage = message;
176
		return this;
177
	}
178
179
	/**
180
	 * Adds a validator ensuring that the parsed decimal is less than the given
181
	 * number. Uses the current {@link #lessMessage(String) validation message}.
182
	 * 
183
	 * @param number
184
	 *            The number which the parsed decimal must be less than.
185
	 * @return This constraints instance for method chaining.
186
	 */
187
	public DecimalConstraints less(double number) {
188
		addValidator(DecimalRangeValidator.less(number, lessMessage,
189
				decimalFormat));
190
		return this;
191
	}
192
193
	/**
194
	 * Sets the validation message pattern for the {@link #less(double)}
195
	 * constraint.
196
	 * 
197
	 * @param message
198
	 *            The validation message pattern for the {@link #less(double)}
199
	 *            constraint. Can be parameterized with the number which the
200
	 *            parsed decimal must be less than.
201
	 * @return This constraints instance for method chaining.
202
	 * 
203
	 * @see #less(double)
204
	 */
205
	public DecimalConstraints lessMessage(String message) {
206
		this.lessMessage = message;
207
		return this;
208
	}
209
210
	/**
211
	 * Adds a validator ensuring that the parsed decimal is less than or equal
212
	 * to the given number. Uses the current {@link #lessEqualMessage(String)
213
	 * validation message}.
214
	 * 
215
	 * @param number
216
	 *            The number which the parsed decimal must be less than or equal
217
	 *            to.
218
	 * @return This constraints instance for method chaining.
219
	 */
220
	public DecimalConstraints lessEqual(double number) {
221
		addValidator(DecimalRangeValidator.greaterEqual(number,
222
				lessEqualMessage, decimalFormat));
223
		return this;
224
	}
225
226
	/**
227
	 * Sets the validation message pattern for the {@link #lessEqual(double)}
228
	 * constraint.
229
	 * 
230
	 * @param message
231
	 *            The validation message pattern for the
232
	 *            {@link #lessEqual(double)} constraint. Can be parameterized
233
	 *            with the number which the parsed decimal must be less than or
234
	 *            equal to.
235
	 * @return This constraints instance for method chaining.
236
	 * 
237
	 * @see #lessEqual(double)
238
	 */
239
	public DecimalConstraints lessEqualMessage(String message) {
240
		this.lessEqualMessage = message;
241
		return this;
242
	}
243
244
	/**
245
	 * Adds a validator ensuring that the parsed decimal is within the given
246
	 * range. Uses the current {@link #rangeMessage(String) validation message}.
247
	 * 
248
	 * @param min
249
	 *            The lower bound of the range (inclusive).
250
	 * @param max
251
	 *            The upper bound of the range (inclusive).
252
	 * @return This constraints instance for method chaining.
253
	 */
254
	public DecimalConstraints range(double min, double max) {
255
		addValidator(DecimalRangeValidator.range(min, max, rangeMessage,
256
				decimalFormat));
257
		return this;
258
	}
259
260
	/**
261
	 * Sets the validation message pattern for the
262
	 * {@link #range(double, double)} constraint.
263
	 * 
264
	 * @param message
265
	 *            The validation message pattern for the
266
	 *            {@link #range(double, double)} constraint. Can be
267
	 *            parameterized with the min and max values of the range in
268
	 *            which the parsed decimal must lie.
269
	 * @return This constraints instance for method chaining.
270
	 * 
271
	 * @see #range(double, double)
272
	 */
273
	public DecimalConstraints rangeMessage(String message) {
274
		this.rangeMessage = message;
275
		return this;
276
	}
277
278
	/**
279
	 * Adds a validator ensuring that the parsed decimal is positive. Uses the
280
	 * current {@link #positiveMessage(String) validation message}.
281
	 * 
282
	 * @return This constraints instance for method chaining.
283
	 */
284
	public DecimalConstraints positive() {
285
		addValidator(DecimalRangeValidator.positive(positiveMessage,
286
				decimalFormat));
287
		return this;
288
	}
289
290
	/**
291
	 * Sets the validation message for the {@link #positive()} constraint.
292
	 * 
293
	 * @param message
294
	 *            The validation message for the {@link #positive()} constraint.
295
	 * @return This constraints instance for method chaining.
296
	 * 
297
	 * @see #positive()
298
	 */
299
	public DecimalConstraints positiveMessage(String message) {
300
		this.positiveMessage = message;
301
		return this;
302
	}
303
304
	/**
305
	 * Adds a validator ensuring that the parsed decimal is non-negative. Uses
306
	 * the current {@link #nonNegativeMessage(String) validation message}.
307
	 * 
308
	 * @return This constraints instance for method chaining.
309
	 */
310
	public DecimalConstraints nonNegative() {
311
		addValidator(DecimalRangeValidator.nonNegative(nonNegativeMessage,
312
				decimalFormat));
313
		return this;
314
	}
315
316
	/**
317
	 * Sets the validation message for the {@link #nonNegative()} constraint.
318
	 * 
319
	 * @param message
320
	 *            The validation message for the {@link #nonNegative()}
321
	 *            constraint.
322
	 * @return This constraints instance for method chaining.
323
	 * 
324
	 * @see #nonNegative()
325
	 */
326
	public DecimalConstraints nonNegativeMessage(String message) {
327
		this.nonNegativeMessage = message;
328
		return this;
329
	}
330
331
	/**
332
	 * Adds a validator ensuring that the parsed decimal's scale is not greater
333
	 * than the given one. Uses the current {@link #maxScaleMessage(String)
334
	 * validation message}.
335
	 * 
336
	 * @param scale
337
	 *            The maximum scale to enforce on the parsed decimal.
338
	 * @return This constraints instance for method chaining.
339
	 */
340
	public DecimalConstraints maxScale(int scale) {
341
		addValidator(DecimalScaleValidator.max(scale, maxScaleMessage,
342
				integerFormat));
343
		return this;
344
	}
345
346
	/**
347
	 * Sets the validation message pattern for the {@link #maxScale(int)}
348
	 * constraint.
349
	 * 
350
	 * @param message
351
	 *            The validation message pattern for the {@link #maxScale(int)}
352
	 *            constraint. Can be parameterized with the maximum scale of the
353
	 *            decimal.
354
	 * @return This constraints instance for method chaining.
355
	 * 
356
	 * @see #maxScale(int)
357
	 */
358
	public DecimalConstraints maxScaleMessage(String message) {
359
		this.maxScaleMessage = message;
360
		return this;
361
	}
362
}
(-)src/org/eclipse/core/databinding/validation/constraint/DateConstraints.java (+252 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import java.util.Date;
15
16
import org.eclipse.core.internal.databinding.validation.DateRangeValidator;
17
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
18
19
import com.ibm.icu.text.DateFormat;
20
21
/**
22
 * @since 1.4
23
 */
24
public final class DateConstraints extends Constraints {
25
26
	private DateFormat displayFormat = DateFormat.getDateInstance();
27
28
	private String requiredMessage = null;
29
30
	private String afterMessage = null;
31
32
	private String afterEqualMessage = null;
33
34
	private String beforeMessage = null;
35
36
	private String beforeEqualMessage = null;
37
38
	private String rangeMessage = null;
39
40
	/**
41
	 * Sets the format to use when formatting a date to be included in any of
42
	 * the validation messages.
43
	 * 
44
	 * <p>
45
	 * This date format will be used for any subsequent constraints which are
46
	 * applied.
47
	 * </p>
48
	 * 
49
	 * @param format
50
	 *            The format to use for displaying dates in validation messages.
51
	 * @return This constraints instance for method chaining.
52
	 */
53
	public DateConstraints dateDisplayFormat(DateFormat format) {
54
		this.displayFormat = format;
55
		return this;
56
	}
57
58
	/**
59
	 * Adds a validator ensuring that the parsed date is not <code>null</code>.
60
	 * Uses the current {@link #requiredMessage(String) validation message}.
61
	 * 
62
	 * @return This constraints instance for method chaining.
63
	 */
64
	public DateConstraints required() {
65
		addValidator(new NonNullValidator(requiredMessage));
66
		return this;
67
	}
68
69
	/**
70
	 * Sets the validation message for the {@link #required()} constraint.
71
	 * 
72
	 * @param message
73
	 *            The validation message for the {@link #required()} constraint.
74
	 * @return This constraints instance for method chaining.
75
	 * 
76
	 * @see #required()
77
	 */
78
	public DateConstraints requiredMessage(String message) {
79
		this.requiredMessage = message;
80
		return this;
81
	}
82
83
	/**
84
	 * Adds a validator ensuring that the parsed date is after the given date.
85
	 * Uses the current {@link #afterMessage(String) validation message}.
86
	 * 
87
	 * @param date
88
	 *            The date which the parsed date must be after.
89
	 * @return This constraints instance for method chaining.
90
	 * 
91
	 * @see Date#after(Date)
92
	 */
93
	public DateConstraints after(Date date) {
94
		addValidator(DateRangeValidator
95
				.after(date, afterMessage, displayFormat));
96
		return this;
97
	}
98
99
	/**
100
	 * Sets the validation message pattern for the {@link #after(Date)}
101
	 * constraint.
102
	 * 
103
	 * @param message
104
	 *            The validation message pattern for the {@link #after(Date)}
105
	 *            constraint. Can be parameterized with the date which the
106
	 *            parsed date must be after.
107
	 * @return This constraints instance for method chaining.
108
	 * 
109
	 * @see #after(Date)
110
	 */
111
	public DateConstraints afterMessage(String message) {
112
		this.afterMessage = message;
113
		return this;
114
	}
115
116
	/**
117
	 * Adds a validator ensuring that the parsed date is after or on the given
118
	 * date. Uses the current {@link #afterEqualMessage(String) validation
119
	 * message}.
120
	 * 
121
	 * @param date
122
	 *            The date which the parsed date must be after or on.
123
	 * @return This constraints instance for method chaining.
124
	 * 
125
	 * @see Date#after(Date)
126
	 * @see Date#equals(Object)
127
	 */
128
	public DateConstraints afterEqual(Date date) {
129
		addValidator(DateRangeValidator.afterEqual(date, afterEqualMessage,
130
				displayFormat));
131
		return this;
132
	}
133
134
	/**
135
	 * Sets the validation message pattern for the {@link #afterEqual(Date)}
136
	 * constraint.
137
	 * 
138
	 * @param message
139
	 *            The validation message pattern for the
140
	 *            {@link #afterEqual(Date)} constraint. Can be parameterized
141
	 *            with the date which the parsed date must be after or on.
142
	 * @return This constraints instance for method chaining.
143
	 * 
144
	 * @see #afterEqual(Date)
145
	 */
146
	public DateConstraints afterEqualMessage(String message) {
147
		this.afterEqualMessage = message;
148
		return this;
149
	}
150
151
	/**
152
	 * Adds a validator ensuring that the parsed date is before the given date.
153
	 * Uses the current {@link #beforeMessage(String) validation message}.
154
	 * 
155
	 * @param date
156
	 *            The date which the parsed date must be before
157
	 * @return This constraints instance for method chaining.
158
	 * 
159
	 * @see Date#before(Date)
160
	 */
161
	public DateConstraints before(Date date) {
162
		addValidator(DateRangeValidator.before(date, beforeMessage,
163
				displayFormat));
164
		return this;
165
	}
166
167
	/**
168
	 * Sets the validation message pattern for the {@link #before(Date)}
169
	 * constraint.
170
	 * 
171
	 * @param message
172
	 *            The validation message pattern for the {@link #before(Date)}
173
	 *            constraint. Can be parameterized with the date which the
174
	 *            parsed date must be before.
175
	 * @return This constraints instance for method chaining.
176
	 * 
177
	 * @see #before(Date)
178
	 */
179
	public DateConstraints beforeMessage(String message) {
180
		this.beforeMessage = message;
181
		return this;
182
	}
183
184
	/**
185
	 * Adds a validator ensuring that the parsed date is before or on the given
186
	 * date. Uses the current {@link #beforeEqualMessage(String) validation
187
	 * message}.
188
	 * 
189
	 * @param date
190
	 *            The date which the parsed date must be before or on.
191
	 * @return This constraints instance for method chaining.
192
	 * 
193
	 * @see Date#before(Date)
194
	 * @see Date#equals(Object)
195
	 */
196
	public DateConstraints beforeEqual(Date date) {
197
		addValidator(DateRangeValidator.beforeEqual(date, beforeEqualMessage,
198
				displayFormat));
199
		return this;
200
	}
201
202
	/**
203
	 * Sets the validation message pattern for the {@link #beforeEqual(Date)}
204
	 * constraint.
205
	 * 
206
	 * @param message
207
	 *            The validation message pattern for the
208
	 *            {@link #beforeEqual(Date)} constraint. Can be parameterized
209
	 *            with the date which the parsed date must be before or on.
210
	 * @return This constraints instance for method chaining.
211
	 * 
212
	 * @see #beforeEqual(Date)
213
	 */
214
	public DateConstraints beforeEqualMessage(String message) {
215
		this.beforeEqualMessage = message;
216
		return this;
217
	}
218
219
	/**
220
	 * Adds a validator ensuring that the parsed date is within the given range.
221
	 * Uses the current {@link #rangeMessage(String) validation message}.
222
	 * 
223
	 * @param minDate
224
	 *            The lower bound of the range (inclusive).
225
	 * @param maxDate
226
	 *            The upper bound of the range (inclusive).
227
	 * @return This constraints instance for method chaining.
228
	 */
229
	public DateConstraints range(Date minDate, Date maxDate) {
230
		addValidator(DateRangeValidator.range(minDate, maxDate, rangeMessage,
231
				displayFormat));
232
		return this;
233
	}
234
235
	/**
236
	 * Sets the validation message pattern for the {@link #range(Date, Date)}
237
	 * constraint.
238
	 * 
239
	 * @param message
240
	 *            The validation message pattern for the
241
	 *            {@link #range(Date, Date)} constraint. Can be parameterized
242
	 *            with the min and max dates of the range in which the parsed
243
	 *            date must lie.
244
	 * @return This constraints instance for method chaining.
245
	 * 
246
	 * @see #range(Date, Date)
247
	 */
248
	public DateConstraints rangeMessage(String message) {
249
		this.rangeMessage = message;
250
		return this;
251
	}
252
}
(-)src/org/eclipse/core/internal/databinding/conversion/StringTrimConverter.java (+45 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.conversion;
13
14
import org.eclipse.core.databinding.conversion.Converter;
15
16
/**
17
 * @since 1.4
18
 */
19
public class StringTrimConverter extends Converter {
20
21
	private final boolean trimToNull;
22
23
	/**
24
	 * 
25
	 * @param trimToNull
26
	 */
27
	public StringTrimConverter(boolean trimToNull) {
28
		super(String.class, String.class);
29
		this.trimToNull = trimToNull;
30
	}
31
32
	public Object convert(Object fromObject) {
33
		String string = (String) fromObject;
34
35
		if (string != null) {
36
			string = string.trim();
37
38
			if (trimToNull && string.length() == 0) {
39
				string = null;
40
			}
41
		}
42
43
		return string;
44
	}
45
}
(-)src/org/eclipse/core/databinding/editing/BooleanEditing.java (+203 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import org.eclipse.core.databinding.validation.constraint.BooleanConstraints;
15
import org.eclipse.core.databinding.validation.constraint.Constraints;
16
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
17
import org.eclipse.core.internal.databinding.conversion.BooleanToStringConverter;
18
import org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter;
19
import org.eclipse.core.internal.databinding.validation.StringToBooleanValidator;
20
21
/**
22
 * @since 1.4
23
 */
24
public final class BooleanEditing extends Editing {
25
26
	private BooleanEditing(String[] trueValues, String[] falseValues,
27
			String parseErrorMessage) {
28
		StringToBooleanConverter targetConverter = new StringToBooleanConverter();
29
		BooleanToStringConverter modelConverter = new BooleanToStringConverter(
30
				Boolean.class);
31
32
		StringToBooleanValidator targetValidator = new StringToBooleanValidator();
33
		if (parseErrorMessage != null) {
34
			targetValidator.setParseErrorMessage(parseErrorMessage);
35
		}
36
37
		if (trueValues != null && falseValues != null) {
38
			targetValidator.setSourceStrings(trueValues, falseValues);
39
			targetConverter.setSourceStrings(trueValues, falseValues);
40
			modelConverter.setTargetStrings(trueValues[0], falseValues[0]);
41
		}
42
43
		setTargetConverter(targetConverter);
44
		setModelConverter(modelConverter);
45
		addTargetValidator(targetValidator);
46
	}
47
48
	/**
49
	 * Creates a new editing object which uses the default set of string
50
	 * representations for boolean values for parsing and displaying.
51
	 * 
52
	 * @return The new editing object for the default set of string
53
	 *         representations for boolean values.
54
	 */
55
	public static BooleanEditing withDefaults() {
56
		return withDefaults(null);
57
	}
58
59
	/**
60
	 * Creates a new editing object which uses the default set of string
61
	 * representations for boolean values for parsing and displaying. Uses the
62
	 * specified custom validation message.
63
	 * 
64
	 * @param parseErrorMessage
65
	 *            The validation message issued in case the input string cannot
66
	 *            be parsed to a boolean.
67
	 * @return The new editing object for the default set of string
68
	 *         representations for boolean values.
69
	 */
70
	public static BooleanEditing withDefaults(String parseErrorMessage) {
71
		return new BooleanEditing(null, null, parseErrorMessage);
72
	}
73
74
	/**
75
	 * Creates a new editing object which uses the given set of string
76
	 * representations for boolean values for parsing and displaying.
77
	 * 
78
	 * <p>
79
	 * For parsing, the given string values will be considered valid
80
	 * representations of {@code true} and {@code false}, respectively. For
81
	 * displaying, the first element of the respective array will be used for
82
	 * representing the corresponding boolean value.
83
	 * </p>
84
	 * 
85
	 * @param trueValues
86
	 *            The set of strings representing a <code>true</code> value.
87
	 * @param falseValues
88
	 *            The set of strings representing a <code>false</code> value.
89
	 * @return The new editing object for the given set of string
90
	 *         representations for boolean values.
91
	 */
92
	public static BooleanEditing forStringValues(String[] trueValues,
93
			String[] falseValues) {
94
		return forStringValues(trueValues, falseValues, null);
95
	}
96
97
	/**
98
	 * Creates a new editing object which uses the given set of string
99
	 * representations for boolean values for parsing and displaying. Uses the
100
	 * specified custom validation message.
101
	 * 
102
	 * <p>
103
	 * For parsing, the given string values will be considered valid
104
	 * representations of {@code true} and {@code false}, respectively. For
105
	 * displaying, the first element of the respective array will be used for
106
	 * representing the corresponding boolean value.
107
	 * </p>
108
	 * 
109
	 * @param trueValues
110
	 *            The set of strings representing a <code>true</code> value.
111
	 * @param falseValues
112
	 *            The set of strings representing a <code>false</code> value.
113
	 * @param parseErrorMessage
114
	 *            The validation message issued in case the input string cannot
115
	 *            be parsed to a boolean.
116
	 * @return The new editing object for the given set of string
117
	 *         representations for boolean values.
118
	 */
119
	public static BooleanEditing forStringValues(String[] trueValues,
120
			String[] falseValues, String parseErrorMessage) {
121
		return new BooleanEditing(trueValues, falseValues, parseErrorMessage);
122
	}
123
124
	/**
125
	 * Returns the target constraints to apply.
126
	 * 
127
	 * <p>
128
	 * This method provides a typesafe access to the {@link StringConstraints
129
	 * string target constraints} of this editing object and is equivalent to
130
	 * {@code (StringConstraints) targetConstraints()}.
131
	 * </p>
132
	 * 
133
	 * @return The target constraints to apply.
134
	 * 
135
	 * @see #targetConstraints()
136
	 * @see StringConstraints
137
	 */
138
	public StringConstraints targetStringConstraints() {
139
		return (StringConstraints) targetConstraints();
140
	}
141
142
	/**
143
	 * Returns the model constraints to apply.
144
	 * 
145
	 * <p>
146
	 * This method provides a typesafe access to the {@link BooleanConstraints
147
	 * bool model constraints} of this editing object and is equivalent to
148
	 * {@code (BooleanConstraints) modelConstraints()}.
149
	 * </p>
150
	 * 
151
	 * @return The model constraints to apply.
152
	 * 
153
	 * @see #modelConstraints()
154
	 * @see BooleanConstraints
155
	 */
156
	public BooleanConstraints modelBooleanConstraints() {
157
		return (BooleanConstraints) modelConstraints();
158
	}
159
160
	/**
161
	 * Returns the before-set model constraints to apply.
162
	 * 
163
	 * <p>
164
	 * This method provides a typesafe access to the {@link BooleanConstraints
165
	 * bool before-set model constraints} of this editing object and is
166
	 * equivalent to {@code (BooleanConstraints) beforeSetModelConstraints()}.
167
	 * </p>
168
	 * 
169
	 * @return The before-set model constraints to apply.
170
	 * 
171
	 * @see #beforeSetModelConstraints()
172
	 * @see BooleanConstraints
173
	 */
174
	public BooleanConstraints beforeSetModelBooleanConstraints() {
175
		return (BooleanConstraints) beforeSetModelConstraints();
176
	}
177
178
	protected Constraints createTargetConstraints() {
179
		return new StringConstraints();
180
	}
181
182
	protected Constraints createModelConstraints() {
183
		return new BooleanConstraints();
184
	}
185
186
	protected Constraints createBeforeSetModelConstraints() {
187
		return new BooleanConstraints();
188
	}
189
190
	/**
191
	 * Convenience method which adds a {@link BooleanConstraints#required()
192
	 * required constraint} to the set of {@link #modelBooleanConstraints()}.
193
	 * 
194
	 * @return This editing instance for method chaining.
195
	 * 
196
	 * @see BooleanConstraints#required()
197
	 * @see #modelBooleanConstraints()
198
	 */
199
	public BooleanEditing required() {
200
		modelBooleanConstraints().required();
201
		return this;
202
	}
203
}
(-)src/org/eclipse/core/databinding/validation/constraint/BooleanConstraints.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
15
16
/**
17
 * @since 1.4
18
 */
19
public final class BooleanConstraints extends Constraints {
20
21
	private String requiredMessage = null;
22
23
	/**
24
	 * Adds a validator ensuring that the boolean value is not <code>null</code>
25
	 * . Uses the current {@link #requiredMessage(String) validation message}.
26
	 * 
27
	 * @return This constraints instance for method chaining.
28
	 */
29
	public BooleanConstraints required() {
30
		addValidator(new NonNullValidator(requiredMessage));
31
		return this;
32
	}
33
34
	/**
35
	 * Sets the validation message for the {@link #required()} constraint.
36
	 * 
37
	 * @param message
38
	 *            The validation message for the {@link #required()} constraint.
39
	 * @return This constraints instance for method chaining.
40
	 * 
41
	 * @see #required()
42
	 */
43
	public BooleanConstraints requiredMessage(String message) {
44
		this.requiredMessage = message;
45
		return this;
46
	}
47
}
(-)src/org/eclipse/core/databinding/validation/constraint/BigDecimalConstraints.java (+369 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import java.math.BigDecimal;
15
16
import org.eclipse.core.internal.databinding.validation.BigDecimalRangeValidator;
17
import org.eclipse.core.internal.databinding.validation.DecimalScaleValidator;
18
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
19
20
import com.ibm.icu.text.NumberFormat;
21
22
/**
23
 * @since 1.4
24
 */
25
public final class BigDecimalConstraints extends Constraints {
26
27
	private NumberFormat bigDecimalFormat = NumberFormat.getNumberInstance();
28
29
	private NumberFormat integerFormat = NumberFormat.getIntegerInstance();
30
31
	private String requiredMessage = null;
32
33
	private String greaterMessage = null;
34
35
	private String greaterEqualMessage = null;
36
37
	private String lessMessage = null;
38
39
	private String lessEqualMessage = null;
40
41
	private String rangeMessage = null;
42
43
	private String positiveMessage = null;
44
45
	private String nonNegativeMessage = null;
46
47
	private String maxScaleMessage = null;
48
49
	/**
50
	 * Sets the format to use when formatting a BigDecimal to be included in any
51
	 * of the validation messages.
52
	 * 
53
	 * <p>
54
	 * This BigDecimal format will be used for any subsequent constraints which
55
	 * are applied.
56
	 * </p>
57
	 * 
58
	 * @param format
59
	 *            The format to use for displaying BigDecimals in validation
60
	 *            messages.
61
	 * @return This constraints instance for method chaining.
62
	 */
63
	public BigDecimalConstraints bigDecimalFormat(NumberFormat format) {
64
		this.bigDecimalFormat = format;
65
		return this;
66
	}
67
68
	/**
69
	 * Sets the format to use when formatting an integer to be included in any
70
	 * of the validation messages.
71
	 * 
72
	 * <p>
73
	 * This integer format will be used for any subsequent constraints which are
74
	 * applied.
75
	 * </p>
76
	 * 
77
	 * @param format
78
	 *            The format to use for displaying integers in validation
79
	 *            messages.
80
	 * @return This constraints instance for method chaining.
81
	 * 
82
	 * @see #maxScale(int)
83
	 */
84
	public BigDecimalConstraints integerFormat(NumberFormat format) {
85
		this.integerFormat = format;
86
		return this;
87
	}
88
89
	/**
90
	 * Adds a validator ensuring that the parsed BigDecimal is not
91
	 * <code>null</code>. Uses the current {@link #requiredMessage(String)
92
	 * validation message}.
93
	 * 
94
	 * @return This constraints instance for method chaining.
95
	 */
96
	public BigDecimalConstraints required() {
97
		addValidator(new NonNullValidator(requiredMessage));
98
		return this;
99
	}
100
101
	/**
102
	 * Sets the validation message for the {@link #required()} constraint.
103
	 * 
104
	 * @param message
105
	 *            The validation message for the {@link #required()} constraint.
106
	 * @return This constraints instance for method chaining.
107
	 * 
108
	 * @see #required()
109
	 */
110
	public BigDecimalConstraints requiredMessage(String message) {
111
		this.requiredMessage = message;
112
		return this;
113
	}
114
115
	/**
116
	 * Adds a validator ensuring that the parsed BigDecimal is greater than the
117
	 * given number. Uses the current {@link #greaterMessage(String) validation
118
	 * message}.
119
	 * 
120
	 * @param number
121
	 *            The number which the parsed BigDecimal must be greater than.
122
	 * @return This constraints instance for method chaining.
123
	 */
124
	public BigDecimalConstraints greater(BigDecimal number) {
125
		addValidator(BigDecimalRangeValidator.greater(number, greaterMessage,
126
				bigDecimalFormat));
127
		return this;
128
	}
129
130
	/**
131
	 * Sets the validation message pattern for the {@link #greater(BigDecimal)}
132
	 * constraint.
133
	 * 
134
	 * @param message
135
	 *            The validation message pattern for the
136
	 *            {@link #greater(BigDecimal)} constraint. Can be parameterized
137
	 *            with the number which the parsed BigDecimal must be greater
138
	 *            than.
139
	 * @return This constraints instance for method chaining.
140
	 * 
141
	 * @see #greater(BigDecimal)
142
	 */
143
	public BigDecimalConstraints greaterMessage(String message) {
144
		this.greaterMessage = message;
145
		return this;
146
	}
147
148
	/**
149
	 * Adds a validator ensuring that the parsed BigDecimal is greater than or
150
	 * equal to the given number. Uses the current
151
	 * {@link #greaterEqualMessage(String) validation message}.
152
	 * 
153
	 * @param number
154
	 *            The number which the parsed BigDecimal must be greater than or
155
	 *            equal to.
156
	 * @return This constraints instance for method chaining.
157
	 */
158
	public BigDecimalConstraints greaterEqual(BigDecimal number) {
159
		addValidator(BigDecimalRangeValidator.greaterEqual(number,
160
				greaterEqualMessage, bigDecimalFormat));
161
		return this;
162
	}
163
164
	/**
165
	 * Sets the validation message pattern for the
166
	 * {@link #greaterEqual(BigDecimal)} constraint.
167
	 * 
168
	 * @param message
169
	 *            The validation message pattern for the
170
	 *            {@link #greaterEqual(BigDecimal)} constraint. Can be
171
	 *            parameterized with the number which the parsed BigDecimal must
172
	 *            be greater than or equal to.
173
	 * @return This constraints instance for method chaining.
174
	 * 
175
	 * @see #greaterEqual(BigDecimal)
176
	 */
177
	public BigDecimalConstraints greaterEqualMessage(String message) {
178
		this.greaterEqualMessage = message;
179
		return this;
180
	}
181
182
	/**
183
	 * Adds a validator ensuring that the parsed BigDecimal is less than the
184
	 * given number. Uses the current {@link #lessMessage(String) validation
185
	 * message}.
186
	 * 
187
	 * @param number
188
	 *            The number which the parsed BigDecimal must be less than.
189
	 * @return This constraints instance for method chaining.
190
	 */
191
	public BigDecimalConstraints less(BigDecimal number) {
192
		addValidator(BigDecimalRangeValidator.less(number, lessMessage,
193
				bigDecimalFormat));
194
		return this;
195
	}
196
197
	/**
198
	 * Sets the validation message pattern for the {@link #less(BigDecimal)}
199
	 * constraint.
200
	 * 
201
	 * @param message
202
	 *            The validation message pattern for the
203
	 *            {@link #less(BigDecimal)} constraint. Can be parameterized
204
	 *            with the number which the parsed BigDecimal must be less than.
205
	 * @return This constraints instance for method chaining.
206
	 * 
207
	 * @see #less(BigDecimal)
208
	 */
209
	public BigDecimalConstraints lessMessage(String message) {
210
		this.lessMessage = message;
211
		return this;
212
	}
213
214
	/**
215
	 * Adds a validator ensuring that the parsed BigDecimal is less than or
216
	 * equal to the given number. Uses the current
217
	 * {@link #lessEqualMessage(String) validation message}.
218
	 * 
219
	 * @param number
220
	 *            The number which the parsed BigDecimal must be less than or
221
	 *            equal to.
222
	 * @return This constraints instance for method chaining.
223
	 */
224
	public BigDecimalConstraints lessEqual(BigDecimal number) {
225
		addValidator(BigDecimalRangeValidator.greaterEqual(number,
226
				lessEqualMessage, bigDecimalFormat));
227
		return this;
228
	}
229
230
	/**
231
	 * Sets the validation message pattern for the
232
	 * {@link #lessEqual(BigDecimal)} constraint.
233
	 * 
234
	 * @param message
235
	 *            The validation message pattern for the
236
	 *            {@link #lessEqual(BigDecimal)} constraint. Can be
237
	 *            parameterized with the number which the parsed BigDecimal must
238
	 *            be less than or equal to.
239
	 * @return This constraints instance for method chaining.
240
	 * 
241
	 * @see #lessEqual(BigDecimal)
242
	 */
243
	public BigDecimalConstraints lessEqualMessage(String message) {
244
		this.lessEqualMessage = message;
245
		return this;
246
	}
247
248
	/**
249
	 * Adds a validator ensuring that the parsed BigDecimal is within the given
250
	 * range. Uses the current {@link #rangeMessage(String) validation message}.
251
	 * 
252
	 * @param min
253
	 *            The lower bound of the range (inclusive).
254
	 * @param max
255
	 *            The upper bound of the range (inclusive).
256
	 * @return This constraints instance for method chaining.
257
	 */
258
	public BigDecimalConstraints range(BigDecimal min, BigDecimal max) {
259
		addValidator(BigDecimalRangeValidator.range(min, max, rangeMessage,
260
				bigDecimalFormat));
261
		return this;
262
	}
263
264
	/**
265
	 * Sets the validation message pattern for the
266
	 * {@link #range(BigDecimal, BigDecimal)} constraint.
267
	 * 
268
	 * @param message
269
	 *            The validation message pattern for the
270
	 *            {@link #range(BigDecimal, BigDecimal)} constraint. Can be
271
	 *            parameterized with the min and max values of the range in
272
	 *            which the parsed BigDecimal must lie.
273
	 * @return This constraints instance for method chaining.
274
	 * 
275
	 * @see #range(BigDecimal, BigDecimal)
276
	 */
277
	public BigDecimalConstraints rangeMessage(String message) {
278
		this.rangeMessage = message;
279
		return this;
280
	}
281
282
	/**
283
	 * Adds a validator ensuring that the parsed BigDecimal is positive. Uses
284
	 * the current {@link #positiveMessage(String) validation message}.
285
	 * 
286
	 * @return This constraints instance for method chaining.
287
	 */
288
	public BigDecimalConstraints positive() {
289
		addValidator(BigDecimalRangeValidator.positive(positiveMessage,
290
				bigDecimalFormat));
291
		return this;
292
	}
293
294
	/**
295
	 * Sets the validation message pattern for the {@link #positive()}
296
	 * constraint.
297
	 * 
298
	 * @param message
299
	 *            The validation message pattern for the {@link #positive()}
300
	 *            constraint.
301
	 * @return This constraints instance for method chaining.
302
	 * 
303
	 * @see #positive()
304
	 */
305
	public BigDecimalConstraints positiveMessage(String message) {
306
		this.positiveMessage = message;
307
		return this;
308
	}
309
310
	/**
311
	 * Adds a validator ensuring that the parsed BigDecimal is non-negative.
312
	 * Uses the current {@link #nonNegativeMessage(String) validation message}.
313
	 * 
314
	 * @return This constraints instance for method chaining.
315
	 */
316
	public BigDecimalConstraints nonNegative() {
317
		addValidator(BigDecimalRangeValidator.nonNegative(nonNegativeMessage,
318
				bigDecimalFormat));
319
		return this;
320
	}
321
322
	/**
323
	 * Sets the validation message pattern for the {@link #nonNegative()}
324
	 * constraint.
325
	 * 
326
	 * @param message
327
	 *            The validation message pattern for the {@link #nonNegative()}
328
	 *            constraint.
329
	 * @return This constraints instance for method chaining.
330
	 * 
331
	 * @see #nonNegative()
332
	 */
333
	public BigDecimalConstraints nonNegativeMessage(String message) {
334
		this.nonNegativeMessage = message;
335
		return this;
336
	}
337
338
	/**
339
	 * Adds a validator ensuring that the parsed BigDecimal's scale is not
340
	 * greater than the given one. Uses the current
341
	 * {@link #maxScaleMessage(String) validation message}.
342
	 * 
343
	 * @param scale
344
	 *            The maximum scale to enforce on the parsed BigDecimal.
345
	 * @return This constraints instance for method chaining.
346
	 */
347
	public BigDecimalConstraints maxScale(int scale) {
348
		addValidator(DecimalScaleValidator.max(scale, maxScaleMessage,
349
				integerFormat));
350
		return this;
351
	}
352
353
	/**
354
	 * Sets the validation message pattern for the {@link #maxScale(int)}
355
	 * constraint.
356
	 * 
357
	 * @param message
358
	 *            The validation message pattern for the {@link #maxScale(int)}
359
	 *            constraint. Can be parameterized with the maximum scale of the
360
	 *            BigDecimal.
361
	 * @return This constraints instance for method chaining.
362
	 * 
363
	 * @see #maxScale(int)
364
	 */
365
	public BigDecimalConstraints maxScaleMessage(String message) {
366
		this.maxScaleMessage = message;
367
		return this;
368
	}
369
}
(-)src/org/eclipse/core/internal/databinding/validation/BigIntegerRangeValidator.java (+206 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.math.BigInteger;
15
16
import com.ibm.icu.text.NumberFormat;
17
18
/**
19
 * Provides validations for BigIntegers which must lie within an open/closed
20
 * range.
21
 * 
22
 * @since 1.4
23
 */
24
public class BigIntegerRangeValidator extends NumberRangeValidator {
25
26
	private static final BigInteger ZERO = new BigInteger("0"); //$NON-NLS-1$
27
	private static final BigInteger ONE = new BigInteger("1"); //$NON-NLS-1$
28
29
	/**
30
	 * Single constructor which supports the individual integer range types.
31
	 * 
32
	 * @param min
33
	 *            The min BigInteger of the range or <code>null</code> in case
34
	 *            no lower bound is defined.
35
	 * @param max
36
	 *            The max BigInteger of the range or <code>null</code> in case
37
	 *            no upper bound is defined.
38
	 * @param minConstraint
39
	 *            The type of constraint imposed by the lower bound of the
40
	 *            range.
41
	 * @param maxConstraint
42
	 *            The type of constraint imposed by the upper bound of the
43
	 *            range.
44
	 * @param validationMessage
45
	 *            The validation message pattern to use. Can be parameterized by
46
	 *            the lower and upper bound of the range, if defined.
47
	 * @param format
48
	 *            The BigInteger format to use for formatting integers in the
49
	 *            validation message.
50
	 */
51
	private BigIntegerRangeValidator(BigInteger min, BigInteger max,
52
			int minConstraint, int maxConstraint, String validationMessage,
53
			NumberFormat format) {
54
		super(min, max, minConstraint, maxConstraint, validationMessage, format);
55
	}
56
57
	/**
58
	 * Creates a validator which checks that an input BigInteger is greater than
59
	 * the given number.
60
	 * 
61
	 * @param number
62
	 *            The reference number of the greater constraint.
63
	 * @param validationMessage
64
	 *            The validation message pattern to use. Can be parameterized
65
	 *            with the given reference number.
66
	 * @param format
67
	 *            The display format to use for formatting BigIntegers in the
68
	 *            validation message.
69
	 * @return The validator instance.
70
	 */
71
	public static BigIntegerRangeValidator greater(BigInteger number,
72
			String validationMessage, NumberFormat format) {
73
		return new BigIntegerRangeValidator(number, null, GREATER, UNDEFINED,
74
				defaultIfNull(validationMessage, GREATER_MESSAGE), format);
75
	}
76
77
	/**
78
	 * Creates a validator which checks that an input BigInteger is greater than
79
	 * or equal to the given number.
80
	 * 
81
	 * @param number
82
	 *            The reference number of the greater-equal constraint.
83
	 * @param validationMessage
84
	 *            The validation message pattern to use. Can be parameterized
85
	 *            with the given reference number.
86
	 * @param format
87
	 *            The display format to use for formatting BigIntegers in the
88
	 *            validation message.
89
	 * @return The validator instance.
90
	 */
91
	public static BigIntegerRangeValidator greaterEqual(BigInteger number,
92
			String validationMessage, NumberFormat format) {
93
		return new BigIntegerRangeValidator(number, null, GREATER_EQUAL,
94
				UNDEFINED, defaultIfNull(validationMessage,
95
						GREATER_EQUAL_MESSAGE), format);
96
	}
97
98
	/**
99
	 * Creates a validator which checks that an input BigInteger is less than
100
	 * the given number.
101
	 * 
102
	 * @param number
103
	 *            The reference number of the less constraint.
104
	 * @param validationMessage
105
	 *            The validation message pattern to use. Can be parameterized
106
	 *            with the given reference number.
107
	 * @param format
108
	 *            The display format to use for formatting BigIntegers in the
109
	 *            validation message.
110
	 * @return The validator instance.
111
	 */
112
	public static BigIntegerRangeValidator less(BigInteger number,
113
			String validationMessage, NumberFormat format) {
114
		return new BigIntegerRangeValidator(null, number, UNDEFINED, LESS,
115
				defaultIfNull(validationMessage, LESS_MESSAGE), format);
116
	}
117
118
	/**
119
	 * Creates a validator which checks that an input BigInteger is less than or
120
	 * equal to the given number.
121
	 * 
122
	 * @param number
123
	 *            The reference number of the less-equal constraint.
124
	 * @param validationMessage
125
	 *            The validation message pattern to use. Can be parameterized
126
	 *            with the given reference number.
127
	 * @param format
128
	 *            The display format to use for formatting BigIntegers in the
129
	 *            validation message.
130
	 * @return The validator instance.
131
	 */
132
	public static BigIntegerRangeValidator lessEqual(BigInteger number,
133
			String validationMessage, NumberFormat format) {
134
		return new BigIntegerRangeValidator(null, number, UNDEFINED,
135
				LESS_EQUAL,
136
				defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
137
	}
138
139
	/**
140
	 * Creates a validator which checks that an input BigInteger is within the
141
	 * given range.
142
	 * 
143
	 * @param min
144
	 *            The lower bound of the range (inclusive).
145
	 * @param max
146
	 *            The upper bound of the range (inclusive).
147
	 * @param validationMessage
148
	 *            The validation message pattern to use. Can be parameterized
149
	 *            with the range's lower and upper bound.
150
	 * @param format
151
	 *            The display format to use for formatting BigIntegers in the
152
	 *            validation message.
153
	 * @return The validator instance.
154
	 */
155
	public static BigIntegerRangeValidator range(BigInteger min,
156
			BigInteger max, String validationMessage, NumberFormat format) {
157
		return new BigIntegerRangeValidator(min, max, GREATER_EQUAL,
158
				LESS_EQUAL, defaultIfNull(validationMessage,
159
						WITHIN_RANGE_MESSAGE), format);
160
	}
161
162
	/**
163
	 * Creates a validator which checks that an input BigInteger is positive.
164
	 * 
165
	 * @param validationMessage
166
	 *            The validation message to use.
167
	 * @param format
168
	 *            The display format to use for formatting BigIntegers in the
169
	 *            validation message.
170
	 * @return The validator instance.
171
	 */
172
	public static BigIntegerRangeValidator positive(String validationMessage,
173
			NumberFormat format) {
174
		return new BigIntegerRangeValidator(ONE, null, GREATER_EQUAL,
175
				UNDEFINED, defaultIfNull(validationMessage, POSITIVE_MESSAGE),
176
				format);
177
	}
178
179
	/**
180
	 * Creates a validator which checks that an input BigInteger is
181
	 * non-negative.
182
	 * 
183
	 * @param validationMessage
184
	 *            The validation message to use.
185
	 * @param format
186
	 *            The display format to use for formatting BigIntegers in the
187
	 *            validation message.
188
	 * @return The validator instance.
189
	 */
190
	public static BigIntegerRangeValidator nonNegative(
191
			String validationMessage, NumberFormat format) {
192
		return new BigIntegerRangeValidator(ZERO, null, GREATER_EQUAL,
193
				UNDEFINED, defaultIfNull(validationMessage,
194
						NON_NEGATIVE_MESSAGE), format);
195
	}
196
197
	protected int compare(Number number1, Number number2) {
198
		BigInteger bigInteger1 = (BigInteger) number1;
199
		BigInteger bigInteger2 = (BigInteger) number2;
200
		return bigInteger1.compareTo(bigInteger2);
201
	}
202
203
	private static String defaultIfNull(String string, String defaultString) {
204
		return (string != null) ? string : defaultString;
205
	}
206
}
(-)src/org/eclipse/core/internal/databinding/validation/StringToBigDecimalValidator.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
/**
15
 * Validates that a string is of the appropriate format for a BigDecimal.
16
 * 
17
 * @since 1.4
18
 */
19
public class StringToBigDecimalValidator extends
20
		AbstractStringToNumberValidator {
21
22
	/**
23
	 * @param converter
24
	 */
25
	public StringToBigDecimalValidator(NumberFormatConverter converter) {
26
		super(converter, null, null);
27
	}
28
29
	protected boolean isInRange(Number number) {
30
		return true;
31
	}
32
}
(-)src/org/eclipse/core/internal/databinding/validation/StringToBooleanValidator.java (+117 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.util.Arrays;
15
import java.util.LinkedList;
16
import java.util.List;
17
import java.util.StringTokenizer;
18
19
import org.eclipse.core.databinding.validation.IValidator;
20
import org.eclipse.core.databinding.validation.ValidationStatus;
21
import org.eclipse.core.internal.databinding.BindingMessages;
22
import org.eclipse.core.runtime.IStatus;
23
24
/**
25
 * @since 1.4
26
 */
27
public class StringToBooleanValidator implements IValidator {
28
29
	// TODO: Some of this code is duplicated from StringToBooleanPrimitiveConverter!
30
	private static final String[] DEFAULT_TRUE_VALUES;
31
	private static final String[] DEFAULT_FALSE_VALUES;
32
33
	static {
34
		String delimiter = BindingMessages.getString(BindingMessages.VALUE_DELIMITER);
35
		String values = BindingMessages.getString(BindingMessages.TRUE_STRING_VALUES);
36
		DEFAULT_TRUE_VALUES = valuesToSortedArray(delimiter, values);
37
38
		values = BindingMessages.getString(BindingMessages.FALSE_STRING_VALUES);
39
		DEFAULT_FALSE_VALUES = valuesToSortedArray(delimiter, values);
40
	}
41
42
	private String[] trueValues = DEFAULT_TRUE_VALUES;
43
	private String[] falseValues = DEFAULT_FALSE_VALUES;
44
45
	private String parseErrorMessage = BindingMessages.getString(BindingMessages.VALIDATE_INVALID_BOOLEAN_STRING);
46
47
	/**
48
	 * Returns a sorted array with all values converted to upper case.
49
	 *
50
	 * @param delimiter
51
	 * @param values
52
	 * @return sorted array of values
53
	 */
54
	private static String[] valuesToSortedArray(String delimiter, String values) {
55
		List list = new LinkedList();
56
		StringTokenizer tokenizer = new StringTokenizer(values, delimiter);
57
		while (tokenizer.hasMoreTokens()) {
58
			list.add(tokenizer.nextToken().toUpperCase());
59
		}
60
61
		String[] array = (String[]) list.toArray(new String[list.size()]);
62
		Arrays.sort(array);
63
64
		return array;
65
	}
66
67
	/**
68
	 * Sets the validation message to be used in case the source string does not
69
	 * represent a valid boolean value.
70
	 * 
71
	 * @param message
72
	 *            The validation message to be used in case the source string
73
	 *            does not represent a valid boolean value.
74
	 */
75
	public final void setParseErrorMessage(String message) {
76
		this.parseErrorMessage = message;
77
	}
78
79
	/**
80
	 * Sets the string values which are considered to represent a
81
	 * <code>true</code> and <code>false</code> value, respectively.
82
	 * 
83
	 * <p>
84
	 * Note that the capitalization of the provided strings is ignored.
85
	 * </p>
86
	 * 
87
	 * @param trueValues
88
	 *            The set of strings representing a <code>true</code> value.
89
	 * @param falseValues
90
	 *            The set of strings representing a <code>false</code> value.
91
	 */
92
	public final void setSourceStrings(String[] trueValues, String[] falseValues) {
93
		this.trueValues = new String[trueValues.length];
94
		for (int i = 0; i < trueValues.length; i++) {
95
			this.trueValues[i] = trueValues[i].toUpperCase();
96
		}
97
		Arrays.sort(this.trueValues); // for binary search
98
99
		this.falseValues = new String[falseValues.length];
100
		for (int i = 0; i < falseValues.length; i++) {
101
			this.falseValues[i] = falseValues[i].toUpperCase();
102
		}
103
		Arrays.sort(this.falseValues); // for binary search
104
	}
105
106
	public IStatus validate(Object value) {
107
		String source = (String) value;
108
		if (source != null && source.length() != 0) {
109
			source = source.toUpperCase();
110
			if (Arrays.binarySearch(trueValues, source) < 0
111
					&& Arrays.binarySearch(falseValues, source) < 0) {
112
				return ValidationStatus.error(parseErrorMessage);
113
			}
114
		}
115
		return ValidationStatus.ok();
116
	}
117
}
(-)src/org/eclipse/core/databinding/validation/constraint/Constraints.java (+211 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import java.util.ArrayList;
15
import java.util.Iterator;
16
import java.util.List;
17
18
import org.eclipse.core.databinding.util.Policy;
19
import org.eclipse.core.databinding.validation.IValidator;
20
import org.eclipse.core.internal.databinding.BindingMessages;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.MultiStatus;
23
import org.eclipse.core.runtime.Status;
24
25
/**
26
 * @since 1.4
27
 */
28
public class Constraints {
29
30
	/**
31
	 * Constant denoting an aggregation strategy that merges multiple non-OK
32
	 * status objects in a {@link MultiStatus}. Returns an OK status result if
33
	 * all statuses from the set of validators to apply are an OK status.
34
	 * Returns a single status if there is only one non-OK status.
35
	 * 
36
	 * @see #aggregationPolicy(int)
37
	 */
38
	public static final int AGGREGATION_MERGED = 1;
39
40
	/**
41
	 * Constant denoting an aggregation strategy that always returns the
42
	 * <i>most</i> severe status from the set of validators to apply. If there
43
	 * is more than one status at the same severity level, it picks the first
44
	 * one it encounters.
45
	 * 
46
	 * @see #aggregationPolicy(int)
47
	 */
48
	public static final int AGGREGATION_MAX_SEVERITY = 2;
49
50
	/**
51
	 * Constant denoting an aggregation strategy that always returns the
52
	 * <i>least</i> severe status from the set of validators to apply. If there
53
	 * is more than one status at the same severity level, it picks the first
54
	 * one it encounters.
55
	 * 
56
	 * @see #aggregationPolicy(int)
57
	 */
58
	public static final int AGGREGATION_MIN_SEVERITY = 3;
59
60
	// Will be initialized lazily.
61
	private List validators = null;
62
63
	private IValidator cachedValidator = null;
64
65
	private int aggregationPolicy = AGGREGATION_MAX_SEVERITY;
66
67
	/**
68
	 * Adds a custom validator to the set of constraints to apply.
69
	 * 
70
	 * @param validator
71
	 *            The custom validator to add to the set of constraints.
72
	 * @return This constraints instance for method chaining.
73
	 */
74
	public final Constraints addValidator(IValidator validator) {
75
		if (validators == null) {
76
			validators = new ArrayList(2);
77
		}
78
		validators.add(validator);
79
		cachedValidator = null;
80
		return this;
81
	}
82
83
	/**
84
	 * Sets the aggregation policy to apply to the individual validations which
85
	 * constitute this set of constraints.
86
	 * 
87
	 * @param policy
88
	 *            The validation aggregation policy to set. Must be one of
89
	 *            {@link #AGGREGATION_MERGED}, {@link #AGGREGATION_MAX_SEVERITY}
90
	 *            or {@link #AGGREGATION_MIN_SEVERITY}.
91
	 * @return This constraints instance for method chaining.
92
	 * 
93
	 * @see #AGGREGATION_MERGED
94
	 * @see #AGGREGATION_MAX_SEVERITY
95
	 * @see #AGGREGATION_MIN_SEVERITY
96
	 */
97
	public final Constraints aggregationPolicy(int policy) {
98
		this.aggregationPolicy = policy;
99
		cachedValidator = null;
100
		return this;
101
	}
102
103
	/**
104
	 * Creates a validator which enforces the current set of constraints.
105
	 * 
106
	 * <p>
107
	 * Note that this method will return <code>null</code> in case the set of
108
	 * constraints to apply is empty.
109
	 * </p>
110
	 * 
111
	 * @return A validator which enforces the current set of constraints. May be
112
	 *         <code>null</code>.
113
	 */
114
	public final IValidator createValidator() {
115
		if (validators != null && !validators.isEmpty()) {
116
			if (cachedValidator == null) {
117
				if (validators.size() == 1) {
118
					cachedValidator = (IValidator) validators.get(0);
119
				} else {
120
					IValidator[] currentValidators = (IValidator[]) validators
121
							.toArray(new IValidator[validators.size()]);
122
					cachedValidator = new ConstraintsValidator(
123
							currentValidators, aggregationPolicy);
124
				}
125
			}
126
			return cachedValidator;
127
		}
128
		return null;
129
	}
130
131
	private static final class ConstraintsValidator implements IValidator {
132
133
		private final IValidator[] validators;
134
135
		private final int aggregationPolicy;
136
137
		public ConstraintsValidator(IValidator[] validators,
138
				int aggregationPolicy) {
139
			this.validators = validators;
140
			this.aggregationPolicy = aggregationPolicy;
141
		}
142
143
		public IStatus validate(Object value) {
144
			switch (aggregationPolicy) {
145
			case AGGREGATION_MERGED:
146
				return validateMerged(value);
147
			case AGGREGATION_MAX_SEVERITY:
148
				return validateMaxSeverity(value);
149
			case AGGREGATION_MIN_SEVERITY:
150
				return validateMinSeverity(value);
151
			default:
152
				throw new IllegalArgumentException(
153
						"Unsupported aggregationPolicy: " + aggregationPolicy); //$NON-NLS-1$
154
			}
155
		}
156
157
		private IStatus validateMerged(Object value) {
158
			List statuses = new ArrayList();
159
			for (int i = 0; i < validators.length; i++) {
160
				IValidator validator = validators[i];
161
				IStatus status = validator.validate(value);
162
				if (!status.isOK()) {
163
					statuses.add(status);
164
				}
165
			}
166
167
			if (statuses.size() == 1) {
168
				return (IStatus) statuses.get(0);
169
			}
170
171
			if (!statuses.isEmpty()) {
172
				MultiStatus result = new MultiStatus(Policy.JFACE_DATABINDING,
173
						0, BindingMessages
174
								.getString(BindingMessages.MULTIPLE_PROBLEMS),
175
						null);
176
				for (Iterator it = statuses.iterator(); it.hasNext();) {
177
					IStatus status = (IStatus) it.next();
178
					result.merge(status);
179
				}
180
				return result;
181
			}
182
183
			return Status.OK_STATUS;
184
		}
185
186
		private IStatus validateMaxSeverity(Object value) {
187
			IStatus maxStatus = Status.OK_STATUS;
188
			for (int i = 0; i < validators.length; i++) {
189
				IValidator validator = validators[i];
190
				IStatus status = validator.validate(value);
191
				if (status.getSeverity() > maxStatus.getSeverity()) {
192
					maxStatus = status;
193
				}
194
			}
195
			return maxStatus;
196
		}
197
198
		private IStatus validateMinSeverity(Object value) {
199
			IStatus minStatus = null;
200
			for (int i = 0; i < validators.length; i++) {
201
				IValidator validator = validators[i];
202
				IStatus status = validator.validate(value);
203
				if (minStatus == null
204
						|| status.getSeverity() < minStatus.getSeverity()) {
205
					minStatus = status;
206
				}
207
			}
208
			return minStatus != null ? minStatus : Status.OK_STATUS;
209
		}
210
	}
211
}
(-)src/org/eclipse/core/databinding/editing/Editing.java (+1009 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import org.eclipse.core.databinding.Binding;
15
import org.eclipse.core.databinding.DataBindingContext;
16
import org.eclipse.core.databinding.UpdateListStrategy;
17
import org.eclipse.core.databinding.UpdateSetStrategy;
18
import org.eclipse.core.databinding.UpdateValueStrategy;
19
import org.eclipse.core.databinding.conversion.IConverter;
20
import org.eclipse.core.databinding.observable.list.IObservableList;
21
import org.eclipse.core.databinding.observable.set.IObservableSet;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.validation.IValidator;
24
import org.eclipse.core.databinding.validation.constraint.Constraints;
25
import org.eclipse.core.runtime.IStatus;
26
import org.eclipse.core.runtime.MultiStatus;
27
28
/**
29
 * @since 1.4
30
 */
31
public class Editing {
32
33
	private Constraints targetConstraints;
34
35
	private Constraints modelConstraints;
36
37
	private Constraints beforeSetModelConstraints;
38
39
	private IConverter targetConverter;
40
41
	private IConverter modelConverter;
42
43
	/**
44
	 * Default constructor which creates an unconfigured editing instance.
45
	 */
46
	protected Editing() {
47
		// empty editing instance
48
	}
49
50
	/**
51
	 * Creates an unconfigured editing instance.
52
	 * 
53
	 * @return A new, unconfigured editing instance.
54
	 */
55
	public static Editing create() {
56
		return new Editing();
57
	}
58
59
	/**
60
	 * Creates an editing instance with the given target-to-model and
61
	 * model-to-target converters.
62
	 * 
63
	 * @param t2mConverter
64
	 *            The target-to-model converter to set. May be <code>null</code>
65
	 *            .
66
	 * @param m2tConverter
67
	 *            The model-to-target converter to set. May be <code>null</code>
68
	 *            .
69
	 * @return A new editing instance with the given target-to-model and
70
	 *         model-to-target converters.
71
	 */
72
	public static Editing withConverters(IConverter t2mConverter,
73
			IConverter m2tConverter) {
74
		Editing editing = new Editing();
75
		editing.setTargetConverter(t2mConverter);
76
		editing.setModelConverter(m2tConverter);
77
		return editing;
78
	}
79
80
	/**
81
	 * Returns the target constraints to apply.
82
	 * 
83
	 * @return The target constraints to apply.
84
	 * 
85
	 * @see #createTargetConstraints()
86
	 */
87
	public final Constraints targetConstraints() {
88
		if (targetConstraints == null) {
89
			targetConstraints = createTargetConstraints();
90
		}
91
		return targetConstraints;
92
	}
93
94
	/**
95
	 * Returns the model constraints to apply.
96
	 * 
97
	 * @return The model constraints to apply.
98
	 * 
99
	 * @see #createModelConstraints()
100
	 */
101
	public final Constraints modelConstraints() {
102
		if (modelConstraints == null) {
103
			modelConstraints = createModelConstraints();
104
		}
105
		return modelConstraints;
106
	}
107
108
	/**
109
	 * Returns the before-set model constraints to apply.
110
	 * 
111
	 * @return The before-set model constraints to apply.
112
	 * 
113
	 * @see #createBeforeSetModelConstraints()
114
	 */
115
	public final Constraints beforeSetModelConstraints() {
116
		if (beforeSetModelConstraints == null) {
117
			beforeSetModelConstraints = createBeforeSetModelConstraints();
118
		}
119
		return beforeSetModelConstraints;
120
	}
121
122
	/**
123
	 * Creates the target constraints to apply.
124
	 * 
125
	 * <p>
126
	 * The constraints object created by this method will be exposed as the
127
	 * {@link #targetConstraints()} of this editing object. By default, this
128
	 * method returns a plain {@link Constraints} object.
129
	 * </p>
130
	 * 
131
	 * <p>
132
	 * This method will be called lazily the first time the target constraints
133
	 * are accessed. Subclasses may overwrite this method in order to create a
134
	 * custom constraints object which will then be typically exposed in the
135
	 * subclass as API in order to allow for a typesafe access.
136
	 * </p>
137
	 * 
138
	 * @return The target constraints to apply.
139
	 * 
140
	 * @see #targetConstraints()
141
	 */
142
	protected Constraints createTargetConstraints() {
143
		return new Constraints();
144
	}
145
146
	/**
147
	 * Creates the model constraints to apply.
148
	 * 
149
	 * <p>
150
	 * The constraints object created by this method will be exposed as the
151
	 * {@link #modelConstraints()} of this editing object. By default, this
152
	 * method returns a plain {@link Constraints} object.
153
	 * </p>
154
	 * 
155
	 * <p>
156
	 * This method will be called lazily the first time the model constraints
157
	 * are accessed. Subclasses may overwrite this method in order to create a
158
	 * custom constraints object which will then be typically exposed in the
159
	 * subclass as API in order to allow for a typesafe access.
160
	 * </p>
161
	 * 
162
	 * @return The model constraints to apply.
163
	 * 
164
	 * @see #modelConstraints()
165
	 */
166
	protected Constraints createModelConstraints() {
167
		return new Constraints();
168
	}
169
170
	/**
171
	 * Creates the before-set model constraints to apply.
172
	 * 
173
	 * <p>
174
	 * The constraints object created by this method will be exposed as the
175
	 * {@link #beforeSetModelConstraints()} of this editing object. By default,
176
	 * this method returns a plain {@link Constraints} object.
177
	 * </p>
178
	 * 
179
	 * <p>
180
	 * This method will be called lazily the first time the before-set model
181
	 * constraints are accessed. Subclasses may overwrite this method in order
182
	 * to create a custom constraints object which will then be typically
183
	 * exposed in the subclass as API in order to allow for a typesafe access.
184
	 * </p>
185
	 * 
186
	 * @return The before-set model constraints to apply.
187
	 * 
188
	 * @see #beforeSetModelConstraints()
189
	 */
190
	protected Constraints createBeforeSetModelConstraints() {
191
		return new Constraints();
192
	}
193
194
	/**
195
	 * Convenience method which {@link Constraints#addValidator(IValidator)
196
	 * adds} the given validator to the set of {@link #targetConstraints()}.
197
	 * 
198
	 * @param validator
199
	 *            The validator to add to the target constraints.
200
	 * @return This editing instance for method chaining.
201
	 * 
202
	 * @see Constraints#addValidator(IValidator)
203
	 * @see #targetConstraints()
204
	 */
205
	public final Editing addTargetValidator(IValidator validator) {
206
		targetConstraints().addValidator(validator);
207
		return this;
208
	}
209
210
	/**
211
	 * Convenience method which {@link Constraints#addValidator(IValidator)
212
	 * adds} the given validator to the set of {@link #modelConstraints()}.
213
	 * 
214
	 * @param validator
215
	 *            The validator to add to the model constraints.
216
	 * @return This editing instance for method chaining.
217
	 * 
218
	 * @see Constraints#addValidator(IValidator)
219
	 * @see #modelConstraints()
220
	 */
221
	public final Editing addModelValidator(IValidator validator) {
222
		modelConstraints().addValidator(validator);
223
		return this;
224
	}
225
226
	/**
227
	 * Convenience method which {@link Constraints#addValidator(IValidator)
228
	 * adds} the given validator to the set of
229
	 * {@link #beforeSetModelConstraints()}.
230
	 * 
231
	 * @param validator
232
	 *            The validator to add to the before-set model constraints.
233
	 * @return This editing instance for method chaining.
234
	 * 
235
	 * @see Constraints#addValidator(IValidator)
236
	 * @see #beforeSetModelConstraints
237
	 */
238
	public final Editing addBeforeSetModelValidator(IValidator validator) {
239
		beforeSetModelConstraints().addValidator(validator);
240
		return this;
241
	}
242
243
	/**
244
	 * Sets the target-to-model converter for this editing instance.
245
	 * 
246
	 * @param converter
247
	 *            The target-to-model converter to set.
248
	 */
249
	protected final void setTargetConverter(IConverter converter) {
250
		this.targetConverter = converter;
251
	}
252
253
	/**
254
	 * Sets the model-to-target converter for this editing instance.
255
	 * 
256
	 * @param converter
257
	 *            The model-to-target converter to set.
258
	 */
259
	protected final void setModelConverter(IConverter converter) {
260
		this.modelConverter = converter;
261
	}
262
263
	/**
264
	 * Creates a new target-to-model {@link UpdateValueStrategy} with a default
265
	 * update policy configured by the current state of this editing object.
266
	 * 
267
	 * @return A new target-to-model {@link UpdateValueStrategy} configured by
268
	 *         the current state of this editing object.
269
	 * 
270
	 * @see UpdateValueStrategy#UpdateValueStrategy()
271
	 * @see #adaptT2MValueStrategy(UpdateValueStrategy)
272
	 */
273
	public final UpdateValueStrategy createT2MValueStrategy() {
274
		return adaptT2MValueStrategy(new UpdateValueStrategy());
275
	}
276
277
	/**
278
	 * Creates a new target-to-model {@link UpdateValueStrategy} with the given
279
	 * update policy configured by the current state of this editing object.
280
	 * 
281
	 * @param updatePolicy
282
	 *            The update policy to use.
283
	 * @return A new target-to-model {@link UpdateValueStrategy} configured by
284
	 *         the current state of this editing object.
285
	 * 
286
	 * @see UpdateValueStrategy#UpdateValueStrategy(int)
287
	 * @see #adaptT2MValueStrategy(UpdateValueStrategy)
288
	 */
289
	public final UpdateValueStrategy createT2MValueStrategy(int updatePolicy) {
290
		return adaptT2MValueStrategy(new UpdateValueStrategy(updatePolicy));
291
	}
292
293
	/**
294
	 * Creates a new model-to-target {@link UpdateValueStrategy} with a default
295
	 * update policy configured by the current state of this editing object.
296
	 * 
297
	 * @return A new model-to-target {@link UpdateValueStrategy} configured by
298
	 *         the current state of this editing object.
299
	 * 
300
	 * @see UpdateValueStrategy#UpdateValueStrategy()
301
	 * @see #adaptM2TValueStrategy(UpdateValueStrategy)
302
	 */
303
	public final UpdateValueStrategy createM2TValueStrategy() {
304
		return adaptM2TValueStrategy(new UpdateValueStrategy());
305
	}
306
307
	/**
308
	 * Creates a new model-to-target {@link UpdateValueStrategy} with the given
309
	 * update policy configured by the current state of this editing object.
310
	 * 
311
	 * @param updatePolicy
312
	 *            The update policy to use.
313
	 * @return A new model-to-target {@link UpdateValueStrategy} configured by
314
	 *         the current state of this editing object.
315
	 * 
316
	 * @see UpdateValueStrategy#UpdateValueStrategy(int)
317
	 * @see #adaptM2TValueStrategy(UpdateValueStrategy)
318
	 */
319
	public final UpdateValueStrategy createM2TValueStrategy(int updatePolicy) {
320
		return adaptM2TValueStrategy(new UpdateValueStrategy(updatePolicy));
321
	}
322
323
	/**
324
	 * Creates a new target-to-model {@link UpdateListStrategy} with a default
325
	 * update policy configured by the current state of this editing object.
326
	 * 
327
	 * @return A new target-to-model {@link UpdateListStrategy} configured by
328
	 *         the current state of this editing object.
329
	 * 
330
	 * @see UpdateListStrategy#UpdateListStrategy()
331
	 * @see #adaptT2MListStrategy(UpdateListStrategy)
332
	 */
333
	public final UpdateListStrategy createT2MListStrategy() {
334
		return adaptT2MListStrategy(new UpdateListStrategy());
335
	}
336
337
	/**
338
	 * Creates a new target-to-model {@link UpdateListStrategy} with the given
339
	 * update policy configured by the current state of this editing object.
340
	 * 
341
	 * @param updatePolicy
342
	 *            The update policy to use.
343
	 * @return A new target-to-model {@link UpdateListStrategy} configured by
344
	 *         the current state of this editing object.
345
	 * 
346
	 * @see UpdateListStrategy#UpdateListStrategy(int)
347
	 * @see #adaptT2MListStrategy(UpdateListStrategy)
348
	 */
349
	public final UpdateListStrategy createT2MListStrategy(int updatePolicy) {
350
		return adaptT2MListStrategy(new UpdateListStrategy(updatePolicy));
351
	}
352
353
	/**
354
	 * Creates a new model-to-target {@link UpdateListStrategy} with a default
355
	 * update policy configured by the current state of this editing object.
356
	 * 
357
	 * @return A new model-to-target {@link UpdateListStrategy} configured by
358
	 *         the current state of this editing object.
359
	 * 
360
	 * @see UpdateListStrategy#UpdateListStrategy()
361
	 * @see #adaptM2TListStrategy(UpdateListStrategy)
362
	 */
363
	public final UpdateListStrategy createM2TListStrategy() {
364
		return adaptM2TListStrategy(new UpdateListStrategy());
365
	}
366
367
	/**
368
	 * Creates a new model-to-target {@link UpdateListStrategy} with the given
369
	 * update policy configured by the current state of this editing object.
370
	 * 
371
	 * @param updatePolicy
372
	 *            The update policy to use.
373
	 * @return A new model-to-target {@link UpdateListStrategy} configured by
374
	 *         the current state of this editing object.
375
	 * 
376
	 * @see UpdateListStrategy#UpdateListStrategy(int)
377
	 * @see #adaptM2TListStrategy(UpdateListStrategy)
378
	 */
379
	public final UpdateListStrategy createM2TListStrategy(int updatePolicy) {
380
		return adaptM2TListStrategy(new UpdateListStrategy(updatePolicy));
381
	}
382
383
	/**
384
	 * Creates a new target-to-model {@link UpdateSetStrategy} with a default
385
	 * update policy configured by the current state of this editing object.
386
	 * 
387
	 * @return A new target-to-model {@link UpdateSetStrategy} configured by the
388
	 *         current state of this editing object.
389
	 * 
390
	 * @see UpdateListStrategy#UpdateListStrategy()
391
	 * @see #adaptT2MSetStrategy(UpdateSetStrategy)
392
	 */
393
	public final UpdateSetStrategy createT2MSetStrategy() {
394
		return adaptT2MSetStrategy(new UpdateSetStrategy());
395
	}
396
397
	/**
398
	 * Creates a new target-to-model {@link UpdateListStrategy} with the given
399
	 * update policy configured by the current state of this editing object.
400
	 * 
401
	 * @param updatePolicy
402
	 *            The update policy to use.
403
	 * @return A new target-to-model {@link UpdateListStrategy} configured by
404
	 *         the current state of this editing object.
405
	 * 
406
	 * @see UpdateSetStrategy#UpdateSetStrategy(int)
407
	 * @see #adaptT2MSetStrategy(UpdateSetStrategy)
408
	 */
409
	public final UpdateSetStrategy createT2MSetStrategy(int updatePolicy) {
410
		return adaptT2MSetStrategy(new UpdateSetStrategy(updatePolicy));
411
	}
412
413
	/**
414
	 * Creates a new model-to-target {@link UpdateSetStrategy} with a default
415
	 * update policy configured by the current state of this editing object.
416
	 * 
417
	 * @return A new model-to-target {@link UpdateSetStrategy} configured by the
418
	 *         current state of this editing object.
419
	 * 
420
	 * @see UpdateSetStrategy#UpdateSetStrategy()
421
	 * @see #adaptM2TSetStrategy(UpdateSetStrategy)
422
	 */
423
	public final UpdateSetStrategy createM2TSetStrategy() {
424
		return adaptM2TSetStrategy(new UpdateSetStrategy());
425
	}
426
427
	/**
428
	 * Creates a new model-to-target {@link UpdateSetStrategy} with the given
429
	 * update policy configured by the current state of this editing object.
430
	 * 
431
	 * @param updatePolicy
432
	 *            The update policy to use.
433
	 * @return A new model-to-target {@link UpdateSetStrategy} configured by the
434
	 *         current state of this editing object.
435
	 * 
436
	 * @see UpdateSetStrategy#UpdateSetStrategy(int)
437
	 * @see #adaptM2TSetStrategy(UpdateSetStrategy)
438
	 */
439
	public final UpdateSetStrategy createM2TSetStrategy(int updatePolicy) {
440
		return adaptM2TSetStrategy(new UpdateSetStrategy(updatePolicy));
441
	}
442
443
	/**
444
	 * Configures an existing target-to-model {@link UpdateValueStrategy} with
445
	 * the current state of this editing object.
446
	 * 
447
	 * <p>
448
	 * The configuration is done as follows:
449
	 * <ul>
450
	 * <li>
451
	 * The {@link Constraints#createValidator() validator} of the
452
	 * {@link #targetConstraints() target constraints} is set as the
453
	 * {@link UpdateValueStrategy#setAfterGetValidator(IValidator) after-get
454
	 * validator} of the update strategy.</li>
455
	 * <li>The {@link #setTargetConverter(IConverter) target converter} is set
456
	 * as the {@link UpdateValueStrategy#setConverter(IConverter) converter} of
457
	 * the update strategy.</li>
458
	 * <li>
459
	 * The {@link Constraints#createValidator() validator} of the
460
	 * {@link #modelConstraints() model constraints} is set as the
461
	 * {@link UpdateValueStrategy#setAfterConvertValidator(IValidator)
462
	 * after-convert validator} of the update strategy.</li>
463
	 * <li>The {@link Constraints#createValidator() validator} of the
464
	 * {@link #beforeSetModelConstraints() before-set model constraints} is set
465
	 * as the {@link UpdateValueStrategy#setBeforeSetValidator(IValidator)
466
	 * before-set validator} of the update strategy.</li>
467
	 * </ul>
468
	 * </p>
469
	 * 
470
	 * @param updateStrategy
471
	 *            The {@link UpdateValueStrategy} to configure.
472
	 * @return The passed-in, configured target-to-model
473
	 *         {@link UpdateValueStrategy}.
474
	 * 
475
	 * @see UpdateValueStrategy#setAfterGetValidator(IValidator)
476
	 * @see UpdateValueStrategy#setConverter(IConverter)
477
	 * @see UpdateValueStrategy#setAfterConvertValidator(IValidator)
478
	 * @see UpdateValueStrategy#setBeforeSetValidator(IValidator)
479
	 */
480
	public final UpdateValueStrategy adaptT2MValueStrategy(
481
			UpdateValueStrategy updateStrategy) {
482
		updateStrategy.setAfterGetValidator(createValidator(targetConstraints));
483
		updateStrategy.setConverter(targetConverter);
484
		updateStrategy
485
				.setAfterConvertValidator(createValidator(modelConstraints));
486
		updateStrategy
487
				.setBeforeSetValidator(createValidator(beforeSetModelConstraints));
488
		return updateStrategy;
489
	}
490
491
	/**
492
	 * Configures an existing model-to-target {@link UpdateValueStrategy} with
493
	 * the current state of this editing object by setting the
494
	 * {@link #setModelConverter(IConverter) model converter} as the
495
	 * {@link UpdateValueStrategy#setConverter(IConverter) converter} of the
496
	 * update strategy.
497
	 * 
498
	 * @param updateStrategy
499
	 *            The {@link UpdateValueStrategy} to configure.
500
	 * @return The passed-in, configured model-to-target
501
	 *         {@link UpdateValueStrategy}.
502
	 * 
503
	 * @see UpdateValueStrategy#setConverter(IConverter)
504
	 */
505
	public final UpdateValueStrategy adaptM2TValueStrategy(
506
			UpdateValueStrategy updateStrategy) {
507
		updateStrategy.setConverter(modelConverter);
508
		return updateStrategy;
509
	}
510
511
	/**
512
	 * Configures an existing target-to-model {@link UpdateListStrategy} with
513
	 * the current state of this editing object by setting the
514
	 * {@link #setTargetConverter(IConverter) target converter} as the
515
	 * {@link UpdateListStrategy#setConverter(IConverter) converter} of the
516
	 * update strategy.
517
	 * 
518
	 * @param updateStrategy
519
	 *            The {@link UpdateListStrategy} to configure.
520
	 * @return The passed-in, configured target-to-model
521
	 *         {@link UpdateListStrategy}.
522
	 * 
523
	 * @see UpdateListStrategy#setConverter(IConverter)
524
	 */
525
	public final UpdateListStrategy adaptT2MListStrategy(
526
			UpdateListStrategy updateStrategy) {
527
		updateStrategy.setConverter(targetConverter);
528
		return updateStrategy;
529
	}
530
531
	/**
532
	 * Configures an existing model-to-target {@link UpdateListStrategy} with
533
	 * the current state of this editing object by setting the
534
	 * {@link #setModelConverter(IConverter) model converter} as the
535
	 * {@link UpdateListStrategy#setConverter(IConverter) converter} of the
536
	 * update strategy.
537
	 * 
538
	 * @param updateStrategy
539
	 *            The {@link UpdateListStrategy} to configure.
540
	 * @return The passed-in, configured model-to-target
541
	 *         {@link UpdateListStrategy}.
542
	 * 
543
	 * @see UpdateListStrategy#setConverter(IConverter)
544
	 */
545
	public final UpdateListStrategy adaptM2TListStrategy(
546
			UpdateListStrategy updateStrategy) {
547
		updateStrategy.setConverter(modelConverter);
548
		return updateStrategy;
549
	}
550
551
	/**
552
	 * Configures an existing target-to-model {@link UpdateListStrategy} with
553
	 * the current state of this editing object by setting the
554
	 * {@link #setTargetConverter(IConverter) target converter} as the
555
	 * {@link UpdateSetStrategy#setConverter(IConverter) converter} of the
556
	 * update strategy.
557
	 * 
558
	 * @param updateStrategy
559
	 *            The {@link UpdateSetStrategy} to configure.
560
	 * @return The passed-in, configured target-to-model
561
	 *         {@link UpdateSetStrategy}.
562
	 * 
563
	 * @see UpdateSetStrategy#setConverter(IConverter)
564
	 */
565
	public final UpdateSetStrategy adaptT2MSetStrategy(
566
			UpdateSetStrategy updateStrategy) {
567
		updateStrategy.setConverter(targetConverter);
568
		return updateStrategy;
569
	}
570
571
	/**
572
	 * Configures an existing model-to-target {@link UpdateSetStrategy} with the
573
	 * current state of this editing object by setting the
574
	 * {@link #setModelConverter(IConverter) model converter} as the
575
	 * {@link UpdateSetStrategy#setConverter(IConverter) converter} of the
576
	 * update strategy.
577
	 * 
578
	 * @param updateStrategy
579
	 *            The {@link UpdateSetStrategy} to configure.
580
	 * @return The passed-in, configured model-to-target
581
	 *         {@link UpdateSetStrategy}.
582
	 * 
583
	 * @see UpdateSetStrategy#setConverter(IConverter)
584
	 */
585
	public final UpdateSetStrategy adaptM2TSetStrategy(
586
			UpdateSetStrategy updateStrategy) {
587
		updateStrategy.setConverter(modelConverter);
588
		return updateStrategy;
589
	}
590
591
	/**
592
	 * Converts a target value to a model value by performing the following
593
	 * steps:
594
	 * <ul>
595
	 * <li>
596
	 * Applying all the {@link #targetConstraints() target constraints} to the
597
	 * given target value.</li>
598
	 * <li>
599
	 * {@link #setTargetConverter(IConverter) Converting} the target value to
600
	 * the model value.</li>
601
	 * <li>
602
	 * Applying all the {@link #modelConstraints() model constraints} to the
603
	 * converted model value.</li>
604
	 * <li>
605
	 * Applying all the {@link #beforeSetModelConstraints() before-set model
606
	 * constraints} to the converted model value.</li>
607
	 * </ul>
608
	 * 
609
	 * <p>
610
	 * The conversion process will be aborted by returning <code>null</code>
611
	 * whenever any of the applied validators produces a {@link IStatus
612
	 * validation status} having {@link IStatus#getSeverity() severity}
613
	 * <code>IStatus.ERROR</code> or <code>IStatus.CANCEL</code>. During the
614
	 * conversion process, any validation status whose severity is different
615
	 * from <code>IStatus.OK</code> will be {@link MultiStatus#merge(IStatus)
616
	 * aggregated} on the given <code>validationStatus</code>.
617
	 * </p>
618
	 * 
619
	 * @param targetValue
620
	 *            The target value to be converted to a model value.
621
	 * @param validationStatus
622
	 *            Aggregate validation status to which to add the validations
623
	 *            produced during the conversion process. May be
624
	 *            <code>null</code>.
625
	 * @return The converted model value or <code>null</code> in case the
626
	 *         conversion has been aborted due to a validation error.
627
	 */
628
	public final Object convertToModel(Object targetValue,
629
			MultiStatus validationStatus) {
630
		if (!applyConstraints(targetConstraints, targetValue, validationStatus)) {
631
			return null;
632
		}
633
634
		Object modelValue = (targetConverter != null) ? targetConverter
635
				.convert(targetValue) : targetValue;
636
637
		if (!applyConstraints(modelConstraints, modelValue, validationStatus)) {
638
			return null;
639
		}
640
641
		if (!applyConstraints(beforeSetModelConstraints, modelValue,
642
				validationStatus)) {
643
			return null;
644
		}
645
646
		return modelValue;
647
	}
648
649
	/**
650
	 * {@link #setModelConverter(IConverter) Converts} a model value to a target
651
	 * value.
652
	 * 
653
	 * @param modelValue
654
	 *            The model value to be converted to a target value.
655
	 * @return The converted target value.
656
	 */
657
	public final Object convertToTarget(Object modelValue) {
658
		return (modelConverter != null) ? modelConverter.convert(modelValue)
659
				: modelValue;
660
	}
661
662
	/**
663
	 * Creates a binding between a target and model observable value on the
664
	 * given binding context by creating new update strategies which will be
665
	 * both configured with the state of this editing object before passing them
666
	 * to the binding.
667
	 * 
668
	 * <p>
669
	 * The target-to-model and model-to-target update strategies for the binding
670
	 * will be created by the methods {@link #createT2MValueStrategy()} and
671
	 * {@link #createM2TValueStrategy()}, respectively.
672
	 * </p>
673
	 * 
674
	 * @param dbc
675
	 *            The binding context on which to create the value binding.
676
	 * @param targetObservableValue
677
	 *            The target observable value of the binding.
678
	 * @param modelObservableValue
679
	 *            The model observable value of the binding.
680
	 * @return The new value binding.
681
	 * 
682
	 * @see #createT2MValueStrategy()
683
	 * @see #createM2TValueStrategy()
684
	 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
685
	 *      UpdateValueStrategy, UpdateValueStrategy)
686
	 */
687
	public final Binding bindValue(DataBindingContext dbc,
688
			IObservableValue targetObservableValue,
689
			IObservableValue modelObservableValue) {
690
		return dbc.bindValue(targetObservableValue, modelObservableValue,
691
				createT2MValueStrategy(), createM2TValueStrategy());
692
	}
693
694
	/**
695
	 * Creates a binding between a target and model observable value on the
696
	 * given binding context by creating new update strategies with the provided
697
	 * update policies which will be both configured with the state of this
698
	 * editing object before passing them to the binding.
699
	 * 
700
	 * @param dbc
701
	 *            The binding context on which to create the value binding.
702
	 * @param targetObservableValue
703
	 *            The target observable value of the binding.
704
	 * @param modelObservableValue
705
	 *            The model observable value of the binding.
706
	 * @param t2mUpdatePolicy
707
	 *            The update policy for the target-to-model
708
	 *            {@link UpdateValueStrategy} which is
709
	 *            {@link #createT2MValueStrategy(int) created} and passed to the
710
	 *            new binding.
711
	 * @param m2tUpdatePolicy
712
	 *            The update policy for the model-to-target
713
	 *            {@link UpdateValueStrategy} which is
714
	 *            {@link #createM2TValueStrategy(int) created} and passed to the
715
	 *            new binding.
716
	 * @return The new value binding.
717
	 * 
718
	 * @see #createT2MValueStrategy(int)
719
	 * @see #createM2TValueStrategy(int)
720
	 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
721
	 *      UpdateValueStrategy, UpdateValueStrategy)
722
	 */
723
	public final Binding bindValue(DataBindingContext dbc,
724
			IObservableValue targetObservableValue,
725
			IObservableValue modelObservableValue, int t2mUpdatePolicy,
726
			int m2tUpdatePolicy) {
727
		return dbc.bindValue(targetObservableValue, modelObservableValue,
728
				createT2MValueStrategy(t2mUpdatePolicy),
729
				createM2TValueStrategy(m2tUpdatePolicy));
730
	}
731
732
	/**
733
	 * Creates a binding between a target and model observable value on the
734
	 * given binding context by using the provided update strategies which will
735
	 * be both configured with the state of this editing object before passing
736
	 * them to the binding.
737
	 * 
738
	 * @param dbc
739
	 *            The binding context on which to create the value binding.
740
	 * @param targetObservableValue
741
	 *            The target observable value of the binding.
742
	 * @param modelObservableValue
743
	 *            The model observable value of the binding.
744
	 * @param t2mUpdateStrategy
745
	 *            The target-to-model {@link UpdateValueStrategy} of the binding
746
	 *            to be {@link #adaptT2MValueStrategy(UpdateValueStrategy)
747
	 *            configured} with the state of this editing object before
748
	 *            passing it to the binding.
749
	 * @param m2tUpdateStrategy
750
	 *            The model-to-target {@link UpdateValueStrategy} of the binding
751
	 *            to be {@link #adaptM2TValueStrategy(UpdateValueStrategy)
752
	 *            configured} with the state of this editing object before
753
	 *            passing it to the binding.
754
	 * @return The new value binding.
755
	 * 
756
	 * @see #adaptT2MValueStrategy(UpdateValueStrategy)
757
	 * @see #adaptM2TValueStrategy(UpdateValueStrategy)
758
	 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
759
	 *      UpdateValueStrategy, UpdateValueStrategy)
760
	 */
761
	public final Binding bindValue(DataBindingContext dbc,
762
			IObservableValue targetObservableValue,
763
			IObservableValue modelObservableValue,
764
			UpdateValueStrategy t2mUpdateStrategy,
765
			UpdateValueStrategy m2tUpdateStrategy) {
766
		return dbc.bindValue(targetObservableValue, modelObservableValue,
767
				adaptT2MValueStrategy(t2mUpdateStrategy),
768
				adaptM2TValueStrategy(m2tUpdateStrategy));
769
	}
770
771
	/**
772
	 * Creates a binding between a target and model observable list on the given
773
	 * binding context by creating new update strategies which will be both
774
	 * configured with the state of this editing object before passing them to
775
	 * the binding.
776
	 * 
777
	 * <p>
778
	 * The target-to-model and model-to-target update strategies for the binding
779
	 * will be created by the methods {@link #createT2MListStrategy()} and
780
	 * {@link #createM2TListStrategy()}, respectively.
781
	 * </p>
782
	 * 
783
	 * @param dbc
784
	 *            The binding context on which to create the list binding.
785
	 * @param targetObservableList
786
	 *            The target observable list of the binding.
787
	 * @param modelObservableList
788
	 *            The model observable list of the binding.
789
	 * @return The new list binding.
790
	 * 
791
	 * @see #createT2MListStrategy()
792
	 * @see #createM2TListStrategy()
793
	 * @see DataBindingContext#bindList(IObservableList, IObservableList,
794
	 *      UpdateListStrategy, UpdateListStrategy)
795
	 */
796
	public final Binding bindList(DataBindingContext dbc,
797
			IObservableList targetObservableList,
798
			IObservableList modelObservableList) {
799
		return dbc.bindList(targetObservableList, modelObservableList,
800
				createT2MListStrategy(), createM2TListStrategy());
801
	}
802
803
	/**
804
	 * Creates a binding between a target and model observable list on the given
805
	 * binding context by creating new update strategies with the provided
806
	 * update policies which will be both configured with the state of this
807
	 * editing object before passing them to the binding.
808
	 * 
809
	 * @param dbc
810
	 *            The binding context on which to create the list binding.
811
	 * @param targetObservableList
812
	 *            The target observable list of the binding.
813
	 * @param modelObservableList
814
	 *            The model observable list of the binding.
815
	 * @param t2mUpdatePolicy
816
	 *            The update policy for the target-to-model
817
	 *            {@link UpdateListStrategy} which is
818
	 *            {@link #createT2MListStrategy(int) created} and passed to the
819
	 *            new binding.
820
	 * @param m2tUpdatePolicy
821
	 *            The update policy for the model-to-target
822
	 *            {@link UpdateListStrategy} which is
823
	 *            {@link #createM2TListStrategy(int) created} and passed to the
824
	 *            new binding.
825
	 * @return The new list binding.
826
	 * 
827
	 * @see #createT2MListStrategy(int)
828
	 * @see #createM2TListStrategy(int)
829
	 * @see DataBindingContext#bindList(IObservableList, IObservableList,
830
	 *      UpdateListStrategy, UpdateListStrategy)
831
	 */
832
	public final Binding bindList(DataBindingContext dbc,
833
			IObservableList targetObservableList,
834
			IObservableList modelObservableList, int t2mUpdatePolicy,
835
			int m2tUpdatePolicy) {
836
		return dbc.bindList(targetObservableList, modelObservableList,
837
				createT2MListStrategy(t2mUpdatePolicy),
838
				createM2TListStrategy(m2tUpdatePolicy));
839
	}
840
841
	/**
842
	 * Creates a binding between a target and model observable list on the given
843
	 * binding context by using the provided update strategies which will be
844
	 * both configured with the state of this editing object before passing them
845
	 * to the binding.
846
	 * 
847
	 * @param dbc
848
	 *            The binding context on which to create the list binding.
849
	 * @param targetObservableList
850
	 *            The target observable list of the binding.
851
	 * @param modelObservableList
852
	 *            The model observable list of the binding.
853
	 * @param t2mUpdateStrategy
854
	 *            The target-to-model {@link UpdateListStrategy} of the binding
855
	 *            to be {@link #adaptT2MListStrategy(UpdateListStrategy)
856
	 *            configured} with the state of this editing object before
857
	 *            passing it to the binding.
858
	 * @param m2tUpdateStrategy
859
	 *            The model-to-target {@link UpdateListStrategy} of the binding
860
	 *            to be {@link #adaptM2TListStrategy(UpdateListStrategy)
861
	 *            configured} with the state of this editing object before
862
	 *            passing it to the binding.
863
	 * @return The new list binding.
864
	 * 
865
	 * @see #adaptT2MListStrategy(UpdateListStrategy)
866
	 * @see #adaptM2TListStrategy(UpdateListStrategy)
867
	 * @see DataBindingContext#bindList(IObservableList, IObservableList,
868
	 *      UpdateListStrategy, UpdateListStrategy)
869
	 */
870
	public final Binding bindList(DataBindingContext dbc,
871
			IObservableList targetObservableList,
872
			IObservableList modelObservableList,
873
			UpdateListStrategy t2mUpdateStrategy,
874
			UpdateListStrategy m2tUpdateStrategy) {
875
		return dbc.bindList(targetObservableList, modelObservableList,
876
				adaptT2MListStrategy(t2mUpdateStrategy),
877
				adaptM2TListStrategy(m2tUpdateStrategy));
878
	}
879
880
	/**
881
	 * Creates a binding between a target and model observable set on the given
882
	 * binding context by creating new update strategies which will be both
883
	 * configured with the state of this editing object before passing them to
884
	 * the binding.
885
	 * 
886
	 * <p>
887
	 * The target-to-model and model-to-target update strategies for the binding
888
	 * will be created by the methods {@link #createT2MSetStrategy()} and
889
	 * {@link #createM2TSetStrategy()}, respectively.
890
	 * </p>
891
	 * 
892
	 * @param dbc
893
	 *            The binding context on which to create the set binding.
894
	 * @param targetObservableSet
895
	 *            The target observable set of the binding.
896
	 * @param modelObservableSet
897
	 *            The model observable set of the binding.
898
	 * @return The new set binding.
899
	 * 
900
	 * @see #createT2MSetStrategy()
901
	 * @see #createM2TSetStrategy()
902
	 * @see DataBindingContext#bindSet(IObservableSet, IObservableSet,
903
	 *      UpdateSetStrategy, UpdateSetStrategy)
904
	 */
905
	public final Binding bindSet(DataBindingContext dbc,
906
			IObservableSet targetObservableSet,
907
			IObservableSet modelObservableSet) {
908
		return dbc.bindSet(targetObservableSet, modelObservableSet,
909
				createT2MSetStrategy(), createM2TSetStrategy());
910
	}
911
912
	/**
913
	 * Creates a binding between a target and model observable set on the given
914
	 * binding context by creating new update strategies with the provided
915
	 * update policies which will be both configured with the state of this
916
	 * editing object before passing them to the binding.
917
	 * 
918
	 * @param dbc
919
	 *            The binding context on which to create the set binding.
920
	 * @param targetObservableSet
921
	 *            The target observable set of the binding.
922
	 * @param modelObservableSet
923
	 *            The model observable set of the binding.
924
	 * @param t2mUpdatePolicy
925
	 *            The update policy for the target-to-model
926
	 *            {@link UpdateSetStrategy} which is
927
	 *            {@link #createT2MSetStrategy(int) created} and passed to the
928
	 *            new binding.
929
	 * @param m2tUpdatePolicy
930
	 *            The update policy for the model-to-target
931
	 *            {@link UpdateSetStrategy} which is
932
	 *            {@link #createM2TSetStrategy(int) created} and passed to the
933
	 *            new binding.
934
	 * @return The new set binding.
935
	 * 
936
	 * @see #createT2MSetStrategy(int)
937
	 * @see #createM2TSetStrategy(int)
938
	 * @see DataBindingContext#bindSet(IObservableSet, IObservableSet,
939
	 *      UpdateSetStrategy, UpdateSetStrategy)
940
	 */
941
	public final Binding bindSet(DataBindingContext dbc,
942
			IObservableSet targetObservableSet,
943
			IObservableSet modelObservableSet, int t2mUpdatePolicy,
944
			int m2tUpdatePolicy) {
945
		return dbc.bindSet(targetObservableSet, modelObservableSet,
946
				createT2MSetStrategy(t2mUpdatePolicy),
947
				createM2TSetStrategy(m2tUpdatePolicy));
948
	}
949
950
	/**
951
	 * Creates a binding between a target and model observable set on the given
952
	 * binding context by using the provided update strategies which will be
953
	 * both configured with the state of this editing object before passing them
954
	 * to the binding.
955
	 * 
956
	 * @param dbc
957
	 *            The binding context on which to create the set binding.
958
	 * @param targetObservableSet
959
	 *            The target observable set of the binding.
960
	 * @param modelObservableSet
961
	 *            The model observable set of the binding.
962
	 * @param t2mUpdateStrategy
963
	 *            The target-to-model {@link UpdateSetStrategy} of the binding
964
	 *            to be {@link #adaptT2MSetStrategy(UpdateSetStrategy)
965
	 *            configured} with the state of this editing object before
966
	 *            passing it to the binding.
967
	 * @param m2tUpdateStrategy
968
	 *            The model-to-target {@link UpdateSetStrategy} of the binding
969
	 *            to be {@link #adaptM2TSetStrategy(UpdateSetStrategy)
970
	 *            configured} with the state of this editing object before
971
	 *            passing it to the binding.
972
	 * @return The new set binding.
973
	 * 
974
	 * @see #adaptT2MSetStrategy(UpdateSetStrategy)
975
	 * @see #adaptM2TSetStrategy(UpdateSetStrategy)
976
	 * @see DataBindingContext#bindSet(IObservableSet, IObservableSet,
977
	 *      UpdateSetStrategy, UpdateSetStrategy)
978
	 */
979
	public final Binding bindSet(DataBindingContext dbc,
980
			IObservableSet targetObservableSet,
981
			IObservableSet modelObservableSet,
982
			UpdateSetStrategy t2mUpdateStrategy,
983
			UpdateSetStrategy m2tUpdateStrategy) {
984
		return dbc.bindSet(targetObservableSet, modelObservableSet,
985
				adaptT2MSetStrategy(t2mUpdateStrategy),
986
				adaptM2TSetStrategy(m2tUpdateStrategy));
987
	}
988
989
	private static IValidator createValidator(Constraints constraints) {
990
		return constraints != null ? constraints.createValidator() : null;
991
	}
992
993
	private static boolean applyConstraints(Constraints constraints,
994
			Object value, MultiStatus aggregateStatus) {
995
		IValidator validator = createValidator(constraints);
996
		if (validator != null) {
997
			IStatus validationStatus = validator.validate(value);
998
			if (aggregateStatus != null && !validationStatus.isOK()) {
999
				aggregateStatus.merge(validationStatus);
1000
			}
1001
			return isValid(validationStatus);
1002
		}
1003
		return true;
1004
	}
1005
1006
	private static boolean isValid(IStatus status) {
1007
		return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING);
1008
	}
1009
}
(-)src/org/eclipse/core/databinding/validation/constraint/StringConstraints.java (+264 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import java.util.regex.Pattern;
15
16
import org.eclipse.core.internal.databinding.validation.NonEmptyStringValidator;
17
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
18
import org.eclipse.core.internal.databinding.validation.StringLengthValidator;
19
import org.eclipse.core.internal.databinding.validation.StringRegexValidator;
20
21
import com.ibm.icu.text.NumberFormat;
22
23
/**
24
 * @since 1.4
25
 */
26
public final class StringConstraints extends Constraints {
27
28
	private NumberFormat integerDisplayFormat = NumberFormat
29
			.getIntegerInstance();
30
31
	private String requiredMessage = null;
32
33
	private String nonEmptyMessage = null;
34
35
	private String minLengthMessage = null;
36
37
	private String maxLengthMessage = null;
38
39
	private String lengthRangeMessage = null;
40
41
	private String matchesMessage = null;
42
43
	/**
44
	 * Sets the format to use when formatting an integer to be included in any
45
	 * of the validation messages.
46
	 * 
47
	 * <p>
48
	 * This integer format will be used for any subsequent constraints which are
49
	 * applied.
50
	 * </p>
51
	 * 
52
	 * @param format
53
	 *            The format to use for displaying integers in validation
54
	 *            messages.
55
	 * @return This constraints instance for method chaining.
56
	 * 
57
	 * @see #minLength(int)
58
	 * @see #maxLength(int)
59
	 * @see #lengthRange(int, int)
60
	 */
61
	public StringConstraints integerDisplayFormat(NumberFormat format) {
62
		this.integerDisplayFormat = format;
63
		return this;
64
	}
65
66
	/**
67
	 * Adds a validator ensuring that the parsed integer is not
68
	 * <code>null</code>. Uses the current {@link #requiredMessage(String)
69
	 * validation message}.
70
	 * 
71
	 * @return This constraints instance for method chaining.
72
	 */
73
	public StringConstraints required() {
74
		addValidator(new NonNullValidator(requiredMessage));
75
		return this;
76
	}
77
78
	/**
79
	 * Sets the validation message for the {@link #required()} constraint.
80
	 * 
81
	 * @param message
82
	 *            The validation message for the {@link #required()} constraint.
83
	 * @return This constraints instance for method chaining.
84
	 * 
85
	 * @see #required()
86
	 */
87
	public StringConstraints requiredMessage(String message) {
88
		this.requiredMessage = message;
89
		return this;
90
	}
91
92
	/**
93
	 * Adds a validator ensuring that the parsed integer is not empty. Uses the
94
	 * current {@link #nonEmptyMessage(String) validation message}.
95
	 * 
96
	 * @return This constraints instance for method chaining.
97
	 */
98
	public StringConstraints nonEmpty() {
99
		addValidator(new NonEmptyStringValidator(nonEmptyMessage));
100
		return this;
101
	}
102
103
	/**
104
	 * Sets the validation message for the {@link #nonEmpty()} constraint.
105
	 * 
106
	 * @param message
107
	 *            The validation message for the {@link #nonEmpty()} constraint.
108
	 * @return This constraints instance for method chaining.
109
	 * 
110
	 * @see #nonEmpty()
111
	 */
112
	public StringConstraints nonEmptyMessage(String message) {
113
		this.nonEmptyMessage = message;
114
		return this;
115
	}
116
117
	/**
118
	 * Adds a validator ensuring that the input string has at least the
119
	 * specified amount of characters. Uses the current
120
	 * {@link #minLengthMessage(String) validation message}.
121
	 * 
122
	 * @param minLength
123
	 *            The minimal length to be enforced on the input string.
124
	 * @return This constraints instance for method chaining.
125
	 */
126
	public StringConstraints minLength(int minLength) {
127
		addValidator(StringLengthValidator.min(minLength, minLengthMessage,
128
				integerDisplayFormat));
129
		return this;
130
	}
131
132
	/**
133
	 * Sets the validation message pattern for the {@link #minLength(int)}
134
	 * constraint.
135
	 * 
136
	 * @param message
137
	 *            The validation message pattern for the {@link #minLength(int)}
138
	 *            constraint. Can be parameterized with the minimum string
139
	 *            length.
140
	 * @return This constraints instance for method chaining.
141
	 * 
142
	 * @see #minLength(int)
143
	 */
144
	public StringConstraints minLengthMessage(String message) {
145
		this.minLengthMessage = message;
146
		return this;
147
	}
148
149
	/**
150
	 * Adds a validator ensuring that the input string has not more than the
151
	 * specified amount of characters. Uses the current
152
	 * {@link #maxLengthMessage(String) validation message}.
153
	 * 
154
	 * @param maxLength
155
	 *            The maximum length to be enforced on the input string.
156
	 * @return This constraints instance for method chaining.
157
	 */
158
	public StringConstraints maxLength(int maxLength) {
159
		addValidator(StringLengthValidator.max(maxLength, maxLengthMessage,
160
				integerDisplayFormat));
161
		return this;
162
	}
163
164
	/**
165
	 * Sets the validation message pattern for the {@link #maxLength(int)}
166
	 * constraint.
167
	 * 
168
	 * @param message
169
	 *            The validation message pattern for the {@link #maxLength(int)}
170
	 *            constraint. Can be parameterized with the maximum string
171
	 *            length.
172
	 * @return This constraints instance for method chaining.
173
	 * 
174
	 * @see #maxLength(int)
175
	 */
176
	public StringConstraints maxLengthMessage(String message) {
177
		this.maxLengthMessage = message;
178
		return this;
179
	}
180
181
	/**
182
	 * Adds a validator ensuring that the length of the input string is between
183
	 * the given bounds. Uses the current {@link #lengthRangeMessage(String)
184
	 * validation message}.
185
	 * 
186
	 * @param minLength
187
	 *            The minimal length to be enforced on the input string.
188
	 * @param maxLength
189
	 *            The maximum length to be enforced on the input string.
190
	 * @return This constraints instance for method chaining.
191
	 */
192
	public StringConstraints lengthRange(int minLength, int maxLength) {
193
		addValidator(StringLengthValidator.range(minLength, maxLength,
194
				lengthRangeMessage, integerDisplayFormat));
195
		return this;
196
	}
197
198
	/**
199
	 * Sets the validation message pattern for the
200
	 * {@link #lengthRange(int, int)} constraint.
201
	 * 
202
	 * @param message
203
	 *            The validation message pattern for the
204
	 *            {@link #lengthRange(int, int)} constraint. Can be
205
	 *            parameterized with the minimum and maximum string lengths.
206
	 * @return This constraints instance for method chaining.
207
	 * 
208
	 * @see #lengthRange(int, int)
209
	 */
210
	public StringConstraints lengthRangeMessage(String message) {
211
		this.lengthRangeMessage = message;
212
		return this;
213
	}
214
215
	/**
216
	 * Adds a validator ensuring that the input string
217
	 * {@link Pattern#matches(String, CharSequence) matches} the given regular
218
	 * expression. Uses the current {@link #matchesMessage(String) validation
219
	 * message}.
220
	 * 
221
	 * @param regex
222
	 *            The regular expression which the input string must match.
223
	 * @return This constraints instance for method chaining.
224
	 * 
225
	 * @see Pattern#matches(String, CharSequence)
226
	 */
227
	public StringConstraints matches(String regex) {
228
		addValidator(new StringRegexValidator(regex, matchesMessage));
229
		return this;
230
	}
231
232
	/**
233
	 * Adds a validator ensuring that the input string
234
	 * {@link Pattern#matches(String, CharSequence) matches} the given pattern.
235
	 * Uses the current {@link #matchesMessage(String) validation message}.
236
	 * 
237
	 * @param pattern
238
	 *            The pattern which the input string must match.
239
	 * @return This constraints instance for method chaining.
240
	 * 
241
	 * @see Pattern#matches(String, CharSequence)
242
	 */
243
	public StringConstraints matches(Pattern pattern) {
244
		addValidator(new StringRegexValidator(pattern, matchesMessage));
245
		return this;
246
	}
247
248
	/**
249
	 * Sets the validation message pattern for the {@link #matches(String)}
250
	 * constraint.
251
	 * 
252
	 * @param message
253
	 *            The validation message pattern for the
254
	 *            {@link #matches(String)} constraint. Can be parameterized with
255
	 *            the pattern string which the parsed integer must match.
256
	 * @return This constraints instance for method chaining.
257
	 * 
258
	 * @see #matches(String)
259
	 */
260
	public StringConstraints matchesMessage(String message) {
261
		this.matchesMessage = message;
262
		return this;
263
	}
264
}
(-)src/org/eclipse/core/internal/databinding/validation/DecimalScaleValidator.java (+91 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.text.MessageFormat;
15
16
import org.eclipse.core.databinding.validation.IValidator;
17
import org.eclipse.core.databinding.validation.ValidationStatus;
18
import org.eclipse.core.internal.databinding.BindingMessages;
19
import org.eclipse.core.runtime.IStatus;
20
21
import com.ibm.icu.math.BigDecimal;
22
import com.ibm.icu.text.NumberFormat;
23
24
/**
25
 * @since 1.4
26
 */
27
public class DecimalScaleValidator implements IValidator {
28
29
	private static final String MAX_SCALE_VALIDATION_MESSAGE = BindingMessages
30
			.getString(BindingMessages.VALIDATE_DECIMAL_MAX_SCALE);
31
32
	private final int maxScale;
33
34
	private final String validationMessage;
35
36
	private String formattedValidationMessage;
37
38
	private final NumberFormat integerDisplayFormat;
39
40
	private DecimalScaleValidator(int maxScale, String maxScaleMessage,
41
			NumberFormat integerDisplayFormat) {
42
		this.maxScale = maxScale;
43
		this.validationMessage = maxScaleMessage != null ? maxScaleMessage
44
				: MAX_SCALE_VALIDATION_MESSAGE;
45
		this.integerDisplayFormat = integerDisplayFormat;
46
	}
47
48
	/**
49
	 * 
50
	 * @param maxScale
51
	 * @param maxScaleMessage
52
	 * @param integerDisplayFormat
53
	 * @return .
54
	 */
55
	public static DecimalScaleValidator max(int maxScale,
56
			String maxScaleMessage, NumberFormat integerDisplayFormat) {
57
		return new DecimalScaleValidator(maxScale, maxScaleMessage,
58
				integerDisplayFormat);
59
	}
60
61
	public IStatus validate(Object value) {
62
		if (value != null) {
63
			Number number = (Number) value;
64
			final int scale;
65
			if (number instanceof BigDecimal) {
66
				scale = ((BigDecimal) number).scale();
67
			} else {
68
				scale = new BigDecimal(number.doubleValue()).scale();
69
			}
70
			if (scale > maxScale) {
71
				return ValidationStatus.error(getFormattedValidationMessage());
72
			}
73
		}
74
		return ValidationStatus.ok();
75
	}
76
77
	private synchronized String getFormattedValidationMessage() {
78
		if (formattedValidationMessage == null) {
79
			formattedValidationMessage = MessageFormat.format(
80
					validationMessage, getValidationMessageArguments());
81
		}
82
		return formattedValidationMessage;
83
	}
84
85
	private String[] getValidationMessageArguments() {
86
		synchronized (integerDisplayFormat) {
87
			return new String[] { integerDisplayFormat.format(new Integer(
88
					maxScale)) };
89
		}
90
	}
91
}
(-)src/org/eclipse/core/databinding/editing/IntegerEditing.java (+571 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import org.eclipse.core.databinding.conversion.NumberToStringConverter;
15
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
16
import org.eclipse.core.databinding.validation.constraint.Constraints;
17
import org.eclipse.core.databinding.validation.constraint.IntegerConstraints;
18
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
19
import org.eclipse.core.internal.databinding.validation.AbstractStringToNumberValidator;
20
import org.eclipse.core.internal.databinding.validation.StringToByteValidator;
21
import org.eclipse.core.internal.databinding.validation.StringToIntegerValidator;
22
import org.eclipse.core.internal.databinding.validation.StringToLongValidator;
23
import org.eclipse.core.internal.databinding.validation.StringToShortValidator;
24
25
import com.ibm.icu.text.NumberFormat;
26
27
/**
28
 * @since 1.4
29
 */
30
public final class IntegerEditing extends Editing {
31
32
	private final NumberFormat displayFormat;
33
34
	private IntegerEditing(NumberFormat format, String parseErrorMessage,
35
			String outOfRangeMessage, Class integerType) {
36
		this.displayFormat = format;
37
38
		final StringToNumberConverter targetConverter;
39
		final NumberToStringConverter modelConverter;
40
		final AbstractStringToNumberValidator targetValidator;
41
		if (Long.class.equals(integerType)) {
42
			targetConverter = StringToNumberConverter.toLong(format, false);
43
			modelConverter = NumberToStringConverter.fromLong(format, false);
44
			targetValidator = new StringToLongValidator(targetConverter);
45
		} else if (Integer.class.equals(integerType)) {
46
			targetConverter = StringToNumberConverter.toInteger(format, false);
47
			modelConverter = NumberToStringConverter.fromInteger(format, false);
48
			targetValidator = new StringToIntegerValidator(targetConverter);
49
		} else if (Short.class.equals(integerType)) {
50
			targetConverter = StringToNumberConverter.toShort(format, false);
51
			modelConverter = NumberToStringConverter.fromShort(format, false);
52
			targetValidator = new StringToShortValidator(targetConverter);
53
		} else if (Byte.class.equals(integerType)) {
54
			targetConverter = StringToNumberConverter.toByte(format, false);
55
			modelConverter = NumberToStringConverter.fromByte(format, false);
56
			targetValidator = new StringToByteValidator(targetConverter);
57
		} else {
58
			throw new IllegalArgumentException(
59
					"Unsupported integer type: " + integerType); //$NON-NLS-1$
60
		}
61
62
		if (parseErrorMessage != null) {
63
			targetValidator.setParseErrorMessage(parseErrorMessage);
64
		}
65
		if (outOfRangeMessage != null) {
66
			targetValidator.setOutOfRangeMessage(outOfRangeMessage);
67
		}
68
69
		setTargetConverter(targetConverter);
70
		setModelConverter(modelConverter);
71
		addTargetValidator(targetValidator);
72
	}
73
74
	/**
75
	 * Creates a new editing object for {@link Long}s which defaults the
76
	 * validations and conversions used for editing based on the platform's
77
	 * locale. Uses the default validation messages.
78
	 * 
79
	 * @return The new editing object using the default validations and
80
	 *         conversions for editing.
81
	 * 
82
	 * @see NumberFormat#getIntegerInstance()
83
	 */
84
	public static IntegerEditing withLongDefaults() {
85
		return withLongDefaults(null, null);
86
	}
87
88
	/**
89
	 * Creates a new editing object for {@link Long}s which defaults the
90
	 * validations and conversions used for editing based on the platform's
91
	 * locale. Uses the specified custom validation messages.
92
	 * 
93
	 * @param parseErrorMessage
94
	 *            The validation message issued in case the input string cannot
95
	 *            be parsed to an integer.
96
	 * @param outOfRangeMessage
97
	 *            The validation message issued in case the input string
98
	 *            represents an integer whose value is out of range. Can be
99
	 *            parameterized by the <code>Long.MIN_VALUE</code> and
100
	 *            <code>Long.MAX_VALUE</code> values.
101
	 * @return The new editing object using the default validations and
102
	 *         conversions for editing.
103
	 * 
104
	 * @see NumberFormat#getIntegerInstance()
105
	 */
106
	public static IntegerEditing withLongDefaults(String parseErrorMessage,
107
			String outOfRangeMessage) {
108
		return new IntegerEditing(NumberFormat.getIntegerInstance(),
109
				parseErrorMessage, outOfRangeMessage, Long.class);
110
	}
111
112
	/**
113
	 * Creates a new editing object for {@link Long}s whose validations and
114
	 * conversions used for editing are based on the given integer format. Uses
115
	 * the default validation messages.
116
	 * 
117
	 * @param format
118
	 *            The integer format defining the validations and conversions
119
	 *            used for editing.
120
	 * @return The new editing object configured by the given integer format.
121
	 */
122
	public static IntegerEditing forLongFormat(NumberFormat format) {
123
		return forLongFormat(format, null, null);
124
	}
125
126
	/**
127
	 * Creates a new editing object for {@link Long}s whose validations and
128
	 * conversions used for editing are based on the given integer format. Uses
129
	 * the specified custom validation messages.
130
	 * 
131
	 * @param format
132
	 *            The integer format defining the validations and conversions
133
	 *            used for editing.
134
	 * @param parseErrorMessage
135
	 *            The validation message issued in case the input string cannot
136
	 *            be parsed to an integer.
137
	 * @param outOfRangeMessage
138
	 *            The validation message issued in case the input string
139
	 *            represents an integer whose value is out of range. Can be
140
	 *            parameterized by the <code>Long.MIN_VALUE</code> and
141
	 *            <code>Long.MAX_VALUE</code> values.
142
	 * @return The new editing object configured by the given integer format.
143
	 */
144
	public static IntegerEditing forLongFormat(NumberFormat format,
145
			String parseErrorMessage, String outOfRangeMessage) {
146
		return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
147
				Long.class);
148
	}
149
150
	/**
151
	 * Creates a new editing object for {@link Integer}s which defaults the
152
	 * validations and conversions used for editing based on the platform's
153
	 * locale. Uses the default validation messages.
154
	 * 
155
	 * @return The new editing object using the default validations and
156
	 *         conversions for editing.
157
	 * 
158
	 * @see NumberFormat#getIntegerInstance()
159
	 */
160
	public static IntegerEditing withIntegerDefaults() {
161
		return withIntegerDefaults(null, null);
162
	}
163
164
	/**
165
	 * Creates a new editing object for {@link Integer}s which defaults the
166
	 * validations and conversions used for editing based on the platform's
167
	 * locale. Uses the specified custom validation messages.
168
	 * 
169
	 * @param parseErrorMessage
170
	 *            The validation message issued in case the input string cannot
171
	 *            be parsed to an integer.
172
	 * @param outOfRangeMessage
173
	 *            The validation message issued in case the input string
174
	 *            represents an integer whose value is out of range. Can be
175
	 *            parameterized by the <code>Integer.MIN_VALUE</code> and
176
	 *            <code>Integer.MAX_VALUE</code> values.
177
	 * @return The new editing object using the default validations and
178
	 *         conversions for editing.
179
	 * 
180
	 * @see NumberFormat#getIntegerInstance()
181
	 */
182
	public static IntegerEditing withIntegerDefaults(String parseErrorMessage,
183
			String outOfRangeMessage) {
184
		return new IntegerEditing(NumberFormat.getIntegerInstance(),
185
				parseErrorMessage, outOfRangeMessage, Integer.class);
186
	}
187
188
	/**
189
	 * Creates a new editing object for {@link Integer}s whose validations and
190
	 * conversions used for editing are based on the given integer format. Uses
191
	 * the default validation messages.
192
	 * 
193
	 * @param format
194
	 *            The integer format defining the validations and conversions
195
	 *            used for editing.
196
	 * @return The new editing object configured by the given integer format.
197
	 */
198
	public static IntegerEditing forIntegerFormat(NumberFormat format) {
199
		return forIntegerFormat(format, null, null);
200
	}
201
202
	/**
203
	 * Creates a new editing object for {@link Integer}s whose validations and
204
	 * conversions used for editing are based on the given integer format. Uses
205
	 * the specified custom validation messages.
206
	 * 
207
	 * @param format
208
	 *            The integer format defining the validations and conversions
209
	 *            used for editing.
210
	 * @param parseErrorMessage
211
	 *            The validation message issued in case the input string cannot
212
	 *            be parsed to an integer.
213
	 * @param outOfRangeMessage
214
	 *            The validation message issued in case the input string
215
	 *            represents an integer whose value is out of range. Can be
216
	 *            parameterized by the <code>Integer.MIN_VALUE</code> and
217
	 *            <code>Integer.MAX_VALUE</code> values.
218
	 * @return The new editing object configured by the given integer format.
219
	 */
220
	public static IntegerEditing forIntegerFormat(NumberFormat format,
221
			String parseErrorMessage, String outOfRangeMessage) {
222
		return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
223
				Integer.class);
224
	}
225
226
	/**
227
	 * Creates a new editing object for {@link Short}s which defaults the
228
	 * validations and conversions used for editing based on the platform's
229
	 * locale. Uses the default validation messages.
230
	 * 
231
	 * @return The new editing object using the default validations and
232
	 *         conversions for editing.
233
	 * 
234
	 * @see NumberFormat#getIntegerInstance()
235
	 */
236
	public static IntegerEditing withShortDefaults() {
237
		return withShortDefaults(null, null);
238
	}
239
240
	/**
241
	 * Creates a new editing object for {@link Short}s which defaults the
242
	 * validations and conversions used for editing based on the platform's
243
	 * locale. Uses the specified custom validation messages.
244
	 * 
245
	 * @param parseErrorMessage
246
	 *            The validation message issued in case the input string cannot
247
	 *            be parsed to an integer.
248
	 * @param outOfRangeMessage
249
	 *            The validation message issued in case the input string
250
	 *            represents an integer whose value is out of range. Can be
251
	 *            parameterized by the <code>Short.MIN_VALUE</code> and
252
	 *            <code>Short.MAX_VALUE</code> values.
253
	 * @return The new editing object using the default validations and
254
	 *         conversions for editing.
255
	 * 
256
	 * @see NumberFormat#getIntegerInstance()
257
	 */
258
	public static IntegerEditing withShortDefaults(String parseErrorMessage,
259
			String outOfRangeMessage) {
260
		return new IntegerEditing(NumberFormat.getIntegerInstance(),
261
				parseErrorMessage, outOfRangeMessage, Short.class);
262
	}
263
264
	/**
265
	 * Creates a new editing object for {@link Short}s whose validations and
266
	 * conversions used for editing are based on the given integer format. Uses
267
	 * the default validation messages.
268
	 * 
269
	 * @param format
270
	 *            The integer format defining the validations and conversions
271
	 *            used for editing.
272
	 * @return The new editing object configured by the given integer format.
273
	 */
274
	public static IntegerEditing forShortFormat(NumberFormat format) {
275
		return forShortFormat(format, null, null);
276
	}
277
278
	/**
279
	 * Creates a new editing object for {@link Short}s whose validations and
280
	 * conversions used for editing are based on the given integer format. Uses
281
	 * the specified custom validation messages.
282
	 * 
283
	 * @param format
284
	 *            The integer format defining the validations and conversions
285
	 *            used for editing.
286
	 * @param parseErrorMessage
287
	 *            The validation message issued in case the input string cannot
288
	 *            be parsed to an integer.
289
	 * @param outOfRangeMessage
290
	 *            The validation message issued in case the input string
291
	 *            represents an integer whose value is out of range. Can be
292
	 *            parameterized by the <code>Short.MIN_VALUE</code> and
293
	 *            <code>Short.MAX_VALUE</code> values.
294
	 * @return The new editing object configured by the given integer format.
295
	 */
296
	public static IntegerEditing forShortFormat(NumberFormat format,
297
			String parseErrorMessage, String outOfRangeMessage) {
298
		return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
299
				Short.class);
300
	}
301
302
	/**
303
	 * Creates a new editing object for {@link Byte}s which defaults the
304
	 * validations and conversions used for editing based on the platform's
305
	 * locale. Uses the default validation messages.
306
	 * 
307
	 * @return The new editing object using the default validations and
308
	 *         conversions for editing.
309
	 * 
310
	 * @see NumberFormat#getIntegerInstance()
311
	 */
312
	public static IntegerEditing withByteDefaults() {
313
		return withByteDefaults(null, null);
314
	}
315
316
	/**
317
	 * Creates a new editing object for {@link Byte}s which defaults the
318
	 * validations and conversions used for editing based on the platform's
319
	 * locale. Uses the specified custom validation messages.
320
	 * 
321
	 * @param parseErrorMessage
322
	 *            The validation message issued in case the input string cannot
323
	 *            be parsed to an integer.
324
	 * @param outOfRangeMessage
325
	 *            The validation message issued in case the input string
326
	 *            represents an integer whose value is out of range. Can be
327
	 *            parameterized by the <code>Byte.MIN_VALUE</code> and
328
	 *            <code>Byte.MAX_VALUE</code> values.
329
	 * @return The new editing object using the default validations and
330
	 *         conversions for editing.
331
	 * 
332
	 * @see NumberFormat#getIntegerInstance()
333
	 */
334
	public static IntegerEditing withByteDefaults(String parseErrorMessage,
335
			String outOfRangeMessage) {
336
		return new IntegerEditing(NumberFormat.getIntegerInstance(),
337
				parseErrorMessage, outOfRangeMessage, Byte.class);
338
	}
339
340
	/**
341
	 * Creates a new editing object for {@link Byte}s whose validations and
342
	 * conversions used for editing are based on the given integer format. Uses
343
	 * the default validation messages.
344
	 * 
345
	 * @param format
346
	 *            The integer format defining the validations and conversions
347
	 *            used for editing.
348
	 * @return The new editing object configured by the given integer format.
349
	 */
350
	public static IntegerEditing forByteFormat(NumberFormat format) {
351
		return forByteFormat(format, null, null);
352
	}
353
354
	/**
355
	 * Creates a new editing object for {@link Byte}s whose validations and
356
	 * conversions used for editing are based on the given integer format. Uses
357
	 * the specified custom validation messages.
358
	 * 
359
	 * @param format
360
	 *            The integer format defining the validations and conversions
361
	 *            used for editing.
362
	 * @param parseErrorMessage
363
	 *            The validation message issued in case the input string cannot
364
	 *            be parsed to an integer.
365
	 * @param outOfRangeMessage
366
	 *            The validation message issued in case the input string
367
	 *            represents an integer whose value is out of range. Can be
368
	 *            parameterized by the <code>Byte.MIN_VALUE</code> and
369
	 *            <code>Byte.MAX_VALUE</code> values.
370
	 * @return The new editing object configured by the given integer format.
371
	 */
372
	public static IntegerEditing forByteFormat(NumberFormat format,
373
			String parseErrorMessage, String outOfRangeMessage) {
374
		return new IntegerEditing(format, parseErrorMessage, outOfRangeMessage,
375
				Byte.class);
376
	}
377
378
	/**
379
	 * Returns the target constraints to apply.
380
	 * 
381
	 * <p>
382
	 * This method provides a typesafe access to the {@link StringConstraints
383
	 * string target constraints} of this editing object and is equivalent to
384
	 * {@code (StringConstraints) targetConstraints()}.
385
	 * </p>
386
	 * 
387
	 * @return The target constraints to apply.
388
	 * 
389
	 * @see #targetConstraints()
390
	 * @see StringConstraints
391
	 */
392
	public StringConstraints targetStringConstraints() {
393
		return (StringConstraints) targetConstraints();
394
	}
395
396
	/**
397
	 * Returns the model constraints to apply.
398
	 * 
399
	 * <p>
400
	 * This method provides a typesafe access to the {@link IntegerConstraints
401
	 * integer model constraints} of this editing object and is equivalent to
402
	 * {@code (IntegerConstraints) modelConstraints()}.
403
	 * </p>
404
	 * 
405
	 * @return The model constraints to apply.
406
	 * 
407
	 * @see #modelConstraints()
408
	 * @see IntegerConstraints
409
	 */
410
	public IntegerConstraints modelIntegerConstraints() {
411
		return (IntegerConstraints) modelConstraints();
412
	}
413
414
	/**
415
	 * Returns the before-set model constraints to apply.
416
	 * 
417
	 * <p>
418
	 * This method provides a typesafe access to the {@link IntegerConstraints
419
	 * integer before-set model constraints} of this editing object and is
420
	 * equivalent to {@code (IntegerConstraints) beforeSetModelConstraints()}.
421
	 * </p>
422
	 * 
423
	 * @return The before-set model constraints to apply.
424
	 * 
425
	 * @see #beforeSetModelConstraints()
426
	 * @see IntegerConstraints
427
	 */
428
	public IntegerConstraints beforeSetModelIntegerConstraints() {
429
		return (IntegerConstraints) beforeSetModelConstraints();
430
	}
431
432
	protected Constraints createTargetConstraints() {
433
		return new StringConstraints();
434
	}
435
436
	protected Constraints createModelConstraints() {
437
		return new IntegerConstraints().integerFormat(displayFormat);
438
	}
439
440
	protected Constraints createBeforeSetModelConstraints() {
441
		return new IntegerConstraints().integerFormat(displayFormat);
442
	}
443
444
	/**
445
	 * Convenience method which adds a {@link IntegerConstraints#required()
446
	 * required constraint} to the set of {@link #modelIntegerConstraints()}.
447
	 * 
448
	 * @return This editing instance for method chaining.
449
	 * 
450
	 * @see IntegerConstraints#required()
451
	 * @see #modelIntegerConstraints()
452
	 */
453
	public IntegerEditing required() {
454
		modelIntegerConstraints().required();
455
		return this;
456
	}
457
458
	/**
459
	 * Convenience method which adds a {@link IntegerConstraints#greater(long)
460
	 * greater constraint} to the set of {@link #modelIntegerConstraints()}.
461
	 * 
462
	 * @param number
463
	 *            The number of the greater constraint.
464
	 * @return This editing instance for method chaining.
465
	 * 
466
	 * @see IntegerConstraints#greater(long)
467
	 * @see #modelIntegerConstraints()
468
	 */
469
	public IntegerEditing greater(long number) {
470
		modelIntegerConstraints().greater(number);
471
		return this;
472
	}
473
474
	/**
475
	 * Convenience method which adds a
476
	 * {@link IntegerConstraints#greaterEqual(long) greater-equal constraint} to
477
	 * the set of {@link #modelIntegerConstraints()}.
478
	 * 
479
	 * @param number
480
	 *            The number of the greater-equal constraint.
481
	 * @return This editing instance for method chaining.
482
	 * 
483
	 * @see IntegerConstraints#greaterEqual(long)
484
	 * @see #modelIntegerConstraints()
485
	 */
486
	public IntegerEditing greaterEqual(long number) {
487
		modelIntegerConstraints().greaterEqual(number);
488
		return this;
489
	}
490
491
	/**
492
	 * Convenience method which adds a {@link IntegerConstraints#less(long) less
493
	 * constraint} to the set of {@link #modelIntegerConstraints()}.
494
	 * 
495
	 * @param number
496
	 *            The number of the less constraint.
497
	 * @return This editing instance for method chaining.
498
	 * 
499
	 * @see IntegerConstraints#less(long)
500
	 * @see #modelIntegerConstraints()
501
	 */
502
	public IntegerEditing less(long number) {
503
		modelIntegerConstraints().less(number);
504
		return this;
505
	}
506
507
	/**
508
	 * Convenience method which adds a
509
	 * {@link IntegerConstraints#lessEqual(long) less-equal constraint} to the
510
	 * set of {@link #modelIntegerConstraints()}.
511
	 * 
512
	 * @param number
513
	 *            The number of the less-equal constraint.
514
	 * @return This editing instance for method chaining.
515
	 * 
516
	 * @see IntegerConstraints#lessEqual(long)
517
	 * @see #modelIntegerConstraints()
518
	 */
519
	public IntegerEditing lessEqual(long number) {
520
		modelIntegerConstraints().lessEqual(number);
521
		return this;
522
	}
523
524
	/**
525
	 * Convenience method which adds a
526
	 * {@link IntegerConstraints#range(long, long) range constraint} to the set
527
	 * of {@link #modelIntegerConstraints()}.
528
	 * 
529
	 * @param min
530
	 *            The min number of the range constraint.
531
	 * @param max
532
	 *            The max number of the range constraint.
533
	 * @return This editing instance for method chaining.
534
	 * 
535
	 * @see IntegerConstraints#range(long, long)
536
	 * @see #modelIntegerConstraints()
537
	 */
538
	public IntegerEditing range(long min, long max) {
539
		modelIntegerConstraints().range(min, max);
540
		return this;
541
	}
542
543
	/**
544
	 * Convenience method which adds a {@link IntegerConstraints#positive()
545
	 * positive constraint} to the set of {@link #modelIntegerConstraints()}.
546
	 * 
547
	 * @return This editing instance for method chaining.
548
	 * 
549
	 * @see IntegerConstraints#positive()
550
	 * @see #modelIntegerConstraints()
551
	 */
552
	public IntegerEditing positive() {
553
		modelIntegerConstraints().positive();
554
		return this;
555
	}
556
557
	/**
558
	 * Convenience method which adds a {@link IntegerConstraints#nonNegative()
559
	 * non-negative constraint} to the set of {@link #modelIntegerConstraints()}
560
	 * .
561
	 * 
562
	 * @return This editing instance for method chaining.
563
	 * 
564
	 * @see IntegerConstraints#nonNegative()
565
	 * @see #modelIntegerConstraints()
566
	 */
567
	public IntegerEditing nonNegative() {
568
		modelIntegerConstraints().nonNegative();
569
		return this;
570
	}
571
}
(-)src/org/eclipse/core/databinding/editing/DateEditing.java (+279 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import java.util.Date;
15
16
import org.eclipse.core.databinding.validation.constraint.Constraints;
17
import org.eclipse.core.databinding.validation.constraint.DateConstraints;
18
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
19
import org.eclipse.core.internal.databinding.conversion.DateToStringConverter;
20
import org.eclipse.core.internal.databinding.conversion.StringToDateConverter;
21
import org.eclipse.core.internal.databinding.validation.StringToDateValidator;
22
23
import com.ibm.icu.text.DateFormat;
24
25
/**
26
 * @since 1.4
27
 */
28
public final class DateEditing extends Editing {
29
30
	private final DateFormat displayFormat;
31
32
	private DateEditing(DateFormat[] inputFormats, String parseErrorMessage,
33
			DateFormat displayFormat) {
34
		this.displayFormat = displayFormat;
35
36
		StringToDateConverter targetConverter = new StringToDateConverter();
37
		if (inputFormats != null) {
38
			targetConverter.setFormatters(inputFormats);
39
		}
40
41
		DateToStringConverter modelConverter = new DateToStringConverter();
42
		if (displayFormat != null) {
43
			modelConverter.setFormatters(new DateFormat[] { displayFormat });
44
		}
45
46
		StringToDateValidator targetValidator = new StringToDateValidator(
47
				targetConverter);
48
		if (parseErrorMessage != null) {
49
			targetValidator.setParseErrorMessage(parseErrorMessage);
50
		}
51
52
		setTargetConverter(targetConverter);
53
		setModelConverter(modelConverter);
54
		addTargetValidator(targetValidator);
55
	}
56
57
	/**
58
	 * Creates a new editing object which defaults the validations and
59
	 * conversions used for editing. Uses the default validation message.
60
	 * 
61
	 * @return The new editing object using the default validations and
62
	 *         conversions for editing.
63
	 */
64
	public static DateEditing withDefaults() {
65
		return withDefaults(null);
66
	}
67
68
	/**
69
	 * Creates a new editing object which defaults the validations and
70
	 * conversions used for editing. Uses the specified custom validation
71
	 * message.
72
	 * 
73
	 * @param parseErrorMessage
74
	 *            The validation message issued in case the input string cannot
75
	 *            be parsed to a date.
76
	 * @return The new editing object using the default validations and
77
	 *         conversions for editing.
78
	 */
79
	public static DateEditing withDefaults(String parseErrorMessage) {
80
		return new DateEditing(null, parseErrorMessage, null);
81
	}
82
83
	/**
84
	 * Creates a new editing object which supports all the given date input
85
	 * formats and which uses the specified format for displaying a date. Uses
86
	 * the default validation message.
87
	 * 
88
	 * @param inputFormats
89
	 *            The date formats supported for reading in dates.
90
	 * @param displayFormat
91
	 *            The date format for displaying dates.
92
	 * @return The new editing object configured by the given date formats.
93
	 */
94
	public static DateEditing forFormats(DateFormat[] inputFormats,
95
			DateFormat displayFormat) {
96
		return new DateEditing(inputFormats, null, displayFormat);
97
	}
98
99
	/**
100
	 * Creates a new editing object which supports all the given date input
101
	 * formats and which uses the specified format for displaying a date. Uses
102
	 * the specified custom validation message.
103
	 * 
104
	 * @param inputFormats
105
	 *            The date formats supported for reading in dates.
106
	 * @param parseErrorMessage
107
	 *            The validation message issued in case the input string cannot
108
	 *            be parsed to a date.
109
	 * @param displayFormat
110
	 *            The date format for displaying dates.
111
	 * @return The new editing object configured by the given date formats.
112
	 */
113
	public static DateEditing forFormats(DateFormat[] inputFormats,
114
			String parseErrorMessage, DateFormat displayFormat) {
115
		return new DateEditing(inputFormats, parseErrorMessage, displayFormat);
116
	}
117
118
	/**
119
	 * Returns the target constraints to apply.
120
	 * 
121
	 * <p>
122
	 * This method provides a typesafe access to the {@link StringConstraints
123
	 * string target constraints} of this editing object and is equivalent to
124
	 * {@code (StringConstraints) targetConstraints()}.
125
	 * </p>
126
	 * 
127
	 * @return The target constraints to apply.
128
	 * 
129
	 * @see #targetConstraints()
130
	 * @see StringConstraints
131
	 */
132
	public StringConstraints targetStringConstraints() {
133
		return (StringConstraints) targetConstraints();
134
	}
135
136
	/**
137
	 * Returns the model constraints to apply.
138
	 * 
139
	 * <p>
140
	 * This method provides a typesafe access to the {@link DateConstraints date
141
	 * model constraints} of this editing object and is equivalent to {@code
142
	 * (DateConstraints) modelConstraints()}.
143
	 * </p>
144
	 * 
145
	 * @return The model constraints to apply.
146
	 * 
147
	 * @see #modelConstraints()
148
	 * @see DateConstraints
149
	 */
150
	public DateConstraints modelDateConstraints() {
151
		return (DateConstraints) modelConstraints();
152
	}
153
154
	/**
155
	 * Returns the before-set model constraints to apply.
156
	 * 
157
	 * <p>
158
	 * This method provides a typesafe access to the {@link DateConstraints date
159
	 * before-set model constraints} of this editing object and is equivalent to
160
	 * {@code (DateConstraints) beforeSetModelConstraints()}.
161
	 * </p>
162
	 * 
163
	 * @return The before-set model constraints to apply.
164
	 * 
165
	 * @see #beforeSetModelConstraints()
166
	 * @see DateConstraints
167
	 */
168
	public DateConstraints beforeSetModelDateConstraints() {
169
		return (DateConstraints) beforeSetModelConstraints();
170
	}
171
172
	protected Constraints createTargetConstraints() {
173
		return new StringConstraints();
174
	}
175
176
	protected Constraints createModelConstraints() {
177
		return new DateConstraints().dateDisplayFormat(displayFormat);
178
	}
179
180
	protected Constraints createBeforeSetModelConstraints() {
181
		return new DateConstraints().dateDisplayFormat(displayFormat);
182
	}
183
184
	/**
185
	 * Convenience method which adds a {@link DateConstraints#required()
186
	 * required constraint} to the set of {@link #modelDateConstraints()}.
187
	 * 
188
	 * @return This editing instance for method chaining.
189
	 * 
190
	 * @see DateConstraints#required()
191
	 * @see #modelDateConstraints()
192
	 */
193
	public DateEditing required() {
194
		modelDateConstraints().required();
195
		return this;
196
	}
197
198
	/**
199
	 * Convenience method which adds a {@link DateConstraints#after(Date) after
200
	 * constraint} to the set of {@link #modelDateConstraints()}.
201
	 * 
202
	 * @param date
203
	 *            The date of the after constraint.
204
	 * @return This editing instance for method chaining.
205
	 * 
206
	 * @see DateConstraints#after(Date)
207
	 * @see #modelDateConstraints()
208
	 */
209
	public DateEditing after(Date date) {
210
		modelDateConstraints().after(date);
211
		return this;
212
	}
213
214
	/**
215
	 * Convenience method which adds a {@link DateConstraints#afterEqual(Date)
216
	 * after-equal constraint} to the set of {@link #modelDateConstraints()}.
217
	 * 
218
	 * @param date
219
	 *            The date of the after-equal constraint.
220
	 * @return This editing instance for method chaining.
221
	 * 
222
	 * @see DateConstraints#afterEqual(Date)
223
	 * @see #modelDateConstraints()
224
	 */
225
	public DateEditing afterEqual(Date date) {
226
		modelDateConstraints().afterEqual(date);
227
		return this;
228
	}
229
230
	/**
231
	 * Convenience method which adds a {@link DateConstraints#before(Date)
232
	 * before constraint} to the set of {@link #modelDateConstraints()}.
233
	 * 
234
	 * @param date
235
	 *            The date of the before constraint.
236
	 * @return This editing instance for method chaining.
237
	 * 
238
	 * @see DateConstraints#before(Date)
239
	 * @see #modelDateConstraints()
240
	 */
241
	public DateEditing before(Date date) {
242
		modelDateConstraints().before(date);
243
		return this;
244
	}
245
246
	/**
247
	 * Convenience method which adds a {@link DateConstraints#beforeEqual(Date)
248
	 * after-equal constraint} to the set of {@link #modelDateConstraints()}.
249
	 * 
250
	 * @param date
251
	 *            The date of the after-equal constraint.
252
	 * @return This editing instance for method chaining.
253
	 * 
254
	 * @see DateConstraints#afterEqual(Date)
255
	 * @see #modelDateConstraints()
256
	 */
257
	public DateEditing beforeEqual(Date date) {
258
		modelDateConstraints().beforeEqual(date);
259
		return this;
260
	}
261
262
	/**
263
	 * Convenience method which adds a {@link DateConstraints#range(Date, Date)
264
	 * range constraint} to the set of {@link #modelDateConstraints()}.
265
	 * 
266
	 * @param minDate
267
	 *            The min date of the range constraint.
268
	 * @param maxDate
269
	 *            The max date of the range constraint.
270
	 * @return This editing instance for method chaining.
271
	 * 
272
	 * @see DateConstraints#range(Date, Date)
273
	 * @see #modelDateConstraints()
274
	 */
275
	public DateEditing range(Date minDate, Date maxDate) {
276
		modelDateConstraints().range(minDate, maxDate);
277
		return this;
278
	}
279
}
(-)src/org/eclipse/core/internal/databinding/validation/StringRegexValidator.java (+83 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.text.MessageFormat;
15
import java.util.regex.Matcher;
16
import java.util.regex.Pattern;
17
18
import org.eclipse.core.databinding.validation.IValidator;
19
import org.eclipse.core.databinding.validation.ValidationStatus;
20
import org.eclipse.core.internal.databinding.BindingMessages;
21
import org.eclipse.core.runtime.IStatus;
22
23
/**
24
 * Provides validations for strings which must match a given regular expression.
25
 * 
26
 * @since 1.4
27
 */
28
public class StringRegexValidator implements IValidator {
29
30
	private static final String REGEX_VALIDATION_MESSAGE = BindingMessages
31
			.getString(BindingMessages.VALIDATE_STRING_REGEX);
32
33
	private final Pattern pattern;
34
	private final String validationMessage;
35
	private String formattedValidationMessage;
36
37
	/**
38
	 * Creates a new regex validator.
39
	 * 
40
	 * @param regex
41
	 *            The regular expression which the input string must match.
42
	 * @param validationMessage
43
	 *            The validation message pattern to use. Can be parameterized
44
	 *            with the given regular expression string.
45
	 */
46
	public StringRegexValidator(String regex, String validationMessage) {
47
		this(Pattern.compile(regex), validationMessage);
48
	}
49
50
	/**
51
	 * Creates a new regex validator.
52
	 * 
53
	 * @param pattern
54
	 *            The pattern which the input string must match.
55
	 * @param validationMessage
56
	 *            The validation message pattern to use. Can be parameterized
57
	 *            with the given regular expression string.
58
	 */
59
	public StringRegexValidator(Pattern pattern, String validationMessage) {
60
		this.pattern = pattern;
61
		this.validationMessage = validationMessage != null ? validationMessage
62
				: REGEX_VALIDATION_MESSAGE;
63
	}
64
65
	public IStatus validate(Object value) {
66
		String input = (String) value;
67
		if (input != null) {
68
			Matcher matcher = pattern.matcher(input);
69
			if (!matcher.matches()) {
70
				return ValidationStatus.error(getFormattedValidationMessage());
71
			}
72
		}
73
		return ValidationStatus.ok();
74
	}
75
76
	private synchronized String getFormattedValidationMessage() {
77
		if (formattedValidationMessage == null) {
78
			formattedValidationMessage = MessageFormat.format(
79
					validationMessage, new String[] { pattern.pattern() });
80
		}
81
		return formattedValidationMessage;
82
	}
83
}
(-)src/org/eclipse/core/databinding/editing/DecimalEditing.java (+426 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import org.eclipse.core.databinding.conversion.NumberToStringConverter;
15
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
16
import org.eclipse.core.databinding.validation.constraint.Constraints;
17
import org.eclipse.core.databinding.validation.constraint.DecimalConstraints;
18
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
19
import org.eclipse.core.internal.databinding.validation.AbstractStringToNumberValidator;
20
import org.eclipse.core.internal.databinding.validation.StringToDoubleValidator;
21
import org.eclipse.core.internal.databinding.validation.StringToFloatValidator;
22
23
import com.ibm.icu.text.NumberFormat;
24
25
/**
26
 * @since 1.4
27
 */
28
public final class DecimalEditing extends Editing {
29
30
	private final NumberFormat displayFormat;
31
32
	private DecimalEditing(NumberFormat format, String parseErrorMessage,
33
			String outOfRangeMessage, Class decimalType) {
34
		this.displayFormat = format;
35
36
		final StringToNumberConverter targetConverter;
37
		final NumberToStringConverter modelConverter;
38
		final AbstractStringToNumberValidator targetValidator;
39
		if (Double.class.equals(decimalType)) {
40
			targetConverter = StringToNumberConverter.toDouble(format, false);
41
			modelConverter = NumberToStringConverter.fromDouble(format, false);
42
			targetValidator = new StringToDoubleValidator(targetConverter);
43
		} else if (Float.class.equals(decimalType)) {
44
			targetConverter = StringToNumberConverter.toFloat(format, false);
45
			modelConverter = NumberToStringConverter.fromFloat(format, false);
46
			targetValidator = new StringToFloatValidator(targetConverter);
47
		} else {
48
			throw new IllegalArgumentException(
49
					"Unsupported decimal type: " + decimalType); //$NON-NLS-1$
50
		}
51
52
		if (parseErrorMessage != null) {
53
			targetValidator.setParseErrorMessage(parseErrorMessage);
54
		}
55
		if (outOfRangeMessage != null) {
56
			targetValidator.setOutOfRangeMessage(outOfRangeMessage);
57
		}
58
59
		setTargetConverter(targetConverter);
60
		setModelConverter(modelConverter);
61
		addTargetValidator(targetValidator);
62
	}
63
64
	/**
65
	 * Creates a new editing object for {@link Double}s which defaults the
66
	 * validations and conversions used for editing based on the platform's
67
	 * locale. Uses the default validation messages.
68
	 * 
69
	 * @return The new editing object using the default validations and
70
	 *         conversions for editing.
71
	 * 
72
	 * @see NumberFormat#getNumberInstance()
73
	 */
74
	public static DecimalEditing withDoubleDefaults() {
75
		return withDoubleDefaults(null, null);
76
	}
77
78
	/**
79
	 * Creates a new editing object for {@link Double}s which defaults the
80
	 * validations and conversions used for editing based on the platform's
81
	 * locale. Uses the specified custom validation messages.
82
	 * 
83
	 * @param parseErrorMessage
84
	 *            The validation message issued in case the input string cannot
85
	 *            be parsed to a double.
86
	 * @param outOfRangeMessage
87
	 *            The validation message issued in case the input string
88
	 *            represents a double whose value is out of range. Can be
89
	 *            parameterized by the <code>-Double.MAX_VALUE</code> and
90
	 *            <code>+Double.MAX_VALUE</code> values.
91
	 * @return The new editing object using the default validations and
92
	 *         conversions for editing.
93
	 * 
94
	 * @see NumberFormat#getNumberInstance()
95
	 */
96
	public static DecimalEditing withDoubleDefaults(String parseErrorMessage,
97
			String outOfRangeMessage) {
98
		return new DecimalEditing(NumberFormat.getNumberInstance(),
99
				parseErrorMessage, outOfRangeMessage, Double.class);
100
	}
101
102
	/**
103
	 * Creates a new editing object for {@link Double}s whose validations and
104
	 * conversions used for editing are based on the given number format. Uses
105
	 * the default validation messages.
106
	 * 
107
	 * @param format
108
	 *            The number format defining the validations and conversions
109
	 *            used for editing.
110
	 * @return The new editing object configured by the given number format.
111
	 */
112
	public static DecimalEditing forDoubleFormat(NumberFormat format) {
113
		return forDoubleFormat(format, null, null);
114
	}
115
116
	/**
117
	 * Creates a new editing object for {@link Double}s whose validations and
118
	 * conversions used for editing are based on the given number format. Uses
119
	 * the specified custom validation messages.
120
	 * 
121
	 * @param format
122
	 *            The number format defining the validations and conversions
123
	 *            used for editing.
124
	 * @param parseErrorMessage
125
	 *            The validation message issued in case the input string cannot
126
	 *            be parsed to a double.
127
	 * @param outOfRangeMessage
128
	 *            The validation message issued in case the input string
129
	 *            represents a double whose value is out of range. Can be
130
	 *            parameterized by the <code>-Double.MAX_VALUE</code> and
131
	 *            <code>+Double.MAX_VALUE</code> values.
132
	 * @return The new editing object configured by the given number format.
133
	 */
134
	public static DecimalEditing forDoubleFormat(NumberFormat format,
135
			String parseErrorMessage, String outOfRangeMessage) {
136
		return new DecimalEditing(format, parseErrorMessage, outOfRangeMessage,
137
				Double.class);
138
	}
139
140
	/**
141
	 * Creates a new editing object for {@link Float}s which defaults the
142
	 * validations and conversions used for editing based on the platform's
143
	 * locale. Uses the default validation messages.
144
	 * 
145
	 * @return The new editing object using the default validations and
146
	 *         conversions for editing.
147
	 * 
148
	 * @see NumberFormat#getNumberInstance()
149
	 */
150
	public static DecimalEditing withFloatDefaults() {
151
		return withFloatDefaults(null, null);
152
	}
153
154
	/**
155
	 * Creates a new editing object for {@link Float}s which defaults the
156
	 * validations and conversions used for editing based on the platform's
157
	 * locale. Uses the specified custom validation messages.
158
	 * 
159
	 * @param parseErrorMessage
160
	 *            The validation message issued in case the input string cannot
161
	 *            be parsed to a double.
162
	 * @param outOfRangeMessage
163
	 *            The validation message issued in case the input string
164
	 *            represents a float whose value is out of range. Can be
165
	 *            parameterized by the <code>-Float.MAX_VALUE</code> and
166
	 *            <code>+Float.MAX_VALUE</code> values.
167
	 * @return The new editing object using the default validations and
168
	 *         conversions for editing.
169
	 * 
170
	 * @see NumberFormat#getNumberInstance()
171
	 */
172
	public static DecimalEditing withFloatDefaults(String parseErrorMessage,
173
			String outOfRangeMessage) {
174
		return new DecimalEditing(NumberFormat.getNumberInstance(),
175
				parseErrorMessage, outOfRangeMessage, Float.class);
176
	}
177
178
	/**
179
	 * Creates a new editing object for {@link Float}s whose validations and
180
	 * conversions used for editing are based on the given number format. Uses
181
	 * the default validation messages.
182
	 * 
183
	 * @param format
184
	 *            The number format defining the validations and conversions
185
	 *            used for editing.
186
	 * @return The new editing object configured by the given number format.
187
	 */
188
	public static DecimalEditing forFloatFormat(NumberFormat format) {
189
		return forFloatFormat(format, null, null);
190
	}
191
192
	/**
193
	 * Creates a new editing object for {@link Float}s whose validations and
194
	 * conversions used for editing are based on the given number format. Uses
195
	 * the specified custom validation messages.
196
	 * 
197
	 * @param format
198
	 *            The number format defining the validations and conversions
199
	 *            used for editing.
200
	 * @param parseErrorMessage
201
	 *            The validation message issued in case the input string cannot
202
	 *            be parsed to a float.
203
	 * @param outOfRangeMessage
204
	 *            The validation message issued in case the input string
205
	 *            represents a float whose value is out of range. Can be
206
	 *            parameterized by the <code>-Float.MAX_VALUE</code> and
207
	 *            <code>+Float.MAX_VALUE</code> values.
208
	 * @return The new editing object configured by the given number format.
209
	 */
210
	public static DecimalEditing forFloatFormat(NumberFormat format,
211
			String parseErrorMessage, String outOfRangeMessage) {
212
		return new DecimalEditing(format, parseErrorMessage, outOfRangeMessage,
213
				Float.class);
214
	}
215
216
	/**
217
	 * Returns the target constraints to apply.
218
	 * 
219
	 * <p>
220
	 * This method provides a typesafe access to the {@link StringConstraints
221
	 * string target constraints} of this editing object and is equivalent to
222
	 * {@code (StringConstraints) targetConstraints()}.
223
	 * </p>
224
	 * 
225
	 * @return The target constraints to apply.
226
	 * 
227
	 * @see #targetConstraints()
228
	 * @see StringConstraints
229
	 */
230
	public StringConstraints targetStringConstraints() {
231
		return (StringConstraints) targetConstraints();
232
	}
233
234
	/**
235
	 * Returns the model constraints to apply.
236
	 * 
237
	 * <p>
238
	 * This method provides a typesafe access to the {@link DecimalConstraints
239
	 * decimal model constraints} of this editing object and is equivalent to
240
	 * {@code (DecimalConstraints) modelConstraints()}.
241
	 * </p>
242
	 * 
243
	 * @return The model constraints to apply.
244
	 * 
245
	 * @see #modelConstraints()
246
	 * @see DecimalConstraints
247
	 */
248
	public DecimalConstraints modelDecimalConstraints() {
249
		return (DecimalConstraints) modelConstraints();
250
	}
251
252
	/**
253
	 * Returns the before-set model constraints to apply.
254
	 * 
255
	 * <p>
256
	 * This method provides a typesafe access to the {@link DecimalConstraints
257
	 * decimal before-set model constraints} of this editing object and is
258
	 * equivalent to {@code (DecimalConstraints) beforeSetModelConstraints()}.
259
	 * </p>
260
	 * 
261
	 * @return The before-set model constraints to apply.
262
	 * 
263
	 * @see #beforeSetModelConstraints()
264
	 * @see DecimalConstraints
265
	 */
266
	public DecimalConstraints beforeSetModelDecimalConstraints() {
267
		return (DecimalConstraints) beforeSetModelConstraints();
268
	}
269
270
	protected Constraints createTargetConstraints() {
271
		return new StringConstraints();
272
	}
273
274
	protected Constraints createModelConstraints() {
275
		return new DecimalConstraints().decimalFormat(displayFormat);
276
	}
277
278
	protected Constraints createBeforeSetModelConstraints() {
279
		return new DecimalConstraints().decimalFormat(displayFormat);
280
	}
281
282
	/**
283
	 * Convenience method which adds a {@link DecimalConstraints#required()
284
	 * required constraint} to the set of {@link #modelDecimalConstraints()}.
285
	 * 
286
	 * @return This editing instance for method chaining.
287
	 * 
288
	 * @see DecimalConstraints#required()
289
	 * @see #modelDecimalConstraints()
290
	 */
291
	public DecimalEditing required() {
292
		modelDecimalConstraints().required();
293
		return this;
294
	}
295
296
	/**
297
	 * Convenience method which adds a
298
	 * {@link DecimalConstraints#greater(double) greater constraint} to the set
299
	 * of {@link #modelDecimalConstraints()}.
300
	 * 
301
	 * @param number
302
	 *            The number of the greater constraint.
303
	 * @return This editing instance for method chaining.
304
	 * 
305
	 * @see DecimalConstraints#greater(double)
306
	 * @see #modelDecimalConstraints()
307
	 */
308
	public DecimalEditing greater(double number) {
309
		modelDecimalConstraints().greater(number);
310
		return this;
311
	}
312
313
	/**
314
	 * Convenience method which adds a
315
	 * {@link DecimalConstraints#greaterEqual(double) greater-equal constraint}
316
	 * to the set of {@link #modelDecimalConstraints()}.
317
	 * 
318
	 * @param number
319
	 *            The number of the greater-equal constraint.
320
	 * @return This editing instance for method chaining.
321
	 * 
322
	 * @see DecimalConstraints#greaterEqual(double)
323
	 * @see #modelDecimalConstraints()
324
	 */
325
	public DecimalEditing greaterEqual(double number) {
326
		modelDecimalConstraints().greaterEqual(number);
327
		return this;
328
	}
329
330
	/**
331
	 * Convenience method which adds a {@link DecimalConstraints#less(double)
332
	 * less constraint} to the set of {@link #modelDecimalConstraints()}.
333
	 * 
334
	 * @param number
335
	 *            The number of the less constraint.
336
	 * @return This editing instance for method chaining.
337
	 * 
338
	 * @see DecimalConstraints#less(double)
339
	 * @see #modelDecimalConstraints()
340
	 */
341
	public DecimalEditing less(double number) {
342
		modelDecimalConstraints().less(number);
343
		return this;
344
	}
345
346
	/**
347
	 * Convenience method which adds a
348
	 * {@link DecimalConstraints#lessEqual(double) less-equal constraint} to the
349
	 * set of {@link #modelDecimalConstraints()}.
350
	 * 
351
	 * @param number
352
	 *            The number of the less-equal constraint.
353
	 * @return This editing instance for method chaining.
354
	 * 
355
	 * @see DecimalConstraints#lessEqual(double)
356
	 * @see #modelDecimalConstraints()
357
	 */
358
	public DecimalEditing lessEqual(double number) {
359
		modelDecimalConstraints().lessEqual(number);
360
		return this;
361
	}
362
363
	/**
364
	 * Convenience method which adds a
365
	 * {@link DecimalConstraints#range(double, double) range constraint} to the
366
	 * set of {@link #modelDecimalConstraints()}.
367
	 * 
368
	 * @param min
369
	 *            The min number of the range constraint.
370
	 * @param max
371
	 *            The max number of the range constraint.
372
	 * @return This editing instance for method chaining.
373
	 * 
374
	 * @see DecimalConstraints#range(double, double)
375
	 * @see #modelDecimalConstraints()
376
	 */
377
	public DecimalEditing range(double min, double max) {
378
		modelDecimalConstraints().range(min, max);
379
		return this;
380
	}
381
382
	/**
383
	 * Convenience method which adds a {@link DecimalConstraints#positive()
384
	 * positive constraint} to the set of {@link #modelDecimalConstraints()}.
385
	 * 
386
	 * @return This editing instance for method chaining.
387
	 * 
388
	 * @see DecimalConstraints#positive()
389
	 * @see #modelDecimalConstraints()
390
	 */
391
	public DecimalEditing positive() {
392
		modelDecimalConstraints().positive();
393
		return this;
394
	}
395
396
	/**
397
	 * Convenience method which adds a {@link DecimalConstraints#nonNegative()
398
	 * non-negative constraint} to the set of {@link #modelDecimalConstraints()}
399
	 * .
400
	 * 
401
	 * @return This editing instance for method chaining.
402
	 * 
403
	 * @see DecimalConstraints#nonNegative()
404
	 * @see #modelDecimalConstraints()
405
	 */
406
	public DecimalEditing nonNegative() {
407
		modelDecimalConstraints().nonNegative();
408
		return this;
409
	}
410
411
	/**
412
	 * Convenience method which adds a {@link DecimalConstraints#maxScale(int)
413
	 * max-scale constraint} to the set of {@link #modelDecimalConstraints()} .
414
	 * 
415
	 * @param scale
416
	 *            The maximum scale to enforce.
417
	 * @return This editing instance for method chaining.
418
	 * 
419
	 * @see DecimalConstraints#maxScale(int)
420
	 * @see #modelDecimalConstraints()
421
	 */
422
	public DecimalEditing maxScale(int scale) {
423
		modelDecimalConstraints().maxScale(scale);
424
		return this;
425
	}
426
}
(-)src/org/eclipse/core/databinding/editing/BigDecimalEditing.java (+332 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import java.math.BigDecimal;
15
16
import org.eclipse.core.databinding.conversion.NumberToStringConverter;
17
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
18
import org.eclipse.core.databinding.validation.constraint.BigDecimalConstraints;
19
import org.eclipse.core.databinding.validation.constraint.Constraints;
20
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
21
import org.eclipse.core.internal.databinding.validation.AbstractStringToNumberValidator;
22
import org.eclipse.core.internal.databinding.validation.StringToBigDecimalValidator;
23
24
import com.ibm.icu.text.NumberFormat;
25
26
/**
27
 * @since 1.4
28
 */
29
public final class BigDecimalEditing extends Editing {
30
31
	private final NumberFormat displayFormat;
32
33
	private BigDecimalEditing(NumberFormat format, String parseErrorMessage) {
34
		this.displayFormat = format;
35
36
		final StringToNumberConverter targetConverter = StringToNumberConverter
37
				.toBigDecimal(format);
38
		final NumberToStringConverter modelConverter = NumberToStringConverter
39
				.fromBigDecimal(format);
40
41
		final AbstractStringToNumberValidator targetValidator = new StringToBigDecimalValidator(
42
				targetConverter);
43
		if (parseErrorMessage != null) {
44
			targetValidator.setParseErrorMessage(parseErrorMessage);
45
		}
46
47
		setTargetConverter(targetConverter);
48
		setModelConverter(modelConverter);
49
		addTargetValidator(targetValidator);
50
	}
51
52
	/**
53
	 * Creates a new editing object for {@link BigDecimal}s which defaults the
54
	 * validations and conversions used for editing based on the platform's
55
	 * locale. Uses the default validation messages.
56
	 * 
57
	 * @return The new editing object using the default validations and
58
	 *         conversions for editing.
59
	 * 
60
	 * @see NumberFormat#getNumberInstance()
61
	 */
62
	public static BigDecimalEditing withDefaults() {
63
		return withDefaults(null);
64
	}
65
66
	/**
67
	 * Creates a new editing object for {@link BigDecimal}s which defaults the
68
	 * validations and conversions used for editing based on the platform's
69
	 * locale. Uses the specified custom validation message.
70
	 * 
71
	 * @param parseErrorMessage
72
	 *            The validation message issued in case the input string cannot
73
	 *            be parsed to a BigDecimal.
74
	 * @return The new editing object using the default validations and
75
	 *         conversions for editing.
76
	 * 
77
	 * @see NumberFormat#getNumberInstance()
78
	 */
79
	public static BigDecimalEditing withDefaults(String parseErrorMessage) {
80
		return new BigDecimalEditing(NumberFormat.getNumberInstance(),
81
				parseErrorMessage);
82
	}
83
84
	/**
85
	 * Creates a new editing object for {@link BigDecimal}s whose validations
86
	 * and conversions used for editing are based on the given BigDecimal
87
	 * format. Uses the default validation messages.
88
	 * 
89
	 * @param format
90
	 *            The BigDecimal format defining the validations and conversions
91
	 *            used for editing.
92
	 * @return The new editing object configured by the given BigDecimal format.
93
	 */
94
	public static BigDecimalEditing forFormat(NumberFormat format) {
95
		return forFormat(format, null);
96
	}
97
98
	/**
99
	 * Creates a new editing object for {@link BigDecimal}s whose validations
100
	 * and conversions used for editing are based on the given BigDecimal
101
	 * format. Uses the specified custom validation message.
102
	 * 
103
	 * @param format
104
	 *            The BigDecimal format defining the validations and conversions
105
	 *            used for editing.
106
	 * @param parseErrorMessage
107
	 *            The validation message issued in case the input string cannot
108
	 *            be parsed to a BigDecimal.
109
	 * @return The new editing object configured by the given BigDecimal format.
110
	 */
111
	public static BigDecimalEditing forFormat(NumberFormat format,
112
			String parseErrorMessage) {
113
		return new BigDecimalEditing(format, parseErrorMessage);
114
	}
115
116
	/**
117
	 * Returns the target constraints to apply.
118
	 * 
119
	 * <p>
120
	 * This method provides a typesafe access to the {@link StringConstraints
121
	 * string target constraints} of this editing object and is equivalent to
122
	 * {@code (StringConstraints) targetConstraints()}.
123
	 * </p>
124
	 * 
125
	 * @return The target constraints to apply.
126
	 * 
127
	 * @see #targetConstraints()
128
	 * @see StringConstraints
129
	 */
130
	public StringConstraints targetStringConstraints() {
131
		return (StringConstraints) targetConstraints();
132
	}
133
134
	/**
135
	 * Returns the model constraints to apply.
136
	 * 
137
	 * <p>
138
	 * This method provides a typesafe access to the
139
	 * {@link BigDecimalConstraints BigDecimal model constraints} of this
140
	 * editing object and is equivalent to {@code (BigDecimalConstraints)
141
	 * modelConstraints()}.
142
	 * </p>
143
	 * 
144
	 * @return The model constraints to apply.
145
	 * 
146
	 * @see #modelConstraints()
147
	 * @see BigDecimalConstraints
148
	 */
149
	public BigDecimalConstraints modelBigDecimalConstraints() {
150
		return (BigDecimalConstraints) modelConstraints();
151
	}
152
153
	/**
154
	 * Returns the before-set model constraints to apply.
155
	 * 
156
	 * <p>
157
	 * This method provides a typesafe access to the
158
	 * {@link BigDecimalConstraints BigDecimal before-set model constraints} of
159
	 * this editing object and is equivalent to {@code (BigDecimalConstraints)
160
	 * beforeSetModelConstraints()}.
161
	 * </p>
162
	 * 
163
	 * @return The before-set model constraints to apply.
164
	 * 
165
	 * @see #beforeSetModelConstraints()
166
	 * @see BigDecimalConstraints
167
	 */
168
	public BigDecimalConstraints beforeSetModelBigDecimalConstraints() {
169
		return (BigDecimalConstraints) beforeSetModelConstraints();
170
	}
171
172
	protected Constraints createTargetConstraints() {
173
		return new StringConstraints();
174
	}
175
176
	protected Constraints createModelConstraints() {
177
		return new BigDecimalConstraints()
178
				.bigDecimalFormat(displayFormat);
179
	}
180
181
	protected Constraints createBeforeSetModelConstraints() {
182
		return new BigDecimalConstraints()
183
				.bigDecimalFormat(displayFormat);
184
	}
185
186
	/**
187
	 * Convenience method which adds a {@link BigDecimalConstraints#required()
188
	 * required constraint} to the set of {@link #modelBigDecimalConstraints()}.
189
	 * 
190
	 * @return This editing instance for method chaining.
191
	 * 
192
	 * @see BigDecimalConstraints#required()
193
	 * @see #modelBigDecimalConstraints()
194
	 */
195
	public BigDecimalEditing required() {
196
		modelBigDecimalConstraints().required();
197
		return this;
198
	}
199
200
	/**
201
	 * Convenience method which adds a
202
	 * {@link BigDecimalConstraints#greater(BigDecimal) greater constraint} to
203
	 * the set of {@link #modelBigDecimalConstraints()}.
204
	 * 
205
	 * @param number
206
	 *            The number of the greater constraint.
207
	 * @return This editing instance for method chaining.
208
	 * 
209
	 * @see BigDecimalConstraints#greater(BigDecimal)
210
	 * @see #modelBigDecimalConstraints()
211
	 */
212
	public BigDecimalEditing greater(BigDecimal number) {
213
		modelBigDecimalConstraints().greater(number);
214
		return this;
215
	}
216
217
	/**
218
	 * Convenience method which adds a
219
	 * {@link BigDecimalConstraints#greaterEqual(BigDecimal) greater-equal
220
	 * constraint} to the set of {@link #modelBigDecimalConstraints()}.
221
	 * 
222
	 * @param number
223
	 *            The number of the greater-equal constraint.
224
	 * @return This editing instance for method chaining.
225
	 * 
226
	 * @see BigDecimalConstraints#greaterEqual(BigDecimal)
227
	 * @see #modelBigDecimalConstraints()
228
	 */
229
	public BigDecimalEditing greaterEqual(BigDecimal number) {
230
		modelBigDecimalConstraints().greaterEqual(number);
231
		return this;
232
	}
233
234
	/**
235
	 * Convenience method which adds a
236
	 * {@link BigDecimalConstraints#less(BigDecimal) less constraint} to the set
237
	 * of {@link #modelBigDecimalConstraints()}.
238
	 * 
239
	 * @param number
240
	 *            The number of the less constraint.
241
	 * @return This editing instance for method chaining.
242
	 * 
243
	 * @see BigDecimalConstraints#less(BigDecimal)
244
	 * @see #modelBigDecimalConstraints()
245
	 */
246
	public BigDecimalEditing less(BigDecimal number) {
247
		modelBigDecimalConstraints().less(number);
248
		return this;
249
	}
250
251
	/**
252
	 * Convenience method which adds a
253
	 * {@link BigDecimalConstraints#lessEqual(BigDecimal) less-equal constraint}
254
	 * to the set of {@link #modelBigDecimalConstraints()}.
255
	 * 
256
	 * @param number
257
	 *            The number of the less-equal constraint.
258
	 * @return This editing instance for method chaining.
259
	 * 
260
	 * @see BigDecimalConstraints#lessEqual(BigDecimal)
261
	 * @see #modelBigDecimalConstraints()
262
	 */
263
	public BigDecimalEditing lessEqual(BigDecimal number) {
264
		modelBigDecimalConstraints().lessEqual(number);
265
		return this;
266
	}
267
268
	/**
269
	 * Convenience method which adds a
270
	 * {@link BigDecimalConstraints#range(BigDecimal, BigDecimal) range
271
	 * constraint} to the set of {@link #modelBigDecimalConstraints()}.
272
	 * 
273
	 * @param min
274
	 *            The min number of the range constraint.
275
	 * @param max
276
	 *            The max number of the range constraint.
277
	 * @return This editing instance for method chaining.
278
	 * 
279
	 * @see BigDecimalConstraints#range(BigDecimal, BigDecimal)
280
	 * @see #modelBigDecimalConstraints()
281
	 */
282
	public BigDecimalEditing range(BigDecimal min, BigDecimal max) {
283
		modelBigDecimalConstraints().range(min, max);
284
		return this;
285
	}
286
287
	/**
288
	 * Convenience method which adds a {@link BigDecimalConstraints#positive()
289
	 * positive constraint} to the set of {@link #modelBigDecimalConstraints()}.
290
	 * 
291
	 * @return This editing instance for method chaining.
292
	 * 
293
	 * @see BigDecimalConstraints#positive()
294
	 * @see #modelBigDecimalConstraints()
295
	 */
296
	public BigDecimalEditing positive() {
297
		modelBigDecimalConstraints().positive();
298
		return this;
299
	}
300
301
	/**
302
	 * Convenience method which adds a
303
	 * {@link BigDecimalConstraints#nonNegative() non-negative constraint} to
304
	 * the set of {@link #modelBigDecimalConstraints()} .
305
	 * 
306
	 * @return This editing instance for method chaining.
307
	 * 
308
	 * @see BigDecimalConstraints#nonNegative()
309
	 * @see #modelBigDecimalConstraints()
310
	 */
311
	public BigDecimalEditing nonNegative() {
312
		modelBigDecimalConstraints().nonNegative();
313
		return this;
314
	}
315
316
	/**
317
	 * Convenience method which adds a
318
	 * {@link BigDecimalConstraints#maxScale(int) max-scale constraint} to the
319
	 * set of {@link #modelBigDecimalConstraints()} .
320
	 * 
321
	 * @param scale
322
	 *            The maximum scale to enforce.
323
	 * @return This editing instance for method chaining.
324
	 * 
325
	 * @see BigDecimalConstraints#maxScale(int)
326
	 * @see #modelBigDecimalConstraints()
327
	 */
328
	public BigDecimalEditing maxScale(int scale) {
329
		modelBigDecimalConstraints().maxScale(scale);
330
		return this;
331
	}
332
}
(-)src/org/eclipse/core/internal/databinding/validation/IntegerRangeValidator.java (+206 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import com.ibm.icu.text.NumberFormat;
15
16
/**
17
 * Provides validations for integer numbers which must lie within an open/closed
18
 * range.
19
 * 
20
 * @since 1.4
21
 */
22
public class IntegerRangeValidator extends NumberRangeValidator {
23
24
	private static final Long ZERO = new Long(0);
25
	private static final Long ONE = new Long(1);
26
27
	/**
28
	 * Single constructor which supports the individual integer range types.
29
	 * 
30
	 * @param min
31
	 *            The min integer of the range or <code>null</code> in case no
32
	 *            lower bound is defined.
33
	 * @param max
34
	 *            The max integer of the range or <code>null</code> in case no
35
	 *            upper bound is defined.
36
	 * @param minConstraint
37
	 *            The type of constraint imposed by the lower bound of the
38
	 *            range.
39
	 * @param maxConstraint
40
	 *            The type of constraint imposed by the upper bound of the
41
	 *            range.
42
	 * @param validationMessage
43
	 *            The validation message pattern to use. Can be parameterized by
44
	 *            the lower and upper bound of the range, if defined.
45
	 * @param format
46
	 *            The integer format to use for formatting integers in the
47
	 *            validation message.
48
	 */
49
	private IntegerRangeValidator(Number min, Number max, int minConstraint,
50
			int maxConstraint, String validationMessage, NumberFormat format) {
51
		super(min, max, minConstraint, maxConstraint, validationMessage, format);
52
	}
53
54
	/**
55
	 * Creates a validator which checks that an input integer is greater than
56
	 * the given number.
57
	 * 
58
	 * @param number
59
	 *            The reference number of the greater constraint.
60
	 * @param validationMessage
61
	 *            The validation message pattern to use. Can be parameterized
62
	 *            with the given reference number.
63
	 * @param format
64
	 *            The display format to use for formatting integers in the
65
	 *            validation message.
66
	 * @return The validator instance.
67
	 */
68
	public static IntegerRangeValidator greater(long number,
69
			String validationMessage, NumberFormat format) {
70
		return new IntegerRangeValidator(new Long(number), null, GREATER,
71
				UNDEFINED, defaultIfNull(validationMessage, GREATER_MESSAGE),
72
				format);
73
	}
74
75
	/**
76
	 * Creates a validator which checks that an input integer is greater than or
77
	 * equal to the given number.
78
	 * 
79
	 * @param number
80
	 *            The reference number of the greater-equal constraint.
81
	 * @param validationMessage
82
	 *            The validation message pattern to use. Can be parameterized
83
	 *            with the given reference number.
84
	 * @param format
85
	 *            The display format to use for formatting integers in the
86
	 *            validation message.
87
	 * @return The validator instance.
88
	 */
89
	public static IntegerRangeValidator greaterEqual(long number,
90
			String validationMessage, NumberFormat format) {
91
		return new IntegerRangeValidator(new Long(number), null, GREATER_EQUAL,
92
				UNDEFINED, defaultIfNull(validationMessage,
93
						GREATER_EQUAL_MESSAGE), format);
94
	}
95
96
	/**
97
	 * Creates a validator which checks that an input integer is less than the
98
	 * given number.
99
	 * 
100
	 * @param number
101
	 *            The reference number of the less constraint.
102
	 * @param validationMessage
103
	 *            The validation message pattern to use. Can be parameterized
104
	 *            with the given reference number.
105
	 * @param format
106
	 *            The display format to use for formatting integers in the
107
	 *            validation message.
108
	 * @return The validator instance.
109
	 */
110
	public static IntegerRangeValidator less(long number,
111
			String validationMessage, NumberFormat format) {
112
		return new IntegerRangeValidator(null, new Long(number), UNDEFINED,
113
				LESS, defaultIfNull(validationMessage, LESS_MESSAGE), format);
114
	}
115
116
	/**
117
	 * Creates a validator which checks that an input integer is less than or
118
	 * equal to the given number.
119
	 * 
120
	 * @param number
121
	 *            The reference number of the less-equal constraint.
122
	 * @param validationMessage
123
	 *            The validation message pattern to use. Can be parameterized
124
	 *            with the given reference number.
125
	 * @param format
126
	 *            The display format to use for formatting integers in the
127
	 *            validation message.
128
	 * @return The validator instance.
129
	 */
130
	public static IntegerRangeValidator lessEqual(long number,
131
			String validationMessage, NumberFormat format) {
132
		return new IntegerRangeValidator(null, new Long(number), UNDEFINED,
133
				LESS_EQUAL,
134
				defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
135
	}
136
137
	/**
138
	 * Creates a validator which checks that an input integer is within the
139
	 * given range.
140
	 * 
141
	 * @param min
142
	 *            The lower bound of the range (inclusive).
143
	 * @param max
144
	 *            The upper bound of the range (inclusive).
145
	 * @param validationMessage
146
	 *            The validation message pattern to use. Can be parameterized
147
	 *            with the range's lower and upper bound.
148
	 * @param format
149
	 *            The display format to use for formatting integers in the
150
	 *            validation message.
151
	 * @return The validator instance.
152
	 */
153
	public static IntegerRangeValidator range(long min, long max,
154
			String validationMessage, NumberFormat format) {
155
		return new IntegerRangeValidator(new Long(min), new Long(max),
156
				GREATER_EQUAL, LESS_EQUAL, defaultIfNull(validationMessage,
157
						WITHIN_RANGE_MESSAGE), format);
158
	}
159
160
	/**
161
	 * Creates a validator which checks that an input integer is positive.
162
	 * 
163
	 * @param validationMessage
164
	 *            The validation message to use.
165
	 * @param format
166
	 *            The display format to use for formatting integers in the
167
	 *            validation message.
168
	 * @return The validator instance.
169
	 */
170
	public static IntegerRangeValidator positive(String validationMessage,
171
			NumberFormat format) {
172
		return new IntegerRangeValidator(ONE, null, GREATER_EQUAL, UNDEFINED,
173
				defaultIfNull(validationMessage, POSITIVE_MESSAGE), format);
174
	}
175
176
	/**
177
	 * Creates a validator which checks that an input integer is non-negative.
178
	 * 
179
	 * @param validationMessage
180
	 *            The validation message to use.
181
	 * @param format
182
	 *            The display format to use for formatting integers in the
183
	 *            validation message.
184
	 * @return The validator instance.
185
	 */
186
	public static IntegerRangeValidator nonNegative(String validationMessage,
187
			NumberFormat format) {
188
		return new IntegerRangeValidator(ZERO, null, GREATER_EQUAL, UNDEFINED,
189
				defaultIfNull(validationMessage, NON_NEGATIVE_MESSAGE), format);
190
	}
191
192
	protected int compare(Number number1, Number number2) {
193
		long diff = number1.longValue() - number2.longValue();
194
		if (diff < 0) {
195
			return -1;
196
		}
197
		if (diff > 0) {
198
			return +1;
199
		}
200
		return 0;
201
	}
202
203
	private static String defaultIfNull(String string, String defaultString) {
204
		return (string != null) ? string : defaultString;
205
	}
206
}
(-)src/org/eclipse/core/databinding/validation/constraint/BigIntegerConstraints.java (+311 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import java.math.BigInteger;
15
16
import org.eclipse.core.internal.databinding.validation.BigIntegerRangeValidator;
17
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
18
19
import com.ibm.icu.text.NumberFormat;
20
21
/**
22
 * @since 1.4
23
 */
24
public final class BigIntegerConstraints extends Constraints {
25
26
	private NumberFormat bigIntegerFormat = NumberFormat.getIntegerInstance();
27
28
	private String requiredMessage = null;
29
30
	private String greaterMessage = null;
31
32
	private String greaterEqualMessage = null;
33
34
	private String lessMessage = null;
35
36
	private String lessEqualMessage = null;
37
38
	private String rangeMessage = null;
39
40
	private String positiveMessage = null;
41
42
	private String nonNegativeMessage = null;
43
44
	/**
45
	 * Sets the format to use when formatting a BigInteger to be included in any
46
	 * of the validation messages.
47
	 * 
48
	 * <p>
49
	 * This BigInteger format will be used for any subsequent constraints which
50
	 * are applied.
51
	 * </p>
52
	 * 
53
	 * @param format
54
	 *            The format to use for displaying BigIntegers in validation
55
	 *            messages.
56
	 * @return This constraints instance for method chaining.
57
	 */
58
	public BigIntegerConstraints bigIntegerFormat(NumberFormat format) {
59
		this.bigIntegerFormat = format;
60
		return this;
61
	}
62
63
	/**
64
	 * Adds a validator ensuring that the parsed BigInteger is not
65
	 * <code>null</code>. Uses the current {@link #requiredMessage(String)
66
	 * validation message}.
67
	 * 
68
	 * @return This constraints instance for method chaining.
69
	 */
70
	public BigIntegerConstraints required() {
71
		addValidator(new NonNullValidator(requiredMessage));
72
		return this;
73
	}
74
75
	/**
76
	 * Sets the validation message for the {@link #required()} constraint.
77
	 * 
78
	 * @param message
79
	 *            The validation message for the {@link #required()} constraint.
80
	 * @return This constraints instance for method chaining.
81
	 * 
82
	 * @see #required()
83
	 */
84
	public BigIntegerConstraints requiredMessage(String message) {
85
		this.requiredMessage = message;
86
		return this;
87
	}
88
89
	/**
90
	 * Adds a validator ensuring that the parsed BigInteger is greater than the
91
	 * given number. Uses the current {@link #greaterMessage(String) validation
92
	 * message}.
93
	 * 
94
	 * @param number
95
	 *            The number which the parsed BigInteger must be greater than.
96
	 * @return This constraints instance for method chaining.
97
	 */
98
	public BigIntegerConstraints greater(BigInteger number) {
99
		addValidator(BigIntegerRangeValidator.greater(number, greaterMessage,
100
				bigIntegerFormat));
101
		return this;
102
	}
103
104
	/**
105
	 * Sets the validation message pattern for the {@link #greater(BigInteger)}
106
	 * constraint.
107
	 * 
108
	 * @param message
109
	 *            The validation message pattern for the
110
	 *            {@link #greater(BigInteger)} constraint. Can be parameterized
111
	 *            with the number which the parsed BigInteger must be greater
112
	 *            than.
113
	 * @return This constraints instance for method chaining.
114
	 * 
115
	 * @see #greater(BigInteger)
116
	 */
117
	public BigIntegerConstraints greaterMessage(String message) {
118
		this.greaterMessage = message;
119
		return this;
120
	}
121
122
	/**
123
	 * Adds a validator ensuring that the parsed BigInteger is greater than or
124
	 * equal to the given number. Uses the current
125
	 * {@link #greaterEqualMessage(String) validation message}.
126
	 * 
127
	 * @param number
128
	 *            The number which the parsed BigInteger must be greater than or
129
	 *            equal to.
130
	 * @return This constraints instance for method chaining.
131
	 */
132
	public BigIntegerConstraints greaterEqual(BigInteger number) {
133
		addValidator(BigIntegerRangeValidator.greaterEqual(number,
134
				greaterEqualMessage, bigIntegerFormat));
135
		return this;
136
	}
137
138
	/**
139
	 * Sets the validation message pattern for the
140
	 * {@link #greaterEqual(BigInteger)} constraint.
141
	 * 
142
	 * @param message
143
	 *            The validation message pattern for the
144
	 *            {@link #greaterEqual(BigInteger)} constraint. Can be
145
	 *            parameterized with the number which the parsed BigInteger must
146
	 *            be greater than or equal to.
147
	 * @return This constraints instance for method chaining.
148
	 * 
149
	 * @see #greaterEqual(BigInteger)
150
	 */
151
	public BigIntegerConstraints greaterEqualMessage(String message) {
152
		this.greaterEqualMessage = message;
153
		return this;
154
	}
155
156
	/**
157
	 * Adds a validator ensuring that the parsed BigInteger is less than the
158
	 * given number. Uses the current {@link #lessMessage(String) validation
159
	 * message}.
160
	 * 
161
	 * @param number
162
	 *            The number which the parsed BigInteger must be less than.
163
	 * @return This constraints instance for method chaining.
164
	 */
165
	public BigIntegerConstraints less(BigInteger number) {
166
		addValidator(BigIntegerRangeValidator.less(number, lessMessage,
167
				bigIntegerFormat));
168
		return this;
169
	}
170
171
	/**
172
	 * Sets the validation message pattern for the {@link #less(BigInteger)}
173
	 * constraint.
174
	 * 
175
	 * @param message
176
	 *            The validation message pattern for the
177
	 *            {@link #less(BigInteger)} constraint. Can be parameterized
178
	 *            with the number which the parsed BigInteger must be less than.
179
	 * @return This constraints instance for method chaining.
180
	 * 
181
	 * @see #less(BigInteger)
182
	 */
183
	public BigIntegerConstraints lessMessage(String message) {
184
		this.lessMessage = message;
185
		return this;
186
	}
187
188
	/**
189
	 * Adds a validator ensuring that the parsed BigInteger is less than or
190
	 * equal to the given number. Uses the current
191
	 * {@link #lessEqualMessage(String) validation message}.
192
	 * 
193
	 * @param number
194
	 *            The number which the parsed BigInteger must be less than or
195
	 *            equal to.
196
	 * @return This constraints instance for method chaining.
197
	 */
198
	public BigIntegerConstraints lessEqual(BigInteger number) {
199
		addValidator(BigIntegerRangeValidator.greaterEqual(number,
200
				lessEqualMessage, bigIntegerFormat));
201
		return this;
202
	}
203
204
	/**
205
	 * Sets the validation message pattern for the
206
	 * {@link #lessEqual(BigInteger)} constraint.
207
	 * 
208
	 * @param message
209
	 *            The validation message pattern for the
210
	 *            {@link #lessEqual(BigInteger)} constraint. Can be
211
	 *            parameterized with the number which the parsed BigInteger must
212
	 *            be less than or equal to.
213
	 * @return This constraints instance for method chaining.
214
	 * 
215
	 * @see #lessEqual(BigInteger)
216
	 */
217
	public BigIntegerConstraints lessEqualMessage(String message) {
218
		this.lessEqualMessage = message;
219
		return this;
220
	}
221
222
	/**
223
	 * Adds a validator ensuring that the parsed BigInteger is within the given
224
	 * range. Uses the current {@link #rangeMessage(String) validation message}.
225
	 * 
226
	 * @param min
227
	 *            The lower bound of the range (inclusive).
228
	 * @param max
229
	 *            The upper bound of the range (inclusive).
230
	 * @return This constraints instance for method chaining.
231
	 */
232
	public BigIntegerConstraints range(BigInteger min, BigInteger max) {
233
		addValidator(BigIntegerRangeValidator.range(min, max, rangeMessage,
234
				bigIntegerFormat));
235
		return this;
236
	}
237
238
	/**
239
	 * Sets the validation message pattern for the
240
	 * {@link #range(BigInteger, BigInteger)} constraint.
241
	 * 
242
	 * @param message
243
	 *            The validation message pattern for the
244
	 *            {@link #range(BigInteger, BigInteger)} constraint. Can be
245
	 *            parameterized with the min and max values of the range in
246
	 *            which the parsed BigInteger must lie.
247
	 * @return This constraints instance for method chaining.
248
	 * 
249
	 * @see #range(BigInteger, BigInteger)
250
	 */
251
	public BigIntegerConstraints rangeMessage(String message) {
252
		this.rangeMessage = message;
253
		return this;
254
	}
255
256
	/**
257
	 * Adds a validator ensuring that the parsed BigInteger is positive. Uses
258
	 * the current {@link #positiveMessage(String) validation message}.
259
	 * 
260
	 * @return This constraints instance for method chaining.
261
	 */
262
	public BigIntegerConstraints positive() {
263
		addValidator(BigIntegerRangeValidator.positive(positiveMessage,
264
				bigIntegerFormat));
265
		return this;
266
	}
267
268
	/**
269
	 * Sets the validation message pattern for the {@link #positive()}
270
	 * constraint.
271
	 * 
272
	 * @param message
273
	 *            The validation message pattern for the {@link #positive()}
274
	 *            constraint.
275
	 * @return This constraints instance for method chaining.
276
	 * 
277
	 * @see #positive()
278
	 */
279
	public BigIntegerConstraints positiveMessage(String message) {
280
		this.positiveMessage = message;
281
		return this;
282
	}
283
284
	/**
285
	 * Adds a validator ensuring that the parsed BigInteger is non-negative.
286
	 * Uses the current {@link #nonNegativeMessage(String) validation message}.
287
	 * 
288
	 * @return This constraints instance for method chaining.
289
	 */
290
	public BigIntegerConstraints nonNegative() {
291
		addValidator(BigIntegerRangeValidator.nonNegative(nonNegativeMessage,
292
				bigIntegerFormat));
293
		return this;
294
	}
295
296
	/**
297
	 * Sets the validation message pattern for the {@link #nonNegative()}
298
	 * constraint.
299
	 * 
300
	 * @param message
301
	 *            The validation message pattern for the {@link #nonNegative()}
302
	 *            constraint.
303
	 * @return This constraints instance for method chaining.
304
	 * 
305
	 * @see #nonNegative()
306
	 */
307
	public BigIntegerConstraints nonNegativeMessage(String message) {
308
		this.nonNegativeMessage = message;
309
		return this;
310
	}
311
}
(-)src/org/eclipse/core/internal/databinding/validation/CharacterValidator.java (+140 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import org.eclipse.core.databinding.validation.IValidator;
15
import org.eclipse.core.databinding.validation.ValidationStatus;
16
import org.eclipse.core.internal.databinding.BindingMessages;
17
import org.eclipse.core.runtime.IStatus;
18
19
/**
20
 * @since 1.4
21
 */
22
public class CharacterValidator implements IValidator {
23
24
	private static final int VALIDATE_NO_WHITESPACE = 0;
25
	private static final int VALIDATE_NO_SPACE = 1;
26
	private static final int VALIDATE_LETTER = 2;
27
	private static final int VALIDATE_DIGIT = 3;
28
	private static final int VALIDATE_LETTER_OR_DIGIT = 4;
29
30
	private static final String NO_WHITESPACE_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_CHARACTER_NO_WHITESPACE);
31
	private static final String NO_SPACE_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_CHARACTER_NO_SPACE);
32
	private static final String LETTER_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_CHARACTER_LETTER);
33
	private static final String DIGIT_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_CHARACTER_DIGIT);
34
	private static final String LETTER_OR_DIGIT_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_CHARACTER_LETTER_OR_DIGIT);
35
36
	private final int validation;
37
	private final String validationMessage;
38
39
	private CharacterValidator(int validation, String validationMessage) {
40
		this.validation = validation;
41
		this.validationMessage = validationMessage;
42
	}
43
44
	/**
45
	 * Creates a validator which checks that an input character is no
46
	 * {@link Character#isWhitespace(char) whitespace}.
47
	 * 
48
	 * @param validationMessage
49
	 *            The validation message to use.
50
	 * @return The validator instance.
51
	 */
52
	public static CharacterValidator noWhitespace(String validationMessage) {
53
		return new CharacterValidator(VALIDATE_NO_WHITESPACE, defaultIfNull(
54
				NO_WHITESPACE_VALIDATION_MESSAGE, validationMessage));
55
	}
56
57
	/**
58
	 * Creates a validator which checks that an input character is no
59
	 * {@link Character#isSpaceChar(char) space}.
60
	 * 
61
	 * @param validationMessage
62
	 *            The validation message to use.
63
	 * @return The validator instance.
64
	 */
65
	public static CharacterValidator noSpace(String validationMessage) {
66
		return new CharacterValidator(VALIDATE_NO_SPACE, defaultIfNull(
67
				NO_SPACE_VALIDATION_MESSAGE, validationMessage));
68
	}
69
70
	/**
71
	 * Creates a validator which checks that an input character is a
72
	 * {@link Character#isLetter(char) letter}.
73
	 * 
74
	 * @param validationMessage
75
	 *            The validation message to use.
76
	 * @return The validator instance.
77
	 */
78
	public static CharacterValidator letter(String validationMessage) {
79
		return new CharacterValidator(VALIDATE_LETTER, defaultIfNull(
80
				LETTER_VALIDATION_MESSAGE, validationMessage));
81
	}
82
83
	/**
84
	 * Creates a validator which checks that an input character is a
85
	 * {@link Character#isDigit(char) digit}.
86
	 * 
87
	 * @param validationMessage
88
	 *            The validation message to use.
89
	 * @return The validator instance.
90
	 */
91
	public static CharacterValidator digit(String validationMessage) {
92
		return new CharacterValidator(VALIDATE_DIGIT, defaultIfNull(
93
				DIGIT_VALIDATION_MESSAGE, validationMessage));
94
	}
95
96
	/**
97
	 * Creates a validator which checks that an input character is a
98
	 * {@link Character#isLetterOrDigit(char) letter or ditig}.
99
	 * 
100
	 * @param validationMessage
101
	 *            The validation message to use.
102
	 * @return The validator instance.
103
	 */
104
	public static CharacterValidator letterOrDigit(String validationMessage) {
105
		return new CharacterValidator(VALIDATE_LETTER_OR_DIGIT, defaultIfNull(
106
				LETTER_OR_DIGIT_VALIDATION_MESSAGE, validationMessage));
107
	}
108
109
	public IStatus validate(Object value) {
110
		if (value != null) {
111
			char character = ((Character) value).charValue();
112
			if (!isValid(character)) {
113
				return ValidationStatus.error(validationMessage);
114
			}
115
		}
116
		return ValidationStatus.ok();
117
	}
118
119
	private boolean isValid(char character) {
120
		switch (validation) {
121
		case VALIDATE_NO_WHITESPACE:
122
			return !Character.isWhitespace(character);
123
		case VALIDATE_NO_SPACE:
124
			return !Character.isSpaceChar(character);
125
		case VALIDATE_LETTER:
126
			return Character.isLetter(character);
127
		case VALIDATE_DIGIT:
128
			return Character.isDigit(character);
129
		case VALIDATE_LETTER_OR_DIGIT:
130
			return Character.isLetterOrDigit(character);
131
		default:
132
			throw new IllegalArgumentException(
133
					"Unsupported validation: " + validation); //$NON-NLS-1$
134
		}
135
	}
136
137
	private static String defaultIfNull(String string, String defaultString) {
138
		return (string != null) ? string : defaultString;
139
	}
140
}
(-)src/org/eclipse/core/databinding/editing/CharacterEditing.java (+220 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import org.eclipse.core.databinding.validation.constraint.CharacterConstraints;
15
import org.eclipse.core.databinding.validation.constraint.Constraints;
16
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
17
import org.eclipse.core.internal.databinding.conversion.CharacterToStringConverter;
18
import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter;
19
import org.eclipse.core.internal.databinding.validation.StringToCharacterValidator;
20
21
/**
22
 * @since 1.4
23
 */
24
public final class CharacterEditing extends Editing {
25
26
	private CharacterEditing(String parseErrorMessage) {
27
		StringToCharacterConverter targetConverter = new StringToCharacterConverter(
28
				false);
29
		CharacterToStringConverter modelConverter = CharacterToStringConverter
30
				.fromCharacter(false);
31
32
		StringToCharacterValidator targetValidator = new StringToCharacterValidator(
33
				targetConverter);
34
		if (parseErrorMessage != null) {
35
			targetValidator.setParseErrorMessage(parseErrorMessage);
36
		}
37
38
		setTargetConverter(targetConverter);
39
		setModelConverter(modelConverter);
40
		addTargetValidator(targetValidator);
41
	}
42
43
	/**
44
	 * Creates a new editing object which uses the default validations and
45
	 * conversions for the editing of characters.
46
	 * 
47
	 * @return The new editing object for the default editing of characters.
48
	 */
49
	public static CharacterEditing withDefaults() {
50
		return withDefaults(null);
51
	}
52
53
	/**
54
	 * Creates a new editing object which uses the default validations and
55
	 * conversions for the editing of characters. Uses the specified custom
56
	 * validation message.
57
	 * 
58
	 * @param parseErrorMessage
59
	 *            The validation message issued in case the input string is not
60
	 *            a valid character.
61
	 * @return The new editing object for the default editing of characters.
62
	 */
63
	public static CharacterEditing withDefaults(String parseErrorMessage) {
64
		return new CharacterEditing(parseErrorMessage);
65
	}
66
67
	/**
68
	 * Returns the target constraints to apply.
69
	 * 
70
	 * <p>
71
	 * This method provides a typesafe access to the {@link StringConstraints
72
	 * string target constraints} of this editing object and is equivalent to
73
	 * {@code (StringConstraints) targetConstraints()}.
74
	 * </p>
75
	 * 
76
	 * @return The target constraints to apply.
77
	 * 
78
	 * @see #targetConstraints()
79
	 * @see StringConstraints
80
	 */
81
	public StringConstraints targetStringConstraints() {
82
		return (StringConstraints) targetConstraints();
83
	}
84
85
	/**
86
	 * Returns the model constraints to apply.
87
	 * 
88
	 * <p>
89
	 * This method provides a typesafe access to the
90
	 * {@link CharacterConstraints character model constraints} of this editing
91
	 * object and is equivalent to {@code (CharacterConstraints)
92
	 * modelConstraints()}.
93
	 * </p>
94
	 * 
95
	 * @return The model constraints to apply.
96
	 * 
97
	 * @see #modelConstraints()
98
	 * @see CharacterConstraints
99
	 */
100
	public CharacterConstraints modelCharacterConstraints() {
101
		return (CharacterConstraints) modelConstraints();
102
	}
103
104
	/**
105
	 * Returns the before-set model constraints to apply.
106
	 * 
107
	 * <p>
108
	 * This method provides a typesafe access to the
109
	 * {@link CharacterConstraints character before-set model constraints} of
110
	 * this editing object and is equivalent to {@code (CharacterConstraints)
111
	 * beforeSetModelConstraints()}.
112
	 * </p>
113
	 * 
114
	 * @return The before-set model constraints to apply.
115
	 * 
116
	 * @see #beforeSetModelConstraints()
117
	 * @see CharacterConstraints
118
	 */
119
	public CharacterConstraints beforeSetModelCharacterConstraints() {
120
		return (CharacterConstraints) beforeSetModelConstraints();
121
	}
122
123
	protected Constraints createTargetConstraints() {
124
		return new StringConstraints();
125
	}
126
127
	protected Constraints createModelConstraints() {
128
		return new CharacterConstraints();
129
	}
130
131
	protected Constraints createBeforeSetModelConstraints() {
132
		return new CharacterConstraints();
133
	}
134
135
	/**
136
	 * Convenience method which adds a {@link CharacterConstraints#required()
137
	 * required constraint} to the set of {@link #modelCharacterConstraints()}.
138
	 * 
139
	 * @return This editing instance for method chaining.
140
	 * 
141
	 * @see CharacterConstraints#required()
142
	 * @see #modelCharacterConstraints()
143
	 */
144
	public CharacterEditing required() {
145
		modelCharacterConstraints().required();
146
		return this;
147
	}
148
149
	/**
150
	 * Convenience method which adds a
151
	 * {@link CharacterConstraints#noWhitespace() no-whitespace constraint} to
152
	 * the set of {@link #modelCharacterConstraints()}.
153
	 * 
154
	 * @return This editing instance for method chaining.
155
	 * 
156
	 * @see CharacterConstraints#noWhitespace()
157
	 * @see #modelCharacterConstraints()
158
	 */
159
	public CharacterEditing noWhitespace() {
160
		modelCharacterConstraints().noWhitespace();
161
		return this;
162
	}
163
164
	/**
165
	 * Convenience method which adds a {@link CharacterConstraints#noSpace()
166
	 * no-space constraint} to the set of {@link #modelCharacterConstraints()}.
167
	 * 
168
	 * @return This editing instance for method chaining.
169
	 * 
170
	 * @see CharacterConstraints#noSpace()
171
	 * @see #modelCharacterConstraints()
172
	 */
173
	public CharacterEditing noSpace() {
174
		modelCharacterConstraints().noSpace();
175
		return this;
176
	}
177
178
	/**
179
	 * Convenience method which adds a {@link CharacterConstraints#letter()
180
	 * letter constraint} to the set of {@link #modelCharacterConstraints()}.
181
	 * 
182
	 * @return This editing instance for method chaining.
183
	 * 
184
	 * @see CharacterConstraints#letter()
185
	 * @see #modelCharacterConstraints()
186
	 */
187
	public CharacterEditing letter() {
188
		modelCharacterConstraints().letter();
189
		return this;
190
	}
191
192
	/**
193
	 * Convenience method which adds a {@link CharacterConstraints#digit() digit
194
	 * constraint} to the set of {@link #modelCharacterConstraints()}.
195
	 * 
196
	 * @return This editing instance for method chaining.
197
	 * 
198
	 * @see CharacterConstraints#digit()
199
	 * @see #modelCharacterConstraints()
200
	 */
201
	public CharacterEditing digit() {
202
		modelCharacterConstraints().digit();
203
		return this;
204
	}
205
206
	/**
207
	 * Convenience method which adds a
208
	 * {@link CharacterConstraints#letterOrDigit() letter-or-digit constraint}
209
	 * to the set of {@link #modelCharacterConstraints()}.
210
	 * 
211
	 * @return This editing instance for method chaining.
212
	 * 
213
	 * @see CharacterConstraints#letterOrDigit()
214
	 * @see #modelCharacterConstraints()
215
	 */
216
	public CharacterEditing letterOrDigit() {
217
		modelCharacterConstraints().letterOrDigit();
218
		return this;
219
	}
220
}
(-)src/org/eclipse/core/internal/databinding/validation/StringToBigIntegerValidator.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
/**
15
 * Validates that a string is of the appropriate format for a BigInteger.
16
 * 
17
 * @since 1.4
18
 */
19
public class StringToBigIntegerValidator extends
20
		AbstractStringToNumberValidator {
21
22
	/**
23
	 * @param converter
24
	 */
25
	public StringToBigIntegerValidator(NumberFormatConverter converter) {
26
		super(converter, null, null);
27
	}
28
29
	protected boolean isInRange(Number number) {
30
		return true;
31
	}
32
}
(-)src/org/eclipse/core/internal/databinding/validation/NonNullValidator.java (+42 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import org.eclipse.core.databinding.validation.IValidator;
15
import org.eclipse.core.databinding.validation.ValidationStatus;
16
import org.eclipse.core.internal.databinding.BindingMessages;
17
import org.eclipse.core.runtime.IStatus;
18
19
/**
20
 * @since 1.4
21
 */
22
public class NonNullValidator implements IValidator {
23
24
	private static final String NON_NULL_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NON_NULL);
25
26
	private final String validationMessage;
27
28
	/**
29
	 * @param validationMessage
30
	 */
31
	public NonNullValidator(String validationMessage) {
32
		this.validationMessage = validationMessage != null ? validationMessage
33
				: NON_NULL_VALIDATION_MESSAGE;
34
	}
35
36
	public IStatus validate(Object value) {
37
		if (value == null) {
38
			return ValidationStatus.error(validationMessage);
39
		}
40
		return ValidationStatus.ok();
41
	}
42
}
(-)src/org/eclipse/core/internal/databinding/validation/DecimalRangeValidator.java (+206 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import com.ibm.icu.text.NumberFormat;
15
16
/**
17
 * Provides validations for decimal numbers which must lie within an open/closed
18
 * range.
19
 * 
20
 * @since 1.4
21
 */
22
public class DecimalRangeValidator extends NumberRangeValidator {
23
24
	private static final Double ZERO = new Double(0);
25
	private static final Double ONE = new Double(1);
26
27
	/**
28
	 * Single constructor which supports the individual decimal range types.
29
	 * 
30
	 * @param min
31
	 *            The min decimal of the range or <code>null</code> in case no
32
	 *            lower bound is defined.
33
	 * @param max
34
	 *            The max decimal of the range or <code>null</code> in case no
35
	 *            upper bound is defined.
36
	 * @param minConstraint
37
	 *            The type of constraint imposed by the lower bound of the
38
	 *            range.
39
	 * @param maxConstraint
40
	 *            The type of constraint imposed by the upper bound of the
41
	 *            range.
42
	 * @param validationMessage
43
	 *            The validation message pattern to use. Can be parameterized by
44
	 *            the lower and upper bound of the range, if defined.
45
	 * @param format
46
	 *            The decimal format to use for formatting integers in the
47
	 *            validation message.
48
	 */
49
	private DecimalRangeValidator(Number min, Number max, int minConstraint,
50
			int maxConstraint, String validationMessage, NumberFormat format) {
51
		super(min, max, minConstraint, maxConstraint, validationMessage, format);
52
	}
53
54
	/**
55
	 * Creates a validator which checks that an input decimal is greater than
56
	 * the given number.
57
	 * 
58
	 * @param number
59
	 *            The reference number of the greater constraint.
60
	 * @param validationMessage
61
	 *            The validation message pattern to use. Can be parameterized
62
	 *            with the given reference number.
63
	 * @param format
64
	 *            The display format to use for formatting integers in the
65
	 *            validation message.
66
	 * @return The validator instance.
67
	 */
68
	public static DecimalRangeValidator greater(double number,
69
			String validationMessage, NumberFormat format) {
70
		return new DecimalRangeValidator(new Double(number), null, GREATER,
71
				UNDEFINED, defaultIfNull(validationMessage, GREATER_MESSAGE),
72
				format);
73
	}
74
75
	/**
76
	 * Creates a validator which checks that an input decimal is greater than or
77
	 * equal to the given number.
78
	 * 
79
	 * @param number
80
	 *            The reference number of the greater-equal constraint.
81
	 * @param validationMessage
82
	 *            The validation message pattern to use. Can be parameterized
83
	 *            with the given reference number.
84
	 * @param format
85
	 *            The display format to use for formatting integers in the
86
	 *            validation message.
87
	 * @return The validator instance.
88
	 */
89
	public static DecimalRangeValidator greaterEqual(double number,
90
			String validationMessage, NumberFormat format) {
91
		return new DecimalRangeValidator(new Double(number), null,
92
				GREATER_EQUAL, UNDEFINED, defaultIfNull(validationMessage,
93
						GREATER_EQUAL_MESSAGE), format);
94
	}
95
96
	/**
97
	 * Creates a validator which checks that an input decimal is less than the
98
	 * given number.
99
	 * 
100
	 * @param number
101
	 *            The reference number of the less constraint.
102
	 * @param validationMessage
103
	 *            The validation message pattern to use. Can be parameterized
104
	 *            with the given reference number.
105
	 * @param format
106
	 *            The display format to use for formatting integers in the
107
	 *            validation message.
108
	 * @return The validator instance.
109
	 */
110
	public static DecimalRangeValidator less(double number,
111
			String validationMessage, NumberFormat format) {
112
		return new DecimalRangeValidator(null, new Double(number), UNDEFINED,
113
				LESS, defaultIfNull(validationMessage, LESS_MESSAGE), format);
114
	}
115
116
	/**
117
	 * Creates a validator which checks that an input decimal is less than or
118
	 * equal to the given number.
119
	 * 
120
	 * @param number
121
	 *            The reference number of the less-equal constraint.
122
	 * @param validationMessage
123
	 *            The validation message pattern to use. Can be parameterized
124
	 *            with the given reference number.
125
	 * @param format
126
	 *            The display format to use for formatting integers in the
127
	 *            validation message.
128
	 * @return The validator instance.
129
	 */
130
	public static DecimalRangeValidator lessEqual(double number,
131
			String validationMessage, NumberFormat format) {
132
		return new DecimalRangeValidator(null, new Double(number), UNDEFINED,
133
				LESS_EQUAL,
134
				defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
135
	}
136
137
	/**
138
	 * Creates a validator which checks that an input decimal is within the
139
	 * given range.
140
	 * 
141
	 * @param min
142
	 *            The lower bound of the range (inclusive).
143
	 * @param max
144
	 *            The upper bound of the range (inclusive).
145
	 * @param validationMessage
146
	 *            The validation message pattern to use. Can be parameterized
147
	 *            with the range's lower and upper bound.
148
	 * @param format
149
	 *            The display format to use for formatting integers in the
150
	 *            validation message.
151
	 * @return The validator instance.
152
	 */
153
	public static DecimalRangeValidator range(double min, double max,
154
			String validationMessage, NumberFormat format) {
155
		return new DecimalRangeValidator(new Double(min), new Double(max),
156
				GREATER_EQUAL, LESS_EQUAL, defaultIfNull(validationMessage,
157
						WITHIN_RANGE_MESSAGE), format);
158
	}
159
160
	/**
161
	 * Creates a validator which checks that an input decimal is positive.
162
	 * 
163
	 * @param validationMessage
164
	 *            The validation message to use.
165
	 * @param format
166
	 *            The display format to use for formatting integers in the
167
	 *            validation message.
168
	 * @return The validator instance.
169
	 */
170
	public static DecimalRangeValidator positive(String validationMessage,
171
			NumberFormat format) {
172
		return new DecimalRangeValidator(ONE, null, GREATER_EQUAL, UNDEFINED,
173
				defaultIfNull(validationMessage, POSITIVE_MESSAGE), format);
174
	}
175
176
	/**
177
	 * Creates a validator which checks that an input decimal is non-negative.
178
	 * 
179
	 * @param validationMessage
180
	 *            The validation message to use.
181
	 * @param format
182
	 *            The display format to use for formatting integers in the
183
	 *            validation message.
184
	 * @return The validator instance.
185
	 */
186
	public static DecimalRangeValidator nonNegative(String validationMessage,
187
			NumberFormat format) {
188
		return new DecimalRangeValidator(ZERO, null, GREATER_EQUAL, UNDEFINED,
189
				defaultIfNull(validationMessage, NON_NEGATIVE_MESSAGE), format);
190
	}
191
192
	protected int compare(Number number1, Number number2) {
193
		double diff = number1.doubleValue() - number2.doubleValue();
194
		if (diff < 0) {
195
			return -1;
196
		}
197
		if (diff > 0) {
198
			return +1;
199
		}
200
		return 0;
201
	}
202
203
	private static String defaultIfNull(String string, String defaultString) {
204
		return (string != null) ? string : defaultString;
205
	}
206
}
(-)src/org/eclipse/core/internal/databinding/validation/BigDecimalRangeValidator.java (+206 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import java.math.BigDecimal;
15
16
import com.ibm.icu.text.NumberFormat;
17
18
/**
19
 * Provides validations for BigDecimals which must lie within an open/closed
20
 * range.
21
 * 
22
 * @since 1.4
23
 */
24
public class BigDecimalRangeValidator extends NumberRangeValidator {
25
26
	private static final BigDecimal ZERO = new BigDecimal("0"); //$NON-NLS-1$
27
	private static final BigDecimal ONE = new BigDecimal("1"); //$NON-NLS-1$
28
29
	/**
30
	 * Single constructor which supports the individual integer range types.
31
	 * 
32
	 * @param min
33
	 *            The min BigDecimal of the range or <code>null</code> in case
34
	 *            no lower bound is defined.
35
	 * @param max
36
	 *            The max BigDecimal of the range or <code>null</code> in case
37
	 *            no upper bound is defined.
38
	 * @param minConstraint
39
	 *            The type of constraint imposed by the lower bound of the
40
	 *            range.
41
	 * @param maxConstraint
42
	 *            The type of constraint imposed by the upper bound of the
43
	 *            range.
44
	 * @param validationMessage
45
	 *            The validation message pattern to use. Can be parameterized by
46
	 *            the lower and upper bound of the range, if defined.
47
	 * @param format
48
	 *            The BigDecimal format to use for formatting integers in the
49
	 *            validation message.
50
	 */
51
	private BigDecimalRangeValidator(BigDecimal min, BigDecimal max,
52
			int minConstraint, int maxConstraint, String validationMessage,
53
			NumberFormat format) {
54
		super(min, max, minConstraint, maxConstraint, validationMessage, format);
55
	}
56
57
	/**
58
	 * Creates a validator which checks that an input BigDecimal is greater than
59
	 * the given number.
60
	 * 
61
	 * @param number
62
	 *            The reference number of the greater constraint.
63
	 * @param validationMessage
64
	 *            The validation message pattern to use. Can be parameterized
65
	 *            with the given reference number.
66
	 * @param format
67
	 *            The display format to use for formatting BigDecimals in the
68
	 *            validation message.
69
	 * @return The validator instance.
70
	 */
71
	public static BigDecimalRangeValidator greater(BigDecimal number,
72
			String validationMessage, NumberFormat format) {
73
		return new BigDecimalRangeValidator(number, null, GREATER, UNDEFINED,
74
				defaultIfNull(validationMessage, GREATER_MESSAGE), format);
75
	}
76
77
	/**
78
	 * Creates a validator which checks that an input BigDecimal is greater than
79
	 * or equal to the given number.
80
	 * 
81
	 * @param number
82
	 *            The reference number of the greater-equal constraint.
83
	 * @param validationMessage
84
	 *            The validation message pattern to use. Can be parameterized
85
	 *            with the given reference number.
86
	 * @param format
87
	 *            The display format to use for formatting BigDecimals in the
88
	 *            validation message.
89
	 * @return The validator instance.
90
	 */
91
	public static BigDecimalRangeValidator greaterEqual(BigDecimal number,
92
			String validationMessage, NumberFormat format) {
93
		return new BigDecimalRangeValidator(number, null, GREATER_EQUAL,
94
				UNDEFINED, defaultIfNull(validationMessage,
95
						GREATER_EQUAL_MESSAGE), format);
96
	}
97
98
	/**
99
	 * Creates a validator which checks that an input BigDecimal is less than
100
	 * the given number.
101
	 * 
102
	 * @param number
103
	 *            The reference number of the less constraint.
104
	 * @param validationMessage
105
	 *            The validation message pattern to use. Can be parameterized
106
	 *            with the given reference number.
107
	 * @param format
108
	 *            The display format to use for formatting BigDecimals in the
109
	 *            validation message.
110
	 * @return The validator instance.
111
	 */
112
	public static BigDecimalRangeValidator less(BigDecimal number,
113
			String validationMessage, NumberFormat format) {
114
		return new BigDecimalRangeValidator(null, number, UNDEFINED, LESS,
115
				defaultIfNull(validationMessage, LESS_MESSAGE), format);
116
	}
117
118
	/**
119
	 * Creates a validator which checks that an input BigDecimal is less than or
120
	 * equal to the given number.
121
	 * 
122
	 * @param number
123
	 *            The reference number of the less-equal constraint.
124
	 * @param validationMessage
125
	 *            The validation message pattern to use. Can be parameterized
126
	 *            with the given reference number.
127
	 * @param format
128
	 *            The display format to use for formatting BigDecimals in the
129
	 *            validation message.
130
	 * @return The validator instance.
131
	 */
132
	public static BigDecimalRangeValidator lessEqual(BigDecimal number,
133
			String validationMessage, NumberFormat format) {
134
		return new BigDecimalRangeValidator(null, number, UNDEFINED,
135
				LESS_EQUAL,
136
				defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
137
	}
138
139
	/**
140
	 * Creates a validator which checks that an input BigDecimal is within the
141
	 * given range.
142
	 * 
143
	 * @param min
144
	 *            The lower bound of the range (inclusive).
145
	 * @param max
146
	 *            The upper bound of the range (inclusive).
147
	 * @param validationMessage
148
	 *            The validation message pattern to use. Can be parameterized
149
	 *            with the range's lower and upper bound.
150
	 * @param format
151
	 *            The display format to use for formatting BigDecimals in the
152
	 *            validation message.
153
	 * @return The validator instance.
154
	 */
155
	public static BigDecimalRangeValidator range(BigDecimal min,
156
			BigDecimal max, String validationMessage, NumberFormat format) {
157
		return new BigDecimalRangeValidator(min, max, GREATER_EQUAL,
158
				LESS_EQUAL, defaultIfNull(validationMessage,
159
						WITHIN_RANGE_MESSAGE), format);
160
	}
161
162
	/**
163
	 * Creates a validator which checks that an input BigDecimal is positive.
164
	 * 
165
	 * @param validationMessage
166
	 *            The validation message to use.
167
	 * @param format
168
	 *            The display format to use for formatting BigDecimals in the
169
	 *            validation message.
170
	 * @return The validator instance.
171
	 */
172
	public static BigDecimalRangeValidator positive(String validationMessage,
173
			NumberFormat format) {
174
		return new BigDecimalRangeValidator(ONE, null, GREATER_EQUAL,
175
				UNDEFINED, defaultIfNull(validationMessage, POSITIVE_MESSAGE),
176
				format);
177
	}
178
179
	/**
180
	 * Creates a validator which checks that an input BigDecimal is
181
	 * non-negative.
182
	 * 
183
	 * @param validationMessage
184
	 *            The validation message to use.
185
	 * @param format
186
	 *            The display format to use for formatting BigDecimals in the
187
	 *            validation message.
188
	 * @return The validator instance.
189
	 */
190
	public static BigDecimalRangeValidator nonNegative(
191
			String validationMessage, NumberFormat format) {
192
		return new BigDecimalRangeValidator(ZERO, null, GREATER_EQUAL,
193
				UNDEFINED, defaultIfNull(validationMessage,
194
						NON_NEGATIVE_MESSAGE), format);
195
	}
196
197
	protected int compare(Number number1, Number number2) {
198
		BigDecimal bigDecimal1 = (BigDecimal) number1;
199
		BigDecimal bigDecimal2 = (BigDecimal) number2;
200
		return bigDecimal1.compareTo(bigDecimal2);
201
	}
202
203
	private static String defaultIfNull(String string, String defaultString) {
204
		return (string != null) ? string : defaultString;
205
	}
206
}
(-)src/org/eclipse/core/internal/databinding/conversion/BooleanToStringConverter.java (+60 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.conversion;
13
14
import org.eclipse.core.databinding.conversion.Converter;
15
16
/**
17
 * @since 1.4
18
 */
19
public class BooleanToStringConverter extends Converter {
20
21
	// Those are the defaults used up to now in UpdateStrategy where a simple
22
	// ObjectToStringConverter was used for converting booleans to strings.
23
	// FIXME: Should/may we change this to convert to a localized string?
24
	private String trueValue = Boolean.TRUE.toString();
25
	private String falseValue = Boolean.FALSE.toString();
26
27
	/**
28
	 * Creates a new converter which converts a boolean to its default string
29
	 * representation.
30
	 * 
31
	 * @param booleanType
32
	 *            The boolean type. Must be one of {@code Boolean.TYPE} or
33
	 *            {@code Boolean.class}.
34
	 */
35
	public BooleanToStringConverter(Class booleanType) {
36
		super(booleanType, String.class);
37
	}
38
39
	/**
40
	 * Sets the string values to which a <code>true</code> and
41
	 * <code>false</code> value should be converted.
42
	 * 
43
	 * @param trueValue
44
	 *            The string to which to convert a <code>true</code> value.
45
	 * @param falseValue
46
	 *            The string to which to convert a <code>false</code> value.
47
	 */
48
	public final void setTargetStrings(String trueValue, String falseValue) {
49
		this.trueValue = trueValue;
50
		this.falseValue = falseValue;
51
	}
52
53
	public Object convert(Object source) {
54
		Boolean value = (Boolean) source;
55
		if (value != null) {
56
			return value.booleanValue() ? trueValue : falseValue;
57
		}
58
		return ""; //$NON-NLS-1$
59
	}
60
}
(-)src/org/eclipse/core/databinding/editing/BigIntegerEditing.java (+315 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import java.math.BigInteger;
15
16
import org.eclipse.core.databinding.conversion.NumberToStringConverter;
17
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
18
import org.eclipse.core.databinding.validation.constraint.BigIntegerConstraints;
19
import org.eclipse.core.databinding.validation.constraint.Constraints;
20
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
21
import org.eclipse.core.internal.databinding.validation.AbstractStringToNumberValidator;
22
import org.eclipse.core.internal.databinding.validation.StringToBigIntegerValidator;
23
24
import com.ibm.icu.text.NumberFormat;
25
26
/**
27
 * @since 1.4
28
 */
29
public final class BigIntegerEditing extends Editing {
30
31
	private final NumberFormat displayFormat;
32
33
	private BigIntegerEditing(NumberFormat format, String parseErrorMessage) {
34
		this.displayFormat = format;
35
36
		final StringToNumberConverter targetConverter = StringToNumberConverter
37
				.toBigInteger(format);
38
		final NumberToStringConverter modelConverter = NumberToStringConverter
39
				.fromBigInteger(format);
40
41
		final AbstractStringToNumberValidator targetValidator = new StringToBigIntegerValidator(
42
				targetConverter);
43
		if (parseErrorMessage != null) {
44
			targetValidator.setParseErrorMessage(parseErrorMessage);
45
		}
46
47
		setTargetConverter(targetConverter);
48
		setModelConverter(modelConverter);
49
		addTargetValidator(targetValidator);
50
	}
51
52
	/**
53
	 * Creates a new editing object for {@link BigInteger}s which defaults the
54
	 * validations and conversions used for editing based on the platform's
55
	 * locale. Uses the default validation messages.
56
	 * 
57
	 * @return The new editing object using the default validations and
58
	 *         conversions for editing.
59
	 * 
60
	 * @see NumberFormat#getIntegerInstance()
61
	 */
62
	public static BigIntegerEditing withDefaults() {
63
		return withDefaults(null);
64
	}
65
66
	/**
67
	 * Creates a new editing object for {@link BigInteger}s which defaults the
68
	 * validations and conversions used for editing based on the platform's
69
	 * locale. Uses the specified custom validation message.
70
	 * 
71
	 * @param parseErrorMessage
72
	 *            The validation message issued in case the input string cannot
73
	 *            be parsed to a BigInteger.
74
	 * @return The new editing object using the default validations and
75
	 *         conversions for editing.
76
	 * 
77
	 * @see NumberFormat#getIntegerInstance()
78
	 */
79
	public static BigIntegerEditing withDefaults(String parseErrorMessage) {
80
		return new BigIntegerEditing(NumberFormat.getIntegerInstance(),
81
				parseErrorMessage);
82
	}
83
84
	/**
85
	 * Creates a new editing object for {@link BigInteger}s whose validations
86
	 * and conversions used for editing are based on the given BigInteger
87
	 * format. Uses the default validation messages.
88
	 * 
89
	 * @param format
90
	 *            The BigInteger format defining the validations and conversions
91
	 *            used for editing.
92
	 * @return The new editing object configured by the given BigInteger format.
93
	 */
94
	public static BigIntegerEditing forFormat(NumberFormat format) {
95
		return forFormat(format, null);
96
	}
97
98
	/**
99
	 * Creates a new editing object for {@link BigInteger}s whose validations
100
	 * and conversions used for editing are based on the given BigInteger
101
	 * format. Uses the specified custom validation message.
102
	 * 
103
	 * @param format
104
	 *            The BigInteger format defining the validations and conversions
105
	 *            used for editing.
106
	 * @param parseErrorMessage
107
	 *            The validation message issued in case the input string cannot
108
	 *            be parsed to a BigInteger.
109
	 * @return The new editing object configured by the given BigInteger format.
110
	 */
111
	public static BigIntegerEditing forFormat(NumberFormat format,
112
			String parseErrorMessage) {
113
		return new BigIntegerEditing(format, parseErrorMessage);
114
	}
115
116
	/**
117
	 * Returns the target constraints to apply.
118
	 * 
119
	 * <p>
120
	 * This method provides a typesafe access to the {@link StringConstraints
121
	 * string target constraints} of this editing object and is equivalent to
122
	 * {@code (StringConstraints) targetConstraints()}.
123
	 * </p>
124
	 * 
125
	 * @return The target constraints to apply.
126
	 * 
127
	 * @see #targetConstraints()
128
	 * @see StringConstraints
129
	 */
130
	public StringConstraints targetStringConstraints() {
131
		return (StringConstraints) targetConstraints();
132
	}
133
134
	/**
135
	 * Returns the model constraints to apply.
136
	 * 
137
	 * <p>
138
	 * This method provides a typesafe access to the
139
	 * {@link BigIntegerConstraints BigInteger model constraints} of this
140
	 * editing object and is equivalent to {@code (BigIntegerConstraints)
141
	 * modelConstraints()}.
142
	 * </p>
143
	 * 
144
	 * @return The model constraints to apply.
145
	 * 
146
	 * @see #modelConstraints()
147
	 * @see BigIntegerConstraints
148
	 */
149
	public BigIntegerConstraints modelBigIntegerConstraints() {
150
		return (BigIntegerConstraints) modelConstraints();
151
	}
152
153
	/**
154
	 * Returns the before-set model constraints to apply.
155
	 * 
156
	 * <p>
157
	 * This method provides a typesafe access to the
158
	 * {@link BigIntegerConstraints BigInteger before-set model constraints} of
159
	 * this editing object and is equivalent to {@code (BigIntegerConstraints)
160
	 * beforeSetModelConstraints()}.
161
	 * </p>
162
	 * 
163
	 * @return The before-set model constraints to apply.
164
	 * 
165
	 * @see #beforeSetModelConstraints()
166
	 * @see BigIntegerConstraints
167
	 */
168
	public BigIntegerConstraints beforeSetModelBigIntegerConstraints() {
169
		return (BigIntegerConstraints) beforeSetModelConstraints();
170
	}
171
172
	protected Constraints createTargetConstraints() {
173
		return new StringConstraints();
174
	}
175
176
	protected Constraints createModelConstraints() {
177
		return new BigIntegerConstraints()
178
				.bigIntegerFormat(displayFormat);
179
	}
180
181
	protected Constraints createBeforeSetModelConstraints() {
182
		return new BigIntegerConstraints()
183
				.bigIntegerFormat(displayFormat);
184
	}
185
186
	/**
187
	 * Convenience method which adds a {@link BigIntegerConstraints#required()
188
	 * required constraint} to the set of {@link #modelBigIntegerConstraints()}.
189
	 * 
190
	 * @return This editing instance for method chaining.
191
	 * 
192
	 * @see BigIntegerConstraints#required()
193
	 * @see #modelBigIntegerConstraints()
194
	 */
195
	public BigIntegerEditing required() {
196
		modelBigIntegerConstraints().required();
197
		return this;
198
	}
199
200
	/**
201
	 * Convenience method which adds a
202
	 * {@link BigIntegerConstraints#greater(BigInteger) greater constraint} to
203
	 * the set of {@link #modelBigIntegerConstraints()}.
204
	 * 
205
	 * @param number
206
	 *            The number of the greater constraint.
207
	 * @return This editing instance for method chaining.
208
	 * 
209
	 * @see BigIntegerConstraints#greater(BigInteger)
210
	 * @see #modelBigIntegerConstraints()
211
	 */
212
	public BigIntegerEditing greater(BigInteger number) {
213
		modelBigIntegerConstraints().greater(number);
214
		return this;
215
	}
216
217
	/**
218
	 * Convenience method which adds a
219
	 * {@link BigIntegerConstraints#greaterEqual(BigInteger) greater-equal
220
	 * constraint} to the set of {@link #modelBigIntegerConstraints()}.
221
	 * 
222
	 * @param number
223
	 *            The number of the greater-equal constraint.
224
	 * @return This editing instance for method chaining.
225
	 * 
226
	 * @see BigIntegerConstraints#greaterEqual(BigInteger)
227
	 * @see #modelBigIntegerConstraints()
228
	 */
229
	public BigIntegerEditing greaterEqual(BigInteger number) {
230
		modelBigIntegerConstraints().greaterEqual(number);
231
		return this;
232
	}
233
234
	/**
235
	 * Convenience method which adds a
236
	 * {@link BigIntegerConstraints#less(BigInteger) less constraint} to the set
237
	 * of {@link #modelBigIntegerConstraints()}.
238
	 * 
239
	 * @param number
240
	 *            The number of the less constraint.
241
	 * @return This editing instance for method chaining.
242
	 * 
243
	 * @see BigIntegerConstraints#less(BigInteger)
244
	 * @see #modelBigIntegerConstraints()
245
	 */
246
	public BigIntegerEditing less(BigInteger number) {
247
		modelBigIntegerConstraints().less(number);
248
		return this;
249
	}
250
251
	/**
252
	 * Convenience method which adds a
253
	 * {@link BigIntegerConstraints#lessEqual(BigInteger) less-equal constraint}
254
	 * to the set of {@link #modelBigIntegerConstraints()}.
255
	 * 
256
	 * @param number
257
	 *            The number of the less-equal constraint.
258
	 * @return This editing instance for method chaining.
259
	 * 
260
	 * @see BigIntegerConstraints#lessEqual(BigInteger)
261
	 * @see #modelBigIntegerConstraints()
262
	 */
263
	public BigIntegerEditing lessEqual(BigInteger number) {
264
		modelBigIntegerConstraints().lessEqual(number);
265
		return this;
266
	}
267
268
	/**
269
	 * Convenience method which adds a
270
	 * {@link BigIntegerConstraints#range(BigInteger, BigInteger) range
271
	 * constraint} to the set of {@link #modelBigIntegerConstraints()}.
272
	 * 
273
	 * @param min
274
	 *            The min number of the range constraint.
275
	 * @param max
276
	 *            The max number of the range constraint.
277
	 * @return This editing instance for method chaining.
278
	 * 
279
	 * @see BigIntegerConstraints#range(BigInteger, BigInteger)
280
	 * @see #modelBigIntegerConstraints()
281
	 */
282
	public BigIntegerEditing range(BigInteger min, BigInteger max) {
283
		modelBigIntegerConstraints().range(min, max);
284
		return this;
285
	}
286
287
	/**
288
	 * Convenience method which adds a {@link BigIntegerConstraints#positive()
289
	 * positive constraint} to the set of {@link #modelBigIntegerConstraints()}.
290
	 * 
291
	 * @return This editing instance for method chaining.
292
	 * 
293
	 * @see BigIntegerConstraints#positive()
294
	 * @see #modelBigIntegerConstraints()
295
	 */
296
	public BigIntegerEditing positive() {
297
		modelBigIntegerConstraints().positive();
298
		return this;
299
	}
300
301
	/**
302
	 * Convenience method which adds a
303
	 * {@link BigIntegerConstraints#nonNegative() non-negative constraint} to
304
	 * the set of {@link #modelBigIntegerConstraints()} .
305
	 * 
306
	 * @return This editing instance for method chaining.
307
	 * 
308
	 * @see BigIntegerConstraints#nonNegative()
309
	 * @see #modelBigIntegerConstraints()
310
	 */
311
	public BigIntegerEditing nonNegative() {
312
		modelBigIntegerConstraints().nonNegative();
313
		return this;
314
	}
315
}
(-)src/org/eclipse/core/databinding/validation/constraint/IntegerConstraints.java (+307 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.validation.constraint;
13
14
import org.eclipse.core.internal.databinding.validation.IntegerRangeValidator;
15
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
16
17
import com.ibm.icu.text.NumberFormat;
18
19
/**
20
 * @since 1.4
21
 */
22
public final class IntegerConstraints extends Constraints {
23
24
	private NumberFormat integerFormat = NumberFormat.getIntegerInstance();
25
26
	private String requiredMessage = null;
27
28
	private String greaterMessage = null;
29
30
	private String greaterEqualMessage = null;
31
32
	private String lessMessage = null;
33
34
	private String lessEqualMessage = null;
35
36
	private String rangeMessage = null;
37
38
	private String positiveMessage = null;
39
40
	private String nonNegativeMessage = null;
41
42
	/**
43
	 * Sets the format to use when formatting an integer to be included in any
44
	 * of the validation messages.
45
	 * 
46
	 * <p>
47
	 * This integer format will be used for any subsequent constraints which are
48
	 * applied.
49
	 * </p>
50
	 * 
51
	 * @param format
52
	 *            The format to use for displaying integers in validation
53
	 *            messages.
54
	 * @return This constraints instance for method chaining.
55
	 */
56
	public IntegerConstraints integerFormat(NumberFormat format) {
57
		this.integerFormat = format;
58
		return this;
59
	}
60
61
	/**
62
	 * Adds a validator ensuring that the parsed integer is not
63
	 * <code>null</code>. Uses the current {@link #requiredMessage(String)
64
	 * validation message}.
65
	 * 
66
	 * @return This constraints instance for method chaining.
67
	 */
68
	public IntegerConstraints required() {
69
		addValidator(new NonNullValidator(requiredMessage));
70
		return this;
71
	}
72
73
	/**
74
	 * Sets the validation message for the {@link #required()} constraint.
75
	 * 
76
	 * @param message
77
	 *            The validation message for the {@link #required()} constraint.
78
	 * @return This constraints instance for method chaining.
79
	 * 
80
	 * @see #required()
81
	 */
82
	public IntegerConstraints requiredMessage(String message) {
83
		this.requiredMessage = message;
84
		return this;
85
	}
86
87
	/**
88
	 * Adds a validator ensuring that the parsed integer is greater than the
89
	 * given number. Uses the current {@link #greaterMessage(String) validation
90
	 * message}.
91
	 * 
92
	 * @param number
93
	 *            The number which the parsed integer must be greater than.
94
	 * @return This constraints instance for method chaining.
95
	 */
96
	public IntegerConstraints greater(long number) {
97
		addValidator(IntegerRangeValidator.greater(number, greaterMessage,
98
				integerFormat));
99
		return this;
100
	}
101
102
	/**
103
	 * Sets the validation message pattern for the {@link #greater(long)}
104
	 * constraint.
105
	 * 
106
	 * @param message
107
	 *            The validation message pattern for the {@link #greater(long)}
108
	 *            constraint. Can be parameterized with the number which the
109
	 *            parsed integer must be greater than.
110
	 * @return This constraints instance for method chaining.
111
	 * 
112
	 * @see #greater(long)
113
	 */
114
	public IntegerConstraints greaterMessage(String message) {
115
		this.greaterMessage = message;
116
		return this;
117
	}
118
119
	/**
120
	 * Adds a validator ensuring that the parsed integer is greater than or
121
	 * equal to the given number. Uses the current
122
	 * {@link #greaterEqualMessage(String) validation message}.
123
	 * 
124
	 * @param number
125
	 *            The number which the parsed integer must be greater than or
126
	 *            equal to.
127
	 * @return This constraints instance for method chaining.
128
	 */
129
	public IntegerConstraints greaterEqual(long number) {
130
		addValidator(IntegerRangeValidator.greaterEqual(number,
131
				greaterEqualMessage, integerFormat));
132
		return this;
133
	}
134
135
	/**
136
	 * Sets the validation message pattern for the {@link #greaterEqual(long)}
137
	 * constraint.
138
	 * 
139
	 * @param message
140
	 *            The validation message pattern for the
141
	 *            {@link #greaterEqual(long)} constraint. Can be parameterized
142
	 *            with the number which the parsed integer must be greater than
143
	 *            or equal to.
144
	 * @return This constraints instance for method chaining.
145
	 * 
146
	 * @see #greaterEqual(long)
147
	 */
148
	public IntegerConstraints greaterEqualMessage(String message) {
149
		this.greaterEqualMessage = message;
150
		return this;
151
	}
152
153
	/**
154
	 * Adds a validator ensuring that the parsed integer is less than the given
155
	 * number. Uses the current {@link #lessMessage(String) validation message}.
156
	 * 
157
	 * @param number
158
	 *            The number which the parsed integer must be less than.
159
	 * @return This constraints instance for method chaining.
160
	 */
161
	public IntegerConstraints less(long number) {
162
		addValidator(IntegerRangeValidator.less(number, lessMessage,
163
				integerFormat));
164
		return this;
165
	}
166
167
	/**
168
	 * Sets the validation message pattern for the {@link #less(long)}
169
	 * constraint.
170
	 * 
171
	 * @param message
172
	 *            The validation message pattern for the {@link #less(long)}
173
	 *            constraint. Can be parameterized with the number which the
174
	 *            parsed integer must be less than.
175
	 * @return This constraints instance for method chaining.
176
	 * 
177
	 * @see #less(long)
178
	 */
179
	public IntegerConstraints lessMessage(String message) {
180
		this.lessMessage = message;
181
		return this;
182
	}
183
184
	/**
185
	 * Adds a validator ensuring that the parsed integer is less than or equal
186
	 * to the given number. Uses the current {@link #lessEqualMessage(String)
187
	 * validation message}.
188
	 * 
189
	 * @param number
190
	 *            The number which the parsed integer must be less than or equal
191
	 *            to.
192
	 * @return This constraints instance for method chaining.
193
	 */
194
	public IntegerConstraints lessEqual(long number) {
195
		addValidator(IntegerRangeValidator.greaterEqual(number,
196
				lessEqualMessage, integerFormat));
197
		return this;
198
	}
199
200
	/**
201
	 * Sets the validation message pattern for the {@link #lessEqual(long)}
202
	 * constraint.
203
	 * 
204
	 * @param message
205
	 *            The validation message pattern for the
206
	 *            {@link #lessEqual(long)} constraint. Can be parameterized with
207
	 *            the number which the parsed integer must be less than or equal
208
	 *            to.
209
	 * @return This constraints instance for method chaining.
210
	 * 
211
	 * @see #lessEqual(long)
212
	 */
213
	public IntegerConstraints lessEqualMessage(String message) {
214
		this.lessEqualMessage = message;
215
		return this;
216
	}
217
218
	/**
219
	 * Adds a validator ensuring that the parsed integer is within the given
220
	 * range. Uses the current {@link #rangeMessage(String) validation message}.
221
	 * 
222
	 * @param min
223
	 *            The lower bound of the range (inclusive).
224
	 * @param max
225
	 *            The upper bound of the range (inclusive).
226
	 * @return This constraints instance for method chaining.
227
	 */
228
	public IntegerConstraints range(long min, long max) {
229
		addValidator(IntegerRangeValidator.range(min, max, rangeMessage,
230
				integerFormat));
231
		return this;
232
	}
233
234
	/**
235
	 * Sets the validation message pattern for the {@link #range(long, long)}
236
	 * constraint.
237
	 * 
238
	 * @param message
239
	 *            The validation message pattern for the
240
	 *            {@link #range(long, long)} constraint. Can be parameterized
241
	 *            with the min and max values of the range in which the parsed
242
	 *            integer must lie.
243
	 * @return This constraints instance for method chaining.
244
	 * 
245
	 * @see #range(long, long)
246
	 */
247
	public IntegerConstraints rangeMessage(String message) {
248
		this.rangeMessage = message;
249
		return this;
250
	}
251
252
	/**
253
	 * Adds a validator ensuring that the parsed integer is positive. Uses the
254
	 * current {@link #positiveMessage(String) validation message}.
255
	 * 
256
	 * @return This constraints instance for method chaining.
257
	 */
258
	public IntegerConstraints positive() {
259
		addValidator(IntegerRangeValidator.positive(positiveMessage,
260
				integerFormat));
261
		return this;
262
	}
263
264
	/**
265
	 * Sets the validation message pattern for the {@link #positive()}
266
	 * constraint.
267
	 * 
268
	 * @param message
269
	 *            The validation message pattern for the {@link #positive()}
270
	 *            constraint.
271
	 * @return This constraints instance for method chaining.
272
	 * 
273
	 * @see #positive()
274
	 */
275
	public IntegerConstraints positiveMessage(String message) {
276
		this.positiveMessage = message;
277
		return this;
278
	}
279
280
	/**
281
	 * Adds a validator ensuring that the parsed integer is non-negative. Uses
282
	 * the current {@link #nonNegativeMessage(String) validation message}.
283
	 * 
284
	 * @return This constraints instance for method chaining.
285
	 */
286
	public IntegerConstraints nonNegative() {
287
		addValidator(IntegerRangeValidator.nonNegative(nonNegativeMessage,
288
				integerFormat));
289
		return this;
290
	}
291
292
	/**
293
	 * Sets the validation message pattern for the {@link #nonNegative()}
294
	 * constraint.
295
	 * 
296
	 * @param message
297
	 *            The validation message pattern for the {@link #nonNegative()}
298
	 *            constraint.
299
	 * @return This constraints instance for method chaining.
300
	 * 
301
	 * @see #nonNegative()
302
	 */
303
	public IntegerConstraints nonNegativeMessage(String message) {
304
		this.nonNegativeMessage = message;
305
		return this;
306
	}
307
}
(-)src/org/eclipse/core/databinding/editing/NumberToNumberEditing.java (+212 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.editing;
13
14
import java.math.BigDecimal;
15
import java.math.BigInteger;
16
17
import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
18
import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
19
import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter;
20
import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter;
21
import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter;
22
import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
23
import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
24
import org.eclipse.core.internal.databinding.conversion.NumberToNumberConverter;
25
import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
26
import org.eclipse.core.internal.databinding.validation.NumberToByteValidator;
27
import org.eclipse.core.internal.databinding.validation.NumberToDoubleValidator;
28
import org.eclipse.core.internal.databinding.validation.NumberToFloatValidator;
29
import org.eclipse.core.internal.databinding.validation.NumberToIntegerValidator;
30
import org.eclipse.core.internal.databinding.validation.NumberToLongValidator;
31
import org.eclipse.core.internal.databinding.validation.NumberToNumberValidator;
32
import org.eclipse.core.internal.databinding.validation.NumberToShortValidator;
33
import org.eclipse.core.internal.databinding.validation.NumberToUnboundedNumberValidator;
34
35
import com.ibm.icu.text.NumberFormat;
36
37
/**
38
 * @since 1.4
39
 */
40
public final class NumberToNumberEditing extends Editing {
41
42
	private NumberToNumberEditing(Class targetNumberType,
43
			Class modelNumberType, NumberFormat displayFormat,
44
			String outOfRangeMessage) {
45
		NumberToNumberConverter targetConverter = createConverter(
46
				displayFormat, targetNumberType, modelNumberType);
47
		NumberToNumberConverter modelConverter = createConverter(displayFormat,
48
				modelNumberType, targetNumberType);
49
50
		NumberToNumberValidator targetValidator = createValidator(modelConverter);
51
		if (outOfRangeMessage != null) {
52
			targetValidator.setOutOfRangeMessage(outOfRangeMessage);
53
		}
54
55
		setTargetConverter(targetConverter);
56
		setModelConverter(modelConverter);
57
		addTargetValidator(targetValidator);
58
	}
59
60
	/**
61
	 * Creates a new editing object for the given target and model number types
62
	 * which defaults the validations and conversions used for editing based on
63
	 * the platform's locale. Uses the default validation message.
64
	 * 
65
	 * @param targetNumberType
66
	 *            The target number type for which the editing is to be set-up.
67
	 * @param modelNumberType
68
	 *            The model number type for which the editing is to be set-up.
69
	 * @return The new editing object using the default validations and
70
	 *         conversions for editing.
71
	 */
72
	public static NumberToNumberEditing withDefaults(Class targetNumberType,
73
			Class modelNumberType) {
74
		return withDefaults(targetNumberType, modelNumberType, null);
75
	}
76
77
	/**
78
	 * Creates a new editing object for the given target and model number types
79
	 * which defaults the validations and conversions used for editing based on
80
	 * the platform's locale. Uses the specified custom validation messages.
81
	 * 
82
	 * @param targetNumberType
83
	 *            The target number type for which the editing is to be set-up.
84
	 * @param modelNumberType
85
	 *            The model number type for which the editing is to be set-up.
86
	 * @param outOfRangeMessage
87
	 *            The validation message issued in case the target number lies
88
	 *            outside the range supported by the model number. Can be
89
	 *            parameterized by the min and max values of the model number
90
	 *            type.
91
	 * @return The new editing object using the default validations and
92
	 *         conversions for editing.
93
	 */
94
	public static NumberToNumberEditing withDefaults(Class targetNumberType,
95
			Class modelNumberType, String outOfRangeMessage) {
96
		return new NumberToNumberEditing(targetNumberType, modelNumberType,
97
				NumberFormat.getNumberInstance(), outOfRangeMessage);
98
	}
99
100
	/**
101
	 * Creates a new editing object for the given target and model number types
102
	 * which uses the given number format for displaying numbers in validation
103
	 * messages. Uses the default validation message.
104
	 * 
105
	 * @param targetNumberType
106
	 *            The target number type for which the editing is to be set-up.
107
	 * @param modelNumberType
108
	 *            The model number type for which the editing is to be set-up.
109
	 * @param displayFormat
110
	 *            The number format to use for displaying numbers in validation
111
	 *            messages.
112
	 * @return The new editing object using the default validations and
113
	 *         conversions for editing.
114
	 */
115
	public static NumberToNumberEditing withDisplayFormat(
116
			Class targetNumberType, Class modelNumberType,
117
			NumberFormat displayFormat) {
118
		return withDisplayFormat(targetNumberType, modelNumberType,
119
				displayFormat, null);
120
	}
121
122
	/**
123
	 * Creates a new editing object for the given target and model number types
124
	 * which uses the given number format for displaying numbers in validation
125
	 * messages. Uses the specified custom validation messages.
126
	 * 
127
	 * @param targetNumberType
128
	 *            The target number type for which the editing is to be set-up.
129
	 * @param modelNumberType
130
	 *            The model number type for which the editing is to be set-up.
131
	 * @param displayFormat
132
	 *            The number format to use for displaying numbers in validation
133
	 *            messages.
134
	 * @param outOfRangeMessage
135
	 *            The validation message issued in case the target number lies
136
	 *            outside the range supported by the model number. Can be
137
	 *            parameterized by the min and max values of the model number
138
	 *            type.
139
	 * @return The new editing object using the default validations and
140
	 *         conversions for editing.
141
	 */
142
	public static NumberToNumberEditing withDisplayFormat(
143
			Class targetNumberType, Class modelNumberType,
144
			NumberFormat displayFormat, String outOfRangeMessage) {
145
		return new NumberToNumberEditing(targetNumberType, modelNumberType,
146
				displayFormat, outOfRangeMessage);
147
	}
148
149
	private static NumberToNumberConverter createConverter(
150
			NumberFormat numberFormat, Class fromNumberType, Class toNumberType) {
151
		boolean isPrimitive = toNumberType.isPrimitive();
152
		if (Long.class.equals(toNumberType) || long.class.equals(toNumberType)) {
153
			return new NumberToLongConverter(numberFormat, fromNumberType,
154
					isPrimitive);
155
		} else if (Integer.class.equals(toNumberType)
156
				|| int.class.equals(toNumberType)) {
157
			return new NumberToIntegerConverter(numberFormat, fromNumberType,
158
					isPrimitive);
159
		} else if (Short.class.equals(toNumberType)
160
				|| short.class.equals(toNumberType)) {
161
			return new NumberToShortConverter(numberFormat, fromNumberType,
162
					isPrimitive);
163
		} else if (Byte.class.equals(toNumberType)
164
				|| byte.class.equals(toNumberType)) {
165
			return new NumberToByteConverter(numberFormat, fromNumberType,
166
					isPrimitive);
167
		} else if (Double.class.equals(toNumberType)
168
				|| double.class.equals(toNumberType)) {
169
			return new NumberToDoubleConverter(numberFormat, fromNumberType,
170
					isPrimitive);
171
		} else if (Float.class.equals(toNumberType)
172
				|| float.class.equals(toNumberType)) {
173
			return new NumberToFloatConverter(numberFormat, fromNumberType,
174
					isPrimitive);
175
		} else if (BigInteger.class.equals(toNumberType)) {
176
			return new NumberToBigIntegerConverter(numberFormat, fromNumberType);
177
		} else if (BigDecimal.class.equals(toNumberType)) {
178
			return new NumberToBigDecimalConverter(numberFormat, fromNumberType);
179
		} else {
180
			throw new IllegalArgumentException(
181
					"Unsupported to number type: " + toNumberType); //$NON-NLS-1$
182
		}
183
	}
184
185
	private static NumberToNumberValidator createValidator(
186
			NumberToNumberConverter converter) {
187
		if (converter instanceof NumberToLongConverter) {
188
			return new NumberToLongValidator((NumberToLongConverter) converter);
189
		} else if (converter instanceof NumberToIntegerConverter) {
190
			return new NumberToIntegerValidator(
191
					(NumberToIntegerConverter) converter);
192
		} else if (converter instanceof NumberToShortConverter) {
193
			return new NumberToShortValidator(
194
					(NumberToShortConverter) converter);
195
		} else if (converter instanceof NumberToByteConverter) {
196
			return new NumberToByteValidator((NumberToByteConverter) converter);
197
		} else if (converter instanceof NumberToDoubleConverter) {
198
			return new NumberToDoubleValidator(
199
					(NumberToDoubleConverter) converter);
200
		} else if (converter instanceof NumberToFloatConverter) {
201
			return new NumberToFloatValidator(
202
					(NumberToFloatConverter) converter);
203
		} else if (converter instanceof NumberToBigIntegerConverter) {
204
			return new NumberToUnboundedNumberValidator(converter);
205
		} else if (converter instanceof NumberToBigDecimalConverter) {
206
			return new NumberToUnboundedNumberValidator(converter);
207
		} else {
208
			throw new IllegalArgumentException(
209
					"Unsupported converter type: " + converter.getClass()); //$NON-NLS-1$
210
		}
211
	}
212
}
(-)src/org/eclipse/core/internal/databinding/validation/NonEmptyStringValidator.java (+50 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.validation;
13
14
import org.eclipse.core.databinding.validation.IValidator;
15
import org.eclipse.core.databinding.validation.ValidationStatus;
16
import org.eclipse.core.internal.databinding.BindingMessages;
17
import org.eclipse.core.runtime.IStatus;
18
19
/**
20
 * @since 1.4
21
 */
22
public class NonEmptyStringValidator implements IValidator {
23
24
	private static final String NON_EMPTY_STRING_VALIDATION_MESSAGE = BindingMessages.getString(BindingMessages.VALIDATE_NON_EMPTY_STRING);
25
26
	private final String validationMessage;
27
28
	/**
29
	 * 
30
	 */
31
	public NonEmptyStringValidator() {
32
		this(null);
33
	}
34
35
	/**
36
	 * @param validationMessage
37
	 */
38
	public NonEmptyStringValidator(String validationMessage) {
39
		this.validationMessage = validationMessage != null ? validationMessage
40
				: NON_EMPTY_STRING_VALIDATION_MESSAGE;
41
	}
42
43
	public IStatus validate(Object value) {
44
		String input = (String) value;
45
		if (input == null || input.length() == 0) {
46
			return ValidationStatus.error(validationMessage);
47
		}
48
		return ValidationStatus.ok();
49
	}
50
}
(-)src/org/eclipse/core/internal/databinding/conversion/StringStripConverter.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.conversion;
13
14
import org.eclipse.core.databinding.conversion.Converter;
15
16
/**
17
 * @since 1.4
18
 */
19
public class StringStripConverter extends Converter {
20
21
	private final boolean stripToNull;
22
23
	/**
24
	 * 
25
	 * @param stripToNull
26
	 */
27
	public StringStripConverter(boolean stripToNull) {
28
		super(String.class, String.class);
29
		this.stripToNull = stripToNull;
30
	}
31
32
	public Object convert(Object fromObject) {
33
		String string = (String) fromObject;
34
35
		if (string != null && string.length() != 0) {
36
			int stripStart = 0;
37
			while (stripStart < string.length()
38
					&& Character.isWhitespace(string.charAt(stripStart))) {
39
				stripStart++;
40
			}
41
42
			int stripEnd = string.length() - 1;
43
			while (stripEnd >= stripStart
44
					&& Character.isWhitespace(string.charAt(stripEnd))) {
45
				stripEnd--;
46
			}
47
48
			if (stripStart <= stripEnd) {
49
				string = string.substring(stripStart, stripEnd + 1);
50
			} else {
51
				string = ""; //$NON-NLS-1$
52
			}
53
		}
54
55
		if (stripToNull && string != null && string.length() == 0) {
56
			string = null;
57
		}
58
59
		return string;
60
	}
61
}
(-)src/org/eclipse/core/tests/internal/databinding/BindingMessagesTest.java (-2 / +3 lines)
Lines 12-17 Link Here
12
 *
12
 *
13
 * Contributors:
13
 * Contributors:
14
 *     IBM Corporation - initial API and implementation
14
 *     IBM Corporation - initial API and implementation
15
 *     Ovidio Mallo - bug 183055
15
 ******************************************************************************/
16
 ******************************************************************************/
16
17
17
/**
18
/**
Lines 21-33 Link Here
21
public class BindingMessagesTest extends TestCase {
22
public class BindingMessagesTest extends TestCase {
22
	public void testFormatString() throws Exception {
23
	public void testFormatString() throws Exception {
23
		String key = "Validate_NumberOutOfRangeError";
24
		String key = "Validate_NumberOutOfRangeError";
24
		String result = BindingMessages.formatString(key, new Object[] {"1", "2"});
25
		String result = BindingMessages.getFormattedString(key, new Object[] {"1", "2"});
25
		assertFalse("key should not be returned", key.equals(result));
26
		assertFalse("key should not be returned", key.equals(result));
26
	}
27
	}
27
	
28
	
28
	public void testFormatStringForKeyNotFound() throws Exception {
29
	public void testFormatStringForKeyNotFound() throws Exception {
29
		String key = "key_that_does_not_exist";
30
		String key = "key_that_does_not_exist";
30
		String result = BindingMessages.formatString(key, null);
31
		String result = BindingMessages.getFormattedString(key, null);
31
		assertTrue(key.equals(result));
32
		assertTrue(key.equals(result));
32
	}
33
	}
33
}
34
}
(-).settings/org.eclipse.jdt.ui.prefs (-2 / +2 lines)
Lines 1-4 Link Here
1
#Tue Feb 10 16:06:05 MST 2009
1
#Thu Jan 07 19:11:15 CET 2010
2
cleanup.add_default_serial_version_id=true
2
cleanup.add_default_serial_version_id=true
3
cleanup.add_generated_serial_version_id=false
3
cleanup.add_generated_serial_version_id=false
4
cleanup.add_missing_annotations=true
4
cleanup.add_missing_annotations=true
Lines 51-57 Link Here
51
cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
51
cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
52
cleanup_settings_version=2
52
cleanup_settings_version=2
53
eclipse.preferences.version=1
53
eclipse.preferences.version=1
54
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
54
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false
55
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
55
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
56
formatter_settings_version=11
56
formatter_settings_version=11
57
org.eclipse.jdt.ui.exception.name=e
57
org.eclipse.jdt.ui.exception.name=e
(-).settings/org.eclipse.jdt.ui.prefs (-3 / +3 lines)
Lines 1-4 Link Here
1
#Tue Feb 10 16:06:02 MST 2009
1
#Thu Jan 07 19:11:04 CET 2010
2
cleanup.add_default_serial_version_id=true
2
cleanup.add_default_serial_version_id=true
3
cleanup.add_generated_serial_version_id=false
3
cleanup.add_generated_serial_version_id=false
4
cleanup.add_missing_annotations=true
4
cleanup.add_missing_annotations=true
Lines 51-57 Link Here
51
cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
51
cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
52
cleanup_settings_version=2
52
cleanup_settings_version=2
53
eclipse.preferences.version=1
53
eclipse.preferences.version=1
54
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
54
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false
55
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
55
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
56
formatter_settings_version=11
56
formatter_settings_version=11
57
org.eclipse.jdt.ui.exception.name=e
57
org.eclipse.jdt.ui.exception.name=e
Lines 78-84 Link Here
78
sp_cleanup.always_use_this_for_non_static_method_access=false
78
sp_cleanup.always_use_this_for_non_static_method_access=false
79
sp_cleanup.convert_to_enhanced_for_loop=false
79
sp_cleanup.convert_to_enhanced_for_loop=false
80
sp_cleanup.correct_indentation=false
80
sp_cleanup.correct_indentation=false
81
sp_cleanup.format_source_code=true
81
sp_cleanup.format_source_code=false
82
sp_cleanup.format_source_code_changes_only=false
82
sp_cleanup.format_source_code_changes_only=false
83
sp_cleanup.make_local_variable_final=false
83
sp_cleanup.make_local_variable_final=false
84
sp_cleanup.make_parameters_final=false
84
sp_cleanup.make_parameters_final=false
(-)META-INF/MANIFEST.MF (-1 / +2 lines)
Lines 17-21 Link Here
17
 org.eclipse.jface.examples.databinding.mask.internal;x-internal:=true,
17
 org.eclipse.jface.examples.databinding.mask.internal;x-internal:=true,
18
 org.eclipse.jface.examples.databinding.model;x-internal:=false,
18
 org.eclipse.jface.examples.databinding.model;x-internal:=false,
19
 org.eclipse.jface.examples.databinding.radioGroup;x-internal:=false
19
 org.eclipse.jface.examples.databinding.radioGroup;x-internal:=false
20
Import-Package: com.ibm.icu.text
20
Import-Package: com.ibm.icu.math,
21
 com.ibm.icu.text
21
Bundle-RequiredExecutionEnvironment: J2SE-1.5
22
Bundle-RequiredExecutionEnvironment: J2SE-1.5
(-)src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingSupport.java (+88 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.util;
13
14
import org.eclipse.core.databinding.editing.Editing;
15
import org.eclipse.core.databinding.observable.map.IObservableMap;
16
import org.eclipse.core.databinding.util.Policy;
17
import org.eclipse.core.runtime.IStatus;
18
import org.eclipse.core.runtime.MultiStatus;
19
import org.eclipse.jface.dialogs.MessageDialog;
20
import org.eclipse.jface.viewers.CellEditor;
21
import org.eclipse.jface.viewers.ColumnViewer;
22
import org.eclipse.jface.viewers.EditingSupport;
23
import org.eclipse.jface.viewers.TextCellEditor;
24
import org.eclipse.swt.widgets.Composite;
25
26
/**
27
 * @since 3.2
28
 */
29
public class ObservableMapEditingSupport extends EditingSupport {
30
31
	private final IObservableMap attributeMap;
32
33
	private final Editing editing;
34
35
	private final CellEditor cellEditor;
36
37
	public ObservableMapEditingSupport(ColumnViewer viewer, IObservableMap attributeMap, Editing editing) {
38
		super(viewer);
39
		this.attributeMap = attributeMap;
40
		this.editing = editing;
41
		this.cellEditor = new TextCellEditor((Composite) getViewer().getControl());
42
	}
43
44
	protected boolean canEdit(Object element) {
45
		return true;
46
	}
47
48
	protected CellEditor getCellEditor(Object element) {
49
		return cellEditor;
50
	}
51
52
	protected Object getValue(Object element) {
53
		return editing.convertToTarget(attributeMap.get(element));
54
	}
55
56
	protected void setValue(Object element, Object value) {
57
		MultiStatus validationStatus = new MultiStatus(Policy.JFACE_DATABINDING, 0, null, null);
58
		Object modelValue = editing.convertToModel(value, validationStatus);
59
		if (handleValidation(validationStatus)) {
60
			attributeMap.put(element, modelValue);
61
		}
62
	}
63
64
	private boolean handleValidation(IStatus validationStatus) {
65
		if (validationStatus.matches(IStatus.ERROR | IStatus.CANCEL)) {
66
			MessageDialog.openError(getViewer().getControl().getShell(), "Validation Error", getValidationMessage(validationStatus));
67
			return false;
68
		}
69
		return true;
70
	}
71
72
	private static String getValidationMessage(IStatus validationStatus) {
73
		if (!validationStatus.isMultiStatus()) {
74
			return validationStatus.getMessage();
75
		}
76
77
		MultiStatus multiStatus = (MultiStatus) validationStatus;
78
		StringBuffer sb = new StringBuffer();
79
		IStatus[] childStatus = multiStatus.getChildren();
80
		for (int i = 0; i < childStatus.length; i++) {
81
			if (i > 0) {
82
				sb.append('\n');
83
			}
84
			sb.append(getValidationMessage(childStatus[i]));
85
		}
86
		return sb.toString();
87
	}
88
}
(-)src/org/eclipse/jface/examples/databinding/snippets/Snippet035Editing.java (+275 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.snippets;
13
14
import java.util.Calendar;
15
import java.util.Date;
16
17
import org.eclipse.core.databinding.Binding;
18
import org.eclipse.core.databinding.DataBindingContext;
19
import org.eclipse.core.databinding.editing.BooleanEditing;
20
import org.eclipse.core.databinding.editing.DateEditing;
21
import org.eclipse.core.databinding.editing.DecimalEditing;
22
import org.eclipse.core.databinding.editing.Editing;
23
import org.eclipse.core.databinding.editing.IntegerEditing;
24
import org.eclipse.core.databinding.observable.Realm;
25
import org.eclipse.core.databinding.observable.list.WritableList;
26
import org.eclipse.core.databinding.observable.value.IObservableValue;
27
import org.eclipse.core.databinding.observable.value.WritableValue;
28
import org.eclipse.core.databinding.validation.IValidator;
29
import org.eclipse.core.databinding.validation.ValidationStatus;
30
import org.eclipse.core.databinding.validation.constraint.Constraints;
31
import org.eclipse.core.databinding.validation.constraint.IntegerConstraints;
32
import org.eclipse.core.runtime.IStatus;
33
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
34
import org.eclipse.jface.databinding.swt.SWTObservables;
35
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
36
import org.eclipse.jface.examples.databinding.util.EditingFactory;
37
import org.eclipse.jface.internal.databinding.provisional.fieldassist.ControlDecorationSupport;
38
import org.eclipse.jface.layout.GridDataFactory;
39
import org.eclipse.jface.layout.GridLayoutFactory;
40
import org.eclipse.jface.viewers.LabelProvider;
41
import org.eclipse.jface.viewers.ListViewer;
42
import org.eclipse.swt.SWT;
43
import org.eclipse.swt.events.FocusAdapter;
44
import org.eclipse.swt.events.FocusEvent;
45
import org.eclipse.swt.events.SelectionAdapter;
46
import org.eclipse.swt.events.SelectionEvent;
47
import org.eclipse.swt.layout.GridLayout;
48
import org.eclipse.swt.widgets.Composite;
49
import org.eclipse.swt.widgets.Control;
50
import org.eclipse.swt.widgets.Display;
51
import org.eclipse.swt.widgets.Group;
52
import org.eclipse.swt.widgets.Label;
53
import org.eclipse.swt.widgets.Shell;
54
import org.eclipse.swt.widgets.Text;
55
56
import com.ibm.icu.text.MessageFormat;
57
58
public class Snippet035Editing {
59
60
	private DataBindingContext dbc;
61
62
	public static void main(String[] args) {
63
		Display display = new Display();
64
65
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
66
			public void run() {
67
				Shell shell = new Snippet035Editing().createShell();
68
				Display display = Display.getCurrent();
69
				while (!shell.isDisposed()) {
70
					if (!display.readAndDispatch()) {
71
						display.sleep();
72
					}
73
				}
74
			}
75
		});
76
	}
77
78
	private Shell createShell() {
79
		Display display = Display.getCurrent();
80
		Shell shell = new Shell(display);
81
		shell.setText("Editing");
82
		shell.setLayout(new GridLayout(1, false));
83
84
		dbc = new DataBindingContext();
85
86
		createValueSection(shell);
87
		createListSection(shell);
88
89
		shell.pack();
90
		shell.open();
91
92
		return shell;
93
	}
94
95
	private void createValueSection(Composite parent) {
96
		Group section = createSectionGroup(parent, "Value bindings", false);
97
98
		// Edit an e-mail address.
99
		Text emailText = createTextField(section, "E-Mail*");
100
		Editing emailEditing = EditingFactory.forEmailString().required();
101
		bindTextField(emailText, new WritableValue(), emailEditing);
102
103
		// Edit a required, positive short using the default validation message.
104
		Text positiveText = createTextField(section, "Positive short*");
105
		IntegerEditing positiveEditing = EditingFactory.forShort().required().positive();
106
		bindTextField(positiveText, new WritableValue(), positiveEditing);
107
108
		// Edit a required double with a maximum of two fractional digits.
109
		Text doubleText = createTextField(section, "Price [�]*");
110
		DecimalEditing doubleEditing = EditingFactory.forDouble().required().maxScale(2);
111
		bindTextField(doubleText, new WritableValue(), doubleEditing);
112
113
		// Edit an integer within the range [1, 100] using the default
114
		// validation message.
115
		Text rangeText = createTextField(section, "Value in [1, 100]");
116
		IntegerEditing rangeEditing = EditingFactory.forInteger().range(1, 100);
117
		bindTextField(rangeText, new WritableValue(0, null), rangeEditing);
118
119
		// Edit a percentage value which must lie within [0, 100] using a custom
120
		// validation message which indicates that the value actually represents
121
		// a percentage value. Note that the constraint message must be specified
122
		// before the actual constraint.
123
		Text percentText = createTextField(section, "Value [%]");
124
		IntegerEditing percentEditing = EditingFactory.forInteger();
125
		percentEditing.modelIntegerConstraints()
126
			.rangeMessage("Please specify a percentage value within [{0}, {1}].")
127
			.range(0, 100);
128
		bindTextField(percentText, new WritableValue(-1, null), percentEditing);
129
130
		// Edit a hex integer within the range [0x00, 0xff]. The range validation
131
		// message will display the range boundaries in hex format as well.
132
		Text hexText = createTextField(section, "Hex value in [0x00, 0xff]");
133
		IntegerEditing hexEditing = EditingFactory.forHexInteger(2).range(0x00, 0xff);
134
		bindTextField(hexText, new WritableValue(0, null), hexEditing);
135
136
		// Edit a boolean value.
137
		Text boolText = createTextField(section, "Boolean value");
138
		BooleanEditing boolEditing = EditingFactory.forBoolean();
139
		bindTextField(boolText, new WritableValue(true, null), boolEditing);
140
141
		// Edit a value within [1, 10] or [20, 30].
142
		Text rangesText = createTextField(section, "Value in [1, 10] or [20, 30]");
143
		Editing rangesEditing = EditingFactory.forInteger().addModelValidator(new RangesValidator(1, 10, 20, 30));
144
		bindTextField(rangesText, new WritableValue(), rangesEditing);
145
	}
146
147
	private void createListSection(Composite parent) {
148
		Group section = createSectionGroup(parent, "List bindings", true);
149
150
		// Our date should be >= 01.01.1990.
151
		Calendar year1990Calendar = Calendar.getInstance();
152
		year1990Calendar.clear();
153
		year1990Calendar.set(1990, 0, 1);
154
		Date year1990 = year1990Calendar.getTime();
155
156
		// Edit a date supporting the default input/display patterns.
157
		Text dateText = createTextField(section, "Date");
158
		DateEditing dateEditing = EditingFactory.forDate().afterEqual(year1990);
159
		final WritableValue dateObservable = new WritableValue();
160
		final Binding dateBinding = bindTextField(dateText, dateObservable, dateEditing);
161
162
		// Create a list to which the dates are added when the user hits ENTER.
163
		new Label(section, SWT.LEFT);
164
		ListViewer dateListViewer = new ListViewer(section);
165
		GridDataFactory.fillDefaults().grab(true, true).hint(150, 200).applyTo(dateListViewer.getList());
166
167
		dateListViewer.setContentProvider(new ObservableListContentProvider());
168
		dateListViewer.setLabelProvider(new LabelProvider());
169
170
		// We use the same DateEditing object as for the text field above to
171
		// create a list binding which maps the entered dates to their string
172
		// representation which is then set as input on the ListViewer.
173
		final WritableList targetDateList = new WritableList();
174
		final WritableList modelDateList = new WritableList();
175
		dateEditing.bindList(dbc, targetDateList, modelDateList);
176
177
		// Set the list containing the string representation of the dates as input.
178
		dateListViewer.setInput(targetDateList);
179
180
		// Add the current date in the text field when the user hits ENTER.
181
		dateText.addSelectionListener(new SelectionAdapter() {
182
			public void widgetDefaultSelected(SelectionEvent e) {
183
				IStatus dateValidationStatus = (IStatus) dateBinding.getValidationStatus().getValue();
184
				Date date = (Date) dateObservable.getValue();
185
				if (dateValidationStatus.isOK() && date != null) {
186
					modelDateList.add(date);
187
				}
188
			}
189
		});
190
	}
191
192
	private Binding bindTextField(Text text, IObservableValue modelValue, Editing editing) {
193
		// Create the binding using the editing object.
194
		ISWTObservableValue textObservable = SWTObservables.observeText(text, SWT.Modify);
195
		Binding binding = editing.bindValue(dbc, textObservable, modelValue);
196
197
		// Decorate the control with the validation status.
198
		ControlDecorationSupport.create(binding, SWT.TOP);
199
200
		// Re-format when the text field looses the focus in order to always
201
		// display the model in the default format in case multiple input formats
202
		// are supported.
203
		formatOnFocusOut(text, binding);
204
205
		return binding;
206
	}
207
208
	private static void formatOnFocusOut(final Control control, final Binding binding) {
209
		control.addFocusListener(new FocusAdapter() {
210
			public void focusLost(FocusEvent e) {
211
				IStatus dateValidationStatus = (IStatus) binding.getValidationStatus().getValue();
212
				if (dateValidationStatus.isOK()) {
213
					binding.updateModelToTarget();
214
				}
215
			}
216
		});
217
	}
218
219
	private static Group createSectionGroup(Composite parent, String groupText, boolean grabVertical) {
220
		Group section = new Group(parent, SWT.SHADOW_ETCHED_IN);
221
		section.setText(groupText);
222
		GridLayoutFactory.fillDefaults()
223
				.numColumns(2)
224
				.equalWidth(false)
225
				.margins(5, 5)
226
				.spacing(15, 5)
227
				.applyTo(section);
228
		GridDataFactory.fillDefaults().grab(true, grabVertical).applyTo(section);
229
		return section;
230
	}
231
232
	private static Text createTextField(Composite parent, String labelText) {
233
		Label label = new Label(parent, SWT.LEFT);
234
		label.setText(labelText);
235
		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
236
237
		final Text text = new Text(parent, SWT.BORDER);
238
		GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).applyTo(text);
239
240
		// Select the text when gaining focus.
241
		text.addFocusListener(new FocusAdapter() {
242
			public void focusGained(FocusEvent e) {
243
				text.selectAll();
244
			}
245
		});
246
247
		return text;
248
	}
249
250
	private static final class RangesValidator implements IValidator {
251
252
		private final String validationMessage;
253
254
		private final IValidator validator;
255
256
		public RangesValidator(int min1, int max1, int min2, int max2) {
257
			this.validationMessage = MessageFormat.format(
258
					"The value must lie within [{0}, {1}] or [{2}, {3}].",
259
					new Object[] { min1, max1, min2, max2 });
260
			this.validator =
261
				new IntegerConstraints()
262
					.range(min1, max1)
263
					.range(min2, max2)
264
					.aggregationPolicy(Constraints.AGGREGATION_MIN_SEVERITY)
265
					.createValidator();
266
		}
267
268
		public IStatus validate(Object value) {
269
			if (!validator.validate(value).isOK()) {
270
				return ValidationStatus.error(validationMessage);
271
			}
272
			return ValidationStatus.ok();
273
		}
274
	}
275
}
(-)src/org/eclipse/jface/examples/databinding/util/EditingFactory.java (+208 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.util;
13
14
import java.util.Locale;
15
16
import org.eclipse.core.databinding.editing.BooleanEditing;
17
import org.eclipse.core.databinding.editing.DateEditing;
18
import org.eclipse.core.databinding.editing.DecimalEditing;
19
import org.eclipse.core.databinding.editing.IntegerEditing;
20
import org.eclipse.core.databinding.editing.StringEditing;
21
22
import com.ibm.icu.text.DateFormat;
23
import com.ibm.icu.text.NumberFormat;
24
25
/**
26
 * @since 3.2
27
 */
28
public final class EditingFactory {
29
30
	private static final String REQUIRED_MESSAGE = "Please specify a value.";
31
32
	private static final String NUMBER_PARSE_ERROR_MESSAGE = "The input is invalid.";
33
34
	private static final String NUMBER_OUT_OF_RANGE_MESSAGE = "The value lies outside the supported range.";
35
36
	private static final String NUMBER_RANGE_MESSAGE = "The value must lie between {0} and {1}.";
37
38
	private static final String[] BOOLEAN_TRUE_VALUES = new String[] {
39
		"yes", "y", "true", "1"
40
	};
41
42
	private static final String[] BOOLEAN_FALSE_VALUES = new String[] {
43
		"no", "n", "false", "0"
44
	};
45
46
	private static final String[] DATE_INPUT_PATTERNS = new String[] {
47
		"yyMMdd",
48
		"yyyyMMdd"
49
	};
50
51
	private static final String DATE_DISPLAY_PATTERN = "yyyyMMdd";
52
53
	private static final String DATE_PARSE_ERROR_MESSAGE = createDateParseErrorMessage(DATE_INPUT_PATTERNS);
54
55
	private static final String EMAIL_REGEX = "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}\\b";
56
57
	private static final String EMAIL_ERROR_MESSAGE = "Please specify a valid e-mail address.";
58
59
	private EditingFactory() {
60
		// prevent instantiation
61
	}
62
63
	public static StringEditing forString() {
64
		return StringEditing.stripped(true);
65
	}
66
67
	public static StringEditing forEmailString() {
68
		StringEditing editing = StringEditing.stripped(true);
69
		editing.modelStringConstraints()
70
				.matchesMessage(EMAIL_ERROR_MESSAGE)
71
				.matches(EMAIL_REGEX);
72
		return editing;
73
	}
74
75
	public static IntegerEditing forLong() {
76
		return forLong(Locale.getDefault());
77
	}
78
79
	public static IntegerEditing forLong(Locale locale) {
80
		IntegerEditing editing = IntegerEditing.forLongFormat(
81
				NumberFormat.getIntegerInstance(locale),
82
				NUMBER_PARSE_ERROR_MESSAGE,
83
				NUMBER_OUT_OF_RANGE_MESSAGE);
84
		configure(editing);
85
		return editing;
86
	}
87
88
	public static IntegerEditing forInteger() {
89
		return forInteger(Locale.getDefault());
90
	}
91
92
	public static IntegerEditing forInteger(Locale locale) {
93
		IntegerEditing editing = IntegerEditing.forIntegerFormat(
94
				NumberFormat.getIntegerInstance(locale),
95
				NUMBER_PARSE_ERROR_MESSAGE,
96
				NUMBER_OUT_OF_RANGE_MESSAGE);
97
		configure(editing);
98
		return editing;
99
	}
100
101
	public static IntegerEditing forShort() {
102
		return forShort(Locale.getDefault());
103
	}
104
105
	public static IntegerEditing forShort(Locale locale) {
106
		IntegerEditing editing = IntegerEditing.forShortFormat(
107
				NumberFormat.getIntegerInstance(locale),
108
				NUMBER_PARSE_ERROR_MESSAGE,
109
				NUMBER_OUT_OF_RANGE_MESSAGE);
110
		configure(editing);
111
		return editing;
112
	}
113
114
	public static IntegerEditing forByte() {
115
		return forByte(Locale.getDefault());
116
	}
117
118
	public static IntegerEditing forByte(Locale locale) {
119
		IntegerEditing editing = IntegerEditing.forByteFormat(
120
				NumberFormat.getIntegerInstance(locale),
121
				NUMBER_PARSE_ERROR_MESSAGE,
122
				NUMBER_OUT_OF_RANGE_MESSAGE);
123
		configure(editing);
124
		return editing;
125
	}
126
127
	public static IntegerEditing forHexInteger(int digits) {
128
		IntegerEditing editing = IntegerEditing.forIntegerFormat(
129
				RadixNumberFormat.getHexInstance("0x", digits),
130
				NUMBER_PARSE_ERROR_MESSAGE,
131
				NUMBER_OUT_OF_RANGE_MESSAGE);
132
		configure(editing);
133
		return editing;
134
	}
135
136
	private static void configure(IntegerEditing editing) {
137
		editing.modelIntegerConstraints()
138
				.requiredMessage(REQUIRED_MESSAGE)
139
				.rangeMessage(NUMBER_RANGE_MESSAGE);
140
	}
141
142
	public static DecimalEditing forDouble() {
143
		return forDouble(Locale.getDefault());
144
	}
145
146
	public static DecimalEditing forDouble(Locale locale) {
147
		DecimalEditing editing = DecimalEditing.forDoubleFormat(
148
				NumberFormat.getNumberInstance(locale),
149
				NUMBER_PARSE_ERROR_MESSAGE,
150
				NUMBER_OUT_OF_RANGE_MESSAGE);
151
		configure(editing);
152
		return editing;
153
	}
154
155
	private static void configure(DecimalEditing editing) {
156
		editing.modelDecimalConstraints()
157
				.requiredMessage(REQUIRED_MESSAGE)
158
				.rangeMessage(NUMBER_RANGE_MESSAGE);
159
	}
160
161
	public static BooleanEditing forBoolean() {
162
		BooleanEditing editing =
163
			BooleanEditing.forStringValues(
164
					BOOLEAN_TRUE_VALUES,
165
					BOOLEAN_FALSE_VALUES);
166
		configure(editing);
167
		return editing;
168
	}
169
170
	private static void configure(BooleanEditing editing) {
171
		editing.modelBooleanConstraints()
172
				.requiredMessage(REQUIRED_MESSAGE);
173
	}
174
175
	public static DateEditing forDate() {
176
		return forDate(Locale.getDefault());
177
	}
178
179
	public static DateEditing forDate(Locale locale) {
180
		DateEditing editing = DateEditing
181
				.forFormats(
182
						createDateFormats(DATE_INPUT_PATTERNS, locale),
183
						DATE_PARSE_ERROR_MESSAGE,
184
						DateFormat.getPatternInstance(DATE_DISPLAY_PATTERN, locale));
185
		editing.modelDateConstraints().requiredMessage(REQUIRED_MESSAGE);
186
		return editing;
187
	}
188
189
	private static DateFormat[] createDateFormats(String[] datePatterns, Locale locale) {
190
		DateFormat[] dateFormats = new DateFormat[datePatterns.length];
191
		for (int i = 0; i < dateFormats.length; i++) {
192
			dateFormats[i] = DateFormat.getPatternInstance(datePatterns[i], locale);
193
		}
194
		return dateFormats;
195
	}
196
197
	private static String createDateParseErrorMessage(String[] datePatterns) {
198
		StringBuffer messageSb = new StringBuffer();
199
		messageSb.append("Supported formats: ");
200
		for (int i = 0; i < datePatterns.length; i++) {
201
			if (i > 0) {
202
				messageSb.append(", ");
203
			}
204
			messageSb.append(datePatterns[i]);
205
		}
206
		return messageSb.toString();
207
	}
208
}
(-)src/org/eclipse/jface/examples/databinding/util/RadixNumberFormat.java (+99 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.util;
13
14
import java.math.BigInteger;
15
import java.text.FieldPosition;
16
import java.text.ParsePosition;
17
18
import com.ibm.icu.math.BigDecimal;
19
import com.ibm.icu.text.NumberFormat;
20
21
/**
22
 * @since 3.2
23
 *
24
 */
25
public class RadixNumberFormat extends NumberFormat {
26
27
	private static final long serialVersionUID = 411884077848863891L;
28
29
	private final int radix;
30
31
	private final String prefix;
32
33
	private final int digits;
34
35
	private RadixNumberFormat(int radix, String prefix, int digits) {
36
		this.radix = radix;
37
		this.prefix = prefix != null ? prefix : "";
38
		this.digits = digits;
39
	}
40
41
	public static RadixNumberFormat getHexInstance() {
42
		return getHexInstance(null, 0);
43
	}
44
45
	public static RadixNumberFormat getHexInstance(String prefix, int digits) {
46
		return new RadixNumberFormat(16, prefix, digits);
47
	}
48
49
	public StringBuffer format(double number, StringBuffer toAppendTo,
50
			FieldPosition pos) {
51
		return format((long) number, toAppendTo, pos);
52
	}
53
54
	public StringBuffer format(long number, StringBuffer toAppendTo,
55
			FieldPosition pos) {
56
		return toAppendTo.append(prefix).append(addPadding(Long.toString(number, radix)));
57
	}
58
59
	public StringBuffer format(BigInteger number, StringBuffer toAppendTo,
60
			FieldPosition pos) {
61
		return toAppendTo.append(prefix).append(addPadding(number.toString(radix)));
62
	}
63
64
	public StringBuffer format(BigDecimal number, StringBuffer toAppendTo,
65
			FieldPosition pos) {
66
		throw new UnsupportedOperationException();
67
	}
68
69
	public Number parse(String text, ParsePosition parsePosition) {
70
		if (text.length() == 0) {
71
			return null;
72
		}
73
74
		parsePosition.setIndex(parsePosition.getIndex() + text.length());
75
76
		try {
77
			if (text.startsWith(prefix)) {
78
				return Integer.parseInt(text.substring(prefix.length()), radix);
79
			}
80
			return Integer.parseInt(text, radix);
81
		} catch (NumberFormatException e) {
82
			parsePosition.setErrorIndex(0);
83
			return null;
84
		}
85
	}
86
87
	private String addPadding(String numberText) {
88
		if (numberText.length() >= digits) {
89
			return numberText;
90
		}
91
92
		StringBuffer sb = new StringBuffer();
93
		for (int i = numberText.length(); i < digits; i++) {
94
			sb.append('0');
95
		}
96
		sb.append(numberText);
97
		return sb.toString();
98
	}
99
}
(-)src/org/eclipse/jface/examples/databinding/util/ObservableMapEditingCellLabelProvider.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.util;
13
14
import org.eclipse.core.databinding.editing.Editing;
15
import org.eclipse.core.databinding.observable.map.IObservableMap;
16
import org.eclipse.jface.databinding.viewers.ObservableMapCellLabelProvider;
17
import org.eclipse.jface.viewers.ViewerCell;
18
19
/**
20
 * @since 3.2
21
 */
22
public class ObservableMapEditingCellLabelProvider extends
23
		ObservableMapCellLabelProvider {
24
25
	private final IObservableMap attributeMap;
26
27
	private final Editing editing;
28
29
	public ObservableMapEditingCellLabelProvider(IObservableMap attributeMap, Editing editing) {
30
		super(attributeMap);
31
		this.attributeMap = attributeMap;
32
		this.editing = editing;
33
	}
34
35
	public void update(ViewerCell cell) {
36
		Object element = cell.getElement();
37
		Object attribute = attributeMap.get(element);
38
		cell.setText((String) editing.convertToTarget(attribute));
39
	}
40
}
(-)src/org/eclipse/jface/examples/databinding/snippets/Snippet036EditingTable.java (+252 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2009 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 183055)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.snippets;
13
14
import java.util.Date;
15
16
import org.eclipse.core.databinding.Binding;
17
import org.eclipse.core.databinding.DataBindingContext;
18
import org.eclipse.core.databinding.beans.BeansObservables;
19
import org.eclipse.core.databinding.editing.DateEditing;
20
import org.eclipse.core.databinding.editing.Editing;
21
import org.eclipse.core.databinding.editing.IntegerEditing;
22
import org.eclipse.core.databinding.editing.StringEditing;
23
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.list.WritableList;
25
import org.eclipse.core.databinding.observable.map.IObservableMap;
26
import org.eclipse.core.databinding.observable.set.IObservableSet;
27
import org.eclipse.core.databinding.observable.value.IObservableValue;
28
import org.eclipse.core.runtime.IStatus;
29
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
30
import org.eclipse.jface.databinding.swt.SWTObservables;
31
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
32
import org.eclipse.jface.databinding.viewers.ViewersObservables;
33
import org.eclipse.jface.examples.databinding.ModelObject;
34
import org.eclipse.jface.examples.databinding.util.EditingFactory;
35
import org.eclipse.jface.examples.databinding.util.ObservableMapEditingCellLabelProvider;
36
import org.eclipse.jface.examples.databinding.util.ObservableMapEditingSupport;
37
import org.eclipse.jface.internal.databinding.provisional.fieldassist.ControlDecorationSupport;
38
import org.eclipse.jface.layout.GridDataFactory;
39
import org.eclipse.jface.layout.GridLayoutFactory;
40
import org.eclipse.jface.viewers.StructuredSelection;
41
import org.eclipse.jface.viewers.TableViewer;
42
import org.eclipse.jface.viewers.TableViewerColumn;
43
import org.eclipse.swt.SWT;
44
import org.eclipse.swt.events.FocusAdapter;
45
import org.eclipse.swt.events.FocusEvent;
46
import org.eclipse.swt.layout.GridLayout;
47
import org.eclipse.swt.widgets.Composite;
48
import org.eclipse.swt.widgets.Control;
49
import org.eclipse.swt.widgets.Display;
50
import org.eclipse.swt.widgets.Group;
51
import org.eclipse.swt.widgets.Label;
52
import org.eclipse.swt.widgets.Shell;
53
import org.eclipse.swt.widgets.Text;
54
55
public class Snippet036EditingTable {
56
57
	private final StringEditing nameEditing = EditingFactory.forString().required();
58
59
	private final IntegerEditing ageEditing = EditingFactory.forInteger().required().nonNegative();
60
61
	private final DateEditing bdayEditing = EditingFactory.forDate().before(new Date());
62
63
	private DataBindingContext dbc;
64
65
	private TableViewer tableViewer;
66
67
	public static void main(String[] args) {
68
		Display display = new Display();
69
70
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
71
			public void run() {
72
				Shell shell = new Snippet036EditingTable().createShell();
73
				Display display = Display.getCurrent();
74
				while (!shell.isDisposed()) {
75
					if (!display.readAndDispatch()) {
76
						display.sleep();
77
					}
78
				}
79
			}
80
		});
81
	}
82
83
	private Shell createShell() {
84
		Display display = Display.getCurrent();
85
		Shell shell = new Shell(display);
86
		shell.setText("Editing");
87
		shell.setLayout(new GridLayout(2, false));
88
89
		dbc = new DataBindingContext();
90
91
		createTableSection(shell);
92
		createFieldSection(shell);
93
94
		shell.pack();
95
		shell.open();
96
97
		return shell;
98
	}
99
100
	private void createTableSection(Composite parent) {
101
		Group section = createSectionGroup(parent, 1);
102
103
		tableViewer = new TableViewer(section, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
104
		GridDataFactory.fillDefaults().grab(true, true).hint(350, 250).applyTo(tableViewer.getTable());
105
		tableViewer.getTable().setHeaderVisible(true);
106
		tableViewer.getTable().setLinesVisible(true);
107
108
		ObservableListContentProvider contentProvider = new ObservableListContentProvider();
109
		tableViewer.setContentProvider(contentProvider);
110
		IObservableSet contentElements = contentProvider.getKnownElements();
111
112
		IObservableMap nameMap = BeansObservables.observeMap(contentElements, "name");
113
		createColumn("Name*", 150, nameMap, nameEditing);
114
115
		IObservableMap ageMap = BeansObservables.observeMap(contentElements, "age");
116
		createColumn("Age*", 50, ageMap, ageEditing);
117
118
		IObservableMap bdayMap = BeansObservables.observeMap(contentElements, "birthday");
119
		createColumn("Birthday", 80, bdayMap, bdayEditing);
120
121
		WritableList people = new WritableList();
122
		people.add(new Person("John Doe", 27));
123
		people.add(new Person("Steve Northover", 33));
124
		people.add(new Person("Grant Gayed", 54));
125
		people.add(new Person("Veronika Irvine", 25));
126
		people.add(new Person("Mike Wilson", 44));
127
		people.add(new Person("Christophe Cornu", 37));
128
		people.add(new Person("Lynne Kues", 65));
129
		people.add(new Person("Silenio Quarti", 15));
130
131
		tableViewer.setInput(people);
132
133
		tableViewer.setSelection(new StructuredSelection(people.get(0)));
134
	}
135
136
	private TableViewerColumn createColumn(String text, int width, IObservableMap attributeMap, Editing modelEditing) {
137
		TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
138
		column.getColumn().setText(text);
139
		column.getColumn().setWidth(width);
140
		column.setLabelProvider(new ObservableMapEditingCellLabelProvider(attributeMap, modelEditing));
141
		column.setEditingSupport(new ObservableMapEditingSupport(tableViewer, attributeMap, modelEditing));
142
		return column;
143
	}
144
145
	private void createFieldSection(Composite parent) {
146
		final Group section = createSectionGroup(parent, 2);
147
148
		final IObservableValue personObservable = ViewersObservables.observeSingleSelection(tableViewer);
149
150
		Text nameText = createTextField(section, "Name*");
151
		IObservableValue nameObservable = BeansObservables.observeDetailValue(personObservable, "name", null);
152
		bindTextField(nameText, nameObservable, nameEditing);
153
154
		Text ageText = createTextField(section, "Age*");
155
		IObservableValue ageObservable = BeansObservables.observeDetailValue(personObservable, "age", null);
156
		bindTextField(ageText, ageObservable, ageEditing);
157
158
		Text bdayText = createTextField(section, "Birthday");
159
		IObservableValue bdayObservable = BeansObservables.observeDetailValue(personObservable, "birthday", null);
160
		bindTextField(bdayText, bdayObservable, bdayEditing);
161
	}
162
163
	private Binding bindTextField(
164
			Text text,
165
			IObservableValue modelValue,
166
			Editing editing) {
167
		// Create the binding using the editing object.
168
		ISWTObservableValue textObservable = SWTObservables.observeText(text, SWT.Modify);
169
		Binding binding = editing.bindValue(dbc, textObservable, modelValue);
170
171
		// Decorate the control with the validation status.
172
		ControlDecorationSupport.create(binding, SWT.TOP);
173
174
		formatOnFocusOut(text, binding);
175
176
		return binding;
177
	}
178
179
	private static void formatOnFocusOut(final Control control, final Binding binding) {
180
		control.addFocusListener(new FocusAdapter() {
181
			public void focusLost(FocusEvent e) {
182
				IStatus dateValidationStatus = (IStatus) binding.getValidationStatus().getValue();
183
				if (dateValidationStatus.isOK()) {
184
					binding.updateModelToTarget();
185
				}
186
			}
187
		});
188
	}
189
190
	private Group createSectionGroup(Composite parent, int numColumns) {
191
		Group section = new Group(parent, SWT.SHADOW_ETCHED_IN);
192
		GridLayoutFactory.fillDefaults().numColumns(numColumns).equalWidth(false).margins(5, 5).spacing(15, 5).applyTo(section);
193
		GridDataFactory.fillDefaults().grab(true, true).applyTo(section);
194
		return section;
195
	}
196
197
	private static Text createTextField(Composite parent, String labelText) {
198
		Label label = new Label(parent, SWT.LEFT);
199
		label.setText(labelText);
200
		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
201
202
		final Text text = new Text(parent, SWT.BORDER);
203
		GridDataFactory.fillDefaults().grab(true, false).hint(200, SWT.DEFAULT).applyTo(text);
204
205
		// Select the text when gaining focus.
206
		text.addFocusListener(new FocusAdapter() {
207
			public void focusGained(FocusEvent e) {
208
				text.selectAll();
209
			}
210
		});
211
212
		return text;
213
	}
214
215
	public static final class Person extends ModelObject {
216
217
		private String name;
218
219
		private int age;
220
221
		private Date birthday;
222
223
		public Person(String name, int age) {
224
			this.name = name;
225
			this.age = age;
226
		}
227
228
		public String getName() {
229
			return name;
230
		}
231
232
		public void setName(String name) {
233
			firePropertyChange("name", this.name, this.name = name);
234
		}
235
236
		public int getAge() {
237
			return age;
238
		}
239
240
		public void setAge(int age) {
241
			firePropertyChange("age", this.age, this.age = age);
242
		}
243
244
		public Date getBirthday() {
245
			return birthday;
246
		}
247
248
		public void setBirthday(Date birthday) {
249
			firePropertyChange("birthday", this.birthday, this.birthday = birthday);
250
		}
251
	}
252
}

Return to bug 183055