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

Collapse All | Expand All

(-).classpath (-1 / +1 lines)
Lines 1-6 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
1
<?xml version="1.0" encoding="UTF-8"?>
2
<classpath>
2
<classpath>
3
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/CDC-1.1%Foundation-1.1"/>
3
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
4
	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
4
	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
5
	<classpathentry kind="src" path="src"/>
5
	<classpathentry kind="src" path="src"/>
6
	<classpathentry kind="output" path="bin"/>
6
	<classpathentry kind="output" path="bin"/>
(-).settings/org.eclipse.jdt.core.prefs (-4 / +4 lines)
Lines 1-4 Link Here
1
#Thu Feb 05 11:35:38 MST 2009
1
#Sun Feb 28 19:30:40 CET 2010
2
eclipse.preferences.version=1
2
eclipse.preferences.version=1
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
Lines 17-25 Link Here
17
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
17
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
18
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
18
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
19
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
19
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
20
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
20
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
21
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
21
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
22
org.eclipse.jdt.core.compiler.compliance=1.4
22
org.eclipse.jdt.core.compiler.compliance=1.5
23
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
23
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
24
org.eclipse.jdt.core.compiler.debug.localVariable=generate
24
org.eclipse.jdt.core.compiler.debug.localVariable=generate
25
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
25
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
Lines 96-102 Link Here
96
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
96
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
97
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
97
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
98
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
98
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
99
org.eclipse.jdt.core.compiler.source=1.3
99
org.eclipse.jdt.core.compiler.source=1.5
100
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
100
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
101
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
101
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
102
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
102
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
(-).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
(-)META-INF/MANIFEST.MF (-2 / +4 lines)
Lines 2-14 Link Here
2
Bundle-ManifestVersion: 2
2
Bundle-ManifestVersion: 2
3
Bundle-Name: %pluginName
3
Bundle-Name: %pluginName
4
Bundle-SymbolicName: org.eclipse.core.databinding
4
Bundle-SymbolicName: org.eclipse.core.databinding
5
Bundle-Version: 1.3.100.qualifier
5
Bundle-Version: 1.4.0.qualifier
6
Bundle-ClassPath: .
6
Bundle-ClassPath: .
7
Bundle-Vendor: %providerName
7
Bundle-Vendor: %providerName
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"
Lines 22-27 Link Here
22
 org.osgi.util.tracker;version="[1.3.3,2.0.0)";resolution:=optional,
24
 org.osgi.util.tracker;version="[1.3.3,2.0.0)";resolution:=optional,
23
 org.eclipse.osgi.framework.log;version="[1.0.0,2.0.0)";resolution:=optional
25
 org.eclipse.osgi.framework.log;version="[1.0.0,2.0.0)";resolution:=optional
24
Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1,
26
Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1,
25
 J2SE-1.4
27
 J2SE-1.5
26
Bundle-Activator: org.eclipse.core.internal.databinding.Activator
28
Bundle-Activator: org.eclipse.core.internal.databinding.Activator
27
Bundle-ActivationPolicy: lazy
29
Bundle-ActivationPolicy: lazy
(-)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$
(-)src/org/eclipse/core/databinding/editing/BooleanEditing.java (+161 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.StringConstraints;
16
import org.eclipse.core.internal.databinding.conversion.BooleanToStringConverter;
17
import org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter;
18
import org.eclipse.core.internal.databinding.validation.StringToBooleanValidator;
19
20
/**
21
 * @noextend This class is not intended to be subclassed by clients.
22
 * @since 1.4
23
 */
24
public class BooleanEditing extends Editing<String, Boolean> {
25
26
	/**
27
	 * Creates a new editing object for booleans.
28
	 * 
29
	 * @param trueValues
30
	 *            The set of strings representing a <code>true</code> value.
31
	 * @param falseValues
32
	 *            The set of strings representing a <code>false</code> value.
33
	 * @param parseErrorMessage
34
	 *            The validation message issued in case the input string cannot
35
	 *            be parsed to a boolean.
36
	 * 
37
	 * @noreference This constructor is not intended to be referenced by
38
	 *              clients.
39
	 */
40
	protected BooleanEditing(String[] trueValues, String[] falseValues,
41
			String parseErrorMessage) {
42
		StringToBooleanConverter targetConverter = new StringToBooleanConverter();
43
		BooleanToStringConverter modelConverter = new BooleanToStringConverter(
44
				Boolean.class);
45
46
		StringToBooleanValidator targetValidator = new StringToBooleanValidator();
47
		if (parseErrorMessage != null) {
48
			targetValidator.setParseErrorMessage(parseErrorMessage);
49
		}
50
51
		if (trueValues != null && falseValues != null) {
52
			targetValidator.setSourceStrings(trueValues, falseValues);
53
			targetConverter.setSourceStrings(trueValues, falseValues);
54
			modelConverter.setTargetStrings(trueValues[0], falseValues[0]);
55
		}
56
57
		setTargetConverter(targetConverter);
58
		setModelConverter(modelConverter);
59
		targetConstraints().addValidator(targetValidator);
60
	}
61
62
	/**
63
	 * Creates a new editing object which uses the default set of string
64
	 * representations for boolean values for parsing and displaying.
65
	 * 
66
	 * @return The new editing object for the default set of string
67
	 *         representations for boolean values.
68
	 */
69
	public static BooleanEditing withDefaults() {
70
		return withDefaults(null);
71
	}
72
73
	/**
74
	 * Creates a new editing object which uses the default set of string
75
	 * representations for boolean values for parsing and displaying. Uses the
76
	 * specified custom validation message.
77
	 * 
78
	 * @param parseErrorMessage
79
	 *            The validation message issued in case the input string cannot
80
	 *            be parsed to a boolean.
81
	 * @return The new editing object for the default set of string
82
	 *         representations for boolean values.
83
	 */
84
	public static BooleanEditing withDefaults(String parseErrorMessage) {
85
		return new BooleanEditing(null, null, parseErrorMessage);
86
	}
87
88
	/**
89
	 * Creates a new editing object which uses the given set of string
90
	 * representations for boolean values for parsing and displaying.
91
	 * 
92
	 * <p>
93
	 * For parsing, the given string values will be considered valid
94
	 * representations of {@code true} and {@code false}, respectively. For
95
	 * displaying, the first element of the respective array will be used for
96
	 * representing the corresponding boolean value.
97
	 * </p>
98
	 * 
99
	 * @param trueValues
100
	 *            The set of strings representing a <code>true</code> value.
101
	 * @param falseValues
102
	 *            The set of strings representing a <code>false</code> value.
103
	 * @return The new editing object for the given set of string
104
	 *         representations for boolean values.
105
	 */
106
	public static BooleanEditing forStringValues(String[] trueValues,
107
			String[] falseValues) {
108
		return forStringValues(trueValues, falseValues, null);
109
	}
110
111
	/**
112
	 * Creates a new editing object which uses the given set of string
113
	 * representations for boolean values for parsing and displaying. Uses the
114
	 * specified custom validation message.
115
	 * 
116
	 * <p>
117
	 * For parsing, the given string values will be considered valid
118
	 * representations of {@code true} and {@code false}, respectively. For
119
	 * displaying, the first element of the respective array will be used for
120
	 * representing the corresponding boolean value.
121
	 * </p>
122
	 * 
123
	 * @param trueValues
124
	 *            The set of strings representing a <code>true</code> value.
125
	 * @param falseValues
126
	 *            The set of strings representing a <code>false</code> value.
127
	 * @param parseErrorMessage
128
	 *            The validation message issued in case the input string cannot
129
	 *            be parsed to a boolean.
130
	 * @return The new editing object for the given set of string
131
	 *         representations for boolean values.
132
	 */
133
	public static BooleanEditing forStringValues(String[] trueValues,
134
			String[] falseValues, String parseErrorMessage) {
135
		return new BooleanEditing(trueValues, falseValues, parseErrorMessage);
136
	}
137
138
	public StringConstraints targetConstraints() {
139
		return (StringConstraints) super.targetConstraints();
140
	}
141
142
	public BooleanConstraints modelConstraints() {
143
		return (BooleanConstraints) super.modelConstraints();
144
	}
145
146
	public BooleanConstraints beforeSetModelConstraints() {
147
		return (BooleanConstraints) super.beforeSetModelConstraints();
148
	}
149
150
	protected StringConstraints createTargetConstraints() {
151
		return new StringConstraints();
152
	}
153
154
	protected BooleanConstraints createModelConstraints() {
155
		return new BooleanConstraints();
156
	}
157
158
	protected BooleanConstraints createBeforeSetModelConstraints() {
159
		return new BooleanConstraints();
160
	}
161
}
(-)src/org/eclipse/core/databinding/editing/CharacterEditing.java (+100 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.StringConstraints;
16
import org.eclipse.core.internal.databinding.conversion.CharacterToStringConverter;
17
import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter;
18
import org.eclipse.core.internal.databinding.validation.StringToCharacterValidator;
19
20
/**
21
 * @noextend This class is not intended to be subclassed by clients.
22
 * @since 1.4
23
 */
24
public class CharacterEditing extends Editing<String, Character> {
25
26
	/**
27
	 * Creates a new editing object for booleans.
28
	 * 
29
	 * @param parseErrorMessage
30
	 *            The validation message issued in case the input string is not
31
	 *            a valid character.
32
	 * 
33
	 * @noreference This constructor is not intended to be referenced by
34
	 *              clients.
35
	 */
36
	protected CharacterEditing(String parseErrorMessage) {
37
		StringToCharacterConverter targetConverter = new StringToCharacterConverter(
38
				false);
39
		CharacterToStringConverter modelConverter = CharacterToStringConverter
40
				.fromCharacter(false);
41
42
		StringToCharacterValidator targetValidator = new StringToCharacterValidator(
43
				targetConverter);
44
		if (parseErrorMessage != null) {
45
			targetValidator.setParseErrorMessage(parseErrorMessage);
46
		}
47
48
		setTargetConverter(targetConverter);
49
		setModelConverter(modelConverter);
50
		targetConstraints().addValidator(targetValidator);
51
	}
52
53
	/**
54
	 * Creates a new editing object which uses the default validations and
55
	 * conversions for the editing of characters.
56
	 * 
57
	 * @return The new editing object for the default editing of characters.
58
	 */
59
	public static CharacterEditing withDefaults() {
60
		return withDefaults(null);
61
	}
62
63
	/**
64
	 * Creates a new editing object which uses the default validations and
65
	 * conversions for the editing of characters. Uses the specified custom
66
	 * validation message.
67
	 * 
68
	 * @param parseErrorMessage
69
	 *            The validation message issued in case the input string is not
70
	 *            a valid character.
71
	 * @return The new editing object for the default editing of characters.
72
	 */
73
	public static CharacterEditing withDefaults(String parseErrorMessage) {
74
		return new CharacterEditing(parseErrorMessage);
75
	}
76
77
	public StringConstraints targetConstraints() {
78
		return (StringConstraints) super.targetConstraints();
79
	}
80
81
	public CharacterConstraints modelConstraints() {
82
		return (CharacterConstraints) super.modelConstraints();
83
	}
84
85
	public CharacterConstraints beforeSetModelConstraints() {
86
		return (CharacterConstraints) super.beforeSetModelConstraints();
87
	}
88
89
	protected StringConstraints createTargetConstraints() {
90
		return new StringConstraints();
91
	}
92
93
	protected CharacterConstraints createModelConstraints() {
94
		return new CharacterConstraints();
95
	}
96
97
	protected CharacterConstraints createBeforeSetModelConstraints() {
98
		return new CharacterConstraints();
99
	}
100
}
(-)src/org/eclipse/core/databinding/editing/DateEditing.java (+155 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.DateConstraints;
17
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
18
import org.eclipse.core.internal.databinding.conversion.DateToStringConverter;
19
import org.eclipse.core.internal.databinding.conversion.StringToDateConverter;
20
import org.eclipse.core.internal.databinding.validation.StringToDateValidator;
21
22
import com.ibm.icu.text.DateFormat;
23
24
/**
25
 * @noextend This class is not intended to be subclassed by clients.
26
 * @since 1.4
27
 */
28
public class DateEditing extends Editing<String, Date> {
29
30
	private final DateFormat displayFormat;
31
32
	/**
33
	 * Creates a new editing object for <code>Date</code>s.
34
	 * 
35
	 * @param inputFormats
36
	 *            The date formats supported for reading in dates.
37
	 * @param parseErrorMessage
38
	 *            The validation message issued in case the input string cannot
39
	 *            be parsed to a date.
40
	 * @param displayFormat
41
	 *            The date format for displaying dates.
42
	 * 
43
	 * @noreference This constructor is not intended to be referenced by
44
	 *              clients.
45
	 */
46
	protected DateEditing(DateFormat[] inputFormats, String parseErrorMessage,
47
			DateFormat displayFormat) {
48
		this.displayFormat = displayFormat;
49
50
		StringToDateConverter targetConverter = new StringToDateConverter();
51
		if (inputFormats != null) {
52
			targetConverter.setFormatters(inputFormats);
53
		}
54
55
		DateToStringConverter modelConverter = new DateToStringConverter();
56
		if (displayFormat != null) {
57
			modelConverter.setFormatters(new DateFormat[] { displayFormat });
58
		}
59
60
		StringToDateValidator targetValidator = new StringToDateValidator(
61
				targetConverter);
62
		if (parseErrorMessage != null) {
63
			targetValidator.setParseErrorMessage(parseErrorMessage);
64
		}
65
66
		setTargetConverter(targetConverter);
67
		setModelConverter(modelConverter);
68
		targetConstraints().addValidator(targetValidator);
69
	}
70
71
	/**
72
	 * Creates a new editing object which defaults the validations and
73
	 * conversions used for editing. Uses the default validation message.
74
	 * 
75
	 * @return The new editing object using the default validations and
76
	 *         conversions for editing.
77
	 */
78
	public static DateEditing withDefaults() {
79
		return withDefaults(null);
80
	}
81
82
	/**
83
	 * Creates a new editing object which defaults the validations and
84
	 * conversions used for editing. Uses the specified custom validation
85
	 * message.
86
	 * 
87
	 * @param parseErrorMessage
88
	 *            The validation message issued in case the input string cannot
89
	 *            be parsed to a date.
90
	 * @return The new editing object using the default validations and
91
	 *         conversions for editing.
92
	 */
93
	public static DateEditing withDefaults(String parseErrorMessage) {
94
		return new DateEditing(null, parseErrorMessage, null);
95
	}
96
97
	/**
98
	 * Creates a new editing object which supports all the given date input
99
	 * formats and which uses the specified format for displaying a date. Uses
100
	 * the default validation message.
101
	 * 
102
	 * @param inputFormats
103
	 *            The date formats supported for reading in dates.
104
	 * @param displayFormat
105
	 *            The date format for displaying dates.
106
	 * @return The new editing object configured by the given date formats.
107
	 */
108
	public static DateEditing forFormats(DateFormat[] inputFormats,
109
			DateFormat displayFormat) {
110
		return new DateEditing(inputFormats, null, displayFormat);
111
	}
112
113
	/**
114
	 * Creates a new editing object which supports all the given date input
115
	 * formats and which uses the specified format for displaying a date. Uses
116
	 * the specified custom validation message.
117
	 * 
118
	 * @param inputFormats
119
	 *            The date formats supported for reading in dates.
120
	 * @param parseErrorMessage
121
	 *            The validation message issued in case the input string cannot
122
	 *            be parsed to a date.
123
	 * @param displayFormat
124
	 *            The date format for displaying dates.
125
	 * @return The new editing object configured by the given date formats.
126
	 */
127
	public static DateEditing forFormats(DateFormat[] inputFormats,
128
			String parseErrorMessage, DateFormat displayFormat) {
129
		return new DateEditing(inputFormats, parseErrorMessage, displayFormat);
130
	}
131
132
	public StringConstraints targetConstraints() {
133
		return (StringConstraints) super.targetConstraints();
134
	}
135
136
	public DateConstraints modelConstraints() {
137
		return (DateConstraints) super.modelConstraints();
138
	}
139
140
	public DateConstraints beforeSetModelConstraints() {
141
		return (DateConstraints) super.beforeSetModelConstraints();
142
	}
143
144
	protected StringConstraints createTargetConstraints() {
145
		return new StringConstraints();
146
	}
147
148
	protected DateConstraints createModelConstraints() {
149
		return new DateConstraints().dateFormat(displayFormat);
150
	}
151
152
	protected DateConstraints createBeforeSetModelConstraints() {
153
		return new DateConstraints().dateFormat(displayFormat);
154
	}
155
}
(-)src/org/eclipse/core/databinding/editing/Editing.java (+972 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
 * @param <T>
30
 * @param <M>
31
 * 
32
 * @since 1.4
33
 */
34
public class Editing<T, M> {
35
36
	private Constraints<T> targetConstraints;
37
38
	private Constraints<M> modelConstraints;
39
40
	private Constraints<M> beforeSetModelConstraints;
41
42
	private IConverter targetConverter;
43
44
	private IConverter modelConverter;
45
46
	/**
47
	 * Default constructor which creates an unconfigured editing instance.
48
	 */
49
	protected Editing() {
50
		// empty editing instance
51
	}
52
53
	/**
54
	 * Creates an unconfigured editing instance.
55
	 * 
56
	 * @return A new, unconfigured editing instance.
57
	 * 
58
	 * @param <MT>
59
	 * @param <MM>
60
	 */
61
	public static <MT, MM> Editing<MT, MM> create() {
62
		return new Editing<MT, MM>();
63
	}
64
65
	/**
66
	 * Creates an editing instance with the given target-to-model and
67
	 * model-to-target converters.
68
	 * 
69
	 * @param t2mConverter
70
	 *            The target-to-model converter to set. May be <code>null</code>
71
	 *            .
72
	 * @param m2tConverter
73
	 *            The model-to-target converter to set. May be <code>null</code>
74
	 *            .
75
	 * @return A new editing instance with the given target-to-model and
76
	 *         model-to-target converters.
77
	 * 
78
	 * @param <MM>
79
	 * @param <MT>
80
	 */
81
	public static <MT, MM> Editing<MT, MM> withConverters(
82
			IConverter t2mConverter, IConverter m2tConverter) {
83
		Editing<MT, MM> editing = new Editing<MT, MM>();
84
		editing.setTargetConverter(t2mConverter);
85
		editing.setModelConverter(m2tConverter);
86
		return editing;
87
	}
88
89
	/**
90
	 * Returns the target constraints to apply.
91
	 * 
92
	 * @return The target constraints to apply.
93
	 * 
94
	 * @see #createTargetConstraints()
95
	 */
96
	public Constraints<T> targetConstraints() {
97
		if (targetConstraints == null) {
98
			targetConstraints = createTargetConstraints();
99
		}
100
		return targetConstraints;
101
	}
102
103
	/**
104
	 * Returns the model constraints to apply.
105
	 * 
106
	 * @return The model constraints to apply.
107
	 * 
108
	 * @see #createModelConstraints()
109
	 */
110
	public Constraints<M> modelConstraints() {
111
		if (modelConstraints == null) {
112
			modelConstraints = createModelConstraints();
113
		}
114
		return modelConstraints;
115
	}
116
117
	/**
118
	 * Returns the before-set model constraints to apply.
119
	 * 
120
	 * @return The before-set model constraints to apply.
121
	 * 
122
	 * @see #createBeforeSetModelConstraints()
123
	 */
124
	public Constraints<M> beforeSetModelConstraints() {
125
		if (beforeSetModelConstraints == null) {
126
			beforeSetModelConstraints = createBeforeSetModelConstraints();
127
		}
128
		return beforeSetModelConstraints;
129
	}
130
131
	/**
132
	 * Creates the target constraints to apply.
133
	 * 
134
	 * <p>
135
	 * The constraints object created by this method will be exposed as the
136
	 * {@link #targetConstraints()} of this editing object. By default, this
137
	 * method returns a plain {@link Constraints} object.
138
	 * </p>
139
	 * 
140
	 * <p>
141
	 * This method will be called lazily the first time the target constraints
142
	 * are accessed. Subclasses may overwrite this method in order to create a
143
	 * custom constraints object which will then be typically exposed in the
144
	 * subclass as API in order to allow for a typesafe access.
145
	 * </p>
146
	 * 
147
	 * @return The target constraints to apply.
148
	 * 
149
	 * @see #targetConstraints()
150
	 */
151
	protected Constraints<T> createTargetConstraints() {
152
		return new Constraints<T>();
153
	}
154
155
	/**
156
	 * Creates the model constraints to apply.
157
	 * 
158
	 * <p>
159
	 * The constraints object created by this method will be exposed as the
160
	 * {@link #modelConstraints()} of this editing object. By default, this
161
	 * method returns a plain {@link Constraints} object.
162
	 * </p>
163
	 * 
164
	 * <p>
165
	 * This method will be called lazily the first time the model constraints
166
	 * are accessed. Subclasses may overwrite this method in order to create a
167
	 * custom constraints object which will then be typically exposed in the
168
	 * subclass as API in order to allow for a typesafe access.
169
	 * </p>
170
	 * 
171
	 * @return The model constraints to apply.
172
	 * 
173
	 * @see #modelConstraints()
174
	 */
175
	protected Constraints<M> createModelConstraints() {
176
		return new Constraints<M>();
177
	}
178
179
	/**
180
	 * Creates the before-set model constraints to apply.
181
	 * 
182
	 * <p>
183
	 * The constraints object created by this method will be exposed as the
184
	 * {@link #beforeSetModelConstraints()} of this editing object. By default,
185
	 * this method returns a plain {@link Constraints} object.
186
	 * </p>
187
	 * 
188
	 * <p>
189
	 * This method will be called lazily the first time the before-set model
190
	 * constraints are accessed. Subclasses may overwrite this method in order
191
	 * to create a custom constraints object which will then be typically
192
	 * exposed in the subclass as API in order to allow for a typesafe access.
193
	 * </p>
194
	 * 
195
	 * @return The before-set model constraints to apply.
196
	 * 
197
	 * @see #beforeSetModelConstraints()
198
	 */
199
	protected Constraints<M> createBeforeSetModelConstraints() {
200
		return new Constraints<M>();
201
	}
202
203
	/**
204
	 * Sets the target-to-model converter for this editing instance.
205
	 * 
206
	 * @param converter
207
	 *            The target-to-model converter to set.
208
	 */
209
	protected final void setTargetConverter(IConverter converter) {
210
		this.targetConverter = converter;
211
	}
212
213
	/**
214
	 * Sets the model-to-target converter for this editing instance.
215
	 * 
216
	 * @param converter
217
	 *            The model-to-target converter to set.
218
	 */
219
	protected final void setModelConverter(IConverter converter) {
220
		this.modelConverter = converter;
221
	}
222
223
	/**
224
	 * Creates a new target-to-model {@link UpdateValueStrategy} with a default
225
	 * update policy configured by the current state of this editing object.
226
	 * 
227
	 * @return A new target-to-model {@link UpdateValueStrategy} configured by
228
	 *         the current state of this editing object.
229
	 * 
230
	 * @see UpdateValueStrategy#UpdateValueStrategy()
231
	 * @see #adaptT2MValueStrategy(UpdateValueStrategy)
232
	 */
233
	public final UpdateValueStrategy createT2MValueStrategy() {
234
		return adaptT2MValueStrategy(new UpdateValueStrategy());
235
	}
236
237
	/**
238
	 * Creates a new target-to-model {@link UpdateValueStrategy} with the given
239
	 * update policy configured by the current state of this editing object.
240
	 * 
241
	 * @param updatePolicy
242
	 *            The update policy to use.
243
	 * @return A new target-to-model {@link UpdateValueStrategy} configured by
244
	 *         the current state of this editing object.
245
	 * 
246
	 * @see UpdateValueStrategy#UpdateValueStrategy(int)
247
	 * @see #adaptT2MValueStrategy(UpdateValueStrategy)
248
	 */
249
	public final UpdateValueStrategy createT2MValueStrategy(int updatePolicy) {
250
		return adaptT2MValueStrategy(new UpdateValueStrategy(updatePolicy));
251
	}
252
253
	/**
254
	 * Creates a new model-to-target {@link UpdateValueStrategy} with a default
255
	 * update policy configured by the current state of this editing object.
256
	 * 
257
	 * @return A new model-to-target {@link UpdateValueStrategy} configured by
258
	 *         the current state of this editing object.
259
	 * 
260
	 * @see UpdateValueStrategy#UpdateValueStrategy()
261
	 * @see #adaptM2TValueStrategy(UpdateValueStrategy)
262
	 */
263
	public final UpdateValueStrategy createM2TValueStrategy() {
264
		return adaptM2TValueStrategy(new UpdateValueStrategy());
265
	}
266
267
	/**
268
	 * Creates a new model-to-target {@link UpdateValueStrategy} with the given
269
	 * update policy configured by the current state of this editing object.
270
	 * 
271
	 * @param updatePolicy
272
	 *            The update policy to use.
273
	 * @return A new model-to-target {@link UpdateValueStrategy} configured by
274
	 *         the current state of this editing object.
275
	 * 
276
	 * @see UpdateValueStrategy#UpdateValueStrategy(int)
277
	 * @see #adaptM2TValueStrategy(UpdateValueStrategy)
278
	 */
279
	public final UpdateValueStrategy createM2TValueStrategy(int updatePolicy) {
280
		return adaptM2TValueStrategy(new UpdateValueStrategy(updatePolicy));
281
	}
282
283
	/**
284
	 * Creates a new target-to-model {@link UpdateListStrategy} with a default
285
	 * update policy configured by the current state of this editing object.
286
	 * 
287
	 * @return A new target-to-model {@link UpdateListStrategy} configured by
288
	 *         the current state of this editing object.
289
	 * 
290
	 * @see UpdateListStrategy#UpdateListStrategy()
291
	 * @see #adaptT2MListStrategy(UpdateListStrategy)
292
	 */
293
	public final UpdateListStrategy createT2MListStrategy() {
294
		return adaptT2MListStrategy(new UpdateListStrategy());
295
	}
296
297
	/**
298
	 * Creates a new target-to-model {@link UpdateListStrategy} with the given
299
	 * update policy configured by the current state of this editing object.
300
	 * 
301
	 * @param updatePolicy
302
	 *            The update policy to use.
303
	 * @return A new target-to-model {@link UpdateListStrategy} configured by
304
	 *         the current state of this editing object.
305
	 * 
306
	 * @see UpdateListStrategy#UpdateListStrategy(int)
307
	 * @see #adaptT2MListStrategy(UpdateListStrategy)
308
	 */
309
	public final UpdateListStrategy createT2MListStrategy(int updatePolicy) {
310
		return adaptT2MListStrategy(new UpdateListStrategy(updatePolicy));
311
	}
312
313
	/**
314
	 * Creates a new model-to-target {@link UpdateListStrategy} with a default
315
	 * update policy configured by the current state of this editing object.
316
	 * 
317
	 * @return A new model-to-target {@link UpdateListStrategy} configured by
318
	 *         the current state of this editing object.
319
	 * 
320
	 * @see UpdateListStrategy#UpdateListStrategy()
321
	 * @see #adaptM2TListStrategy(UpdateListStrategy)
322
	 */
323
	public final UpdateListStrategy createM2TListStrategy() {
324
		return adaptM2TListStrategy(new UpdateListStrategy());
325
	}
326
327
	/**
328
	 * Creates a new model-to-target {@link UpdateListStrategy} with the given
329
	 * update policy configured by the current state of this editing object.
330
	 * 
331
	 * @param updatePolicy
332
	 *            The update policy to use.
333
	 * @return A new model-to-target {@link UpdateListStrategy} configured by
334
	 *         the current state of this editing object.
335
	 * 
336
	 * @see UpdateListStrategy#UpdateListStrategy(int)
337
	 * @see #adaptM2TListStrategy(UpdateListStrategy)
338
	 */
339
	public final UpdateListStrategy createM2TListStrategy(int updatePolicy) {
340
		return adaptM2TListStrategy(new UpdateListStrategy(updatePolicy));
341
	}
342
343
	/**
344
	 * Creates a new target-to-model {@link UpdateSetStrategy} with a default
345
	 * update policy configured by the current state of this editing object.
346
	 * 
347
	 * @return A new target-to-model {@link UpdateSetStrategy} configured by the
348
	 *         current state of this editing object.
349
	 * 
350
	 * @see UpdateListStrategy#UpdateListStrategy()
351
	 * @see #adaptT2MSetStrategy(UpdateSetStrategy)
352
	 */
353
	public final UpdateSetStrategy createT2MSetStrategy() {
354
		return adaptT2MSetStrategy(new UpdateSetStrategy());
355
	}
356
357
	/**
358
	 * Creates a new target-to-model {@link UpdateListStrategy} with the given
359
	 * update policy configured by the current state of this editing object.
360
	 * 
361
	 * @param updatePolicy
362
	 *            The update policy to use.
363
	 * @return A new target-to-model {@link UpdateListStrategy} configured by
364
	 *         the current state of this editing object.
365
	 * 
366
	 * @see UpdateSetStrategy#UpdateSetStrategy(int)
367
	 * @see #adaptT2MSetStrategy(UpdateSetStrategy)
368
	 */
369
	public final UpdateSetStrategy createT2MSetStrategy(int updatePolicy) {
370
		return adaptT2MSetStrategy(new UpdateSetStrategy(updatePolicy));
371
	}
372
373
	/**
374
	 * Creates a new model-to-target {@link UpdateSetStrategy} with a default
375
	 * update policy configured by the current state of this editing object.
376
	 * 
377
	 * @return A new model-to-target {@link UpdateSetStrategy} configured by the
378
	 *         current state of this editing object.
379
	 * 
380
	 * @see UpdateSetStrategy#UpdateSetStrategy()
381
	 * @see #adaptM2TSetStrategy(UpdateSetStrategy)
382
	 */
383
	public final UpdateSetStrategy createM2TSetStrategy() {
384
		return adaptM2TSetStrategy(new UpdateSetStrategy());
385
	}
386
387
	/**
388
	 * Creates a new model-to-target {@link UpdateSetStrategy} with the given
389
	 * update policy configured by the current state of this editing object.
390
	 * 
391
	 * @param updatePolicy
392
	 *            The update policy to use.
393
	 * @return A new model-to-target {@link UpdateSetStrategy} configured by the
394
	 *         current state of this editing object.
395
	 * 
396
	 * @see UpdateSetStrategy#UpdateSetStrategy(int)
397
	 * @see #adaptM2TSetStrategy(UpdateSetStrategy)
398
	 */
399
	public final UpdateSetStrategy createM2TSetStrategy(int updatePolicy) {
400
		return adaptM2TSetStrategy(new UpdateSetStrategy(updatePolicy));
401
	}
402
403
	/**
404
	 * Configures an existing target-to-model {@link UpdateValueStrategy} with
405
	 * the current state of this editing object.
406
	 * 
407
	 * <p>
408
	 * The configuration is done as follows:
409
	 * <ul>
410
	 * <li>
411
	 * The {@link Constraints#createValidator() validator} of the
412
	 * {@link #targetConstraints() target constraints} is set as the
413
	 * {@link UpdateValueStrategy#setAfterGetValidator(IValidator) after-get
414
	 * validator} of the update strategy.</li>
415
	 * <li>The {@link #setTargetConverter(IConverter) target converter} is set
416
	 * as the {@link UpdateValueStrategy#setConverter(IConverter) converter} of
417
	 * the update strategy.</li>
418
	 * <li>
419
	 * The {@link Constraints#createValidator() validator} of the
420
	 * {@link #modelConstraints() model constraints} is set as the
421
	 * {@link UpdateValueStrategy#setAfterConvertValidator(IValidator)
422
	 * after-convert validator} of the update strategy.</li>
423
	 * <li>The {@link Constraints#createValidator() validator} of the
424
	 * {@link #beforeSetModelConstraints() before-set model constraints} is set
425
	 * as the {@link UpdateValueStrategy#setBeforeSetValidator(IValidator)
426
	 * before-set validator} of the update strategy.</li>
427
	 * </ul>
428
	 * </p>
429
	 * 
430
	 * @param updateStrategy
431
	 *            The {@link UpdateValueStrategy} to configure.
432
	 * @return The passed-in, configured target-to-model
433
	 *         {@link UpdateValueStrategy}.
434
	 * 
435
	 * @see UpdateValueStrategy#setAfterGetValidator(IValidator)
436
	 * @see UpdateValueStrategy#setConverter(IConverter)
437
	 * @see UpdateValueStrategy#setAfterConvertValidator(IValidator)
438
	 * @see UpdateValueStrategy#setBeforeSetValidator(IValidator)
439
	 */
440
	public final UpdateValueStrategy adaptT2MValueStrategy(
441
			UpdateValueStrategy updateStrategy) {
442
		updateStrategy.setAfterGetValidator(createValidator(targetConstraints));
443
		updateStrategy.setConverter(targetConverter);
444
		updateStrategy
445
				.setAfterConvertValidator(createValidator(modelConstraints));
446
		updateStrategy
447
				.setBeforeSetValidator(createValidator(beforeSetModelConstraints));
448
		return updateStrategy;
449
	}
450
451
	/**
452
	 * Configures an existing model-to-target {@link UpdateValueStrategy} with
453
	 * the current state of this editing object by setting the
454
	 * {@link #setModelConverter(IConverter) model converter} as the
455
	 * {@link UpdateValueStrategy#setConverter(IConverter) converter} of the
456
	 * update strategy.
457
	 * 
458
	 * @param updateStrategy
459
	 *            The {@link UpdateValueStrategy} to configure.
460
	 * @return The passed-in, configured model-to-target
461
	 *         {@link UpdateValueStrategy}.
462
	 * 
463
	 * @see UpdateValueStrategy#setConverter(IConverter)
464
	 */
465
	public final UpdateValueStrategy adaptM2TValueStrategy(
466
			UpdateValueStrategy updateStrategy) {
467
		updateStrategy.setConverter(modelConverter);
468
		return updateStrategy;
469
	}
470
471
	/**
472
	 * Configures an existing target-to-model {@link UpdateListStrategy} with
473
	 * the current state of this editing object by setting the
474
	 * {@link #setTargetConverter(IConverter) target converter} as the
475
	 * {@link UpdateListStrategy#setConverter(IConverter) converter} of the
476
	 * update strategy.
477
	 * 
478
	 * @param updateStrategy
479
	 *            The {@link UpdateListStrategy} to configure.
480
	 * @return The passed-in, configured target-to-model
481
	 *         {@link UpdateListStrategy}.
482
	 * 
483
	 * @see UpdateListStrategy#setConverter(IConverter)
484
	 */
485
	public final UpdateListStrategy adaptT2MListStrategy(
486
			UpdateListStrategy updateStrategy) {
487
		updateStrategy.setConverter(targetConverter);
488
		return updateStrategy;
489
	}
490
491
	/**
492
	 * Configures an existing model-to-target {@link UpdateListStrategy} with
493
	 * the current state of this editing object by setting the
494
	 * {@link #setModelConverter(IConverter) model converter} as the
495
	 * {@link UpdateListStrategy#setConverter(IConverter) converter} of the
496
	 * update strategy.
497
	 * 
498
	 * @param updateStrategy
499
	 *            The {@link UpdateListStrategy} to configure.
500
	 * @return The passed-in, configured model-to-target
501
	 *         {@link UpdateListStrategy}.
502
	 * 
503
	 * @see UpdateListStrategy#setConverter(IConverter)
504
	 */
505
	public final UpdateListStrategy adaptM2TListStrategy(
506
			UpdateListStrategy 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 UpdateSetStrategy#setConverter(IConverter) converter} of the
516
	 * update strategy.
517
	 * 
518
	 * @param updateStrategy
519
	 *            The {@link UpdateSetStrategy} to configure.
520
	 * @return The passed-in, configured target-to-model
521
	 *         {@link UpdateSetStrategy}.
522
	 * 
523
	 * @see UpdateSetStrategy#setConverter(IConverter)
524
	 */
525
	public final UpdateSetStrategy adaptT2MSetStrategy(
526
			UpdateSetStrategy updateStrategy) {
527
		updateStrategy.setConverter(targetConverter);
528
		return updateStrategy;
529
	}
530
531
	/**
532
	 * Configures an existing model-to-target {@link UpdateSetStrategy} with the
533
	 * current state of this editing object by setting the
534
	 * {@link #setModelConverter(IConverter) model converter} as the
535
	 * {@link UpdateSetStrategy#setConverter(IConverter) converter} of the
536
	 * update strategy.
537
	 * 
538
	 * @param updateStrategy
539
	 *            The {@link UpdateSetStrategy} to configure.
540
	 * @return The passed-in, configured model-to-target
541
	 *         {@link UpdateSetStrategy}.
542
	 * 
543
	 * @see UpdateSetStrategy#setConverter(IConverter)
544
	 */
545
	public final UpdateSetStrategy adaptM2TSetStrategy(
546
			UpdateSetStrategy updateStrategy) {
547
		updateStrategy.setConverter(modelConverter);
548
		return updateStrategy;
549
	}
550
551
	/**
552
	 * Converts a target value to a model value by performing the following
553
	 * steps:
554
	 * <ul>
555
	 * <li>
556
	 * Applying all the {@link #targetConstraints() target constraints} to the
557
	 * given target value.</li>
558
	 * <li>
559
	 * {@link #setTargetConverter(IConverter) Converting} the target value to
560
	 * the model value.</li>
561
	 * <li>
562
	 * Applying all the {@link #modelConstraints() model constraints} to the
563
	 * converted model value.</li>
564
	 * <li>
565
	 * Applying all the {@link #beforeSetModelConstraints() before-set model
566
	 * constraints} to the converted model value.</li>
567
	 * </ul>
568
	 * 
569
	 * <p>
570
	 * The conversion process will be aborted by returning <code>null</code>
571
	 * whenever any of the applied validators produces a {@link IStatus
572
	 * validation status} having {@link IStatus#getSeverity() severity}
573
	 * <code>IStatus.ERROR</code> or <code>IStatus.CANCEL</code>. During the
574
	 * conversion process, any validation status whose severity is different
575
	 * from <code>IStatus.OK</code> will be {@link MultiStatus#merge(IStatus)
576
	 * aggregated} on the given <code>validationStatus</code>.
577
	 * </p>
578
	 * 
579
	 * @param targetValue
580
	 *            The target value to be converted to a model value.
581
	 * @param validationStatus
582
	 *            Aggregate validation status to which to add the validations
583
	 *            produced during the conversion process. May be
584
	 *            <code>null</code>.
585
	 * @return The converted model value or <code>null</code> in case the
586
	 *         conversion has been aborted due to a validation error.
587
	 */
588
	public final M convertToModel(T targetValue, MultiStatus validationStatus) {
589
		if (!applyConstraints(targetConstraints, targetValue, validationStatus)) {
590
			return null;
591
		}
592
593
		@SuppressWarnings("unchecked")
594
		M modelValue = (M) applyConverter(targetConverter, targetValue);
595
596
		if (!applyConstraints(modelConstraints, modelValue, validationStatus)) {
597
			return null;
598
		}
599
600
		if (!applyConstraints(beforeSetModelConstraints, modelValue,
601
				validationStatus)) {
602
			return null;
603
		}
604
605
		return modelValue;
606
	}
607
608
	/**
609
	 * {@link #setModelConverter(IConverter) Converts} a model value to a target
610
	 * value.
611
	 * 
612
	 * @param modelValue
613
	 *            The model value to be converted to a target value.
614
	 * @return The converted target value.
615
	 */
616
	@SuppressWarnings("unchecked")
617
	public final T convertToTarget(M modelValue) {
618
		return (T) applyConverter(modelConverter, modelValue);
619
	}
620
621
	/**
622
	 * Creates a binding between a target and model observable value on the
623
	 * given binding context by creating new update strategies which will be
624
	 * both configured with the state of this editing object before passing them
625
	 * to the binding.
626
	 * 
627
	 * <p>
628
	 * The target-to-model and model-to-target update strategies for the binding
629
	 * will be created by the methods {@link #createT2MValueStrategy()} and
630
	 * {@link #createM2TValueStrategy()}, respectively.
631
	 * </p>
632
	 * 
633
	 * @param dbc
634
	 *            The binding context on which to create the value binding.
635
	 * @param targetObservableValue
636
	 *            The target observable value of the binding.
637
	 * @param modelObservableValue
638
	 *            The model observable value of the binding.
639
	 * @return The new value binding.
640
	 * 
641
	 * @see #createT2MValueStrategy()
642
	 * @see #createM2TValueStrategy()
643
	 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
644
	 *      UpdateValueStrategy, UpdateValueStrategy)
645
	 */
646
	public final Binding bindValue(DataBindingContext dbc,
647
			IObservableValue targetObservableValue,
648
			IObservableValue modelObservableValue) {
649
		return dbc.bindValue(targetObservableValue, modelObservableValue,
650
				createT2MValueStrategy(), createM2TValueStrategy());
651
	}
652
653
	/**
654
	 * Creates a binding between a target and model observable value on the
655
	 * given binding context by creating new update strategies with the provided
656
	 * update policies which will be both configured with the state of this
657
	 * editing object before passing them to the binding.
658
	 * 
659
	 * @param dbc
660
	 *            The binding context on which to create the value binding.
661
	 * @param targetObservableValue
662
	 *            The target observable value of the binding.
663
	 * @param modelObservableValue
664
	 *            The model observable value of the binding.
665
	 * @param t2mUpdatePolicy
666
	 *            The update policy for the target-to-model
667
	 *            {@link UpdateValueStrategy} which is
668
	 *            {@link #createT2MValueStrategy(int) created} and passed to the
669
	 *            new binding.
670
	 * @param m2tUpdatePolicy
671
	 *            The update policy for the model-to-target
672
	 *            {@link UpdateValueStrategy} which is
673
	 *            {@link #createM2TValueStrategy(int) created} and passed to the
674
	 *            new binding.
675
	 * @return The new value binding.
676
	 * 
677
	 * @see #createT2MValueStrategy(int)
678
	 * @see #createM2TValueStrategy(int)
679
	 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
680
	 *      UpdateValueStrategy, UpdateValueStrategy)
681
	 */
682
	public final Binding bindValue(DataBindingContext dbc,
683
			IObservableValue targetObservableValue,
684
			IObservableValue modelObservableValue, int t2mUpdatePolicy,
685
			int m2tUpdatePolicy) {
686
		return dbc.bindValue(targetObservableValue, modelObservableValue,
687
				createT2MValueStrategy(t2mUpdatePolicy),
688
				createM2TValueStrategy(m2tUpdatePolicy));
689
	}
690
691
	/**
692
	 * Creates a binding between a target and model observable value on the
693
	 * given binding context by using the provided update strategies which will
694
	 * be both configured with the state of this editing object before passing
695
	 * them to the binding.
696
	 * 
697
	 * @param dbc
698
	 *            The binding context on which to create the value binding.
699
	 * @param targetObservableValue
700
	 *            The target observable value of the binding.
701
	 * @param modelObservableValue
702
	 *            The model observable value of the binding.
703
	 * @param t2mUpdateStrategy
704
	 *            The target-to-model {@link UpdateValueStrategy} of the binding
705
	 *            to be {@link #adaptT2MValueStrategy(UpdateValueStrategy)
706
	 *            configured} with the state of this editing object before
707
	 *            passing it to the binding.
708
	 * @param m2tUpdateStrategy
709
	 *            The model-to-target {@link UpdateValueStrategy} of the binding
710
	 *            to be {@link #adaptM2TValueStrategy(UpdateValueStrategy)
711
	 *            configured} with the state of this editing object before
712
	 *            passing it to the binding.
713
	 * @return The new value binding.
714
	 * 
715
	 * @see #adaptT2MValueStrategy(UpdateValueStrategy)
716
	 * @see #adaptM2TValueStrategy(UpdateValueStrategy)
717
	 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
718
	 *      UpdateValueStrategy, UpdateValueStrategy)
719
	 */
720
	public final Binding bindValue(DataBindingContext dbc,
721
			IObservableValue targetObservableValue,
722
			IObservableValue modelObservableValue,
723
			UpdateValueStrategy t2mUpdateStrategy,
724
			UpdateValueStrategy m2tUpdateStrategy) {
725
		return dbc.bindValue(targetObservableValue, modelObservableValue,
726
				adaptT2MValueStrategy(t2mUpdateStrategy),
727
				adaptM2TValueStrategy(m2tUpdateStrategy));
728
	}
729
730
	/**
731
	 * Creates a binding between a target and model observable list on the given
732
	 * binding context by creating new update strategies which will be both
733
	 * configured with the state of this editing object before passing them to
734
	 * the binding.
735
	 * 
736
	 * <p>
737
	 * The target-to-model and model-to-target update strategies for the binding
738
	 * will be created by the methods {@link #createT2MListStrategy()} and
739
	 * {@link #createM2TListStrategy()}, respectively.
740
	 * </p>
741
	 * 
742
	 * @param dbc
743
	 *            The binding context on which to create the list binding.
744
	 * @param targetObservableList
745
	 *            The target observable list of the binding.
746
	 * @param modelObservableList
747
	 *            The model observable list of the binding.
748
	 * @return The new list binding.
749
	 * 
750
	 * @see #createT2MListStrategy()
751
	 * @see #createM2TListStrategy()
752
	 * @see DataBindingContext#bindList(IObservableList, IObservableList,
753
	 *      UpdateListStrategy, UpdateListStrategy)
754
	 */
755
	public final Binding bindList(DataBindingContext dbc,
756
			IObservableList targetObservableList,
757
			IObservableList modelObservableList) {
758
		return dbc.bindList(targetObservableList, modelObservableList,
759
				createT2MListStrategy(), createM2TListStrategy());
760
	}
761
762
	/**
763
	 * Creates a binding between a target and model observable list on the given
764
	 * binding context by creating new update strategies with the provided
765
	 * update policies which will be both configured with the state of this
766
	 * editing object before passing them to the binding.
767
	 * 
768
	 * @param dbc
769
	 *            The binding context on which to create the list binding.
770
	 * @param targetObservableList
771
	 *            The target observable list of the binding.
772
	 * @param modelObservableList
773
	 *            The model observable list of the binding.
774
	 * @param t2mUpdatePolicy
775
	 *            The update policy for the target-to-model
776
	 *            {@link UpdateListStrategy} which is
777
	 *            {@link #createT2MListStrategy(int) created} and passed to the
778
	 *            new binding.
779
	 * @param m2tUpdatePolicy
780
	 *            The update policy for the model-to-target
781
	 *            {@link UpdateListStrategy} which is
782
	 *            {@link #createM2TListStrategy(int) created} and passed to the
783
	 *            new binding.
784
	 * @return The new list binding.
785
	 * 
786
	 * @see #createT2MListStrategy(int)
787
	 * @see #createM2TListStrategy(int)
788
	 * @see DataBindingContext#bindList(IObservableList, IObservableList,
789
	 *      UpdateListStrategy, UpdateListStrategy)
790
	 */
791
	public final Binding bindList(DataBindingContext dbc,
792
			IObservableList targetObservableList,
793
			IObservableList modelObservableList, int t2mUpdatePolicy,
794
			int m2tUpdatePolicy) {
795
		return dbc.bindList(targetObservableList, modelObservableList,
796
				createT2MListStrategy(t2mUpdatePolicy),
797
				createM2TListStrategy(m2tUpdatePolicy));
798
	}
799
800
	/**
801
	 * Creates a binding between a target and model observable list on the given
802
	 * binding context by using the provided update strategies which will be
803
	 * both configured with the state of this editing object before passing them
804
	 * to the binding.
805
	 * 
806
	 * @param dbc
807
	 *            The binding context on which to create the list binding.
808
	 * @param targetObservableList
809
	 *            The target observable list of the binding.
810
	 * @param modelObservableList
811
	 *            The model observable list of the binding.
812
	 * @param t2mUpdateStrategy
813
	 *            The target-to-model {@link UpdateListStrategy} of the binding
814
	 *            to be {@link #adaptT2MListStrategy(UpdateListStrategy)
815
	 *            configured} with the state of this editing object before
816
	 *            passing it to the binding.
817
	 * @param m2tUpdateStrategy
818
	 *            The model-to-target {@link UpdateListStrategy} of the binding
819
	 *            to be {@link #adaptM2TListStrategy(UpdateListStrategy)
820
	 *            configured} with the state of this editing object before
821
	 *            passing it to the binding.
822
	 * @return The new list binding.
823
	 * 
824
	 * @see #adaptT2MListStrategy(UpdateListStrategy)
825
	 * @see #adaptM2TListStrategy(UpdateListStrategy)
826
	 * @see DataBindingContext#bindList(IObservableList, IObservableList,
827
	 *      UpdateListStrategy, UpdateListStrategy)
828
	 */
829
	public final Binding bindList(DataBindingContext dbc,
830
			IObservableList targetObservableList,
831
			IObservableList modelObservableList,
832
			UpdateListStrategy t2mUpdateStrategy,
833
			UpdateListStrategy m2tUpdateStrategy) {
834
		return dbc.bindList(targetObservableList, modelObservableList,
835
				adaptT2MListStrategy(t2mUpdateStrategy),
836
				adaptM2TListStrategy(m2tUpdateStrategy));
837
	}
838
839
	/**
840
	 * Creates a binding between a target and model observable set on the given
841
	 * binding context by creating new update strategies which will be both
842
	 * configured with the state of this editing object before passing them to
843
	 * the binding.
844
	 * 
845
	 * <p>
846
	 * The target-to-model and model-to-target update strategies for the binding
847
	 * will be created by the methods {@link #createT2MSetStrategy()} and
848
	 * {@link #createM2TSetStrategy()}, respectively.
849
	 * </p>
850
	 * 
851
	 * @param dbc
852
	 *            The binding context on which to create the set binding.
853
	 * @param targetObservableSet
854
	 *            The target observable set of the binding.
855
	 * @param modelObservableSet
856
	 *            The model observable set of the binding.
857
	 * @return The new set binding.
858
	 * 
859
	 * @see #createT2MSetStrategy()
860
	 * @see #createM2TSetStrategy()
861
	 * @see DataBindingContext#bindSet(IObservableSet, IObservableSet,
862
	 *      UpdateSetStrategy, UpdateSetStrategy)
863
	 */
864
	public final Binding bindSet(DataBindingContext dbc,
865
			IObservableSet targetObservableSet,
866
			IObservableSet modelObservableSet) {
867
		return dbc.bindSet(targetObservableSet, modelObservableSet,
868
				createT2MSetStrategy(), createM2TSetStrategy());
869
	}
870
871
	/**
872
	 * Creates a binding between a target and model observable set on the given
873
	 * binding context by creating new update strategies with the provided
874
	 * update policies which will be both configured with the state of this
875
	 * editing object before passing them to the binding.
876
	 * 
877
	 * @param dbc
878
	 *            The binding context on which to create the set binding.
879
	 * @param targetObservableSet
880
	 *            The target observable set of the binding.
881
	 * @param modelObservableSet
882
	 *            The model observable set of the binding.
883
	 * @param t2mUpdatePolicy
884
	 *            The update policy for the target-to-model
885
	 *            {@link UpdateSetStrategy} which is
886
	 *            {@link #createT2MSetStrategy(int) created} and passed to the
887
	 *            new binding.
888
	 * @param m2tUpdatePolicy
889
	 *            The update policy for the model-to-target
890
	 *            {@link UpdateSetStrategy} which is
891
	 *            {@link #createM2TSetStrategy(int) created} and passed to the
892
	 *            new binding.
893
	 * @return The new set binding.
894
	 * 
895
	 * @see #createT2MSetStrategy(int)
896
	 * @see #createM2TSetStrategy(int)
897
	 * @see DataBindingContext#bindSet(IObservableSet, IObservableSet,
898
	 *      UpdateSetStrategy, UpdateSetStrategy)
899
	 */
900
	public final Binding bindSet(DataBindingContext dbc,
901
			IObservableSet targetObservableSet,
902
			IObservableSet modelObservableSet, int t2mUpdatePolicy,
903
			int m2tUpdatePolicy) {
904
		return dbc.bindSet(targetObservableSet, modelObservableSet,
905
				createT2MSetStrategy(t2mUpdatePolicy),
906
				createM2TSetStrategy(m2tUpdatePolicy));
907
	}
908
909
	/**
910
	 * Creates a binding between a target and model observable set on the given
911
	 * binding context by using the provided update strategies which will be
912
	 * both configured with the state of this editing object before passing them
913
	 * to the binding.
914
	 * 
915
	 * @param dbc
916
	 *            The binding context on which to create the set binding.
917
	 * @param targetObservableSet
918
	 *            The target observable set of the binding.
919
	 * @param modelObservableSet
920
	 *            The model observable set of the binding.
921
	 * @param t2mUpdateStrategy
922
	 *            The target-to-model {@link UpdateSetStrategy} of the binding
923
	 *            to be {@link #adaptT2MSetStrategy(UpdateSetStrategy)
924
	 *            configured} with the state of this editing object before
925
	 *            passing it to the binding.
926
	 * @param m2tUpdateStrategy
927
	 *            The model-to-target {@link UpdateSetStrategy} of the binding
928
	 *            to be {@link #adaptM2TSetStrategy(UpdateSetStrategy)
929
	 *            configured} with the state of this editing object before
930
	 *            passing it to the binding.
931
	 * @return The new set binding.
932
	 * 
933
	 * @see #adaptT2MSetStrategy(UpdateSetStrategy)
934
	 * @see #adaptM2TSetStrategy(UpdateSetStrategy)
935
	 * @see DataBindingContext#bindSet(IObservableSet, IObservableSet,
936
	 *      UpdateSetStrategy, UpdateSetStrategy)
937
	 */
938
	public final Binding bindSet(DataBindingContext dbc,
939
			IObservableSet targetObservableSet,
940
			IObservableSet modelObservableSet,
941
			UpdateSetStrategy t2mUpdateStrategy,
942
			UpdateSetStrategy m2tUpdateStrategy) {
943
		return dbc.bindSet(targetObservableSet, modelObservableSet,
944
				adaptT2MSetStrategy(t2mUpdateStrategy),
945
				adaptM2TSetStrategy(m2tUpdateStrategy));
946
	}
947
948
	private static IValidator createValidator(Constraints<?> constraints) {
949
		return constraints != null ? constraints.createValidator() : null;
950
	}
951
952
	private static boolean applyConstraints(Constraints<?> constraints,
953
			Object value, MultiStatus aggregateStatus) {
954
		IValidator validator = createValidator(constraints);
955
		if (validator != null) {
956
			IStatus validationStatus = validator.validate(value);
957
			if (aggregateStatus != null && !validationStatus.isOK()) {
958
				aggregateStatus.merge(validationStatus);
959
			}
960
			return isValid(validationStatus);
961
		}
962
		return true;
963
	}
964
965
	private static Object applyConverter(IConverter converter, Object value) {
966
		return converter != null ? converter.convert(value) : value;
967
	}
968
969
	private static boolean isValid(IStatus status) {
970
		return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING);
971
	}
972
}
(-)src/org/eclipse/core/databinding/editing/NumberEditing.java (+762 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.databinding.conversion.NumberToStringConverter;
18
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
19
import org.eclipse.core.databinding.validation.constraint.NumberConstraints;
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
import org.eclipse.core.internal.databinding.validation.StringToBigIntegerValidator;
24
import org.eclipse.core.internal.databinding.validation.StringToByteValidator;
25
import org.eclipse.core.internal.databinding.validation.StringToDoubleValidator;
26
import org.eclipse.core.internal.databinding.validation.StringToFloatValidator;
27
import org.eclipse.core.internal.databinding.validation.StringToIntegerValidator;
28
import org.eclipse.core.internal.databinding.validation.StringToLongValidator;
29
import org.eclipse.core.internal.databinding.validation.StringToShortValidator;
30
31
import com.ibm.icu.text.NumberFormat;
32
33
/**
34
 * @param <N>
35
 * 
36
 * @noextend This class is not intended to be subclassed by clients.
37
 * @since 1.4
38
 */
39
public class NumberEditing<N extends Number & Comparable<N>> extends
40
		Editing<String, N> {
41
42
	private final NumberFormat displayFormat;
43
44
	private final Class<N> numberType;
45
46
	/**
47
	 * Creates a new editing object for integer numbers.
48
	 * 
49
	 * @param format
50
	 *            The integer format defining the validations and conversions
51
	 *            used for editing.
52
	 * @param parseErrorMessage
53
	 *            The validation message issued in case the input string cannot
54
	 *            be parsed to an integer.
55
	 * @param outOfRangeMessage
56
	 *            The validation message issued in case the input string
57
	 *            represents an integer whose value is out of range.
58
	 * @param numberType
59
	 *            The specific integer type for which to set up an editing
60
	 *            instance.
61
	 * 
62
	 * @noreference This constructor is not intended to be referenced by
63
	 *              clients.
64
	 */
65
	protected NumberEditing(NumberFormat format, String parseErrorMessage,
66
			String outOfRangeMessage, Class<N> numberType) {
67
		this.displayFormat = format;
68
		this.numberType = numberType;
69
70
		final StringToNumberConverter targetConverter;
71
		final NumberToStringConverter modelConverter;
72
		final AbstractStringToNumberValidator targetValidator;
73
		if (Long.class.equals(numberType)) {
74
			targetConverter = StringToNumberConverter.toLong(format, false);
75
			modelConverter = NumberToStringConverter.fromLong(format, false);
76
			targetValidator = new StringToLongValidator(targetConverter);
77
		} else if (Integer.class.equals(numberType)) {
78
			targetConverter = StringToNumberConverter.toInteger(format, false);
79
			modelConverter = NumberToStringConverter.fromInteger(format, false);
80
			targetValidator = new StringToIntegerValidator(targetConverter);
81
		} else if (Short.class.equals(numberType)) {
82
			targetConverter = StringToNumberConverter.toShort(format, false);
83
			modelConverter = NumberToStringConverter.fromShort(format, false);
84
			targetValidator = new StringToShortValidator(targetConverter);
85
		} else if (Byte.class.equals(numberType)) {
86
			targetConverter = StringToNumberConverter.toByte(format, false);
87
			modelConverter = NumberToStringConverter.fromByte(format, false);
88
			targetValidator = new StringToByteValidator(targetConverter);
89
		} else if (Double.class.equals(numberType)) {
90
			targetConverter = StringToNumberConverter.toDouble(format, false);
91
			modelConverter = NumberToStringConverter.fromDouble(format, false);
92
			targetValidator = new StringToDoubleValidator(targetConverter);
93
		} else if (Float.class.equals(numberType)) {
94
			targetConverter = StringToNumberConverter.toFloat(format, false);
95
			modelConverter = NumberToStringConverter.fromFloat(format, false);
96
			targetValidator = new StringToFloatValidator(targetConverter);
97
		} else if (BigInteger.class.equals(numberType)) {
98
			targetConverter = StringToNumberConverter.toBigInteger(format);
99
			modelConverter = NumberToStringConverter.fromBigInteger(format);
100
			targetValidator = new StringToBigIntegerValidator(targetConverter);
101
		} else if (BigDecimal.class.equals(numberType)) {
102
			targetConverter = StringToNumberConverter.toBigDecimal(format);
103
			modelConverter = NumberToStringConverter.fromBigDecimal(format);
104
			targetValidator = new StringToBigDecimalValidator(targetConverter);
105
		} else {
106
			throw new IllegalArgumentException(
107
					"Unsupported number type: " + numberType); //$NON-NLS-1$
108
		}
109
110
		if (parseErrorMessage != null) {
111
			targetValidator.setParseErrorMessage(parseErrorMessage);
112
		}
113
		if (outOfRangeMessage != null) {
114
			targetValidator.setOutOfRangeMessage(outOfRangeMessage);
115
		}
116
117
		setTargetConverter(targetConverter);
118
		setModelConverter(modelConverter);
119
		targetConstraints().addValidator(targetValidator);
120
	}
121
122
	/**
123
	 * Creates a new editing object for {@link Long}s which defaults the
124
	 * validations and conversions used for editing based on the platform's
125
	 * locale. Uses the default validation messages.
126
	 * 
127
	 * @return The new editing object using the default validations and
128
	 *         conversions for editing.
129
	 * 
130
	 * @see NumberFormat#getIntegerInstance()
131
	 */
132
	public static NumberEditing<Long> withLongDefaults() {
133
		return withLongDefaults(null, null);
134
	}
135
136
	/**
137
	 * Creates a new editing object for {@link Long}s which defaults the
138
	 * validations and conversions used for editing based on the platform's
139
	 * locale. Uses the specified custom validation messages.
140
	 * 
141
	 * @param parseErrorMessage
142
	 *            The validation message issued in case the input string cannot
143
	 *            be parsed to an integer.
144
	 * @param outOfRangeMessage
145
	 *            The validation message issued in case the input string
146
	 *            represents an integer whose value is out of range. Can be
147
	 *            parameterized by the <code>Long.MIN_VALUE</code> ({0}) and
148
	 *            <code>Long.MAX_VALUE</code> ({1}) values.
149
	 * @return The new editing object using the default validations and
150
	 *         conversions for editing.
151
	 * 
152
	 * @see NumberFormat#getIntegerInstance()
153
	 */
154
	public static NumberEditing<Long> withLongDefaults(
155
			String parseErrorMessage, String outOfRangeMessage) {
156
		return new NumberEditing<Long>(NumberFormat.getIntegerInstance(),
157
				parseErrorMessage, outOfRangeMessage, Long.class);
158
	}
159
160
	/**
161
	 * Creates a new editing object for {@link Long}s whose validations and
162
	 * conversions used for editing are based on the given integer format. Uses
163
	 * the default validation messages.
164
	 * 
165
	 * @param format
166
	 *            The integer format defining the validations and conversions
167
	 *            used for editing.
168
	 * @return The new editing object configured by the given integer format.
169
	 */
170
	public static NumberEditing<Long> forLongFormat(NumberFormat format) {
171
		return forLongFormat(format, null, null);
172
	}
173
174
	/**
175
	 * Creates a new editing object for {@link Long}s whose validations and
176
	 * conversions used for editing are based on the given integer format. Uses
177
	 * the specified custom validation messages.
178
	 * 
179
	 * @param format
180
	 *            The integer format defining the validations and conversions
181
	 *            used for editing.
182
	 * @param parseErrorMessage
183
	 *            The validation message issued in case the input string cannot
184
	 *            be parsed to an integer.
185
	 * @param outOfRangeMessage
186
	 *            The validation message issued in case the input string
187
	 *            represents an integer whose value is out of range. Can be
188
	 *            parameterized by the <code>Long.MIN_VALUE</code> ({0}) and
189
	 *            <code>Long.MAX_VALUE</code> ({1}) values.
190
	 * @return The new editing object configured by the given integer format.
191
	 */
192
	public static NumberEditing<Long> forLongFormat(NumberFormat format,
193
			String parseErrorMessage, String outOfRangeMessage) {
194
		return new NumberEditing<Long>(format, parseErrorMessage,
195
				outOfRangeMessage, Long.class);
196
	}
197
198
	/**
199
	 * Creates a new editing object for {@link Integer}s which defaults the
200
	 * validations and conversions used for editing based on the platform's
201
	 * locale. Uses the default validation messages.
202
	 * 
203
	 * @return The new editing object using the default validations and
204
	 *         conversions for editing.
205
	 * 
206
	 * @see NumberFormat#getIntegerInstance()
207
	 */
208
	public static NumberEditing<Integer> withIntegerDefaults() {
209
		return withIntegerDefaults(null, null);
210
	}
211
212
	/**
213
	 * Creates a new editing object for {@link Integer}s which defaults the
214
	 * validations and conversions used for editing based on the platform's
215
	 * locale. Uses the specified custom validation messages.
216
	 * 
217
	 * @param parseErrorMessage
218
	 *            The validation message issued in case the input string cannot
219
	 *            be parsed to an integer.
220
	 * @param outOfRangeMessage
221
	 *            The validation message issued in case the input string
222
	 *            represents an integer whose value is out of range. Can be
223
	 *            parameterized by the <code>Integer.MIN_VALUE</code> ({0}) and
224
	 *            <code>Integer.MAX_VALUE</code> ({1}) values.
225
	 * @return The new editing object using the default validations and
226
	 *         conversions for editing.
227
	 * 
228
	 * @see NumberFormat#getIntegerInstance()
229
	 */
230
	public static NumberEditing<Integer> withIntegerDefaults(
231
			String parseErrorMessage, String outOfRangeMessage) {
232
		return new NumberEditing<Integer>(NumberFormat.getIntegerInstance(),
233
				parseErrorMessage, outOfRangeMessage, Integer.class);
234
	}
235
236
	/**
237
	 * Creates a new editing object for {@link Integer}s whose validations and
238
	 * conversions used for editing are based on the given integer format. Uses
239
	 * the default validation messages.
240
	 * 
241
	 * @param format
242
	 *            The integer format defining the validations and conversions
243
	 *            used for editing.
244
	 * @return The new editing object configured by the given integer format.
245
	 */
246
	public static NumberEditing<Integer> forIntegerFormat(NumberFormat format) {
247
		return forIntegerFormat(format, null, null);
248
	}
249
250
	/**
251
	 * Creates a new editing object for {@link Integer}s whose validations and
252
	 * conversions used for editing are based on the given integer format. Uses
253
	 * the specified custom validation messages.
254
	 * 
255
	 * @param format
256
	 *            The integer format defining the validations and conversions
257
	 *            used for editing.
258
	 * @param parseErrorMessage
259
	 *            The validation message issued in case the input string cannot
260
	 *            be parsed to an integer.
261
	 * @param outOfRangeMessage
262
	 *            The validation message issued in case the input string
263
	 *            represents an integer whose value is out of range. Can be
264
	 *            parameterized by the <code>Integer.MIN_VALUE</code> ({0}) and
265
	 *            <code>Integer.MAX_VALUE</code> ({1}) values.
266
	 * @return The new editing object configured by the given integer format.
267
	 */
268
	public static NumberEditing<Integer> forIntegerFormat(NumberFormat format,
269
			String parseErrorMessage, String outOfRangeMessage) {
270
		return new NumberEditing<Integer>(format, parseErrorMessage,
271
				outOfRangeMessage, Integer.class);
272
	}
273
274
	/**
275
	 * Creates a new editing object for {@link Short}s which defaults the
276
	 * validations and conversions used for editing based on the platform's
277
	 * locale. Uses the default validation messages.
278
	 * 
279
	 * @return The new editing object using the default validations and
280
	 *         conversions for editing.
281
	 * 
282
	 * @see NumberFormat#getIntegerInstance()
283
	 */
284
	public static NumberEditing<Short> withShortDefaults() {
285
		return withShortDefaults(null, null);
286
	}
287
288
	/**
289
	 * Creates a new editing object for {@link Short}s which defaults the
290
	 * validations and conversions used for editing based on the platform's
291
	 * locale. Uses the specified custom validation messages.
292
	 * 
293
	 * @param parseErrorMessage
294
	 *            The validation message issued in case the input string cannot
295
	 *            be parsed to an integer.
296
	 * @param outOfRangeMessage
297
	 *            The validation message issued in case the input string
298
	 *            represents an integer whose value is out of range. Can be
299
	 *            parameterized by the <code>Short.MIN_VALUE</code> ({0}) and
300
	 *            <code>Short.MAX_VALUE</code> ({1}) values.
301
	 * @return The new editing object using the default validations and
302
	 *         conversions for editing.
303
	 * 
304
	 * @see NumberFormat#getIntegerInstance()
305
	 */
306
	public static NumberEditing<Short> withShortDefaults(
307
			String parseErrorMessage, String outOfRangeMessage) {
308
		return new NumberEditing<Short>(NumberFormat.getIntegerInstance(),
309
				parseErrorMessage, outOfRangeMessage, Short.class);
310
	}
311
312
	/**
313
	 * Creates a new editing object for {@link Short}s whose validations and
314
	 * conversions used for editing are based on the given integer format. Uses
315
	 * the default validation messages.
316
	 * 
317
	 * @param format
318
	 *            The integer format defining the validations and conversions
319
	 *            used for editing.
320
	 * @return The new editing object configured by the given integer format.
321
	 */
322
	public static NumberEditing<Short> forShortFormat(NumberFormat format) {
323
		return forShortFormat(format, null, null);
324
	}
325
326
	/**
327
	 * Creates a new editing object for {@link Short}s whose validations and
328
	 * conversions used for editing are based on the given integer format. Uses
329
	 * the specified custom validation messages.
330
	 * 
331
	 * @param format
332
	 *            The integer format defining the validations and conversions
333
	 *            used for editing.
334
	 * @param parseErrorMessage
335
	 *            The validation message issued in case the input string cannot
336
	 *            be parsed to an integer.
337
	 * @param outOfRangeMessage
338
	 *            The validation message issued in case the input string
339
	 *            represents an integer whose value is out of range. Can be
340
	 *            parameterized by the <code>Short.MIN_VALUE</code> ({0}) and
341
	 *            <code>Short.MAX_VALUE</code> ({1}) values.
342
	 * @return The new editing object configured by the given integer format.
343
	 */
344
	public static NumberEditing<Short> forShortFormat(NumberFormat format,
345
			String parseErrorMessage, String outOfRangeMessage) {
346
		return new NumberEditing<Short>(format, parseErrorMessage,
347
				outOfRangeMessage, Short.class);
348
	}
349
350
	/**
351
	 * Creates a new editing object for {@link Byte}s which defaults the
352
	 * validations and conversions used for editing based on the platform's
353
	 * locale. Uses the default validation messages.
354
	 * 
355
	 * @return The new editing object using the default validations and
356
	 *         conversions for editing.
357
	 * 
358
	 * @see NumberFormat#getIntegerInstance()
359
	 */
360
	public static NumberEditing<Byte> withByteDefaults() {
361
		return withByteDefaults(null, null);
362
	}
363
364
	/**
365
	 * Creates a new editing object for {@link Byte}s which defaults the
366
	 * validations and conversions used for editing based on the platform's
367
	 * locale. Uses the specified custom validation messages.
368
	 * 
369
	 * @param parseErrorMessage
370
	 *            The validation message issued in case the input string cannot
371
	 *            be parsed to an integer.
372
	 * @param outOfRangeMessage
373
	 *            The validation message issued in case the input string
374
	 *            represents an integer whose value is out of range. Can be
375
	 *            parameterized by the <code>Byte.MIN_VALUE</code> ({0}) and
376
	 *            <code>Byte.MAX_VALUE</code> ({1}) values.
377
	 * @return The new editing object using the default validations and
378
	 *         conversions for editing.
379
	 * 
380
	 * @see NumberFormat#getIntegerInstance()
381
	 */
382
	public static NumberEditing<Byte> withByteDefaults(
383
			String parseErrorMessage, String outOfRangeMessage) {
384
		return new NumberEditing<Byte>(NumberFormat.getIntegerInstance(),
385
				parseErrorMessage, outOfRangeMessage, Byte.class);
386
	}
387
388
	/**
389
	 * Creates a new editing object for {@link Byte}s whose validations and
390
	 * conversions used for editing are based on the given integer format. Uses
391
	 * the default validation messages.
392
	 * 
393
	 * @param format
394
	 *            The integer format defining the validations and conversions
395
	 *            used for editing.
396
	 * @return The new editing object configured by the given integer format.
397
	 */
398
	public static NumberEditing<Byte> forByteFormat(NumberFormat format) {
399
		return forByteFormat(format, null, null);
400
	}
401
402
	/**
403
	 * Creates a new editing object for {@link Byte}s whose validations and
404
	 * conversions used for editing are based on the given integer format. Uses
405
	 * the specified custom validation messages.
406
	 * 
407
	 * @param format
408
	 *            The integer format defining the validations and conversions
409
	 *            used for editing.
410
	 * @param parseErrorMessage
411
	 *            The validation message issued in case the input string cannot
412
	 *            be parsed to an integer.
413
	 * @param outOfRangeMessage
414
	 *            The validation message issued in case the input string
415
	 *            represents an integer whose value is out of range. Can be
416
	 *            parameterized by the <code>Byte.MIN_VALUE</code> ({0}) and
417
	 *            <code>Byte.MAX_VALUE</code> ({1}) values.
418
	 * @return The new editing object configured by the given integer format.
419
	 */
420
	public static NumberEditing<Byte> forByteFormat(NumberFormat format,
421
			String parseErrorMessage, String outOfRangeMessage) {
422
		return new NumberEditing<Byte>(format, parseErrorMessage,
423
				outOfRangeMessage, Byte.class);
424
	}
425
426
	/**
427
	 * Creates a new editing object for {@link Double}s which defaults the
428
	 * validations and conversions used for editing based on the platform's
429
	 * locale. Uses the default validation messages.
430
	 * 
431
	 * @return The new editing object using the default validations and
432
	 *         conversions for editing.
433
	 * 
434
	 * @see NumberFormat#getNumberInstance()
435
	 */
436
	public static NumberEditing<Double> withDoubleDefaults() {
437
		return withDoubleDefaults(null, null);
438
	}
439
440
	/**
441
	 * Creates a new editing object for {@link Double}s which defaults the
442
	 * validations and conversions used for editing based on the platform's
443
	 * locale. Uses the specified custom validation messages.
444
	 * 
445
	 * @param parseErrorMessage
446
	 *            The validation message issued in case the input string cannot
447
	 *            be parsed to a double.
448
	 * @param outOfRangeMessage
449
	 *            The validation message issued in case the input string
450
	 *            represents a double whose value is out of range. Can be
451
	 *            parameterized by the <code>-Double.MAX_VALUE</code> ({0}) and
452
	 *            <code>+Double.MAX_VALUE</code> ({1}) values.
453
	 * @return The new editing object using the default validations and
454
	 *         conversions for editing.
455
	 * 
456
	 * @see NumberFormat#getNumberInstance()
457
	 */
458
	public static NumberEditing<Double> withDoubleDefaults(
459
			String parseErrorMessage, String outOfRangeMessage) {
460
		return new NumberEditing<Double>(NumberFormat.getNumberInstance(),
461
				parseErrorMessage, outOfRangeMessage, Double.class);
462
	}
463
464
	/**
465
	 * Creates a new editing object for {@link Double}s whose validations and
466
	 * conversions used for editing are based on the given number format. Uses
467
	 * the default validation messages.
468
	 * 
469
	 * @param format
470
	 *            The number format defining the validations and conversions
471
	 *            used for editing.
472
	 * @return The new editing object configured by the given number format.
473
	 */
474
	public static NumberEditing<Double> forDoubleFormat(NumberFormat format) {
475
		return forDoubleFormat(format, null, null);
476
	}
477
478
	/**
479
	 * Creates a new editing object for {@link Double}s whose validations and
480
	 * conversions used for editing are based on the given number format. Uses
481
	 * the specified custom validation messages.
482
	 * 
483
	 * @param format
484
	 *            The number format defining the validations and conversions
485
	 *            used for editing.
486
	 * @param parseErrorMessage
487
	 *            The validation message issued in case the input string cannot
488
	 *            be parsed to a double.
489
	 * @param outOfRangeMessage
490
	 *            The validation message issued in case the input string
491
	 *            represents a double whose value is out of range. Can be
492
	 *            parameterized by the <code>-Double.MAX_VALUE</code> ({0}) and
493
	 *            <code>+Double.MAX_VALUE</code> ({1}) values.
494
	 * @return The new editing object configured by the given number format.
495
	 */
496
	public static NumberEditing<Double> forDoubleFormat(NumberFormat format,
497
			String parseErrorMessage, String outOfRangeMessage) {
498
		return new NumberEditing<Double>(format, parseErrorMessage,
499
				outOfRangeMessage, Double.class);
500
	}
501
502
	/**
503
	 * Creates a new editing object for {@link Float}s which defaults the
504
	 * validations and conversions used for editing based on the platform's
505
	 * locale. Uses the default validation messages.
506
	 * 
507
	 * @return The new editing object using the default validations and
508
	 *         conversions for editing.
509
	 * 
510
	 * @see NumberFormat#getNumberInstance()
511
	 */
512
	public static NumberEditing<Float> withFloatDefaults() {
513
		return withFloatDefaults(null, null);
514
	}
515
516
	/**
517
	 * Creates a new editing object for {@link Float}s which defaults the
518
	 * validations and conversions used for editing based on the platform's
519
	 * locale. Uses the specified custom validation messages.
520
	 * 
521
	 * @param parseErrorMessage
522
	 *            The validation message issued in case the input string cannot
523
	 *            be parsed to a double.
524
	 * @param outOfRangeMessage
525
	 *            The validation message issued in case the input string
526
	 *            represents a float whose value is out of range. Can be
527
	 *            parameterized by the <code>-Float.MAX_VALUE</code> ({0}) and
528
	 *            <code>+Float.MAX_VALUE</code> ({1}) values.
529
	 * @return The new editing object using the default validations and
530
	 *         conversions for editing.
531
	 * 
532
	 * @see NumberFormat#getNumberInstance()
533
	 */
534
	public static NumberEditing<Float> withFloatDefaults(
535
			String parseErrorMessage, String outOfRangeMessage) {
536
		return new NumberEditing<Float>(NumberFormat.getNumberInstance(),
537
				parseErrorMessage, outOfRangeMessage, Float.class);
538
	}
539
540
	/**
541
	 * Creates a new editing object for {@link Float}s whose validations and
542
	 * conversions used for editing are based on the given number format. Uses
543
	 * the default validation messages.
544
	 * 
545
	 * @param format
546
	 *            The number format defining the validations and conversions
547
	 *            used for editing.
548
	 * @return The new editing object configured by the given number format.
549
	 */
550
	public static NumberEditing<Float> forFloatFormat(NumberFormat format) {
551
		return forFloatFormat(format, null, null);
552
	}
553
554
	/**
555
	 * Creates a new editing object for {@link Float}s whose validations and
556
	 * conversions used for editing are based on the given number format. Uses
557
	 * the specified custom validation messages.
558
	 * 
559
	 * @param format
560
	 *            The number format defining the validations and conversions
561
	 *            used for editing.
562
	 * @param parseErrorMessage
563
	 *            The validation message issued in case the input string cannot
564
	 *            be parsed to a float.
565
	 * @param outOfRangeMessage
566
	 *            The validation message issued in case the input string
567
	 *            represents a float whose value is out of range. Can be
568
	 *            parameterized by the <code>-Float.MAX_VALUE</code> ({0}) and
569
	 *            <code>+Float.MAX_VALUE</code> ({1}) values.
570
	 * @return The new editing object configured by the given number format.
571
	 */
572
	public static NumberEditing<Float> forFloatFormat(NumberFormat format,
573
			String parseErrorMessage, String outOfRangeMessage) {
574
		return new NumberEditing<Float>(format, parseErrorMessage,
575
				outOfRangeMessage, Float.class);
576
	}
577
578
	/**
579
	 * Creates a new editing object for {@link BigInteger}s which defaults the
580
	 * validations and conversions used for editing based on the platform's
581
	 * locale. Uses the default validation messages.
582
	 * 
583
	 * @return The new editing object using the default validations and
584
	 *         conversions for editing.
585
	 * 
586
	 * @see NumberFormat#getIntegerInstance()
587
	 */
588
	public static NumberEditing<BigInteger> withBigIntegerDefaults() {
589
		return withBigIntegerDefaults(null);
590
	}
591
592
	/**
593
	 * Creates a new editing object for {@link BigInteger}s which defaults the
594
	 * validations and conversions used for editing based on the platform's
595
	 * locale. Uses the specified custom validation message.
596
	 * 
597
	 * @param parseErrorMessage
598
	 *            The validation message issued in case the input string cannot
599
	 *            be parsed to a BigInteger.
600
	 * @return The new editing object using the default validations and
601
	 *         conversions for editing.
602
	 * 
603
	 * @see NumberFormat#getIntegerInstance()
604
	 */
605
	public static NumberEditing<BigInteger> withBigIntegerDefaults(
606
			String parseErrorMessage) {
607
		return new NumberEditing<BigInteger>(NumberFormat.getIntegerInstance(),
608
				parseErrorMessage, null, BigInteger.class);
609
	}
610
611
	/**
612
	 * Creates a new editing object for {@link BigInteger}s whose validations
613
	 * and conversions used for editing are based on the given BigInteger
614
	 * format. Uses the default validation messages.
615
	 * 
616
	 * @param format
617
	 *            The BigInteger format defining the validations and conversions
618
	 *            used for editing.
619
	 * @return The new editing object configured by the given BigInteger format.
620
	 */
621
	public static NumberEditing<BigInteger> forBigIntegerFormat(
622
			NumberFormat format) {
623
		return forBigIntegerFormat(format, null);
624
	}
625
626
	/**
627
	 * Creates a new editing object for {@link BigInteger}s whose validations
628
	 * and conversions used for editing are based on the given BigInteger
629
	 * format. Uses the specified custom validation message.
630
	 * 
631
	 * @param format
632
	 *            The BigInteger format defining the validations and conversions
633
	 *            used for editing.
634
	 * @param parseErrorMessage
635
	 *            The validation message issued in case the input string cannot
636
	 *            be parsed to a BigInteger.
637
	 * @return The new editing object configured by the given BigInteger format.
638
	 */
639
	public static NumberEditing<BigInteger> forBigIntegerFormat(
640
			NumberFormat format, String parseErrorMessage) {
641
		return new NumberEditing<BigInteger>(format, parseErrorMessage, null,
642
				BigInteger.class);
643
	}
644
645
	/**
646
	 * Creates a new editing object for {@link BigDecimal}s which defaults the
647
	 * validations and conversions used for editing based on the platform's
648
	 * locale. Uses the default validation messages.
649
	 * 
650
	 * @return The new editing object using the default validations and
651
	 *         conversions for editing.
652
	 * 
653
	 * @see NumberFormat#getNumberInstance()
654
	 */
655
	public static NumberEditing<BigDecimal> withBigDecimalDefaults() {
656
		return withBigDecimalDefaults(null);
657
	}
658
659
	/**
660
	 * Creates a new editing object for {@link BigDecimal}s which defaults the
661
	 * validations and conversions used for editing based on the platform's
662
	 * locale. Uses the specified custom validation message.
663
	 * 
664
	 * @param parseErrorMessage
665
	 *            The validation message issued in case the input string cannot
666
	 *            be parsed to a BigDecimal.
667
	 * @return The new editing object using the default validations and
668
	 *         conversions for editing.
669
	 * 
670
	 * @see NumberFormat#getNumberInstance()
671
	 */
672
	public static NumberEditing<BigDecimal> withBigDecimalDefaults(
673
			String parseErrorMessage) {
674
		return new NumberEditing<BigDecimal>(NumberFormat.getNumberInstance(),
675
				parseErrorMessage, null, BigDecimal.class);
676
	}
677
678
	/**
679
	 * Creates a new editing object for {@link BigDecimal}s whose validations
680
	 * and conversions used for editing are based on the given BigDecimal
681
	 * format. Uses the default validation messages.
682
	 * 
683
	 * @param format
684
	 *            The BigDecimal format defining the validations and conversions
685
	 *            used for editing.
686
	 * @return The new editing object configured by the given BigDecimal format.
687
	 */
688
	public static NumberEditing<BigDecimal> forBigDecimalFormat(
689
			NumberFormat format) {
690
		return forBigDecimalFormat(format, null);
691
	}
692
693
	/**
694
	 * Creates a new editing object for {@link BigDecimal}s whose validations
695
	 * and conversions used for editing are based on the given BigDecimal
696
	 * format. Uses the specified custom validation message.
697
	 * 
698
	 * @param format
699
	 *            The BigDecimal format defining the validations and conversions
700
	 *            used for editing.
701
	 * @param parseErrorMessage
702
	 *            The validation message issued in case the input string cannot
703
	 *            be parsed to a BigDecimal.
704
	 * @return The new editing object configured by the given BigDecimal format.
705
	 */
706
	public static NumberEditing<BigDecimal> forBigDecimalFormat(
707
			NumberFormat format, String parseErrorMessage) {
708
		return new NumberEditing<BigDecimal>(format, parseErrorMessage, null,
709
				BigDecimal.class);
710
	}
711
712
	public StringConstraints targetConstraints() {
713
		return (StringConstraints) super.targetConstraints();
714
	}
715
716
	public NumberConstraints<N> modelConstraints() {
717
		return (NumberConstraints<N>) super.modelConstraints();
718
	}
719
720
	public NumberConstraints<N> beforeSetModelConstraints() {
721
		return (NumberConstraints<N>) super.beforeSetModelConstraints();
722
	}
723
724
	protected StringConstraints createTargetConstraints() {
725
		return new StringConstraints();
726
	}
727
728
	@SuppressWarnings("unchecked")
729
	protected NumberConstraints<N> createModelConstraints() {
730
		return (NumberConstraints<N>) createModelConstraints(numberType)
731
				.numberFormat(displayFormat);
732
	}
733
734
	@SuppressWarnings("unchecked")
735
	protected NumberConstraints<N> createBeforeSetModelConstraints() {
736
		return (NumberConstraints<N>) createModelConstraints(numberType)
737
				.numberFormat(displayFormat);
738
	}
739
740
	private NumberConstraints<?> createModelConstraints(Class<N> numberType) {
741
		if (Long.class.equals(numberType)) {
742
			return NumberConstraints.forLong();
743
		} else if (Integer.class.equals(numberType)) {
744
			return NumberConstraints.forInteger();
745
		} else if (Short.class.equals(numberType)) {
746
			return NumberConstraints.forShort();
747
		} else if (Byte.class.equals(numberType)) {
748
			return NumberConstraints.forByte();
749
		} else if (Double.class.equals(numberType)) {
750
			return NumberConstraints.forDouble();
751
		} else if (Float.class.equals(numberType)) {
752
			return NumberConstraints.forFloat();
753
		} else if (BigInteger.class.equals(numberType)) {
754
			return NumberConstraints.forBigInteger();
755
		} else if (BigDecimal.class.equals(numberType)) {
756
			return NumberConstraints.forBigDecimal();
757
		} else {
758
			throw new IllegalArgumentException(
759
					"Unsupported number type: " + numberType); //$NON-NLS-1$
760
		}
761
	}
762
}
(-)src/org/eclipse/core/databinding/editing/StringEditing.java (+129 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.IConverter;
15
import org.eclipse.core.databinding.validation.constraint.StringConstraints;
16
import org.eclipse.core.internal.databinding.conversion.StringStripConverter;
17
import org.eclipse.core.internal.databinding.conversion.StringTrimConverter;
18
19
/**
20
 * @noextend This class is not intended to be subclassed by clients.
21
 * @since 1.4
22
 */
23
public class StringEditing extends Editing<String, String> {
24
25
	/**
26
	 * Creates a new editing object for booleans.
27
	 * 
28
	 * @param targetConverter
29
	 *            The {@link #setTargetConverter(IConverter) target converter}
30
	 *            to use for editing.
31
	 * 
32
	 * @noreference This constructor is not intended to be referenced by
33
	 *              clients.
34
	 */
35
	protected StringEditing(IConverter targetConverter) {
36
		setTargetConverter(targetConverter);
37
	}
38
39
	/**
40
	 * Creates a new editing object for strings which performs no validation or
41
	 * conversion.
42
	 * 
43
	 * @return The new editing object which performs no validation or
44
	 *         conversion.
45
	 */
46
	public static StringEditing withDefaults() {
47
		return new StringEditing(null);
48
	}
49
50
	/**
51
	 * Creates a new editing object which strips whitespace from both ends of
52
	 * the input string.
53
	 * 
54
	 * @return The new editing object which strips whitespace from both ends of
55
	 *         the input string.
56
	 * 
57
	 * @see Character#isWhitespace(char)
58
	 */
59
	public static StringEditing stripped() {
60
		return new StringEditing(new StringStripConverter(false));
61
	}
62
63
	/**
64
	 * Creates a new editing object which strips whitespace from both ends of
65
	 * the input string. In case stripping the input string results in an empty
66
	 * string, the input string will be converted to <code>null</code>.
67
	 * 
68
	 * @return The new editing object which strips whitespace from both ends of
69
	 *         the input string. Resulting empty strings are converted to
70
	 *         <code>null</code>.
71
	 * 
72
	 * @see Character#isWhitespace(char)
73
	 */
74
	public static StringEditing strippedToNull() {
75
		return new StringEditing(new StringStripConverter(true));
76
	}
77
78
	/**
79
	 * Creates a new editing object which {@link String#trim()}s the input
80
	 * string.
81
	 * 
82
	 * @return The new editing object which trims whitespace from both ends of
83
	 *         the input string.
84
	 * 
85
	 * @see String#trim()
86
	 */
87
	public static StringEditing trimmed() {
88
		return new StringEditing(new StringTrimConverter(false));
89
	}
90
91
	/**
92
	 * Creates a new editing object which {@link String#trim()}s the input
93
	 * string. In case trimming the input string results in an empty string, the
94
	 * input string will be converted to <code>null</code>.
95
	 * 
96
	 * @return The new editing object which trims whitespace from both ends of
97
	 *         the input string. Resulting empty strings are converted to
98
	 *         <code>null</code>.
99
	 * 
100
	 * @see String#trim()
101
	 */
102
	public static StringEditing trimmedToNull() {
103
		return new StringEditing(new StringTrimConverter(true));
104
	}
105
106
	public StringConstraints targetConstraints() {
107
		return (StringConstraints) super.targetConstraints();
108
	}
109
110
	public StringConstraints modelConstraints() {
111
		return (StringConstraints) super.modelConstraints();
112
	}
113
114
	public StringConstraints beforeSetModelConstraints() {
115
		return (StringConstraints) super.beforeSetModelConstraints();
116
	}
117
118
	protected StringConstraints createTargetConstraints() {
119
		return new StringConstraints();
120
	}
121
122
	protected StringConstraints createModelConstraints() {
123
		return new StringConstraints();
124
	}
125
126
	protected StringConstraints createBeforeSetModelConstraints() {
127
		return new StringConstraints();
128
	}
129
}
(-)src/org/eclipse/core/databinding/validation/constraint/BaseObjectConstraints.java (+67 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.databinding.validation.IValidator;
15
import org.eclipse.core.internal.databinding.validation.NonNullValidator;
16
17
/**
18
 * @param <T>
19
 * @param <C>
20
 * 
21
 * @since 1.4
22
 */
23
public class BaseObjectConstraints<T, C extends BaseObjectConstraints<T, C>>
24
		extends Constraints<T> {
25
26
	private String requiredMessage = null;
27
28
	public C addValidator(IValidator validator) {
29
		super.addValidator(validator);
30
		return getThis();
31
	}
32
33
	public C aggregationPolicy(Aggregation aggregation) {
34
		super.aggregationPolicy(aggregation);
35
		return getThis();
36
	}
37
38
	/**
39
	 * Adds a validator ensuring that the input number is not <code>null</code>
40
	 * . Uses the current {@link #requiredMessage(String) validation message}.
41
	 * 
42
	 * @return This constraints instance for method chaining.
43
	 */
44
	public C required() {
45
		addValidator(new NonNullValidator(requiredMessage));
46
		return getThis();
47
	}
48
49
	/**
50
	 * Sets the validation message for the {@link #required()} constraint.
51
	 * 
52
	 * @param message
53
	 *            The validation message for the {@link #required()} constraint.
54
	 * @return This constraints instance for method chaining.
55
	 * 
56
	 * @see #required()
57
	 */
58
	public C requiredMessage(String message) {
59
		this.requiredMessage = message;
60
		return getThis();
61
	}
62
63
	@SuppressWarnings("unchecked")
64
	private C getThis() {
65
		return (C) this;
66
	}
67
}
(-)src/org/eclipse/core/databinding/validation/constraint/BooleanConstraints.java (+30 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
/**
15
 * Provides a set of constraints to apply to <code>Boolean</code>s.
16
 * 
17
 * <p>
18
 * Instances of this class can be used to define a set of constraints to apply
19
 * to booleans. In addition, the validation messages to be issued for the
20
 * individual constraints can be configured.
21
 * </p>
22
 * 
23
 * @noextend This class is not intended to be subclassed by clients.
24
 * @since 1.4
25
 */
26
public class BooleanConstraints extends
27
		BaseObjectConstraints<Boolean, BooleanConstraints> {
28
29
	// no additional constraints than those inherited from the subclass
30
}
(-)src/org/eclipse/core/databinding/validation/constraint/CharacterConstraints.java (+172 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
16
/**
17
 * Provides a set of constraints to apply to <code>Character</code>s.
18
 * 
19
 * <p>
20
 * Instances of this class can be used to define a set of constraints to apply
21
 * to characters. In addition, the validation messages to be issued for the
22
 * individual constraints can be configured.
23
 * </p>
24
 * 
25
 * @noextend This class is not intended to be subclassed by clients.
26
 * @since 1.4
27
 */
28
public class CharacterConstraints extends
29
		BaseObjectConstraints<Character, CharacterConstraints> {
30
31
	private String noWhitespaceMessage = null;
32
33
	private String noSpaceMessage = null;
34
35
	private String letterMessage = null;
36
37
	private String digitMessage = null;
38
39
	private String letterOrDigitMessage = null;
40
41
	/**
42
	 * Adds a validator ensuring that the character is no
43
	 * {@link Character#isWhitespace(char) whitespace}. Uses the current
44
	 * {@link #noWhitespaceMessage(String) validation message}.
45
	 * 
46
	 * @return This constraints instance for method chaining.
47
	 */
48
	public CharacterConstraints noWhitespace() {
49
		addValidator(CharacterValidator.noWhitespace(noWhitespaceMessage));
50
		return this;
51
	}
52
53
	/**
54
	 * Sets the validation message for the {@link #noWhitespace()} constraint.
55
	 * 
56
	 * @param message
57
	 *            The validation message for the {@link #noWhitespace()}
58
	 *            constraint.
59
	 * @return This constraints instance for method chaining.
60
	 * 
61
	 * @see #noWhitespace()
62
	 */
63
	public CharacterConstraints noWhitespaceMessage(String message) {
64
		this.noWhitespaceMessage = message;
65
		return this;
66
	}
67
68
	/**
69
	 * Adds a validator ensuring that the character is no
70
	 * {@link Character#isSpaceChar(char) space}. Uses the current
71
	 * {@link #noSpaceMessage(String) validation message}.
72
	 * 
73
	 * @return This constraints instance for method chaining.
74
	 */
75
	public CharacterConstraints noSpace() {
76
		addValidator(CharacterValidator.noSpace(noSpaceMessage));
77
		return this;
78
	}
79
80
	/**
81
	 * Sets the validation message for the {@link #noSpace()} constraint.
82
	 * 
83
	 * @param message
84
	 *            The validation message for the {@link #noSpace()} constraint.
85
	 * @return This constraints instance for method chaining.
86
	 * 
87
	 * @see #noSpace()
88
	 */
89
	public CharacterConstraints noSpaceMessage(String message) {
90
		this.noSpaceMessage = message;
91
		return this;
92
	}
93
94
	/**
95
	 * Adds a validator ensuring that the character is a
96
	 * {@link Character#isLetter(char) letter}. Uses the current
97
	 * {@link #letterMessage(String) validation message}.
98
	 * 
99
	 * @return This constraints instance for method chaining.
100
	 */
101
	public CharacterConstraints letter() {
102
		addValidator(CharacterValidator.letter(letterMessage));
103
		return this;
104
	}
105
106
	/**
107
	 * Sets the validation message for the {@link #letter()} constraint.
108
	 * 
109
	 * @param message
110
	 *            The validation message for the {@link #letter()} constraint.
111
	 * @return This constraints instance for method chaining.
112
	 * 
113
	 * @see #letter()
114
	 */
115
	public CharacterConstraints letterMessage(String message) {
116
		this.letterMessage = message;
117
		return this;
118
	}
119
120
	/**
121
	 * Adds a validator ensuring that the character is a
122
	 * {@link Character#isDigit(char) digit}. Uses the current
123
	 * {@link #digitMessage(String) validation message}.
124
	 * 
125
	 * @return This constraints instance for method chaining.
126
	 */
127
	public CharacterConstraints digit() {
128
		addValidator(CharacterValidator.digit(digitMessage));
129
		return this;
130
	}
131
132
	/**
133
	 * Sets the validation message for the {@link #digit()} constraint.
134
	 * 
135
	 * @param message
136
	 *            The validation message for the {@link #digit()} constraint.
137
	 * @return This constraints instance for method chaining.
138
	 * 
139
	 * @see #digit()
140
	 */
141
	public CharacterConstraints digitMessage(String message) {
142
		this.digitMessage = message;
143
		return this;
144
	}
145
146
	/**
147
	 * Adds a validator ensuring that the character is a
148
	 * {@link Character#isLetterOrDigit(char) letter or digit}. Uses the current
149
	 * {@link #letterOrDigitMessage(String) validation message}.
150
	 * 
151
	 * @return This constraints instance for method chaining.
152
	 */
153
	public CharacterConstraints letterOrDigit() {
154
		addValidator(CharacterValidator.letterOrDigit(letterOrDigitMessage));
155
		return this;
156
	}
157
158
	/**
159
	 * Sets the validation message for the {@link #letterOrDigit()} constraint.
160
	 * 
161
	 * @param message
162
	 *            The validation message for the {@link #letterOrDigit()}
163
	 *            constraint.
164
	 * @return This constraints instance for method chaining.
165
	 * 
166
	 * @see #letterOrDigit()
167
	 */
168
	public CharacterConstraints letterOrDigitMessage(String message) {
169
		this.letterOrDigitMessage = message;
170
		return this;
171
	}
172
}
(-)src/org/eclipse/core/databinding/validation/constraint/Constraints.java (+228 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.List;
16
17
import org.eclipse.core.databinding.util.Policy;
18
import org.eclipse.core.databinding.validation.IValidator;
19
import org.eclipse.core.internal.databinding.BindingMessages;
20
import org.eclipse.core.runtime.IStatus;
21
import org.eclipse.core.runtime.MultiStatus;
22
import org.eclipse.core.runtime.Status;
23
24
/**
25
 * This class allows to aggregate a set of {@link IValidator validators} and to
26
 * combine their individual validation statuses in different ways.
27
 * 
28
 * <p>
29
 * The set of validators to be applied can be {@link #addValidator(IValidator)
30
 * added} to a constraints object from which an aggregate validator can then be
31
 * {@link #createValidator() created} which combines the statuses of all the
32
 * accumulated validators as dictated by the specified
33
 * {@link #aggregationPolicy(Aggregation) aggregation policy}.
34
 * </p>
35
 * 
36
 * @param <T>
37
 * 
38
 * @see IValidator
39
 * 
40
 * @since 1.4
41
 */
42
public class Constraints<T> {
43
44
	/**
45
	 * The supported aggregation policies to apply to the individual validations
46
	 * which constitute the set of constraints.
47
	 */
48
	public static enum Aggregation {
49
50
		/**
51
		 * Constant denoting an aggregation strategy that merges multiple non-OK
52
		 * status objects in a {@link MultiStatus}. Returns an OK status result
53
		 * if all statuses from the set of validators to apply are an OK status.
54
		 * Returns a single status if there is only one non-OK status.
55
		 * 
56
		 * @see #aggregationPolicy(Aggregation)
57
		 */
58
		MERGED,
59
60
		/**
61
		 * Constant denoting an aggregation strategy that always returns the
62
		 * <i>most</i> severe status from the set of validators to apply. If
63
		 * there is more than one status at the same severity level, it picks
64
		 * the first one it encounters.
65
		 * 
66
		 * @see #aggregationPolicy(Aggregation)
67
		 */
68
		MAX_SEVERITY,
69
70
		/**
71
		 * Constant denoting an aggregation strategy that always returns the
72
		 * <i>least</i> severe status from the set of validators to apply. If
73
		 * there is more than one status at the same severity level, it picks
74
		 * the first one it encounters.
75
		 * 
76
		 * @see #aggregationPolicy(Aggregation)
77
		 */
78
		MIN_SEVERITY;
79
	}
80
81
	// Will be initialized lazily.
82
	private List<IValidator> validators = null;
83
84
	private IValidator cachedValidator = null;
85
86
	private Aggregation aggregationPolicy = Aggregation.MAX_SEVERITY;
87
88
	/**
89
	 * Adds a custom validator to the set of constraints to apply.
90
	 * 
91
	 * @param validator
92
	 *            The custom validator to add to the set of constraints.
93
	 * @return This constraints instance for method chaining.
94
	 */
95
	public Constraints<T> addValidator(IValidator validator) {
96
		if (validators == null) {
97
			validators = new ArrayList<IValidator>(2);
98
		}
99
		validators.add(validator);
100
		cachedValidator = null;
101
		return this;
102
	}
103
104
	/**
105
	 * Sets the aggregation policy to apply to the individual validations which
106
	 * constitute this set of constraints.
107
	 * 
108
	 * @param policy
109
	 *            The validation aggregation policy to set. Must be one of
110
	 *            {@link Aggregation#MERGED}, {@link Aggregation#MAX_SEVERITY}
111
	 *            or {@link Aggregation#MIN_SEVERITY}.
112
	 * @return This constraints instance for method chaining.
113
	 * 
114
	 * @see Aggregation#MERGED
115
	 * @see Aggregation#MAX_SEVERITY
116
	 * @see Aggregation#MIN_SEVERITY
117
	 */
118
	public Constraints<T> aggregationPolicy(Aggregation policy) {
119
		this.aggregationPolicy = policy;
120
		cachedValidator = null;
121
		return this;
122
	}
123
124
	/**
125
	 * Creates a validator which enforces the current set of constraints.
126
	 * 
127
	 * <p>
128
	 * Note that this method will return <code>null</code> in case the set of
129
	 * constraints to apply is empty.
130
	 * </p>
131
	 * 
132
	 * @return A validator which enforces the current set of constraints. May be
133
	 *         <code>null</code>.
134
	 */
135
	public final IValidator createValidator() {
136
		if (validators != null && !validators.isEmpty()) {
137
			if (cachedValidator == null) {
138
				if (validators.size() == 1) {
139
					cachedValidator = validators.get(0);
140
				} else {
141
					IValidator[] currentValidators = validators
142
							.toArray(new IValidator[validators.size()]);
143
					cachedValidator = new ConstraintsValidator(
144
							currentValidators, aggregationPolicy);
145
				}
146
			}
147
			return cachedValidator;
148
		}
149
		return null;
150
	}
151
152
	private static final class ConstraintsValidator implements IValidator {
153
154
		private final IValidator[] validators;
155
156
		private final Aggregation aggregationPolicy;
157
158
		public ConstraintsValidator(IValidator[] validators,
159
				Aggregation aggregationPolicy) {
160
			this.validators = validators;
161
			this.aggregationPolicy = aggregationPolicy;
162
		}
163
164
		public IStatus validate(Object value) {
165
			switch (aggregationPolicy) {
166
			case MERGED:
167
				return validateMerged(value);
168
			case MAX_SEVERITY:
169
				return validateMaxSeverity(value);
170
			case MIN_SEVERITY:
171
				return validateMinSeverity(value);
172
			default:
173
				throw new IllegalArgumentException(
174
						"Unsupported aggregationPolicy: " + aggregationPolicy); //$NON-NLS-1$
175
			}
176
		}
177
178
		private IStatus validateMerged(Object value) {
179
			List<IStatus> statuses = new ArrayList<IStatus>();
180
			for (IValidator validator : validators) {
181
				IStatus status = validator.validate(value);
182
				if (!status.isOK()) {
183
					statuses.add(status);
184
				}
185
			}
186
187
			if (statuses.size() == 1) {
188
				return statuses.get(0);
189
			}
190
191
			if (!statuses.isEmpty()) {
192
				MultiStatus result = new MultiStatus(Policy.JFACE_DATABINDING,
193
						0, BindingMessages
194
								.getString(BindingMessages.MULTIPLE_PROBLEMS),
195
						null);
196
				for (IStatus status : statuses) {
197
					result.merge(status);
198
				}
199
				return result;
200
			}
201
202
			return Status.OK_STATUS;
203
		}
204
205
		private IStatus validateMaxSeverity(Object value) {
206
			IStatus maxStatus = Status.OK_STATUS;
207
			for (IValidator validator : validators) {
208
				IStatus status = validator.validate(value);
209
				if (status.getSeverity() > maxStatus.getSeverity()) {
210
					maxStatus = status;
211
				}
212
			}
213
			return maxStatus;
214
		}
215
216
		private IStatus validateMinSeverity(Object value) {
217
			IStatus minStatus = null;
218
			for (IValidator validator : validators) {
219
				IStatus status = validator.validate(value);
220
				if (minStatus == null
221
						|| status.getSeverity() < minStatus.getSeverity()) {
222
					minStatus = status;
223
				}
224
			}
225
			return minStatus != null ? minStatus : Status.OK_STATUS;
226
		}
227
	}
228
}
(-)src/org/eclipse/core/databinding/validation/constraint/DateConstraints.java (+233 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
18
import com.ibm.icu.text.DateFormat;
19
20
/**
21
 * Provides a set of constraints to apply to <code>Date</code>s.
22
 * 
23
 * <p>
24
 * Instances of this class can be used to define a set of constraints to apply
25
 * to dates. In addition, the validation messages to be issued for the
26
 * individual constraints as well as the way in which model objects are
27
 * formatted in the validation messages can be configured.
28
 * </p>
29
 * 
30
 * @see Date
31
 * 
32
 * @noextend This class is not intended to be subclassed by clients.
33
 * @since 1.4
34
 */
35
public class DateConstraints extends
36
		BaseObjectConstraints<Date, DateConstraints> {
37
38
	private DateFormat dateFormat = DateFormat.getDateInstance();
39
40
	private String afterMessage = null;
41
42
	private String afterEqualMessage = null;
43
44
	private String beforeMessage = null;
45
46
	private String beforeEqualMessage = null;
47
48
	private String rangeMessage = null;
49
50
	/**
51
	 * Sets the format to use when formatting a date to be included in any of
52
	 * the validation messages.
53
	 * 
54
	 * @param format
55
	 *            The format to use for displaying dates in validation messages.
56
	 * @return This constraints instance for method chaining.
57
	 */
58
	public DateConstraints dateFormat(DateFormat format) {
59
		this.dateFormat = format;
60
		return this;
61
	}
62
63
	/**
64
	 * Adds a validator ensuring that the input date is after the given date.
65
	 * Uses the current {@link #afterMessage(String) validation message} and
66
	 * {@link #dateFormat(DateFormat) date format}.
67
	 * 
68
	 * @param date
69
	 *            The date which the input date must be after.
70
	 * @return This constraints instance for method chaining.
71
	 * 
72
	 * @see Date#after(Date)
73
	 */
74
	public DateConstraints after(Date date) {
75
		addValidator(DateRangeValidator.after(date, afterMessage, dateFormat));
76
		return this;
77
	}
78
79
	/**
80
	 * Sets the validation message pattern for the {@link #after(Date)}
81
	 * constraint.
82
	 * 
83
	 * @param message
84
	 *            The validation message pattern for the {@link #after(Date)}
85
	 *            constraint. Can be parameterized with the date ({0}) which the
86
	 *            input date must be after.
87
	 * @return This constraints instance for method chaining.
88
	 * 
89
	 * @see #after(Date)
90
	 */
91
	public DateConstraints afterMessage(String message) {
92
		this.afterMessage = message;
93
		return this;
94
	}
95
96
	/**
97
	 * Adds a validator ensuring that the input date is after or on the given
98
	 * date. Uses the current {@link #afterEqualMessage(String) validation
99
	 * message} and {@link #dateFormat(DateFormat) date format}.
100
	 * 
101
	 * @param date
102
	 *            The date which the input date must be after or on.
103
	 * @return This constraints instance for method chaining.
104
	 * 
105
	 * @see Date#after(Date)
106
	 * @see Date#equals(Object)
107
	 */
108
	public DateConstraints afterEqual(Date date) {
109
		addValidator(DateRangeValidator.afterEqual(date, afterEqualMessage,
110
				dateFormat));
111
		return this;
112
	}
113
114
	/**
115
	 * Sets the validation message pattern for the {@link #afterEqual(Date)}
116
	 * constraint.
117
	 * 
118
	 * @param message
119
	 *            The validation message pattern for the
120
	 *            {@link #afterEqual(Date)} constraint. Can be parameterized
121
	 *            with the date ({0}) which the input date must be after or on.
122
	 * @return This constraints instance for method chaining.
123
	 * 
124
	 * @see #afterEqual(Date)
125
	 */
126
	public DateConstraints afterEqualMessage(String message) {
127
		this.afterEqualMessage = message;
128
		return this;
129
	}
130
131
	/**
132
	 * Adds a validator ensuring that the input date is before the given date.
133
	 * Uses the current {@link #beforeMessage(String) validation message} and
134
	 * {@link #dateFormat(DateFormat) date format}.
135
	 * 
136
	 * @param date
137
	 *            The date which the input date must be before
138
	 * @return This constraints instance for method chaining.
139
	 * 
140
	 * @see Date#before(Date)
141
	 */
142
	public DateConstraints before(Date date) {
143
		addValidator(DateRangeValidator.before(date, beforeMessage, dateFormat));
144
		return this;
145
	}
146
147
	/**
148
	 * Sets the validation message pattern for the {@link #before(Date)}
149
	 * constraint.
150
	 * 
151
	 * @param message
152
	 *            The validation message pattern for the {@link #before(Date)}
153
	 *            constraint. Can be parameterized with the date ({0}) which the
154
	 *            input date must be before.
155
	 * @return This constraints instance for method chaining.
156
	 * 
157
	 * @see #before(Date)
158
	 */
159
	public DateConstraints beforeMessage(String message) {
160
		this.beforeMessage = message;
161
		return this;
162
	}
163
164
	/**
165
	 * Adds a validator ensuring that the input date is before or on the given
166
	 * date. Uses the current {@link #beforeEqualMessage(String) validation
167
	 * message} and {@link #dateFormat(DateFormat) date format}.
168
	 * 
169
	 * @param date
170
	 *            The date which the input date must be before or on.
171
	 * @return This constraints instance for method chaining.
172
	 * 
173
	 * @see Date#before(Date)
174
	 * @see Date#equals(Object)
175
	 */
176
	public DateConstraints beforeEqual(Date date) {
177
		addValidator(DateRangeValidator.beforeEqual(date, beforeEqualMessage,
178
				dateFormat));
179
		return this;
180
	}
181
182
	/**
183
	 * Sets the validation message pattern for the {@link #beforeEqual(Date)}
184
	 * constraint.
185
	 * 
186
	 * @param message
187
	 *            The validation message pattern for the
188
	 *            {@link #beforeEqual(Date)} constraint. Can be parameterized
189
	 *            ({0}) with the date which the input date must be before or on.
190
	 * @return This constraints instance for method chaining.
191
	 * 
192
	 * @see #beforeEqual(Date)
193
	 */
194
	public DateConstraints beforeEqualMessage(String message) {
195
		this.beforeEqualMessage = message;
196
		return this;
197
	}
198
199
	/**
200
	 * Adds a validator ensuring that the input date is within the given range.
201
	 * Uses the current {@link #rangeMessage(String) validation message} and
202
	 * {@link #dateFormat(DateFormat) date format}.
203
	 * 
204
	 * @param minDate
205
	 *            The lower bound of the range (inclusive).
206
	 * @param maxDate
207
	 *            The upper bound of the range (inclusive).
208
	 * @return This constraints instance for method chaining.
209
	 */
210
	public DateConstraints range(Date minDate, Date maxDate) {
211
		addValidator(DateRangeValidator.range(minDate, maxDate, rangeMessage,
212
				dateFormat));
213
		return this;
214
	}
215
216
	/**
217
	 * Sets the validation message pattern for the {@link #range(Date, Date)}
218
	 * constraint.
219
	 * 
220
	 * @param message
221
	 *            The validation message pattern for the
222
	 *            {@link #range(Date, Date)} constraint. Can be parameterized
223
	 *            with the min ({0}) and max ({1}) dates of the range in which
224
	 *            the input date must lie.
225
	 * @return This constraints instance for method chaining.
226
	 * 
227
	 * @see #range(Date, Date)
228
	 */
229
	public DateConstraints rangeMessage(String message) {
230
		this.rangeMessage = message;
231
		return this;
232
	}
233
}
(-)src/org/eclipse/core/databinding/validation/constraint/NumberConstraints.java (+490 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
import java.math.BigInteger;
16
17
import org.eclipse.core.internal.databinding.validation.DecimalPrecisionValidator;
18
import org.eclipse.core.internal.databinding.validation.DecimalScaleValidator;
19
import org.eclipse.core.internal.databinding.validation.NumberRangeValidator;
20
21
import com.ibm.icu.text.NumberFormat;
22
23
/**
24
 * Provides a set of constraints to apply to number numbers.
25
 * 
26
 * <p>
27
 * Instances of this class can be used to define a set of constraints to apply
28
 * to numbers. In addition, the validation messages to be issued for the
29
 * individual constraints as well as the way in which model objects are
30
 * formatted in the validation messages can be configured.
31
 * </p>
32
 * 
33
 * @param <N>
34
 * 
35
 * @noextend This class is not intended to be subclassed by clients.
36
 * @since 1.4
37
 */
38
public class NumberConstraints<N extends Number & Comparable<N>> extends
39
		BaseObjectConstraints<N, NumberConstraints<N>> {
40
41
	private NumberFormat numberFormat = NumberFormat.getNumberInstance();
42
43
	private NumberFormat scaleFormat = NumberFormat.getIntegerInstance();
44
45
	private NumberFormat precisionFormat = NumberFormat.getIntegerInstance();
46
47
	private String greaterMessage = null;
48
49
	private String greaterEqualMessage = null;
50
51
	private String lessMessage = null;
52
53
	private String lessEqualMessage = null;
54
55
	private String rangeMessage = null;
56
57
	private String positiveMessage = null;
58
59
	private String nonNegativeMessage = null;
60
61
	private String maxScaleMessage = null;
62
63
	private String maxPrecisionMessage = null;
64
65
	private final N zeroNumber;
66
67
	private final N oneNumber;
68
69
	/**
70
	 * 
71
	 * @param zeroNumber
72
	 * @param oneNumber
73
	 * 
74
	 * @noreference This constructor is not intended to be referenced by
75
	 *              clients.
76
	 */
77
	protected NumberConstraints(N zeroNumber, N oneNumber) {
78
		this.zeroNumber = zeroNumber;
79
		this.oneNumber = oneNumber;
80
	}
81
82
	/**
83
	 * Creates a constraints object for <code>Long</code>s.
84
	 * 
85
	 * @return The constraints object for <code>Long</code>s.
86
	 */
87
	public static NumberConstraints<Long> forLong() {
88
		return new NumberConstraints<Long>(new Long(0), new Long(1));
89
	}
90
91
	/**
92
	 * Creates a constraints object for <code>Integer</code>s.
93
	 * 
94
	 * @return The constraints object for <code>Integer</code>s.
95
	 */
96
	public static NumberConstraints<Integer> forInteger() {
97
		return new NumberConstraints<Integer>(new Integer(0), new Integer(1));
98
	}
99
100
	/**
101
	 * Creates a constraints object for <code>Short</code>s.
102
	 * 
103
	 * @return The constraints object for <code>Short</code>s.
104
	 */
105
	public static NumberConstraints<Short> forShort() {
106
		return new NumberConstraints<Short>(new Short((short) 0), new Short(
107
				(short) 1));
108
	}
109
110
	/**
111
	 * Creates a constraints object for <code>Byte</code>s.
112
	 * 
113
	 * @return The constraints object for <code>Byte</code>s.
114
	 */
115
	public static NumberConstraints<Byte> forByte() {
116
		return new NumberConstraints<Byte>(new Byte((byte) 0), new Byte(
117
				(byte) 1));
118
	}
119
120
	/**
121
	 * Creates a constraints object for <code>Double</code>s.
122
	 * 
123
	 * @return The constraints object for <code>Double</code>s.
124
	 */
125
	public static NumberConstraints<Double> forDouble() {
126
		return new NumberConstraints<Double>(new Double(0.0), new Double(1.0));
127
	}
128
129
	/**
130
	 * Creates a constraints object for <code>Float</code>s.
131
	 * 
132
	 * @return The constraints object for <code>Float</code>s.
133
	 */
134
	public static NumberConstraints<Float> forFloat() {
135
		return new NumberConstraints<Float>(new Float(0.0f), new Float(1.0f));
136
	}
137
138
	/**
139
	 * Creates a constraints object for <code>BigInteger</code>s.
140
	 * 
141
	 * @return The constraints object for <code>BigInteger</code>s.
142
	 */
143
	public static NumberConstraints<BigInteger> forBigInteger() {
144
		return new NumberConstraints<BigInteger>(BigInteger.ZERO,
145
				BigInteger.ONE);
146
	}
147
148
	/**
149
	 * Creates a constraints object for <code>BigDecimal</code>s.
150
	 * 
151
	 * @return The constraints object for <code>BigDecimal</code>s.
152
	 */
153
	public static NumberConstraints<BigDecimal> forBigDecimal() {
154
		return new NumberConstraints<BigDecimal>(BigDecimal.ZERO,
155
				BigDecimal.ONE);
156
	}
157
158
	/**
159
	 * Sets the format to use when formatting a number to be included in any of
160
	 * the validation messages.
161
	 * 
162
	 * @param format
163
	 *            The format to use for displaying numbers in validation
164
	 *            messages.
165
	 * @return This constraints instance for method chaining.
166
	 */
167
	public NumberConstraints<N> numberFormat(NumberFormat format) {
168
		this.numberFormat = format;
169
		return this;
170
	}
171
172
	/**
173
	 * Adds a validator ensuring that the input number is greater than the given
174
	 * number. Uses the current {@link #greaterMessage(String) validation
175
	 * message} and {@link #numberFormat(NumberFormat) number format}.
176
	 * 
177
	 * @param number
178
	 *            The number which the input number must be greater than.
179
	 * @return This constraints instance for method chaining.
180
	 */
181
	public NumberConstraints<N> greater(N number) {
182
		addValidator(NumberRangeValidator.greater(number, greaterMessage,
183
				numberFormat));
184
		return this;
185
	}
186
187
	/**
188
	 * Sets the validation message pattern for the {@link #greater(Number)}
189
	 * constraint.
190
	 * 
191
	 * @param message
192
	 *            The validation message pattern for the
193
	 *            {@link #greater(Number)} constraint. Can be parameterized with
194
	 *            the number ({0}) which the input number must be greater than.
195
	 * @return This constraints instance for method chaining.
196
	 * 
197
	 * @see #greater(Number)
198
	 */
199
	public NumberConstraints<N> greaterMessage(String message) {
200
		this.greaterMessage = message;
201
		return this;
202
	}
203
204
	/**
205
	 * Adds a validator ensuring that the input number is greater than or equal
206
	 * to the given number. Uses the current
207
	 * {@link #greaterEqualMessage(String) validation message} and
208
	 * {@link #numberFormat(NumberFormat) number format}.
209
	 * 
210
	 * @param number
211
	 *            The number which the input number must be greater than or
212
	 *            equal to.
213
	 * @return This constraints instance for method chaining.
214
	 */
215
	public NumberConstraints<N> greaterEqual(N number) {
216
		addValidator(NumberRangeValidator.greaterEqual(number,
217
				greaterEqualMessage, numberFormat));
218
		return this;
219
	}
220
221
	/**
222
	 * Sets the validation message pattern for the {@link #greaterEqual(Number)}
223
	 * constraint.
224
	 * 
225
	 * @param message
226
	 *            The validation message pattern for the
227
	 *            {@link #greaterEqual(Number)} constraint. Can be parameterized
228
	 *            with the number ({0}) which the input number must be greater
229
	 *            than or equal to.
230
	 * @return This constraints instance for method chaining.
231
	 * 
232
	 * @see #greaterEqual(Number)
233
	 */
234
	public NumberConstraints<N> greaterEqualMessage(String message) {
235
		this.greaterEqualMessage = message;
236
		return this;
237
	}
238
239
	/**
240
	 * Adds a validator ensuring that the input number is less than the given
241
	 * number. Uses the current {@link #lessMessage(String) validation message}
242
	 * and {@link #numberFormat(NumberFormat) number format}.
243
	 * 
244
	 * @param number
245
	 *            The number which the input number must be less than.
246
	 * @return This constraints instance for method chaining.
247
	 */
248
	public NumberConstraints<N> less(N number) {
249
		addValidator(NumberRangeValidator.less(number, lessMessage,
250
				numberFormat));
251
		return this;
252
	}
253
254
	/**
255
	 * Sets the validation message pattern for the {@link #less(Number)}
256
	 * constraint.
257
	 * 
258
	 * @param message
259
	 *            The validation message pattern for the {@link #less(Number)}
260
	 *            constraint. Can be parameterized with the number ({0}) which
261
	 *            the input number must be less than.
262
	 * @return This constraints instance for method chaining.
263
	 * 
264
	 * @see #less(Number)
265
	 */
266
	public NumberConstraints<N> lessMessage(String message) {
267
		this.lessMessage = message;
268
		return this;
269
	}
270
271
	/**
272
	 * Adds a validator ensuring that the input number is less than or equal to
273
	 * the given number. Uses the current {@link #lessEqualMessage(String)
274
	 * validation message} and {@link #numberFormat(NumberFormat) number format}
275
	 * .
276
	 * 
277
	 * @param number
278
	 *            The number which the input number must be less than or equal
279
	 *            to.
280
	 * @return This constraints instance for method chaining.
281
	 */
282
	public NumberConstraints<N> lessEqual(N number) {
283
		addValidator(NumberRangeValidator.greaterEqual(number,
284
				lessEqualMessage, numberFormat));
285
		return this;
286
	}
287
288
	/**
289
	 * Sets the validation message pattern for the {@link #lessEqual(Number)}
290
	 * constraint.
291
	 * 
292
	 * @param message
293
	 *            The validation message pattern for the
294
	 *            {@link #lessEqual(Number)} constraint. Can be parameterized
295
	 *            with the number ({0}) which the input number must be less than
296
	 *            or equal to.
297
	 * @return This constraints instance for method chaining.
298
	 * 
299
	 * @see #lessEqual(Number)
300
	 */
301
	public NumberConstraints<N> lessEqualMessage(String message) {
302
		this.lessEqualMessage = message;
303
		return this;
304
	}
305
306
	/**
307
	 * Adds a validator ensuring that the input number is within the given
308
	 * range. Uses the current {@link #rangeMessage(String) validation message}
309
	 * and {@link #numberFormat(NumberFormat) number format}.
310
	 * 
311
	 * @param min
312
	 *            The lower bound of the range (inclusive).
313
	 * @param max
314
	 *            The upper bound of the range (inclusive).
315
	 * @return This constraints instance for method chaining.
316
	 */
317
	public NumberConstraints<N> range(N min, N max) {
318
		addValidator(NumberRangeValidator.range(min, max, rangeMessage,
319
				numberFormat));
320
		return this;
321
	}
322
323
	/**
324
	 * Sets the validation message pattern for the
325
	 * {@link #range(Number, Number)} constraint.
326
	 * 
327
	 * @param message
328
	 *            The validation message pattern for the
329
	 *            {@link #range(Number, Number)} constraint. Can be
330
	 *            parameterized with the min ({0}) and max ({1}) values of the
331
	 *            range in which the input number must lie.
332
	 * @return This constraints instance for method chaining.
333
	 * 
334
	 * @see #range(Number, Number)
335
	 */
336
	public NumberConstraints<N> rangeMessage(String message) {
337
		this.rangeMessage = message;
338
		return this;
339
	}
340
341
	/**
342
	 * Adds a validator ensuring that the input number is positive. Uses the
343
	 * current {@link #positiveMessage(String) validation message}.
344
	 * 
345
	 * @return This constraints instance for method chaining.
346
	 */
347
	public NumberConstraints<N> positive() {
348
		addValidator(NumberRangeValidator.positive(oneNumber, positiveMessage,
349
				numberFormat));
350
		return this;
351
	}
352
353
	/**
354
	 * Sets the validation message for the {@link #positive()} constraint.
355
	 * 
356
	 * @param message
357
	 *            The validation message for the {@link #positive()} constraint.
358
	 * @return This constraints instance for method chaining.
359
	 * 
360
	 * @see #positive()
361
	 */
362
	public NumberConstraints<N> positiveMessage(String message) {
363
		this.positiveMessage = message;
364
		return this;
365
	}
366
367
	/**
368
	 * Adds a validator ensuring that the input number is non-negative. Uses the
369
	 * current {@link #nonNegativeMessage(String) validation message}.
370
	 * 
371
	 * @return This constraints instance for method chaining.
372
	 */
373
	public NumberConstraints<N> nonNegative() {
374
		addValidator(NumberRangeValidator.nonNegative(zeroNumber,
375
				nonNegativeMessage, numberFormat));
376
		return this;
377
	}
378
379
	/**
380
	 * Sets the validation message for the {@link #nonNegative()} constraint.
381
	 * 
382
	 * @param message
383
	 *            The validation message for the {@link #nonNegative()}
384
	 *            constraint.
385
	 * @return This constraints instance for method chaining.
386
	 * 
387
	 * @see #nonNegative()
388
	 */
389
	public NumberConstraints<N> nonNegativeMessage(String message) {
390
		this.nonNegativeMessage = message;
391
		return this;
392
	}
393
394
	/**
395
	 * Sets the format to use when formatting the scale in any of the validation
396
	 * messages stemming from a scale constraint.
397
	 * 
398
	 * @param format
399
	 *            The format to use for displaying the scale in validation
400
	 *            messages stemming from a scale constraint.
401
	 * @return This constraints instance for method chaining.
402
	 * 
403
	 * @see #maxScale(int)
404
	 */
405
	public NumberConstraints<N> scaleFormat(NumberFormat format) {
406
		this.scaleFormat = format;
407
		return this;
408
	}
409
410
	/**
411
	 * Adds a validator ensuring that the input number's scale is not greater
412
	 * than the given one. Uses the current {@link #maxScaleMessage(String)
413
	 * validation message} and {@link #scaleFormat(NumberFormat) scale format}.
414
	 * 
415
	 * @param scale
416
	 *            The maximum scale to enforce on the input number.
417
	 * @return This constraints instance for method chaining.
418
	 */
419
	public NumberConstraints<N> maxScale(int scale) {
420
		addValidator(DecimalScaleValidator.max(scale, maxScaleMessage,
421
				scaleFormat));
422
		return this;
423
	}
424
425
	/**
426
	 * Sets the validation message pattern for the {@link #maxScale(int)}
427
	 * constraint.
428
	 * 
429
	 * @param message
430
	 *            The validation message pattern for the {@link #maxScale(int)}
431
	 *            constraint. Can be parameterized with the maximum scale ({0})
432
	 *            of the number.
433
	 * @return This constraints instance for method chaining.
434
	 * 
435
	 * @see #maxScale(int)
436
	 */
437
	public NumberConstraints<N> maxScaleMessage(String message) {
438
		this.maxScaleMessage = message;
439
		return this;
440
	}
441
442
	/**
443
	 * Sets the format to use when formatting the precision in any of the
444
	 * validation messages stemming from a precision constraint.
445
	 * 
446
	 * @param format
447
	 *            The format to use for displaying the precision in validation
448
	 *            messages stemming from a precision constraint.
449
	 * @return This constraints instance for method chaining.
450
	 * 
451
	 * @see #maxPrecision(int)
452
	 */
453
	public NumberConstraints<N> precisionFormat(NumberFormat format) {
454
		this.precisionFormat = format;
455
		return this;
456
	}
457
458
	/**
459
	 * Adds a validator ensuring that the input number's precision is not
460
	 * greater than the given one. Uses the current
461
	 * {@link #maxPrecisionMessage(String) validation message} and
462
	 * {@link #precisionFormat(NumberFormat) precision format}.
463
	 * 
464
	 * @param precision
465
	 *            The maximum precision to enforce on the input number.
466
	 * @return This constraints instance for method chaining.
467
	 */
468
	public NumberConstraints<N> maxPrecision(int precision) {
469
		addValidator(DecimalPrecisionValidator.max(precision,
470
				maxPrecisionMessage, precisionFormat));
471
		return this;
472
	}
473
474
	/**
475
	 * Sets the validation message pattern for the {@link #maxPrecision(int)}
476
	 * constraint.
477
	 * 
478
	 * @param message
479
	 *            The validation message pattern for the
480
	 *            {@link #maxPrecision(int)} constraint. Can be parameterized
481
	 *            with the maximum precision ({0}) of the number.
482
	 * @return This constraints instance for method chaining.
483
	 * 
484
	 * @see #maxPrecision(int)
485
	 */
486
	public NumberConstraints<N> maxPrecisionMessage(String message) {
487
		this.maxPrecisionMessage = message;
488
		return this;
489
	}
490
}
(-)src/org/eclipse/core/databinding/validation/constraint/StringConstraints.java (+245 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.StringLengthValidator;
18
import org.eclipse.core.internal.databinding.validation.StringRegexValidator;
19
20
import com.ibm.icu.text.NumberFormat;
21
22
/**
23
 * Provides a set of constraints to apply to <code>String</code>s.
24
 * 
25
 * <p>
26
 * Instances of this class can be used to define a set of constraints to apply
27
 * to strings. In addition, the validation messages to be issued for the
28
 * individual constraints as well as the way in which model objects are
29
 * formatted in the validation messages can be configured.
30
 * </p>
31
 * 
32
 * @noextend This class is not intended to be subclassed by clients.
33
 * @since 1.4
34
 */
35
public class StringConstraints extends
36
		BaseObjectConstraints<String, StringConstraints> {
37
38
	private NumberFormat lengthFormat = NumberFormat.getIntegerInstance();
39
40
	private String nonEmptyMessage = null;
41
42
	private String minLengthMessage = null;
43
44
	private String maxLengthMessage = null;
45
46
	private String lengthRangeMessage = null;
47
48
	private String matchesMessage = null;
49
50
	/**
51
	 * Adds a validator ensuring that the input integer is not empty. Uses the
52
	 * current {@link #nonEmptyMessage(String) validation message}.
53
	 * 
54
	 * @return This constraints instance for method chaining.
55
	 */
56
	public StringConstraints nonEmpty() {
57
		addValidator(new NonEmptyStringValidator(nonEmptyMessage));
58
		return this;
59
	}
60
61
	/**
62
	 * Sets the validation message for the {@link #nonEmpty()} constraint.
63
	 * 
64
	 * @param message
65
	 *            The validation message for the {@link #nonEmpty()} constraint.
66
	 * @return This constraints instance for method chaining.
67
	 * 
68
	 * @see #nonEmpty()
69
	 */
70
	public StringConstraints nonEmptyMessage(String message) {
71
		this.nonEmptyMessage = message;
72
		return this;
73
	}
74
75
	/**
76
	 * Sets the format to use when formatting the string length in any of the
77
	 * validation messages stemming from a length constraint.
78
	 * 
79
	 * @param format
80
	 *            The format to use for displaying the string length in
81
	 *            validation messages stemming from a length constraint.
82
	 *            messages.
83
	 * @return This constraints instance for method chaining.
84
	 * 
85
	 * @see #minLength(int)
86
	 * @see #maxLength(int)
87
	 * @see #lengthRange(int, int)
88
	 */
89
	public StringConstraints lengthFormat(NumberFormat format) {
90
		this.lengthFormat = format;
91
		return this;
92
	}
93
94
	/**
95
	 * Adds a validator ensuring that the input string has at least the
96
	 * specified amount of characters. Uses the current
97
	 * {@link #minLengthMessage(String) validation message} and
98
	 * {@link #lengthFormat(NumberFormat) length format}.
99
	 * 
100
	 * @param minLength
101
	 *            The minimal length to be enforced on the input string.
102
	 * @return This constraints instance for method chaining.
103
	 */
104
	public StringConstraints minLength(int minLength) {
105
		addValidator(StringLengthValidator.min(minLength, minLengthMessage,
106
				lengthFormat));
107
		return this;
108
	}
109
110
	/**
111
	 * Sets the validation message pattern for the {@link #minLength(int)}
112
	 * constraint.
113
	 * 
114
	 * @param message
115
	 *            The validation message pattern for the {@link #minLength(int)}
116
	 *            constraint. Can be parameterized with the minimum string
117
	 *            length ({0}).
118
	 * @return This constraints instance for method chaining.
119
	 * 
120
	 * @see #minLength(int)
121
	 */
122
	public StringConstraints minLengthMessage(String message) {
123
		this.minLengthMessage = message;
124
		return this;
125
	}
126
127
	/**
128
	 * Adds a validator ensuring that the input string has not more than the
129
	 * specified amount of characters. Uses the current
130
	 * {@link #maxLengthMessage(String) validation message} and
131
	 * {@link #lengthFormat(NumberFormat) length format}.
132
	 * 
133
	 * @param maxLength
134
	 *            The maximum length to be enforced on the input string.
135
	 * @return This constraints instance for method chaining.
136
	 */
137
	public StringConstraints maxLength(int maxLength) {
138
		addValidator(StringLengthValidator.max(maxLength, maxLengthMessage,
139
				lengthFormat));
140
		return this;
141
	}
142
143
	/**
144
	 * Sets the validation message pattern for the {@link #maxLength(int)}
145
	 * constraint.
146
	 * 
147
	 * @param message
148
	 *            The validation message pattern for the {@link #maxLength(int)}
149
	 *            constraint. Can be parameterized with the maximum string
150
	 *            length ({0}).
151
	 * @return This constraints instance for method chaining.
152
	 * 
153
	 * @see #maxLength(int)
154
	 */
155
	public StringConstraints maxLengthMessage(String message) {
156
		this.maxLengthMessage = message;
157
		return this;
158
	}
159
160
	/**
161
	 * Adds a validator ensuring that the length of the input string is between
162
	 * the given bounds. Uses the current {@link #lengthRangeMessage(String)
163
	 * validation message} and {@link #lengthFormat(NumberFormat) length format}
164
	 * .
165
	 * 
166
	 * @param minLength
167
	 *            The minimal length to be enforced on the input string.
168
	 * @param maxLength
169
	 *            The maximum length to be enforced on the input string.
170
	 * @return This constraints instance for method chaining.
171
	 */
172
	public StringConstraints lengthRange(int minLength, int maxLength) {
173
		addValidator(StringLengthValidator.range(minLength, maxLength,
174
				lengthRangeMessage, lengthFormat));
175
		return this;
176
	}
177
178
	/**
179
	 * Sets the validation message pattern for the
180
	 * {@link #lengthRange(int, int)} constraint.
181
	 * 
182
	 * @param message
183
	 *            The validation message pattern for the
184
	 *            {@link #lengthRange(int, int)} constraint. Can be
185
	 *            parameterized with the minimum ({0}) and maximum ({1}) string
186
	 *            lengths.
187
	 * @return This constraints instance for method chaining.
188
	 * 
189
	 * @see #lengthRange(int, int)
190
	 */
191
	public StringConstraints lengthRangeMessage(String message) {
192
		this.lengthRangeMessage = message;
193
		return this;
194
	}
195
196
	/**
197
	 * Adds a validator ensuring that the input string
198
	 * {@link Pattern#matches(String, CharSequence) matches} the given regular
199
	 * expression. Uses the current {@link #matchesMessage(String) validation
200
	 * message}.
201
	 * 
202
	 * @param regex
203
	 *            The regular expression which the input string must match.
204
	 * @return This constraints instance for method chaining.
205
	 * 
206
	 * @see Pattern#matches(String, CharSequence)
207
	 */
208
	public StringConstraints matches(String regex) {
209
		addValidator(new StringRegexValidator(regex, matchesMessage));
210
		return this;
211
	}
212
213
	/**
214
	 * Adds a validator ensuring that the input string
215
	 * {@link Pattern#matches(String, CharSequence) matches} the given pattern.
216
	 * Uses the current {@link #matchesMessage(String) validation message}.
217
	 * 
218
	 * @param pattern
219
	 *            The pattern which the input string must match.
220
	 * @return This constraints instance for method chaining.
221
	 * 
222
	 * @see Pattern#matches(String, CharSequence)
223
	 */
224
	public StringConstraints matches(Pattern pattern) {
225
		addValidator(new StringRegexValidator(pattern, matchesMessage));
226
		return this;
227
	}
228
229
	/**
230
	 * Sets the validation message pattern for the {@link #matches(String)}
231
	 * constraint.
232
	 * 
233
	 * @param message
234
	 *            The validation message pattern for the
235
	 *            {@link #matches(String)} constraint. Can be parameterized with
236
	 *            the pattern string ({0}) which the input integer must match.
237
	 * @return This constraints instance for method chaining.
238
	 * 
239
	 * @see #matches(String)
240
	 */
241
	public StringConstraints matchesMessage(String message) {
242
		this.matchesMessage = message;
243
		return this;
244
	}
245
}
(-)src/org/eclipse/core/internal/databinding/BindingMessages.java (-4 / +146 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
	/**
238
	 * Key to be used for a "Validate_DecimalMaxPrecision" message
239
	 */
240
	public static final String VALIDATE_DECIMAL_MAX_PRECISION = "Validate_DecimalMaxPrecision"; //$NON-NLS-1$
241
242
	/**
112
	 * Returns the resource object with the given key in the resource bundle for
243
	 * 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
244
	 * JFace Data Binding. If there isn't any value under the given key, the key
114
	 * is returned.
245
	 * is returned.
115
	 *
246
	 * 
116
	 * @param key
247
	 * @param key
117
	 *            the resource name
248
	 *            the resource name
118
	 * @return the string
249
	 * @return the string
Lines 128-143 Link Here
128
	/**
259
	/**
129
	 * Returns a formatted string with the given key in the resource bundle for
260
	 * Returns a formatted string with the given key in the resource bundle for
130
	 * JFace Data Binding.
261
	 * JFace Data Binding.
131
	 *
262
	 * 
132
	 * @param key
263
	 * @param key
133
	 * @param arguments
264
	 * @param arguments
134
	 * @return formatted string, the key if the key is invalid
265
	 * @return formatted string, the key if the key is invalid
135
	 */
266
	 */
136
	public static String formatString(String key, Object[] arguments) {
267
	public static String getFormattedString(String key, Object[] arguments) {
137
		try {
268
		try {
138
			return MessageFormat.format(bundle.getString(key), arguments);
269
			return formatMessage(getString(key), arguments);
139
		} catch (MissingResourceException e) {
270
		} catch (MissingResourceException e) {
140
			return key;
271
			return key;
141
		}
272
		}
142
	}
273
	}
274
275
	/**
276
	 * Formats the given message pattern with the provided arguments.
277
	 * 
278
	 * @param pattern
279
	 * @param arguments
280
	 * @return formatted string
281
	 */
282
	public static String formatMessage(String pattern, Object[] arguments) {
283
		return MessageFormat.format(pattern, arguments);
284
	}
143
}
285
}
(-)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.3
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/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.
(-)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.3
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/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/StringToNumberParser.java (-4 / +22 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-126 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(
119
			return BindingMessages.getFormattedString(
119
					BindingMessages.VALIDATE_NUMBER_PARSE_ERROR, new Object[] {
120
					BindingMessages.VALIDATE_NUMBER_PARSE_ERROR, new Object[] {
120
							value, new Integer(errorIndex + 1),
121
							value, new Integer(errorIndex + 1),
121
							new Character(value.charAt(errorIndex)) });
122
							new Character(value.charAt(errorIndex)) });
122
		}
123
		}
123
		return BindingMessages.formatString(
124
		return BindingMessages.getFormattedString(
124
				BindingMessages.VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER,
125
				BindingMessages.VALIDATE_NUMBER_PARSE_ERROR_NO_CHARACTER,
125
				new Object[] { value, new Integer(errorIndex + 1) });
126
				new Object[] { value, new Integer(errorIndex + 1) });
126
	}
127
	}
Lines 136-141 Link Here
136
	 */
137
	 */
137
	public static String createOutOfRangeMessage(Number minValue,
138
	public static String createOutOfRangeMessage(Number minValue,
138
			Number maxValue, NumberFormat numberFormat) {
139
			Number maxValue, NumberFormat numberFormat) {
140
		return createOutOfRangeMessage(BindingMessages
141
				.getString(BindingMessages.VALIDATE_NUMBER_OUT_OF_RANGE_ERROR),
142
				minValue, maxValue, numberFormat);
143
	}
144
145
	/**
146
	 * Formats an appropriate message for an out of range error.
147
	 * 
148
	 * @param message
149
	 * @param minValue
150
	 * @param maxValue
151
	 * @param numberFormat
152
	 *            when accessed method synchronizes on instance
153
	 * @return message
154
	 */
155
	public static String createOutOfRangeMessage(String message,
156
			Number minValue, Number maxValue, NumberFormat numberFormat) {
139
		String min = null;
157
		String min = null;
140
		String max = null;
158
		String max = null;
141
159
Lines 144-151 Link Here
144
			max = numberFormat.format(maxValue);
162
			max = numberFormat.format(maxValue);
145
		}
163
		}
146
164
147
		return BindingMessages.formatString(
165
		return BindingMessages
148
				"Validate_NumberOutOfRangeError", new Object[] { min, max }); //$NON-NLS-1$
166
				.formatMessage(message, new Object[] { min, max });
149
	}
167
	}
150
168
151
	/**
169
	/**
(-)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.3
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/internal/databinding/messages.properties (+45 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
98
#DecimalPrecisionValidator
99
Validate_DecimalMaxPrecision=The decimal must not have more than {0} significant digits.
100
56
Examples=Examples
101
Examples=Examples
(-)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/internal/databinding/validation/CharacterValidator.java (+145 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.3
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
31
			.getString(BindingMessages.VALIDATE_CHARACTER_NO_WHITESPACE);
32
	private static final String NO_SPACE_VALIDATION_MESSAGE = BindingMessages
33
			.getString(BindingMessages.VALIDATE_CHARACTER_NO_SPACE);
34
	private static final String LETTER_VALIDATION_MESSAGE = BindingMessages
35
			.getString(BindingMessages.VALIDATE_CHARACTER_LETTER);
36
	private static final String DIGIT_VALIDATION_MESSAGE = BindingMessages
37
			.getString(BindingMessages.VALIDATE_CHARACTER_DIGIT);
38
	private static final String LETTER_OR_DIGIT_VALIDATION_MESSAGE = BindingMessages
39
			.getString(BindingMessages.VALIDATE_CHARACTER_LETTER_OR_DIGIT);
40
41
	private final int validation;
42
	private final String validationMessage;
43
44
	private CharacterValidator(int validation, String validationMessage) {
45
		this.validation = validation;
46
		this.validationMessage = validationMessage;
47
	}
48
49
	/**
50
	 * Creates a validator which checks that an input character is no
51
	 * {@link Character#isWhitespace(char) whitespace}.
52
	 * 
53
	 * @param validationMessage
54
	 *            The validation message to use.
55
	 * @return The validator instance.
56
	 */
57
	public static CharacterValidator noWhitespace(String validationMessage) {
58
		return new CharacterValidator(VALIDATE_NO_WHITESPACE, defaultIfNull(
59
				NO_WHITESPACE_VALIDATION_MESSAGE, validationMessage));
60
	}
61
62
	/**
63
	 * Creates a validator which checks that an input character is no
64
	 * {@link Character#isSpaceChar(char) space}.
65
	 * 
66
	 * @param validationMessage
67
	 *            The validation message to use.
68
	 * @return The validator instance.
69
	 */
70
	public static CharacterValidator noSpace(String validationMessage) {
71
		return new CharacterValidator(VALIDATE_NO_SPACE, defaultIfNull(
72
				NO_SPACE_VALIDATION_MESSAGE, validationMessage));
73
	}
74
75
	/**
76
	 * Creates a validator which checks that an input character is a
77
	 * {@link Character#isLetter(char) letter}.
78
	 * 
79
	 * @param validationMessage
80
	 *            The validation message to use.
81
	 * @return The validator instance.
82
	 */
83
	public static CharacterValidator letter(String validationMessage) {
84
		return new CharacterValidator(VALIDATE_LETTER, defaultIfNull(
85
				LETTER_VALIDATION_MESSAGE, validationMessage));
86
	}
87
88
	/**
89
	 * Creates a validator which checks that an input character is a
90
	 * {@link Character#isDigit(char) digit}.
91
	 * 
92
	 * @param validationMessage
93
	 *            The validation message to use.
94
	 * @return The validator instance.
95
	 */
96
	public static CharacterValidator digit(String validationMessage) {
97
		return new CharacterValidator(VALIDATE_DIGIT, defaultIfNull(
98
				DIGIT_VALIDATION_MESSAGE, validationMessage));
99
	}
100
101
	/**
102
	 * Creates a validator which checks that an input character is a
103
	 * {@link Character#isLetterOrDigit(char) letter or ditig}.
104
	 * 
105
	 * @param validationMessage
106
	 *            The validation message to use.
107
	 * @return The validator instance.
108
	 */
109
	public static CharacterValidator letterOrDigit(String validationMessage) {
110
		return new CharacterValidator(VALIDATE_LETTER_OR_DIGIT, defaultIfNull(
111
				LETTER_OR_DIGIT_VALIDATION_MESSAGE, validationMessage));
112
	}
113
114
	public IStatus validate(Object value) {
115
		if (value != null) {
116
			char character = ((Character) value).charValue();
117
			if (!isValid(character)) {
118
				return ValidationStatus.error(validationMessage);
119
			}
120
		}
121
		return ValidationStatus.ok();
122
	}
123
124
	private boolean isValid(char character) {
125
		switch (validation) {
126
		case VALIDATE_NO_WHITESPACE:
127
			return !Character.isWhitespace(character);
128
		case VALIDATE_NO_SPACE:
129
			return !Character.isSpaceChar(character);
130
		case VALIDATE_LETTER:
131
			return Character.isLetter(character);
132
		case VALIDATE_DIGIT:
133
			return Character.isDigit(character);
134
		case VALIDATE_LETTER_OR_DIGIT:
135
			return Character.isLetterOrDigit(character);
136
		default:
137
			throw new IllegalArgumentException(
138
					"Unsupported validation: " + validation); //$NON-NLS-1$
139
		}
140
	}
141
142
	private static String defaultIfNull(String string, String defaultString) {
143
		return (string != null) ? string : defaultString;
144
	}
145
}
(-)src/org/eclipse/core/internal/databinding/validation/DateRangeValidator.java (+243 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.3
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
40
			.getString(BindingMessages.VALIDATE_DATE_RANGE_AFTER);
41
	private static final String AFTER_EQUAL_MESSAGE = BindingMessages
42
			.getString(BindingMessages.VALIDATE_DATE_RANGE_AFTER_EQUAL);
43
	private static final String BEFORE_MESSAGE = BindingMessages
44
			.getString(BindingMessages.VALIDATE_DATE_RANGE_BEFORE);
45
	private static final String BEFORE_EQUAL_MESSAGE = BindingMessages
46
			.getString(BindingMessages.VALIDATE_DATE_RANGE_BEFORE_EQUAL);
47
	private static final String WITHIN_RANGE_MESSAGE = BindingMessages
48
			.getString(BindingMessages.VALIDATE_DATE_RANGE_WITHIN_RANGE);
49
50
	private final Date min;
51
	private final Date max;
52
	private final int minConstraint;
53
	private final int maxConstraint;
54
	private final String validationMessage;
55
	private String formattedValidationMessage;
56
	private final DateFormat format;
57
58
	/**
59
	 * Single constructor which supports the individual date range types.
60
	 * 
61
	 * @param min
62
	 *            The min date of the range or <code>null</code> in case no
63
	 *            lower bound is defined.
64
	 * @param max
65
	 *            The max date of the range or <code>null</code> in case no
66
	 *            upper bound is defined.
67
	 * @param minConstraint
68
	 *            The type of constraint imposed by the lower bound of the
69
	 *            range.
70
	 * @param maxConstraint
71
	 *            The type of constraint imposed by the upper bound of the
72
	 *            range.
73
	 * @param validationMessage
74
	 *            The validation message pattern to use. Can be parameterized by
75
	 *            the lower and upper bound of the range, if defined.
76
	 * @param format
77
	 *            The date format to use for formatting dates in the validation
78
	 *            message.
79
	 */
80
	private DateRangeValidator(Date min, Date max, int minConstraint,
81
			int maxConstraint, String validationMessage, DateFormat format) {
82
		this.min = min;
83
		this.max = max;
84
		this.minConstraint = minConstraint;
85
		this.maxConstraint = maxConstraint;
86
		this.validationMessage = validationMessage;
87
		this.format = format;
88
	}
89
90
	/**
91
	 * Creates a validator which checks that an input date is after the given
92
	 * date.
93
	 * 
94
	 * @param date
95
	 *            The reference date of the after constraint.
96
	 * @param validationMessage
97
	 *            The validation message pattern to use. Can be parameterized
98
	 *            with the given reference date.
99
	 * @param format
100
	 *            The display format to use for formatting dates in the
101
	 *            validation message.
102
	 * @return The validator instance.
103
	 */
104
	public static DateRangeValidator after(Date date, String validationMessage,
105
			DateFormat format) {
106
		return new DateRangeValidator(date, null, AFTER, UNDEFINED,
107
				defaultIfNull(validationMessage, AFTER_MESSAGE), format);
108
	}
109
110
	/**
111
	 * Creates a validator which checks that an input date is after or on the
112
	 * given date.
113
	 * 
114
	 * @param date
115
	 *            The reference date of the after-equal constraint.
116
	 * @param validationMessage
117
	 *            The validation message pattern to use. Can be parameterized
118
	 *            with the given reference date.
119
	 * @param format
120
	 *            The display format to use for formatting dates in the
121
	 *            validation message.
122
	 * @return The validator instance.
123
	 */
124
	public static DateRangeValidator afterEqual(Date date,
125
			String validationMessage, DateFormat format) {
126
		return new DateRangeValidator(date, null, AFTER_EQUAL, UNDEFINED,
127
				defaultIfNull(validationMessage, AFTER_EQUAL_MESSAGE), format);
128
	}
129
130
	/**
131
	 * Creates a validator which checks that an input date is before the given
132
	 * date.
133
	 * 
134
	 * @param date
135
	 *            The reference date of the before constraint.
136
	 * @param validationMessage
137
	 *            The validation message pattern to use. Can be parameterized
138
	 *            with the given reference date.
139
	 * @param format
140
	 *            The display format to use for formatting dates in the
141
	 *            validation message.
142
	 * @return The validator instance.
143
	 */
144
	public static DateRangeValidator before(Date date,
145
			String validationMessage, DateFormat format) {
146
		return new DateRangeValidator(null, date, UNDEFINED, BEFORE,
147
				defaultIfNull(validationMessage, BEFORE_MESSAGE), format);
148
	}
149
150
	/**
151
	 * Creates a validator which checks that an input date is before or on the
152
	 * given date.
153
	 * 
154
	 * @param date
155
	 *            The reference date of the before-equal constraint.
156
	 * @param validationMessage
157
	 *            The validation message pattern to use. Can be parameterized
158
	 *            with the given reference date.
159
	 * @param format
160
	 *            The display format to use for formatting dates in the
161
	 *            validation message.
162
	 * @return The validator instance.
163
	 */
164
	public static DateRangeValidator beforeEqual(Date date,
165
			String validationMessage, DateFormat format) {
166
		return new DateRangeValidator(null, date, UNDEFINED, BEFORE_EQUAL,
167
				defaultIfNull(validationMessage, BEFORE_EQUAL_MESSAGE), format);
168
	}
169
170
	/**
171
	 * Creates a validator which checks that an input date is within the given
172
	 * range.
173
	 * 
174
	 * @param min
175
	 *            The lower bound of the range (inclusive).
176
	 * @param max
177
	 *            The upper bound of the range (inclusive).
178
	 * @param validationMessage
179
	 *            The validation message pattern to use. Can be parameterized
180
	 *            with the range's lower and upper bound.
181
	 * @param format
182
	 *            The display format to use for formatting dates in the
183
	 *            validation message.
184
	 * @return The validator instance.
185
	 */
186
	public static DateRangeValidator range(Date min, Date max,
187
			String validationMessage, DateFormat format) {
188
		return new DateRangeValidator(min, max, AFTER_EQUAL, BEFORE_EQUAL,
189
				defaultIfNull(validationMessage, WITHIN_RANGE_MESSAGE), format);
190
	}
191
192
	public IStatus validate(Object value) {
193
		if (value != null) {
194
			Date date = (Date) value;
195
			if ((min != null && !fulfillsConstraint(date, min, minConstraint))
196
					|| (max != null && !fulfillsConstraint(date, max,
197
							maxConstraint))) {
198
				return ValidationStatus.error(getFormattedValidationMessage());
199
			}
200
		}
201
		return ValidationStatus.ok();
202
	}
203
204
	private boolean fulfillsConstraint(Date date1, Date date2, int constraint) {
205
		switch (constraint) {
206
		case AFTER:
207
			return date1.after(date2);
208
		case AFTER_EQUAL:
209
			return date1.after(date2) || date1.equals(date2);
210
		case BEFORE:
211
			return date1.before(date2);
212
		case BEFORE_EQUAL:
213
			return date1.before(date2) || date1.equals(date2);
214
		case UNDEFINED:
215
		default:
216
			throw new IllegalArgumentException(
217
					"Unsupported constraint: " + constraint); //$NON-NLS-1$
218
		}
219
	}
220
221
	private synchronized String getFormattedValidationMessage() {
222
		if (formattedValidationMessage == null) {
223
			formattedValidationMessage = MessageFormat.format(
224
					validationMessage, getValidationMessageArguments());
225
		}
226
		return formattedValidationMessage;
227
	}
228
229
	private String[] getValidationMessageArguments() {
230
		synchronized (format) {
231
			if (min == null) {
232
				return new String[] { format.format(max) };
233
			} else if (max == null) {
234
				return new String[] { format.format(min) };
235
			}
236
			return new String[] { format.format(min), format.format(max) };
237
		}
238
	}
239
240
	private static String defaultIfNull(String string, String defaultString) {
241
		return (string != null) ? string : defaultString;
242
	}
243
}
(-)src/org/eclipse/core/internal/databinding/validation/DecimalPrecisionValidator.java (+108 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
 * Provides validations for the precision of decimal numbers.
26
 * 
27
 * @since 1.3
28
 */
29
public class DecimalPrecisionValidator implements IValidator {
30
31
	private static final String MAX_PRECISION_VALIDATION_MESSAGE = BindingMessages
32
			.getString(BindingMessages.VALIDATE_DECIMAL_MAX_PRECISION);
33
34
	private final int maxPrecision;
35
36
	private final String validationMessage;
37
38
	private String formattedValidationMessage;
39
40
	private final NumberFormat precisionFormat;
41
42
	private DecimalPrecisionValidator(int maxPrecision,
43
			String validationMessage, NumberFormat precisionFormat) {
44
		this.maxPrecision = maxPrecision;
45
		this.validationMessage = validationMessage != null ? validationMessage
46
				: MAX_PRECISION_VALIDATION_MESSAGE;
47
		this.precisionFormat = precisionFormat;
48
	}
49
50
	/**
51
	 * Creates a validator which checks that an input decimal has a precision
52
	 * which is less or equal to the given precision.
53
	 * 
54
	 * @param maxPrecision
55
	 *            The maximum precision to enforce on the input decimal.
56
	 * @param validationMessage
57
	 *            The validation message pattern to use. Can be parameterized
58
	 *            with the maximum precision to be enforced.
59
	 * @param precisionFormat
60
	 *            The display format to use for formatting the precision in the
61
	 *            validation message.
62
	 * @return The validator instance.
63
	 */
64
	public static DecimalPrecisionValidator max(int maxPrecision,
65
			String validationMessage, NumberFormat precisionFormat) {
66
		return new DecimalPrecisionValidator(maxPrecision, validationMessage,
67
				precisionFormat);
68
	}
69
70
	public IStatus validate(Object value) {
71
		if (value != null) {
72
			Number number = (Number) value;
73
			final int precision;
74
			if (number instanceof BigDecimal) {
75
				precision = computePrecision(((BigDecimal) number));
76
			} else {
77
				precision = computePrecision(new BigDecimal(number
78
						.doubleValue()));
79
			}
80
			if (precision > maxPrecision) {
81
				return ValidationStatus.error(getFormattedValidationMessage());
82
			}
83
		}
84
		return ValidationStatus.ok();
85
	}
86
87
	private static int computePrecision(BigDecimal bigDecimal) {
88
		// In Java 1.4, there is no direct API for retrieving the precision of
89
		// a BigDecimal so we use the length of the string representation of the
90
		// unscaled BigInteger value of the BigDecimal to actually compute it.
91
		return bigDecimal.unscaledValue().abs().toString().length();
92
	}
93
94
	private synchronized String getFormattedValidationMessage() {
95
		if (formattedValidationMessage == null) {
96
			formattedValidationMessage = MessageFormat.format(
97
					validationMessage, getValidationMessageArguments());
98
		}
99
		return formattedValidationMessage;
100
	}
101
102
	private String[] getValidationMessageArguments() {
103
		synchronized (precisionFormat) {
104
			return new String[] { precisionFormat.format(new Integer(
105
					maxPrecision)) };
106
		}
107
	}
108
}
(-)src/org/eclipse/core/internal/databinding/validation/DecimalScaleValidator.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.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
 * Provides validations for the scale of decimal numbers.
26
 * 
27
 * @since 1.3
28
 */
29
public class DecimalScaleValidator implements IValidator {
30
31
	private static final String MAX_SCALE_VALIDATION_MESSAGE = BindingMessages
32
			.getString(BindingMessages.VALIDATE_DECIMAL_MAX_SCALE);
33
34
	private final int maxScale;
35
36
	private final String validationMessage;
37
38
	private String formattedValidationMessage;
39
40
	private final NumberFormat scaleFormat;
41
42
	private DecimalScaleValidator(int maxScale, String validationMessage,
43
			NumberFormat scaleFormat) {
44
		this.maxScale = maxScale;
45
		this.validationMessage = validationMessage != null ? validationMessage
46
				: MAX_SCALE_VALIDATION_MESSAGE;
47
		this.scaleFormat = scaleFormat;
48
	}
49
50
	/**
51
	 * Creates a validator which checks that an input decimal has a scale which
52
	 * is less or equal to the given scale.
53
	 * 
54
	 * @param maxScale
55
	 *            The maximum scale to enforce on the input decimal.
56
	 * @param validationMessage
57
	 *            The validation message pattern to use. Can be parameterized
58
	 *            with the maximum scale to be enforced.
59
	 * @param scaleFormat
60
	 *            The display format to use for formatting the scale in the
61
	 *            validation message.
62
	 * @return The validator instance.
63
	 */
64
	public static DecimalScaleValidator max(int maxScale,
65
			String validationMessage, NumberFormat scaleFormat) {
66
		return new DecimalScaleValidator(maxScale, validationMessage,
67
				scaleFormat);
68
	}
69
70
	public IStatus validate(Object value) {
71
		if (value != null) {
72
			Number number = (Number) value;
73
			final int scale;
74
			if (number instanceof BigDecimal) {
75
				scale = ((BigDecimal) number).scale();
76
			} else {
77
				scale = new BigDecimal(number.doubleValue()).scale();
78
			}
79
			if (scale > maxScale) {
80
				return ValidationStatus.error(getFormattedValidationMessage());
81
			}
82
		}
83
		return ValidationStatus.ok();
84
	}
85
86
	private synchronized String getFormattedValidationMessage() {
87
		if (formattedValidationMessage == null) {
88
			formattedValidationMessage = MessageFormat.format(
89
					validationMessage, getValidationMessageArguments());
90
		}
91
		return formattedValidationMessage;
92
	}
93
94
	private String[] getValidationMessageArguments() {
95
		synchronized (scaleFormat) {
96
			return new String[] { scaleFormat.format(new Integer(maxScale)) };
97
		}
98
	}
99
}
(-)src/org/eclipse/core/internal/databinding/validation/NonEmptyStringValidator.java (+51 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.3
21
 */
22
public class NonEmptyStringValidator implements IValidator {
23
24
	private static final String NON_EMPTY_STRING_VALIDATION_MESSAGE = BindingMessages
25
			.getString(BindingMessages.VALIDATE_NON_EMPTY_STRING);
26
27
	private final String validationMessage;
28
29
	/**
30
	 * 
31
	 */
32
	public NonEmptyStringValidator() {
33
		this(null);
34
	}
35
36
	/**
37
	 * @param validationMessage
38
	 */
39
	public NonEmptyStringValidator(String validationMessage) {
40
		this.validationMessage = validationMessage != null ? validationMessage
41
				: NON_EMPTY_STRING_VALIDATION_MESSAGE;
42
	}
43
44
	public IStatus validate(Object value) {
45
		String input = (String) value;
46
		if (input == null || input.length() == 0) {
47
			return ValidationStatus.error(validationMessage);
48
		}
49
		return ValidationStatus.ok();
50
	}
51
}
(-)src/org/eclipse/core/internal/databinding/validation/NonNullValidator.java (+43 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.3
21
 */
22
public class NonNullValidator implements IValidator {
23
24
	private static final String NON_NULL_VALIDATION_MESSAGE = BindingMessages
25
			.getString(BindingMessages.VALIDATE_NON_NULL);
26
27
	private final String validationMessage;
28
29
	/**
30
	 * @param validationMessage
31
	 */
32
	public NonNullValidator(String validationMessage) {
33
		this.validationMessage = validationMessage != null ? validationMessage
34
				: NON_NULL_VALIDATION_MESSAGE;
35
	}
36
37
	public IStatus validate(Object value) {
38
		if (value == null) {
39
			return ValidationStatus.error(validationMessage);
40
		}
41
		return ValidationStatus.ok();
42
	}
43
}
(-)src/org/eclipse/core/internal/databinding/validation/NumberRangeValidator.java (+285 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
 * @param <N>
27
 * 
28
 * @since 1.3
29
 */
30
public class NumberRangeValidator<N extends Number & Comparable<N>> implements
31
		IValidator {
32
33
	// The set of constraint types for the lower/upper bound of the date range.
34
	protected static final int UNDEFINED = -1;
35
	protected static final int GREATER = 0;
36
	protected static final int GREATER_EQUAL = 1;
37
	protected static final int LESS = 2;
38
	protected static final int LESS_EQUAL = 3;
39
40
	// The default validation messages.
41
	protected static final String GREATER_MESSAGE = BindingMessages
42
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_GREATER);
43
	protected static final String GREATER_EQUAL_MESSAGE = BindingMessages
44
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_GREATER_EQUAL);
45
	protected static final String LESS_MESSAGE = BindingMessages
46
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_LESS);
47
	protected static final String LESS_EQUAL_MESSAGE = BindingMessages
48
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_LESS_EQUAL);
49
	protected static final String WITHIN_RANGE_MESSAGE = BindingMessages
50
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_WITHIN_RANGE);
51
	protected static final String POSITIVE_MESSAGE = BindingMessages
52
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_POSITIVE);
53
	protected static final String NON_NEGATIVE_MESSAGE = BindingMessages
54
			.getString(BindingMessages.VALIDATE_NUMBER_RANGE_NON_NEGATIVE);
55
56
	private final N min;
57
	private final N max;
58
	private final int minConstraint;
59
	private final int maxConstraint;
60
	private final String validationMessage;
61
	private String formattedValidationMessage;
62
	private final NumberFormat format;
63
64
	/**
65
	 * Single constructor which supports the individual number range types.
66
	 * 
67
	 * @param min
68
	 *            The min number of the range or <code>null</code> in case no
69
	 *            lower bound is defined.
70
	 * @param max
71
	 *            The max number of the range or <code>null</code> in case no
72
	 *            upper bound is defined.
73
	 * @param minConstraint
74
	 *            The type of constraint imposed by the lower bound of the
75
	 *            range.
76
	 * @param maxConstraint
77
	 *            The type of constraint imposed by the upper bound of the
78
	 *            range.
79
	 * @param validationMessage
80
	 *            The validation message pattern to use. Can be parameterized by
81
	 *            the lower and upper bound of the range, if defined.
82
	 * @param format
83
	 *            The integer format to use for formatting numbers in the
84
	 *            validation message.
85
	 */
86
	protected NumberRangeValidator(N min, N max, int minConstraint,
87
			int maxConstraint, String validationMessage, NumberFormat format) {
88
		this.min = min;
89
		this.max = max;
90
		this.minConstraint = minConstraint;
91
		this.maxConstraint = maxConstraint;
92
		this.validationMessage = validationMessage;
93
		this.format = format;
94
	}
95
96
	/**
97
	 * Creates a validator which checks that an input integer is greater than
98
	 * the given number.
99
	 * 
100
	 * @param <M>
101
	 * @param number
102
	 *            The reference number of the greater constraint.
103
	 * @param validationMessage
104
	 *            The validation message pattern to use. Can be parameterized
105
	 *            with the given reference number.
106
	 * @param format
107
	 *            The display format to use for formatting integers in the
108
	 *            validation message.
109
	 * @return The validator instance.
110
	 */
111
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> greater(
112
			M number, String validationMessage, NumberFormat format) {
113
		return new NumberRangeValidator<M>(number, null, GREATER, UNDEFINED,
114
				defaultIfNull(validationMessage, GREATER_MESSAGE), format);
115
	}
116
117
	/**
118
	 * Creates a validator which checks that an input integer is greater than or
119
	 * equal to the given number.
120
	 * 
121
	 * @param <M>
122
	 * @param number
123
	 *            The reference number of the greater-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 integers in the
129
	 *            validation message.
130
	 * @return The validator instance.
131
	 */
132
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> greaterEqual(
133
			M number, String validationMessage, NumberFormat format) {
134
		return new NumberRangeValidator<M>(number, null, GREATER_EQUAL,
135
				UNDEFINED, defaultIfNull(validationMessage,
136
						GREATER_EQUAL_MESSAGE), format);
137
	}
138
139
	/**
140
	 * Creates a validator which checks that an input integer is less than the
141
	 * given number.
142
	 * 
143
	 * @param <M>
144
	 * @param number
145
	 *            The reference number of the less constraint.
146
	 * @param validationMessage
147
	 *            The validation message pattern to use. Can be parameterized
148
	 *            with the given reference number.
149
	 * @param format
150
	 *            The display format to use for formatting integers in the
151
	 *            validation message.
152
	 * @return The validator instance.
153
	 */
154
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> less(
155
			M number, String validationMessage, NumberFormat format) {
156
		return new NumberRangeValidator<M>(null, number, UNDEFINED, LESS,
157
				defaultIfNull(validationMessage, LESS_MESSAGE), format);
158
	}
159
160
	/**
161
	 * Creates a validator which checks that an input integer is less than or
162
	 * equal to the given number.
163
	 * 
164
	 * @param <M>
165
	 * @param number
166
	 *            The reference number of the less-equal constraint.
167
	 * @param validationMessage
168
	 *            The validation message pattern to use. Can be parameterized
169
	 *            with the given reference number.
170
	 * @param format
171
	 *            The display format to use for formatting integers in the
172
	 *            validation message.
173
	 * @return The validator instance.
174
	 */
175
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> lessEqual(
176
			M number, String validationMessage, NumberFormat format) {
177
		return new NumberRangeValidator<M>(null, number, UNDEFINED, LESS_EQUAL,
178
				defaultIfNull(validationMessage, LESS_EQUAL_MESSAGE), format);
179
	}
180
181
	/**
182
	 * Creates a validator which checks that an input integer is within the
183
	 * given range.
184
	 * 
185
	 * @param <M>
186
	 * @param min
187
	 *            The lower bound of the range (inclusive).
188
	 * @param max
189
	 *            The upper bound of the range (inclusive).
190
	 * @param validationMessage
191
	 *            The validation message pattern to use. Can be parameterized
192
	 *            with the range's lower and upper bound.
193
	 * @param format
194
	 *            The display format to use for formatting integers in the
195
	 *            validation message.
196
	 * @return The validator instance.
197
	 */
198
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> range(
199
			M min, M max, String validationMessage, NumberFormat format) {
200
		return new NumberRangeValidator<M>(min, max, GREATER_EQUAL, LESS_EQUAL,
201
				defaultIfNull(validationMessage, WITHIN_RANGE_MESSAGE), format);
202
	}
203
204
	/**
205
	 * 
206
	 * @param <M>
207
	 * @param one
208
	 * @param validationMessage
209
	 * @param format
210
	 * @return .
211
	 */
212
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> positive(
213
			M one, String validationMessage, NumberFormat format) {
214
		return new NumberRangeValidator<M>(one, null, GREATER_EQUAL, UNDEFINED,
215
				defaultIfNull(validationMessage, POSITIVE_MESSAGE), format);
216
	}
217
218
	/**
219
	 * 
220
	 * @param <M>
221
	 * @param zero
222
	 * @param validationMessage
223
	 * @param format
224
	 * @return .
225
	 */
226
	public static <M extends Number & Comparable<M>> NumberRangeValidator<M> nonNegative(
227
			M zero, String validationMessage, NumberFormat format) {
228
		return new NumberRangeValidator<M>(zero, null, GREATER_EQUAL,
229
				UNDEFINED, defaultIfNull(validationMessage,
230
						NON_NEGATIVE_MESSAGE), format);
231
	}
232
233
	public IStatus validate(Object value) {
234
		if (value != null) {
235
			N number = (N) value;
236
			if ((min != null && !fulfillsConstraint(number, min, minConstraint))
237
					|| (max != null && !fulfillsConstraint(number, max,
238
							maxConstraint))) {
239
				return ValidationStatus.error(getFormattedValidationMessage());
240
			}
241
		}
242
		return ValidationStatus.ok();
243
	}
244
245
	private boolean fulfillsConstraint(N number1, N number2, int constraint) {
246
		int compareResult = number1.compareTo(number2);
247
		switch (constraint) {
248
		case GREATER:
249
			return compareResult > 0;
250
		case GREATER_EQUAL:
251
			return compareResult >= 0;
252
		case LESS:
253
			return compareResult < 0;
254
		case LESS_EQUAL:
255
			return compareResult <= 0;
256
		case UNDEFINED:
257
		default:
258
			throw new IllegalArgumentException(
259
					"Unsupported constraint: " + constraint); //$NON-NLS-1$
260
		}
261
	}
262
263
	private synchronized String getFormattedValidationMessage() {
264
		if (formattedValidationMessage == null) {
265
			formattedValidationMessage = MessageFormat.format(
266
					validationMessage, getValidationMessageArguments());
267
		}
268
		return formattedValidationMessage;
269
	}
270
271
	private String[] getValidationMessageArguments() {
272
		synchronized (format) {
273
			if (min == null) {
274
				return new String[] { format.format(max) };
275
			} else if (max == null) {
276
				return new String[] { format.format(min) };
277
			}
278
			return new String[] { format.format(min), format.format(max) };
279
		}
280
	}
281
282
	private static String defaultIfNull(String string, String defaultString) {
283
		return (string != null) ? string : defaultString;
284
	}
285
}
(-)src/org/eclipse/core/internal/databinding/validation/StringLengthValidator.java (+167 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.3
27
 */
28
public class StringLengthValidator implements IValidator {
29
30
	// The default validation messages.
31
	private static final String MIN_LENGTH_MESSAGE = BindingMessages
32
			.getString(BindingMessages.VALIDATE_STRING_LENGTH_MIN);
33
	private static final String MAX_LENGTH_MESSAGE = BindingMessages
34
			.getString(BindingMessages.VALIDATE_STRING_LENGTH_MAX);
35
	private static final String LENGTH_RANGE_MESSAGE = BindingMessages
36
			.getString(BindingMessages.VALIDATE_STRING_LENGTH_RANGE);
37
38
	private final Integer minLength;
39
	private final Integer maxLength;
40
	private final String validationMessage;
41
	private String formattedValidationMessage;
42
	private final NumberFormat format;
43
44
	/**
45
	 * Creates a string length validator defining a minimum and/or maximum
46
	 * length for a string.
47
	 * 
48
	 * @param minLength
49
	 *            The minimum length of the string or <code>null</code> in case
50
	 *            no minimum length is defined.
51
	 * @param maxLength
52
	 *            The maximum length of the string or <code>null</code> in case
53
	 *            no maximum length is defined.
54
	 * @param validationMessage
55
	 *            The validation message pattern to use. Can be parameterized by
56
	 *            the lower and upper bound of the range, if defined.
57
	 * @param format
58
	 *            The number format to use for formatting integers (the length
59
	 *            bounds) in the validation message.
60
	 */
61
	private StringLengthValidator(Integer minLength, Integer maxLength,
62
			String validationMessage, NumberFormat format) {
63
		this.minLength = minLength;
64
		this.maxLength = maxLength;
65
		this.validationMessage = validationMessage;
66
		this.format = format;
67
	}
68
69
	/**
70
	 * Creates a validator which checks that an input string has the given
71
	 * minimum length.
72
	 * 
73
	 * @param minLength
74
	 *            The minimum length which the input string must have.
75
	 * @param validationMessage
76
	 *            The validation message pattern to use. Can be parameterized
77
	 *            with the given minimum length.
78
	 * @param format
79
	 *            The display format to use for formatting integers (the minimum
80
	 *            length) in the validation message.
81
	 * @return The validator instance.
82
	 */
83
	public static StringLengthValidator min(int minLength,
84
			String validationMessage, NumberFormat format) {
85
		return new StringLengthValidator(new Integer(minLength), null,
86
				defaultIfNull(validationMessage, MIN_LENGTH_MESSAGE), format);
87
	}
88
89
	/**
90
	 * Creates a validator which checks that an input string has the given
91
	 * maximum length.
92
	 * 
93
	 * @param maxLength
94
	 *            The maximum length which the input string must have.
95
	 * @param validationMessage
96
	 *            The validation message pattern to use. Can be parameterized
97
	 *            with the given maximum length.
98
	 * @param format
99
	 *            The display format to use for formatting integers (the maximum
100
	 *            length) in the validation message.
101
	 * @return The validator instance.
102
	 */
103
	public static StringLengthValidator max(int maxLength,
104
			String validationMessage, NumberFormat format) {
105
		return new StringLengthValidator(null, new Integer(maxLength),
106
				defaultIfNull(validationMessage, MAX_LENGTH_MESSAGE), format);
107
	}
108
109
	/**
110
	 * Creates a validator which checks that the length of an input string lies
111
	 * in the given range.
112
	 * 
113
	 * @param minLength
114
	 *            The minimum length which the input string must have.
115
	 * @param maxLength
116
	 *            The maximum length which the input string must have.
117
	 * @param validationMessage
118
	 *            The validation message pattern to use. Can be parameterized
119
	 *            with the given minimum and maximum lengths.
120
	 * @param format
121
	 *            The display format to use for formatting integers (the
122
	 *            minimum/maximum length) in the validation message.
123
	 * @return The validator instance.
124
	 */
125
	public static StringLengthValidator range(int minLength, int maxLength,
126
			String validationMessage, NumberFormat format) {
127
		return new StringLengthValidator(new Integer(minLength), new Integer(
128
				maxLength), defaultIfNull(validationMessage,
129
				LENGTH_RANGE_MESSAGE), format);
130
	}
131
132
	public IStatus validate(Object value) {
133
		String input = (String) value;
134
		if (input != null) {
135
			int inputLength = input.length();
136
			if ((minLength != null && inputLength < minLength.intValue())
137
					|| maxLength != null && inputLength > maxLength.intValue()) {
138
				return ValidationStatus.error(getFormattedValidationMessage());
139
			}
140
		}
141
		return ValidationStatus.ok();
142
	}
143
144
	private synchronized String getFormattedValidationMessage() {
145
		if (formattedValidationMessage == null) {
146
			formattedValidationMessage = MessageFormat.format(
147
					validationMessage, getValidationMessageArguments());
148
		}
149
		return formattedValidationMessage;
150
	}
151
152
	private String[] getValidationMessageArguments() {
153
		synchronized (format) {
154
			if (minLength == null) {
155
				return new String[] { format.format(maxLength) };
156
			} else if (maxLength == null) {
157
				return new String[] { format.format(minLength) };
158
			}
159
			return new String[] { format.format(minLength),
160
					format.format(maxLength) };
161
		}
162
	}
163
164
	private static String defaultIfNull(String string, String defaultString) {
165
		return (string != null) ? string : defaultString;
166
	}
167
}
(-)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.3
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/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.3
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/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.3
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/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.3
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/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 {
(-).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/snippets/Snippet035Editing.java (+283 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.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.Editing;
22
import org.eclipse.core.databinding.editing.NumberEditing;
23
import org.eclipse.core.databinding.editing.StringEditing;
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.NumberConstraints;
32
import org.eclipse.core.runtime.IStatus;
33
import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;
34
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
35
import org.eclipse.jface.databinding.swt.SWTObservables;
36
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
37
import org.eclipse.jface.examples.databinding.util.EditingFactory;
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
		StringEditing emailEditing = EditingFactory.forEmailString();
101
		emailEditing.modelConstraints().required();
102
		bindTextField(emailText, new WritableValue(), emailEditing);
103
104
		// Edit a required, positive short using the default validation message.
105
		Text positiveText = createTextField(section, "Positive short*");
106
		NumberEditing<Short> positiveEditing = EditingFactory.forShort();
107
		positiveEditing.modelConstraints().required().positive();
108
		bindTextField(positiveText, new WritableValue(), positiveEditing);
109
110
		// Edit a required double with a maximum of five significant and two
111
		// fractional digits.
112
		Text priceText = createTextField(section, "Price [$]*");
113
		NumberEditing<Double> priceEditing = EditingFactory.forDouble();
114
		priceEditing.modelConstraints().required().maxPrecision(5).maxScale(2);
115
		bindTextField(priceText, new WritableValue(), priceEditing);
116
117
		// Edit an integer within the range [1, 100] using the default
118
		// validation message.
119
		Text rangeText = createTextField(section, "Value in [1, 100]");
120
		NumberEditing<Integer> rangeEditing = EditingFactory.forInteger();
121
		rangeEditing.modelConstraints().range(1, 100);
122
		bindTextField(rangeText, new WritableValue(0, null), rangeEditing);
123
124
		// Edit a percentage value which must lie within [0, 100] using a custom
125
		// validation message which indicates that the value actually represents
126
		// a percentage value. Note that the constraint message must be specified
127
		// before the actual constraint.
128
		Text percentText = createTextField(section, "Percentage [%]");
129
		NumberEditing<Integer> percentEditing = EditingFactory.forInteger();
130
		percentEditing.modelConstraints()
131
			.rangeMessage("Please specify a percentage value within [{0}, {1}].")
132
			.range(0, 100);
133
		bindTextField(percentText, new WritableValue(-1, null), percentEditing);
134
135
		// Edit a hex integer within the range [0x00, 0xff]. The range validation
136
		// message will display the range boundaries in hex format as well.
137
		Text hexText = createTextField(section, "Hex value in [0x00, 0xff]");
138
		NumberEditing<Integer> hexEditing = EditingFactory.forHexInteger(2);
139
		hexEditing.modelConstraints().range(0x00, 0xff);
140
		bindTextField(hexText, new WritableValue(0, null), hexEditing);
141
142
		// Edit a boolean value.
143
		Text boolText = createTextField(section, "Boolean value");
144
		BooleanEditing boolEditing = EditingFactory.forBoolean();
145
		bindTextField(boolText, new WritableValue(true, null), boolEditing);
146
147
		// Edit a value within [1, 10] or [20, 30].
148
		Text rangesText = createTextField(section, "Value in [1, 10] or [20, 30]");
149
		NumberEditing<Integer> rangesEditing = EditingFactory.forInteger();
150
		rangesEditing.modelConstraints().addValidator(new RangesValidator(1, 10, 20, 30));
151
		bindTextField(rangesText, new WritableValue(), rangesEditing);
152
	}
153
154
	private void createListSection(Composite parent) {
155
		Group section = createSectionGroup(parent, "List bindings", true);
156
157
		// Our date should be >= 01.01.1990.
158
		Calendar year1990Calendar = Calendar.getInstance();
159
		year1990Calendar.clear();
160
		year1990Calendar.set(1990, 0, 1);
161
		Date year1990 = year1990Calendar.getTime();
162
163
		// Edit a date supporting the default input/display patterns.
164
		Text dateText = createTextField(section, "Date");
165
		DateEditing dateEditing = EditingFactory.forDate();
166
		dateEditing.modelConstraints().afterEqual(year1990);
167
		final WritableValue dateObservable = new WritableValue();
168
		final Binding dateBinding = bindTextField(dateText, dateObservable, dateEditing);
169
170
		// Create a list to which the dates are added when the user hits ENTER.
171
		new Label(section, SWT.LEFT);
172
		ListViewer dateListViewer = new ListViewer(section);
173
		GridDataFactory.fillDefaults().grab(true, true).hint(150, 200).applyTo(dateListViewer.getList());
174
175
		dateListViewer.setContentProvider(new ObservableListContentProvider());
176
		dateListViewer.setLabelProvider(new LabelProvider());
177
178
		// We use the same DateEditing object as for the text field above to
179
		// create a list binding which maps the entered dates to their string
180
		// representation which is then set as input on the ListViewer.
181
		final WritableList targetDateList = new WritableList();
182
		final WritableList modelDateList = new WritableList();
183
		dateEditing.bindList(dbc, targetDateList, modelDateList);
184
185
		// Set the list containing the string representation of the dates as input.
186
		dateListViewer.setInput(targetDateList);
187
188
		// Add the current date in the text field when the user hits ENTER.
189
		dateText.addSelectionListener(new SelectionAdapter() {
190
			public void widgetDefaultSelected(SelectionEvent e) {
191
				IStatus dateValidationStatus = (IStatus) dateBinding.getValidationStatus().getValue();
192
				Date date = (Date) dateObservable.getValue();
193
				if (dateValidationStatus.isOK() && date != null) {
194
					modelDateList.add(date);
195
				}
196
			}
197
		});
198
	}
199
200
	private Binding bindTextField(Text text, IObservableValue modelValue, Editing editing) {
201
		// Create the binding using the editing object.
202
		ISWTObservableValue textObservable = SWTObservables.observeText(text, SWT.Modify);
203
		Binding binding = editing.bindValue(dbc, textObservable, modelValue);
204
205
		// Decorate the control with the validation status.
206
		ControlDecorationSupport.create(binding, SWT.TOP);
207
208
		// Re-format when the text field looses the focus in order to always
209
		// display the model in the default format in case multiple input formats
210
		// are supported.
211
		formatOnFocusOut(text, binding);
212
213
		return binding;
214
	}
215
216
	private static void formatOnFocusOut(final Control control, final Binding binding) {
217
		control.addFocusListener(new FocusAdapter() {
218
			public void focusLost(FocusEvent e) {
219
				IStatus dateValidationStatus = (IStatus) binding.getValidationStatus().getValue();
220
				if (dateValidationStatus.isOK()) {
221
					binding.updateModelToTarget();
222
				}
223
			}
224
		});
225
	}
226
227
	private static Group createSectionGroup(Composite parent, String groupText, boolean grabVertical) {
228
		Group section = new Group(parent, SWT.SHADOW_ETCHED_IN);
229
		section.setText(groupText);
230
		GridLayoutFactory.fillDefaults()
231
				.numColumns(2)
232
				.equalWidth(false)
233
				.margins(5, 5)
234
				.spacing(15, 5)
235
				.applyTo(section);
236
		GridDataFactory.fillDefaults().grab(true, grabVertical).applyTo(section);
237
		return section;
238
	}
239
240
	private static Text createTextField(Composite parent, String labelText) {
241
		Label label = new Label(parent, SWT.LEFT);
242
		label.setText(labelText);
243
		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
244
245
		final Text text = new Text(parent, SWT.BORDER);
246
		GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).applyTo(text);
247
248
		// Select the text when gaining focus.
249
		text.addFocusListener(new FocusAdapter() {
250
			public void focusGained(FocusEvent e) {
251
				text.selectAll();
252
			}
253
		});
254
255
		return text;
256
	}
257
258
	private static final class RangesValidator implements IValidator {
259
260
		private final String validationMessage;
261
262
		private final IValidator validator;
263
264
		public RangesValidator(int min1, int max1, int min2, int max2) {
265
			this.validationMessage = MessageFormat.format(
266
					"The value must lie within [{0}, {1}] or [{2}, {3}].",
267
					new Object[] { min1, max1, min2, max2 });
268
			this.validator =
269
				NumberConstraints.forInteger()
270
					.range(min1, max1)
271
					.range(min2, max2)
272
					.aggregationPolicy(Constraints.Aggregation.MIN_SEVERITY)
273
					.createValidator();
274
		}
275
276
		public IStatus validate(Object value) {
277
			if (!validator.validate(value).isOK()) {
278
				return ValidationStatus.error(validationMessage);
279
			}
280
			return ValidationStatus.ok();
281
		}
282
	}
283
}
(-)src/org/eclipse/jface/examples/databinding/snippets/Snippet036EditingTable.java (+261 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.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.NumberEditing;
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.fieldassist.ControlDecorationSupport;
30
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
31
import org.eclipse.jface.databinding.swt.SWTObservables;
32
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
33
import org.eclipse.jface.databinding.viewers.ViewersObservables;
34
import org.eclipse.jface.examples.databinding.ModelObject;
35
import org.eclipse.jface.examples.databinding.util.EditingFactory;
36
import org.eclipse.jface.examples.databinding.util.ObservableMapEditingCellLabelProvider;
37
import org.eclipse.jface.examples.databinding.util.ObservableMapEditingSupport;
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 StringEditing nameEditing;
58
59
	private NumberEditing<Integer> ageEditing;
60
61
	private DateEditing bdayEditing;
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
		nameEditing = EditingFactory.forString();
90
		nameEditing.modelConstraints().required();
91
92
		ageEditing = EditingFactory.forInteger();
93
		ageEditing.modelConstraints().required().nonNegative();
94
95
		bdayEditing = EditingFactory.forDate();
96
		bdayEditing.modelConstraints().before(new Date());
97
98
		dbc = new DataBindingContext();
99
100
		createTableSection(shell);
101
		createFieldSection(shell);
102
103
		shell.pack();
104
		shell.open();
105
106
		return shell;
107
	}
108
109
	private void createTableSection(Composite parent) {
110
		Group section = createSectionGroup(parent, 1);
111
112
		tableViewer = new TableViewer(section, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
113
		GridDataFactory.fillDefaults().grab(true, true).hint(350, 250).applyTo(tableViewer.getTable());
114
		tableViewer.getTable().setHeaderVisible(true);
115
		tableViewer.getTable().setLinesVisible(true);
116
117
		ObservableListContentProvider contentProvider = new ObservableListContentProvider();
118
		tableViewer.setContentProvider(contentProvider);
119
		IObservableSet contentElements = contentProvider.getKnownElements();
120
121
		IObservableMap nameMap = BeansObservables.observeMap(contentElements, "name");
122
		createColumn("Name*", 150, nameMap, nameEditing);
123
124
		IObservableMap ageMap = BeansObservables.observeMap(contentElements, "age");
125
		createColumn("Age*", 50, ageMap, ageEditing);
126
127
		IObservableMap bdayMap = BeansObservables.observeMap(contentElements, "birthday");
128
		createColumn("Birthday", 80, bdayMap, bdayEditing);
129
130
		WritableList people = new WritableList();
131
		people.add(new Person("John Doe", 27));
132
		people.add(new Person("Steve Northover", 33));
133
		people.add(new Person("Grant Gayed", 54));
134
		people.add(new Person("Veronika Irvine", 25));
135
		people.add(new Person("Mike Wilson", 44));
136
		people.add(new Person("Christophe Cornu", 37));
137
		people.add(new Person("Lynne Kues", 65));
138
		people.add(new Person("Silenio Quarti", 15));
139
140
		tableViewer.setInput(people);
141
142
		tableViewer.setSelection(new StructuredSelection(people.get(0)));
143
	}
144
145
	private TableViewerColumn createColumn(String text, int width, IObservableMap attributeMap, Editing modelEditing) {
146
		TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
147
		column.getColumn().setText(text);
148
		column.getColumn().setWidth(width);
149
		column.setLabelProvider(new ObservableMapEditingCellLabelProvider(attributeMap, modelEditing));
150
		column.setEditingSupport(new ObservableMapEditingSupport(tableViewer, attributeMap, modelEditing));
151
		return column;
152
	}
153
154
	private void createFieldSection(Composite parent) {
155
		final Group section = createSectionGroup(parent, 2);
156
157
		final IObservableValue personObservable = ViewersObservables.observeSingleSelection(tableViewer);
158
159
		Text nameText = createTextField(section, "Name*");
160
		IObservableValue nameObservable = BeansObservables.observeDetailValue(personObservable, "name", null);
161
		bindTextField(nameText, nameObservable, nameEditing);
162
163
		Text ageText = createTextField(section, "Age*");
164
		IObservableValue ageObservable = BeansObservables.observeDetailValue(personObservable, "age", null);
165
		bindTextField(ageText, ageObservable, ageEditing);
166
167
		Text bdayText = createTextField(section, "Birthday");
168
		IObservableValue bdayObservable = BeansObservables.observeDetailValue(personObservable, "birthday", null);
169
		bindTextField(bdayText, bdayObservable, bdayEditing);
170
	}
171
172
	private Binding bindTextField(
173
			Text text,
174
			IObservableValue modelValue,
175
			Editing editing) {
176
		// Create the binding using the editing object.
177
		ISWTObservableValue textObservable = SWTObservables.observeText(text, SWT.Modify);
178
		Binding binding = editing.bindValue(dbc, textObservable, modelValue);
179
180
		// Decorate the control with the validation status.
181
		ControlDecorationSupport.create(binding, SWT.TOP);
182
183
		formatOnFocusOut(text, binding);
184
185
		return binding;
186
	}
187
188
	private static void formatOnFocusOut(final Control control, final Binding binding) {
189
		control.addFocusListener(new FocusAdapter() {
190
			public void focusLost(FocusEvent e) {
191
				IStatus dateValidationStatus = (IStatus) binding.getValidationStatus().getValue();
192
				if (dateValidationStatus.isOK()) {
193
					binding.updateModelToTarget();
194
				}
195
			}
196
		});
197
	}
198
199
	private Group createSectionGroup(Composite parent, int numColumns) {
200
		Group section = new Group(parent, SWT.SHADOW_ETCHED_IN);
201
		GridLayoutFactory.fillDefaults().numColumns(numColumns).equalWidth(false).margins(5, 5).spacing(15, 5).applyTo(section);
202
		GridDataFactory.fillDefaults().grab(true, true).applyTo(section);
203
		return section;
204
	}
205
206
	private static Text createTextField(Composite parent, String labelText) {
207
		Label label = new Label(parent, SWT.LEFT);
208
		label.setText(labelText);
209
		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
210
211
		final Text text = new Text(parent, SWT.BORDER);
212
		GridDataFactory.fillDefaults().grab(true, false).hint(200, SWT.DEFAULT).applyTo(text);
213
214
		// Select the text when gaining focus.
215
		text.addFocusListener(new FocusAdapter() {
216
			public void focusGained(FocusEvent e) {
217
				text.selectAll();
218
			}
219
		});
220
221
		return text;
222
	}
223
224
	public static final class Person extends ModelObject {
225
226
		private String name;
227
228
		private int age;
229
230
		private Date birthday;
231
232
		public Person(String name, int age) {
233
			this.name = name;
234
			this.age = age;
235
		}
236
237
		public String getName() {
238
			return name;
239
		}
240
241
		public void setName(String name) {
242
			firePropertyChange("name", this.name, this.name = name);
243
		}
244
245
		public int getAge() {
246
			return age;
247
		}
248
249
		public void setAge(int age) {
250
			firePropertyChange("age", this.age, this.age = age);
251
		}
252
253
		public Date getBirthday() {
254
			return birthday;
255
		}
256
257
		public void setBirthday(Date birthday) {
258
			firePropertyChange("birthday", this.birthday, this.birthday = birthday);
259
		}
260
	}
261
}
(-)src/org/eclipse/jface/examples/databinding/util/EditingFactory.java (+205 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.NumberEditing;
19
import org.eclipse.core.databinding.editing.StringEditing;
20
21
import com.ibm.icu.text.DateFormat;
22
import com.ibm.icu.text.NumberFormat;
23
24
/**
25
 * @since 3.2
26
 */
27
public final class EditingFactory {
28
29
	private static final String REQUIRED_MESSAGE = "Please specify a value.";
30
31
	private static final String NUMBER_PARSE_ERROR_MESSAGE = "The input is invalid.";
32
33
	private static final String NUMBER_OUT_OF_RANGE_MESSAGE = "The value lies outside the supported range.";
34
35
	private static final String NUMBER_RANGE_MESSAGE = "The value must lie between {0} and {1}.";
36
37
	private static final String[] BOOLEAN_TRUE_VALUES = new String[] {
38
		"yes", "y", "true", "1"
39
	};
40
41
	private static final String[] BOOLEAN_FALSE_VALUES = new String[] {
42
		"no", "n", "false", "0"
43
	};
44
45
	private static final String[] DATE_INPUT_PATTERNS = new String[] {
46
		"yyMMdd",
47
		"yyyyMMdd"
48
	};
49
50
	private static final String DATE_DISPLAY_PATTERN = "yyyyMMdd";
51
52
	private static final String DATE_PARSE_ERROR_MESSAGE = createDateParseErrorMessage(DATE_INPUT_PATTERNS);
53
54
	private static final String EMAIL_REGEX = "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}\\b";
55
56
	private static final String EMAIL_ERROR_MESSAGE = "Please specify a valid e-mail address.";
57
58
	private EditingFactory() {
59
		// prevent instantiation
60
	}
61
62
	public static StringEditing forString() {
63
		return StringEditing.strippedToNull();
64
	}
65
66
	public static StringEditing forEmailString() {
67
		StringEditing editing = StringEditing.strippedToNull();
68
		editing.modelConstraints()
69
				.matchesMessage(EMAIL_ERROR_MESSAGE)
70
				.matches(EMAIL_REGEX);
71
		return editing;
72
	}
73
74
	public static NumberEditing<Long> forLong() {
75
		return forLong(Locale.getDefault());
76
	}
77
78
	public static NumberEditing<Long> forLong(Locale locale) {
79
		NumberEditing<Long> editing = NumberEditing.forLongFormat(
80
				NumberFormat.getIntegerInstance(locale),
81
				NUMBER_PARSE_ERROR_MESSAGE,
82
				NUMBER_OUT_OF_RANGE_MESSAGE);
83
		configure(editing, locale);
84
		return editing;
85
	}
86
87
	public static NumberEditing<Integer> forInteger() {
88
		return forInteger(Locale.getDefault());
89
	}
90
91
	public static NumberEditing<Integer> forInteger(Locale locale) {
92
		NumberEditing<Integer> editing = NumberEditing.forIntegerFormat(
93
				NumberFormat.getIntegerInstance(locale),
94
				NUMBER_PARSE_ERROR_MESSAGE,
95
				NUMBER_OUT_OF_RANGE_MESSAGE);
96
		configure(editing, locale);
97
		return editing;
98
	}
99
100
	public static NumberEditing<Short> forShort() {
101
		return forShort(Locale.getDefault());
102
	}
103
104
	public static NumberEditing<Short> forShort(Locale locale) {
105
		NumberEditing<Short> editing = NumberEditing.forShortFormat(
106
				NumberFormat.getIntegerInstance(locale),
107
				NUMBER_PARSE_ERROR_MESSAGE,
108
				NUMBER_OUT_OF_RANGE_MESSAGE);
109
		configure(editing, locale);
110
		return editing;
111
	}
112
113
	public static NumberEditing<Byte> forByte() {
114
		return forByte(Locale.getDefault());
115
	}
116
117
	public static NumberEditing<Byte> forByte(Locale locale) {
118
		NumberEditing<Byte> editing = NumberEditing.forByteFormat(
119
				NumberFormat.getIntegerInstance(locale),
120
				NUMBER_PARSE_ERROR_MESSAGE,
121
				NUMBER_OUT_OF_RANGE_MESSAGE);
122
		configure(editing, locale);
123
		return editing;
124
	}
125
126
	public static NumberEditing<Integer> forHexInteger(int digits) {
127
		RadixNumberFormat hexFormat = RadixNumberFormat.getHexInstance("0x", digits);
128
		NumberEditing<Integer> editing = NumberEditing.forIntegerFormat(
129
				hexFormat,
130
				NUMBER_PARSE_ERROR_MESSAGE,
131
				NUMBER_OUT_OF_RANGE_MESSAGE);
132
		configure(editing, Locale.getDefault());
133
		editing.modelConstraints().numberFormat(hexFormat);
134
		return editing;
135
	}
136
137
	public static NumberEditing<Double> forDouble() {
138
		return forDouble(Locale.getDefault());
139
	}
140
141
	public static NumberEditing<Double> forDouble(Locale locale) {
142
		NumberEditing<Double> editing = NumberEditing.forDoubleFormat(
143
				NumberFormat.getNumberInstance(locale),
144
				NUMBER_PARSE_ERROR_MESSAGE,
145
				NUMBER_OUT_OF_RANGE_MESSAGE);
146
		configure(editing, locale);
147
		return editing;
148
	}
149
150
	private static void configure(NumberEditing<?> editing, Locale locale) {
151
		editing.modelConstraints()
152
				.numberFormat(NumberFormat.getNumberInstance(locale))
153
				.scaleFormat(NumberFormat.getIntegerInstance(locale))
154
				.precisionFormat(NumberFormat.getIntegerInstance(locale))
155
				.requiredMessage(REQUIRED_MESSAGE)
156
				.rangeMessage(NUMBER_RANGE_MESSAGE);
157
	}
158
159
	public static BooleanEditing forBoolean() {
160
		BooleanEditing editing =
161
			BooleanEditing.forStringValues(
162
					BOOLEAN_TRUE_VALUES,
163
					BOOLEAN_FALSE_VALUES);
164
		configure(editing);
165
		return editing;
166
	}
167
168
	private static void configure(BooleanEditing editing) {
169
		editing.modelConstraints().requiredMessage(REQUIRED_MESSAGE);
170
	}
171
172
	public static DateEditing forDate() {
173
		return forDate(Locale.getDefault());
174
	}
175
176
	public static DateEditing forDate(Locale locale) {
177
		DateEditing editing = DateEditing
178
				.forFormats(
179
						createDateFormats(DATE_INPUT_PATTERNS, locale),
180
						DATE_PARSE_ERROR_MESSAGE,
181
						DateFormat.getPatternInstance(DATE_DISPLAY_PATTERN, locale));
182
		editing.modelConstraints().requiredMessage(REQUIRED_MESSAGE);
183
		return editing;
184
	}
185
186
	private static DateFormat[] createDateFormats(String[] datePatterns, Locale locale) {
187
		DateFormat[] dateFormats = new DateFormat[datePatterns.length];
188
		for (int i = 0; i < dateFormats.length; i++) {
189
			dateFormats[i] = DateFormat.getPatternInstance(datePatterns[i], locale);
190
		}
191
		return dateFormats;
192
	}
193
194
	private static String createDateParseErrorMessage(String[] datePatterns) {
195
		StringBuffer messageSb = new StringBuffer();
196
		messageSb.append("Supported formats: ");
197
		for (int i = 0; i < datePatterns.length; i++) {
198
			if (i > 0) {
199
				messageSb.append(", ");
200
			}
201
			messageSb.append(datePatterns[i]);
202
		}
203
		return messageSb.toString();
204
	}
205
}
(-)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/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/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
}
(-).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
(-)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
}

Return to bug 183055