Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 203492 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/databinding/ValueBindingBuilderDelegate.java (+79 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding;
13
14
import org.eclipse.core.databinding.observable.value.IObservableValue;
15
16
/**
17
 * Implementation of {@link IValueBindingBuilderDelegate} that determines
18
 * converters and validators from an {@link IStrategyDefaultsProvider}.
19
 */
20
public class ValueBindingBuilderDelegate implements
21
		IValueBindingBuilderDelegate {
22
	private IStrategyDefaultsProvider defaultsProvider;
23
24
	/**
25
	 * Constructs a new instance with the provided <code>defaultsProvider</code>.
26
	 * 
27
	 * @param defaultsProvider
28
	 */
29
	public ValueBindingBuilderDelegate(IStrategyDefaultsProvider defaultsProvider) {
30
		if (defaultsProvider == null) {
31
			throw new IllegalArgumentException(
32
					"Parameter 'defaultsProvider' was null."); //$NON-NLS-1$
33
		}
34
35
		this.defaultsProvider = defaultsProvider;
36
	}
37
38
	/*
39
	 * (non-Javadoc)
40
	 * 
41
	 * @see org.eclipse.core.databinding.IValueBindingBuilderDelegate#prepare(org.eclipse.core.databinding.observable.value.IObservableValue,
42
	 *      org.eclipse.core.databinding.observable.value.IObservableValue,
43
	 *      org.eclipse.core.databinding.UpdateValueStrategy,
44
	 *      org.eclipse.core.databinding.UpdateValueStrategy)
45
	 */
46
	public void prepare(IObservableValue source, IObservableValue destination,
47
			UpdateValueStrategy sourceToModelStrategy,
48
			UpdateValueStrategy destinationToTargetStrategy) {
49
50
		Object sourceType = source.getValueType();
51
		Object destinationType = destination.getValueType();
52
53
		if (sourceType != null && destinationType != null) {
54
			StrategyDefaults defaults = defaultsProvider.getDefaults(sourceType, destinationType);
55
			sourceToModelStrategy.setConverter(defaults.getConverter());
56
			sourceToModelStrategy.setAfterGetValidator(defaults.getValidator());
57
58
			defaults = defaultsProvider.getDefaults(destinationType, sourceType);
59
			destinationToTargetStrategy.setConverter(defaults.getConverter());
60
			destinationToTargetStrategy.setAfterGetValidator(defaults.getValidator());
61
		}
62
	}
63
64
	/* (non-Javadoc)
65
	 * @see org.eclipse.core.databinding.IValueBindingBuilderDelegate#createDestinationToSourceStrategy(int, org.eclipse.core.databinding.observable.value.IObservableValue, org.eclipse.core.databinding.observable.value.IObservableValue)
66
	 */
67
	public UpdateValueStrategy createDestinationToSourceStrategy(int policy,
68
			IObservableValue source, IObservableValue destination) {
69
		return new UpdateValueStrategy(policy);
70
	}
71
72
	/* (non-Javadoc)
73
	 * @see org.eclipse.core.databinding.IValueBindingBuilderDelegate#createSourceToDestinationStrategy(int, org.eclipse.core.databinding.observable.value.IObservableValue, org.eclipse.core.databinding.observable.value.IObservableValue)
74
	 */
75
	public UpdateValueStrategy createSourceToDestinationStrategy(int policy,
76
			IObservableValue source, IObservableValue destination) {
77
		return new UpdateValueStrategy(policy);
78
	}
79
}
(-)src/org/eclipse/core/databinding/IStrategyDefaultsProvider.java (+30 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding;
13
14
import org.eclipse.core.databinding.conversion.IConverter;
15
import org.eclipse.core.databinding.validation.IValidator;
16
17
/**
18
 * Provider of defaults (e.g. {@link IConverter converters} and
19
 * {@link IValidator validators}) to the binding process.
20
 */
21
public interface IStrategyDefaultsProvider {
22
	/**
23
	 * Provides a default converter and validator for the provides types.
24
	 * 
25
	 * @param sourceType
26
	 * @param destinationType
27
	 * @return defaults, <code>null</code> if none found
28
	 */
29
	public StrategyDefaults getDefaults(Object sourceType, Object destinationType);
30
}
(-)src/org/eclipse/core/databinding/IValueBindingBuilderDelegate.java (+58 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding;
13
14
import org.eclipse.core.databinding.observable.value.IObservableValue;
15
16
/**
17
 * A delegate for a {@link ValueBindingBuilder} to externalize the setup of the
18
 * binding.
19
 */
20
public interface IValueBindingBuilderDelegate {
21
	/**
22
	 * Creates the update strategy to be used when updating from source to
23
	 * destination.
24
	 * 
25
	 * @param policy
26
	 * 
27
	 * @param source
28
	 * @param destination
29
	 * @return strategy
30
	 */
31
	public UpdateValueStrategy createSourceToDestinationStrategy(int policy,
32
			IObservableValue source, IObservableValue destination);
33
34
	/**
35
	 * Creates the update strategy to be used when updating from destination to
36
	 * source.
37
	 * 
38
	 * @param policy
39
	 * @param source
40
	 * @param destination
41
	 * @return strategy
42
	 */
43
	public UpdateValueStrategy createDestinationToSourceStrategy(int policy,
44
			IObservableValue source, IObservableValue destination);
45
46
	/**
47
	 * Invoked for the customization of the provided strategies. This allows for
48
	 * the configuring of converters and validators in the strategies.
49
	 * 
50
	 * @param source
51
	 * @param destination
52
	 * @param sourceToDestinationStrategy
53
	 * @param destinationToSourceStrategy
54
	 */
55
	public void prepare(IObservableValue source, IObservableValue destination,
56
			UpdateValueStrategy sourceToDestinationStrategy,
57
			UpdateValueStrategy destinationToSourceStrategy);
58
}
(-)src/org/eclipse/core/databinding/StrategyDefaults.java (+59 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding;
13
14
import org.eclipse.core.databinding.conversion.IConverter;
15
import org.eclipse.core.databinding.validation.IValidator;
16
17
/**
18
 * 
19
 */
20
public class StrategyDefaults {
21
	private IConverter converter;
22
	private IValidator validator;
23
	
24
	public StrategyDefaults() {
25
	}
26
	
27
	public StrategyDefaults(IConverter converter, IValidator validator) {
28
		this.setConverter(converter);
29
		this.setValidator(validator);
30
	}
31
32
	/**
33
	 * @param converter The converter to set.
34
	 */
35
	public void setConverter(IConverter converter) {
36
		this.converter = converter;
37
	}
38
39
	/**
40
	 * @return Returns the converter.
41
	 */
42
	public IConverter getConverter() {
43
		return converter;
44
	}
45
46
	/**
47
	 * @param validator The validator to set.
48
	 */
49
	public void setValidator(IValidator validator) {
50
		this.validator = validator;
51
	}
52
53
	/**
54
	 * @return Returns the validator.
55
	 */
56
	public IValidator getValidator() {
57
		return validator;
58
	}
59
}
(-)src/org/eclipse/core/databinding/ValueBindingBuilder.java (+228 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding;
13
14
import org.eclipse.core.databinding.observable.value.IObservableValue;
15
import org.eclipse.core.runtime.Assert;
16
17
/**
18
 * A builder to streamline the process of constructing {@link Binding bindings}
19
 * between {@link IObservableValue observable values}.
20
 */
21
public class ValueBindingBuilder {
22
	private int sourceToDestinationPolicy = -1;
23
24
	private int destinationToSourcePolicy = -1;
25
26
	private DataBindingContext dbc;
27
28
	private IValueBindingBuilderDelegate delegate;
29
30
	/**
31
	 * Constructs a new instance. Public instantiation is not allowed.
32
	 * 
33
	 * @see #withDefaults()
34
	 */
35
	private ValueBindingBuilder() {
36
	}
37
38
	/**
39
	 * Sets the {@link UpdateValueStrategy#getUpdatePolicy() update policy} to
40
	 * be used for source to destination updates.
41
	 * 
42
	 * @param updatePolicy
43
	 * @return this builder for chaining
44
	 */
45
	public ValueBindingBuilder sourceToDestinationPolicy(int updatePolicy) {
46
		sourceToDestinationPolicy = updatePolicy;
47
		return this;
48
	}
49
50
	public int getSourceToDestinationPolicy() {
51
		return sourceToDestinationPolicy;
52
	}
53
54
	/**
55
	 * Sets the {@link UpdateValueStrategy#getUpdatePolicy() update policy} to
56
	 * be used for destination to source updates.
57
	 * 
58
	 * @param updatePolicy
59
	 * @return this builder for chaining
60
	 */
61
	public ValueBindingBuilder destinationToSourcePolicy(int updatePolicy) {
62
		destinationToSourcePolicy = updatePolicy;
63
		return this;
64
	}
65
66
	public int getDestinationToSourcePolicy() {
67
		return destinationToSourcePolicy;
68
	}
69
70
	/**
71
	 * Sets the {@link DataBindingContext} to be used when creating bindings.
72
	 * 
73
	 * @param dbc
74
	 * @return this builder for chaining
75
	 */
76
	public ValueBindingBuilder dbc(DataBindingContext dbc) {
77
		this.dbc = dbc;
78
		return this;
79
	}
80
81
	public DataBindingContext getDbc() {
82
		return dbc;
83
	}
84
85
	/**
86
	 * Creates a copy of the builder inheriting all state.
87
	 * 
88
	 * @return new builder
89
	 */
90
	public ValueBindingBuilder copy() {
91
		ValueBindingBuilder builder = new ValueBindingBuilder();
92
		builder.sourceToDestinationPolicy = sourceToDestinationPolicy;
93
		builder.destinationToSourcePolicy = destinationToSourcePolicy;
94
		builder.dbc = dbc;
95
		builder.delegate = delegate;
96
97
		return builder;
98
	}
99
100
	/**
101
	 * Sets the delegate to prepare strategies.
102
	 * 
103
	 * @param delegate
104
	 * @return this builder for chaining
105
	 */
106
	public ValueBindingBuilder delegate(IValueBindingBuilderDelegate delegate) {
107
		this.delegate = delegate;
108
		return this;
109
	}
110
111
	public IValueBindingBuilderDelegate getDelegate() {
112
		return delegate;
113
	}
114
115
	/**
116
	 * Binds the provided <code>source</code> to the provided
117
	 * <code>destination</code> using the {@link DataBindingContext} in
118
	 * context.
119
	 * 
120
	 * @param source
121
	 *            source to bind, does not become state in the builder
122
	 * @param destination
123
	 *            destination to bind, does not become state in the builder
124
	 * @return binding
125
	 */
126
	public Binding bind(IObservableValue source, IObservableValue destination) {
127
		return bind(dbc, source, destination);
128
	}
129
130
	/**
131
	 * Binds the provided <code>source</code> to the provided
132
	 * <code>destination</code> using the provided <code>dbc</code>.
133
	 * 
134
	 * @param dbc
135
	 *            dbc to create the binding, does not become state in the
136
	 *            builder
137
	 * @param source
138
	 *            source to bind, does not become state in the builder
139
	 * @param destination
140
	 *            destination to bind, does not become state in the builder
141
	 * @return binding
142
	 */
143
	public Binding bind(DataBindingContext dbc, IObservableValue source,
144
			IObservableValue destination) {
145
		return bind(dbc, sourceToDestinationPolicy, destinationToSourcePolicy,
146
				source, destination);
147
	}
148
149
	/**
150
	 * Binds the provided <code>source</code> to the provided
151
	 * <code>destination</code> using the provided <code>dbc</code>.
152
	 * 
153
	 * @param dbc
154
	 *            creates the binding, does not become state in the builder
155
	 * @param sourceToDestinationPolicy
156
	 *            policy for source to destination updates, does not become
157
	 *            state in the builder
158
	 * @param destinationToSourcePolicy
159
	 *            policy for destination to source updates, does not become
160
	 *            state in the builder
161
	 * @param source
162
	 *            source to bind, does not become state in the builder
163
	 * @param destination
164
	 *            destination to bind, does not become state in the builder
165
	 * @return binding
166
	 */
167
	public Binding bind(DataBindingContext dbc, int sourceToDestinationPolicy,
168
			int destinationToSourcePolicy, IObservableValue source,
169
			IObservableValue destination) {
170
		if (dbc == null) {
171
			throw new IllegalArgumentException("Parameter 'dbc' was null."); //$NON-NLS-1$
172
		}
173
		if (source == null) {
174
			throw new IllegalArgumentException("Parameter 'source' was null."); //$NON-NLS-1$
175
		}
176
		if (destination == null) {
177
			throw new IllegalArgumentException(
178
					"Parameter 'destination' was null."); //$NON-NLS-1$
179
		}
180
181
		if (delegate == null) {
182
			// Default a delegate if one hasn't been set yet.
183
			delegate = new ValueBindingBuilderDelegate(
184
					new CoreStrategyDefaultsProvider());
185
		}
186
		
187
		UpdateValueStrategy sourceToDestinationStrategy = delegate
188
				.createSourceToDestinationStrategy(sourceToDestinationPolicy,
189
						source, destination);
190
		UpdateValueStrategy destinationToSourceStrategy = delegate
191
				.createSourceToDestinationStrategy(destinationToSourcePolicy,
192
						source, destination);
193
194
		Assert.isNotNull(sourceToDestinationStrategy,
195
				"source to destination strategy"); //$NON-NLS-1$
196
		Assert.isNotNull(destinationToSourceStrategy,
197
				"destination to source strategy"); //$NON-NLS-1$
198
199
200
		delegate.prepare(source, destination, sourceToDestinationStrategy,
201
				destinationToSourceStrategy);
202
203
		// For backwards compability.
204
		sourceToDestinationStrategy.fillDefaults(source, destination);
205
		destinationToSourceStrategy.fillDefaults(destination, source);
206
207
		return dbc.bindValue(source, destination, sourceToDestinationStrategy,
208
				destinationToSourceStrategy);
209
	}
210
211
	/**
212
	 * Constructs a builder with the following defaults.
213
	 * <ul>
214
	 * <li>Source to destination policy =
215
	 * {@link UpdateValueStrategy#POLICY_UPDATE}</li>
216
	 * <li>Destination to source policy =
217
	 * {@link UpdateValueStrategy#POLICY_UPDATE}</li>
218
	 * </ul>
219
	 * 
220
	 * @return builder
221
	 */
222
	public static ValueBindingBuilder withDefaults() {
223
		ValueBindingBuilder builder = new ValueBindingBuilder();
224
		builder.sourceToDestinationPolicy = builder.destinationToSourcePolicy = UpdateValueStrategy.POLICY_UPDATE;
225
226
		return builder;
227
	}
228
}
(-)src/org/eclipse/core/databinding/CoreStrategyDefaultsProvider.java (+939 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding;
13
14
import java.math.BigDecimal;
15
import java.math.BigInteger;
16
import java.util.Date;
17
import java.util.HashMap;
18
import java.util.Map;
19
20
import org.eclipse.core.databinding.conversion.IConverter;
21
import org.eclipse.core.databinding.conversion.NumberToStringConverter;
22
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
23
import org.eclipse.core.databinding.util.Policy;
24
import org.eclipse.core.databinding.validation.IValidator;
25
import org.eclipse.core.internal.databinding.ClassLookupSupport;
26
import org.eclipse.core.internal.databinding.Pair;
27
import org.eclipse.core.internal.databinding.conversion.CharacterToStringConverter;
28
import org.eclipse.core.internal.databinding.conversion.IdentityConverter;
29
import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter;
30
import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
31
import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
32
import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter;
33
import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter;
34
import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter;
35
import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
36
import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
37
import org.eclipse.core.internal.databinding.conversion.NumberToNumberConverter;
38
import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
39
import org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter;
40
import org.eclipse.core.internal.databinding.conversion.StringToByteConverter;
41
import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter;
42
import org.eclipse.core.internal.databinding.conversion.StringToDateConverter;
43
import org.eclipse.core.internal.databinding.conversion.StringToShortConverter;
44
import org.eclipse.core.internal.databinding.validation.NumberFormatConverter;
45
import org.eclipse.core.internal.databinding.validation.NumberToByteValidator;
46
import org.eclipse.core.internal.databinding.validation.NumberToDoubleValidator;
47
import org.eclipse.core.internal.databinding.validation.NumberToFloatValidator;
48
import org.eclipse.core.internal.databinding.validation.NumberToIntegerValidator;
49
import org.eclipse.core.internal.databinding.validation.NumberToLongValidator;
50
import org.eclipse.core.internal.databinding.validation.NumberToShortValidator;
51
import org.eclipse.core.internal.databinding.validation.NumberToUnboundedNumberValidator;
52
import org.eclipse.core.internal.databinding.validation.ObjectToPrimitiveValidator;
53
import org.eclipse.core.internal.databinding.validation.StringToByteValidator;
54
import org.eclipse.core.internal.databinding.validation.StringToCharacterValidator;
55
import org.eclipse.core.internal.databinding.validation.StringToDateValidator;
56
import org.eclipse.core.internal.databinding.validation.StringToDoubleValidator;
57
import org.eclipse.core.internal.databinding.validation.StringToFloatValidator;
58
import org.eclipse.core.internal.databinding.validation.StringToIntegerValidator;
59
import org.eclipse.core.internal.databinding.validation.StringToLongValidator;
60
import org.eclipse.core.internal.databinding.validation.StringToShortValidator;
61
import org.eclipse.core.runtime.IStatus;
62
import org.eclipse.core.runtime.Status;
63
64
import com.ibm.icu.text.NumberFormat;
65
66
/**
67
 * @since 3.3
68
 */
69
public class CoreStrategyDefaultsProvider implements IStrategyDefaultsProvider {
70
	private static ValidatorRegistry validatorRegistry = new ValidatorRegistry();
71
72
	private static HashMap validatorsByConverter = new HashMap();
73
74
	/*
75
	 * (non-Javadoc)
76
	 * 
77
	 * @see org.eclipse.core.databinding.IStrategyDefaultsProvider#getDefaults(java.lang.Object,
78
	 *      java.lang.Object, org.eclipse.core.databinding.StrategyDefaults)
79
	 */
80
	public StrategyDefaults getDefaults(Object sourceType, Object destinationType) {
81
		IConverter converter = createConverter(sourceType, destinationType);
82
83
		if (converter != null) {
84
			IValidator validator = createValidator(converter, sourceType,
85
					destinationType);
86
			return new StrategyDefaults(converter, validator);
87
		}
88
		
89
		return null;
90
	}
91
92
	/**
93
	 * Tries to create a validator that can validate values of type fromType.
94
	 * Returns <code>null</code> if no validator could be created. Either
95
	 * toType or modelDescription can be <code>null</code>, but not both.
96
	 * 
97
	 * @param converter 
98
	 * @param fromType
99
	 * @param toType
100
	 * @return an IValidator, or <code>null</code> if unsuccessful
101
	 */
102
	private IValidator createValidator(IConverter converter, Object fromType,
103
			Object toType) {
104
		if (fromType == null || toType == null) {
105
			return new IValidator() {
106
107
				public IStatus validate(Object value) {
108
					return Status.OK_STATUS;
109
				}
110
			};
111
		}
112
113
		return findValidator(converter, fromType, toType);
114
	}
115
116
	private IValidator findValidator(IConverter converter, Object fromType,
117
			Object toType) {
118
		IValidator result = null;
119
120
		if (String.class.equals(fromType)) {
121
			result = (IValidator) validatorsByConverter.get(converter);
122
123
			if (result == null) {
124
				// TODO sring based lookup
125
				if (Integer.class.equals(toType) || Integer.TYPE.equals(toType)) {
126
					result = new StringToIntegerValidator(
127
							(NumberFormatConverter) converter);
128
				} else if (Long.class.equals(toType)
129
						|| Long.TYPE.equals(toType)) {
130
					result = new StringToLongValidator(
131
							(NumberFormatConverter) converter);
132
				} else if (Float.class.equals(toType)
133
						|| Float.TYPE.equals(toType)) {
134
					result = new StringToFloatValidator(
135
							(NumberFormatConverter) converter);
136
				} else if (Double.class.equals(toType)
137
						|| Double.TYPE.equals(toType)) {
138
					result = new StringToDoubleValidator(
139
							(NumberFormatConverter) converter);
140
				} else if (Byte.class.equals(toType)
141
						|| Byte.TYPE.equals(toType)) {
142
					result = new StringToByteValidator(
143
							(NumberFormatConverter) converter);
144
				} else if (Short.class.equals(toType)
145
						|| Short.TYPE.equals(toType)) {
146
					result = new StringToShortValidator(
147
							(NumberFormatConverter) converter);
148
				} else if (Character.class.equals(toType)
149
						|| Character.TYPE.equals(toType)
150
						&& converter instanceof StringToCharacterConverter) {
151
					result = new StringToCharacterValidator(
152
							(StringToCharacterConverter) converter);
153
				} else if (Date.class.equals(toType)
154
						&& converter instanceof StringToDateConverter) {
155
					result = new StringToDateValidator(
156
							(StringToDateConverter) converter);
157
				}
158
159
				if (result != null) {
160
					validatorsByConverter.put(converter, result);
161
				}
162
			}
163
		} else if (converter instanceof NumberToNumberConverter) {
164
			result = (IValidator) validatorsByConverter.get(converter);
165
166
			if (result == null) {
167
				if (converter instanceof NumberToByteConverter) {
168
					result = new NumberToByteValidator(
169
							(NumberToByteConverter) converter);
170
				} else if (converter instanceof NumberToShortConverter) {
171
					result = new NumberToShortValidator(
172
							(NumberToShortConverter) converter);
173
				} else if (converter instanceof NumberToIntegerConverter) {
174
					result = new NumberToIntegerValidator(
175
							(NumberToIntegerConverter) converter);
176
				} else if (converter instanceof NumberToLongConverter) {
177
					result = new NumberToLongValidator(
178
							(NumberToLongConverter) converter);
179
				} else if (converter instanceof NumberToFloatConverter) {
180
					result = new NumberToFloatValidator(
181
							(NumberToFloatConverter) converter);
182
				} else if (converter instanceof NumberToDoubleConverter) {
183
					result = new NumberToDoubleValidator(
184
							(NumberToDoubleConverter) converter);
185
				} else if (converter instanceof NumberToBigIntegerConverter
186
						|| converter instanceof NumberToBigDecimalConverter) {
187
					result = new NumberToUnboundedNumberValidator(
188
							(NumberToNumberConverter) converter);
189
				}
190
			}
191
		}
192
193
		if (result == null) {
194
			// TODO string based lookup
195
			result = validatorRegistry.get(fromType, toType);
196
		}
197
198
		return result;
199
	}
200
201
	private static class ValidatorRegistry {
202
203
		private HashMap validators = new HashMap();
204
205
		/**
206
		 * Adds the system-provided validators to the current validator
207
		 * registry. This is done automatically for the validator registry
208
		 * singleton.
209
		 */
210
		private ValidatorRegistry() {
211
			// Standalone validators here...
212
			associate(Integer.class, Integer.TYPE,
213
					new ObjectToPrimitiveValidator(Integer.TYPE));
214
			associate(Byte.class, Byte.TYPE, new ObjectToPrimitiveValidator(
215
					Byte.TYPE));
216
			associate(Short.class, Short.TYPE, new ObjectToPrimitiveValidator(
217
					Short.TYPE));
218
			associate(Long.class, Long.TYPE, new ObjectToPrimitiveValidator(
219
					Long.TYPE));
220
			associate(Float.class, Float.TYPE, new ObjectToPrimitiveValidator(
221
					Float.TYPE));
222
			associate(Double.class, Double.TYPE,
223
					new ObjectToPrimitiveValidator(Double.TYPE));
224
			associate(Boolean.class, Boolean.TYPE,
225
					new ObjectToPrimitiveValidator(Boolean.TYPE));
226
227
			associate(Object.class, Integer.TYPE,
228
					new ObjectToPrimitiveValidator(Integer.TYPE));
229
			associate(Object.class, Byte.TYPE, new ObjectToPrimitiveValidator(
230
					Byte.TYPE));
231
			associate(Object.class, Short.TYPE, new ObjectToPrimitiveValidator(
232
					Short.TYPE));
233
			associate(Object.class, Long.TYPE, new ObjectToPrimitiveValidator(
234
					Long.TYPE));
235
			associate(Object.class, Float.TYPE, new ObjectToPrimitiveValidator(
236
					Float.TYPE));
237
			associate(Object.class, Double.TYPE,
238
					new ObjectToPrimitiveValidator(Double.TYPE));
239
			associate(Object.class, Boolean.TYPE,
240
					new ObjectToPrimitiveValidator(Boolean.TYPE));
241
		}
242
243
		/**
244
		 * Associate a particular validator that can validate the conversion
245
		 * (fromClass, toClass)
246
		 * 
247
		 * @param fromClass
248
		 *            The Class to convert from
249
		 * @param toClass
250
		 *            The Class to convert to
251
		 * @param validator
252
		 *            The IValidator
253
		 */
254
		private void associate(Object fromClass, Object toClass,
255
				IValidator validator) {
256
			validators.put(new Pair(fromClass, toClass), validator);
257
		}
258
259
		/**
260
		 * Return an IValidator for a specific fromClass and toClass.
261
		 * 
262
		 * @param fromClass
263
		 *            The Class to convert from
264
		 * @param toClass
265
		 *            The Class to convert to
266
		 * @return An appropriate IValidator
267
		 */
268
		private IValidator get(Object fromClass, Object toClass) {
269
			IValidator result = (IValidator) validators.get(new Pair(fromClass,
270
					toClass));
271
			if (result != null)
272
				return result;
273
			if (fromClass != null && toClass != null && fromClass == toClass) {
274
				return new IValidator() {
275
					public IStatus validate(Object value) {
276
						return Status.OK_STATUS;
277
					}
278
				};
279
			}
280
			return new IValidator() {
281
				public IStatus validate(Object value) {
282
					return Status.OK_STATUS;
283
				}
284
			};
285
		}
286
	}
287
288
	private static final String BOOLEAN_TYPE = "java.lang.Boolean.TYPE"; //$NON-NLS-1$
289
290
	private static final String SHORT_TYPE = "java.lang.Short.TYPE"; //$NON-NLS-1$
291
292
	private static final String BYTE_TYPE = "java.lang.Byte.TYPE"; //$NON-NLS-1$
293
294
	private static final String DOUBLE_TYPE = "java.lang.Double.TYPE"; //$NON-NLS-1$
295
296
	private static final String FLOAT_TYPE = "java.lang.Float.TYPE"; //$NON-NLS-1$
297
298
	private static final String INTEGER_TYPE = "java.lang.Integer.TYPE"; //$NON-NLS-1$
299
300
	private static final String LONG_TYPE = "java.lang.Long.TYPE"; //$NON-NLS-1$
301
302
	private static final String CHARACTER_TYPE = "java.lang.Character.TYPE"; //$NON-NLS-1$
303
304
	private static Map converterMap;
305
306
	private static Class autoboxed(Class clazz) {
307
		if (clazz == Float.TYPE)
308
			return Float.class;
309
		else if (clazz == Double.TYPE)
310
			return Double.class;
311
		else if (clazz == Short.TYPE)
312
			return Short.class;
313
		else if (clazz == Integer.TYPE)
314
			return Integer.class;
315
		else if (clazz == Long.TYPE)
316
			return Long.class;
317
		else if (clazz == Byte.TYPE)
318
			return Byte.class;
319
		else if (clazz == Boolean.TYPE)
320
			return Boolean.class;
321
		else if (clazz == Character.TYPE)
322
			return Character.class;
323
		return clazz;
324
	}
325
326
	final protected void checkAssignable(Object toType, Object fromType,
327
			String errorString) {
328
		Boolean assignableFromModelToModelConverter = isAssignableFromTo(
329
				fromType, toType);
330
		if (assignableFromModelToModelConverter != null
331
				&& !assignableFromModelToModelConverter.booleanValue()) {
332
			throw new BindingException(errorString
333
					+ " Expected: " + fromType + ", actual: " + toType); //$NON-NLS-1$//$NON-NLS-2$
334
		}
335
	}
336
337
	/**
338
	 * Tries to create a converter that can convert from values of type
339
	 * fromType. Returns <code>null</code> if no converter could be created.
340
	 * Either toType or modelDescription can be <code>null</code>, but not
341
	 * both.
342
	 * 
343
	 * @param fromType
344
	 * @param toType
345
	 * @return an IConverter, or <code>null</code> if unsuccessful
346
	 */
347
	private IConverter createConverter(Object fromType, Object toType) {
348
		if (!(fromType instanceof Class) || !(toType instanceof Class)) {
349
			return new DefaultConverter(fromType, toType);
350
		}
351
		Class toClass = (Class) toType;
352
		Class originalToClass = toClass;
353
		if (toClass.isPrimitive()) {
354
			toClass = autoboxed(toClass);
355
		}
356
		Class fromClass = (Class) fromType;
357
		Class originalFromClass = fromClass;
358
		if (fromClass.isPrimitive()) {
359
			fromClass = autoboxed(fromClass);
360
		}
361
		if (!((Class) toType).isPrimitive()
362
				&& toClass.isAssignableFrom(fromClass)) {
363
			return new IdentityConverter(originalFromClass, originalToClass);
364
		}
365
		if (((Class) fromType).isPrimitive() && ((Class) toType).isPrimitive()
366
				&& fromType.equals(toType)) {
367
			return new IdentityConverter(originalFromClass, originalToClass);
368
		}
369
		Map converterMap = getConverterMap();
370
		Class[] supertypeHierarchyFlattened = ClassLookupSupport
371
				.getTypeHierarchyFlattened(fromClass);
372
		for (int i = 0; i < supertypeHierarchyFlattened.length; i++) {
373
			Class currentFromClass = supertypeHierarchyFlattened[i];
374
			if (currentFromClass == toType) {
375
				// converting to toType is just a widening
376
				return new IdentityConverter(fromClass, toClass);
377
			}
378
			Pair key = new Pair(getKeyForClass(fromType, currentFromClass),
379
					getKeyForClass(toType, toClass));
380
			Object converterOrClassname = converterMap.get(key);
381
			if (converterOrClassname instanceof IConverter) {
382
				return (IConverter) converterOrClassname;
383
			} else if (converterOrClassname instanceof String) {
384
				String classname = (String) converterOrClassname;
385
				Class converterClass;
386
				try {
387
					converterClass = Class.forName(classname);
388
					IConverter result = (IConverter) converterClass
389
							.newInstance();
390
					converterMap.put(key, result);
391
					return result;
392
				} catch (Exception e) {
393
					Policy
394
							.getLog()
395
							.log(
396
									new Status(
397
											IStatus.ERROR,
398
											Policy.JFACE_DATABINDING,
399
											0,
400
											"Error while instantiating default converter", e)); //$NON-NLS-1$
401
				}
402
			}
403
		}
404
		// Since we found no converter yet, try a "downcast" converter;
405
		// the IdentityConverter will automatically check the actual types at
406
		// runtime.
407
		if (fromClass.isAssignableFrom(toClass)) {
408
			return new IdentityConverter(originalFromClass, originalToClass);
409
		}
410
		return new DefaultConverter(fromType, toType);
411
	}
412
413
	private static Map getConverterMap() {
414
		// using string-based lookup avoids loading of too many classes
415
		if (converterMap == null) {
416
			// NumberFormat to be shared across converters for the formatting of
417
			// integer values
418
			NumberFormat integerFormat = NumberFormat.getIntegerInstance();
419
			// NumberFormat to be shared across converters for formatting non
420
			// integer values
421
			NumberFormat numberFormat = NumberFormat.getNumberInstance();
422
423
			converterMap = new HashMap();
424
			// Standard and Boxed Types
425
			converterMap
426
					.put(
427
							new Pair("java.util.Date", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.DateToStringConverter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
428
			converterMap
429
					.put(
430
							new Pair("java.lang.String", "java.lang.Boolean"), "org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
431
			converterMap
432
					.put(
433
							new Pair("java.lang.String", "java.lang.Byte"), StringToByteConverter.toByte(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
434
			converterMap
435
					.put(
436
							new Pair("java.lang.String", "java.util.Date"), "org.eclipse.core.internal.databinding.conversion.StringToDateConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
437
			converterMap
438
					.put(
439
							new Pair("java.lang.String", "java.lang.Short"), StringToShortConverter.toShort(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
440
			converterMap
441
					.put(
442
							new Pair("java.lang.String", "java.lang.Character"), StringToCharacterConverter.toCharacter(false)); //$NON-NLS-1$//$NON-NLS-2$			
443
			converterMap
444
					.put(
445
							new Pair("java.lang.String", "java.lang.Integer"), StringToNumberConverter.toInteger(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
446
			converterMap
447
					.put(
448
							new Pair("java.lang.String", "java.lang.Double"), StringToNumberConverter.toDouble(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
449
			converterMap
450
					.put(
451
							new Pair("java.lang.String", "java.lang.Long"), StringToNumberConverter.toLong(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
452
			converterMap
453
					.put(
454
							new Pair("java.lang.String", "java.lang.Float"), StringToNumberConverter.toFloat(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$			
455
			converterMap
456
					.put(
457
							new Pair("java.lang.String", "java.math.BigInteger"), StringToNumberConverter.toBigInteger(integerFormat)); //$NON-NLS-1$//$NON-NLS-2$			
458
			converterMap
459
					.put(
460
							new Pair("java.lang.Integer", "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
461
			converterMap
462
					.put(
463
							new Pair("java.lang.Long", "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
464
			converterMap
465
					.put(
466
							new Pair("java.lang.Double", "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
467
			converterMap
468
					.put(
469
							new Pair("java.lang.Float", "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
470
			converterMap
471
					.put(
472
							new Pair("java.math.BigInteger", "java.lang.String"), NumberToStringConverter.fromBigInteger(integerFormat)); //$NON-NLS-1$//$NON-NLS-2$
473
			converterMap
474
					.put(
475
							new Pair("java.lang.Byte", "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
476
			converterMap
477
					.put(
478
							new Pair("java.lang.Short", "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
479
			converterMap
480
					.put(
481
							new Pair("java.lang.Character", "java.lang.String"), CharacterToStringConverter.fromCharacter(false)); //$NON-NLS-1$//$NON-NLS-2$
482
483
			converterMap
484
					.put(
485
							new Pair("java.lang.Object", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
486
487
			// Integer.TYPE
488
			converterMap
489
					.put(
490
							new Pair("java.lang.String", INTEGER_TYPE), StringToNumberConverter.toInteger(integerFormat, true)); //$NON-NLS-1$
491
			converterMap
492
					.put(
493
							new Pair(INTEGER_TYPE, "java.lang.Integer"), new IdentityConverter(Integer.TYPE, Integer.class)); //$NON-NLS-1$
494
			converterMap
495
					.put(
496
							new Pair(INTEGER_TYPE, "java.lang.Object"), new IdentityConverter(Integer.TYPE, Object.class)); //$NON-NLS-1$
497
			converterMap
498
					.put(
499
							new Pair(INTEGER_TYPE, "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, true)); //$NON-NLS-1$
500
501
			// Byte.TYPE
502
			converterMap
503
					.put(
504
							new Pair("java.lang.String", BYTE_TYPE), StringToByteConverter.toByte(integerFormat, true)); //$NON-NLS-1$
505
			converterMap
506
					.put(
507
							new Pair(BYTE_TYPE, "java.lang.Byte"), new IdentityConverter(Byte.TYPE, Byte.class)); //$NON-NLS-1$
508
			converterMap
509
					.put(
510
							new Pair(BYTE_TYPE, "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, true)); //$NON-NLS-1$
511
			converterMap
512
					.put(
513
							new Pair(BYTE_TYPE, "java.lang.Object"), new IdentityConverter(Byte.TYPE, Object.class)); //$NON-NLS-1$
514
515
			// Double.TYPE
516
			converterMap
517
					.put(
518
							new Pair("java.lang.String", DOUBLE_TYPE), StringToNumberConverter.toDouble(numberFormat, true)); //$NON-NLS-1$
519
			converterMap
520
					.put(
521
							new Pair(DOUBLE_TYPE, "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, true)); //$NON-NLS-1$
522
523
			converterMap
524
					.put(
525
							new Pair(DOUBLE_TYPE, "java.lang.Double"), new IdentityConverter(Double.TYPE, Double.class)); //$NON-NLS-1$
526
			converterMap
527
					.put(
528
							new Pair(DOUBLE_TYPE, "java.lang.Object"), new IdentityConverter(Double.TYPE, Object.class)); //$NON-NLS-1$
529
530
			// Boolean.TYPE
531
			converterMap
532
					.put(
533
							new Pair("java.lang.String", BOOLEAN_TYPE), "org.eclipse.core.internal.databinding.conversion.StringToBooleanPrimitiveConverter"); //$NON-NLS-1$ //$NON-NLS-2$
534
			converterMap
535
					.put(
536
							new Pair(BOOLEAN_TYPE, "java.lang.Boolean"), new IdentityConverter(Boolean.TYPE, Boolean.class)); //$NON-NLS-1$
537
			converterMap
538
					.put(
539
							new Pair(BOOLEAN_TYPE, "java.lang.String"), new ObjectToStringConverter(Boolean.TYPE)); //$NON-NLS-1$
540
			converterMap
541
					.put(
542
							new Pair(BOOLEAN_TYPE, "java.lang.Object"), new IdentityConverter(Boolean.TYPE, Object.class)); //$NON-NLS-1$
543
544
			// Float.TYPE
545
			converterMap
546
					.put(
547
							new Pair("java.lang.String", FLOAT_TYPE), StringToNumberConverter.toFloat(numberFormat, true)); //$NON-NLS-1$
548
			converterMap
549
					.put(
550
							new Pair(FLOAT_TYPE, "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, true)); //$NON-NLS-1$
551
			converterMap
552
					.put(
553
							new Pair(FLOAT_TYPE, "java.lang.Float"), new IdentityConverter(Float.TYPE, Float.class)); //$NON-NLS-1$
554
			converterMap
555
					.put(
556
							new Pair(FLOAT_TYPE, "java.lang.Object"), new IdentityConverter(Float.TYPE, Object.class)); //$NON-NLS-1$		
557
558
			// Short.TYPE
559
			converterMap
560
					.put(
561
							new Pair("java.lang.String", SHORT_TYPE), StringToShortConverter.toShort(integerFormat, true)); //$NON-NLS-1$
562
			converterMap
563
					.put(
564
							new Pair(SHORT_TYPE, "java.lang.Short"), new IdentityConverter(Short.TYPE, Short.class)); //$NON-NLS-1$
565
			converterMap
566
					.put(
567
							new Pair(SHORT_TYPE, "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, true)); //$NON-NLS-1$
568
			converterMap
569
					.put(
570
							new Pair(SHORT_TYPE, "java.lang.Object"), new IdentityConverter(Short.TYPE, Object.class)); //$NON-NLS-1$		
571
572
			// Long.TYPE
573
			converterMap
574
					.put(
575
							new Pair("java.lang.String", LONG_TYPE), StringToNumberConverter.toLong(integerFormat, true)); //$NON-NLS-1$
576
			converterMap
577
					.put(
578
							new Pair(LONG_TYPE, "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, true)); //$NON-NLS-1$
579
			converterMap
580
					.put(
581
							new Pair(LONG_TYPE, "java.lang.Long"), new IdentityConverter(Long.TYPE, Long.class)); //$NON-NLS-1$
582
			converterMap
583
					.put(
584
							new Pair(LONG_TYPE, "java.lang.Object"), new IdentityConverter(Long.TYPE, Object.class)); //$NON-NLS-1$		
585
586
			// Character.TYPE
587
			converterMap
588
					.put(
589
							new Pair("java.lang.String", CHARACTER_TYPE), StringToCharacterConverter.toCharacter(true)); //$NON-NLS-1$
590
			converterMap
591
					.put(
592
							new Pair(CHARACTER_TYPE, "java.lang.Character"), new IdentityConverter(Character.TYPE, Character.class)); //$NON-NLS-1$
593
			converterMap
594
					.put(
595
							new Pair(CHARACTER_TYPE, "java.lang.String"), CharacterToStringConverter.fromCharacter(true)); //$NON-NLS-1$
596
			converterMap
597
					.put(
598
							new Pair(CHARACTER_TYPE, "java.lang.Object"), new IdentityConverter(Character.TYPE, Object.class)); //$NON-NLS-1$		
599
600
			// Miscellaneous
601
			converterMap
602
					.put(
603
							new Pair(
604
									"org.eclipse.core.runtime.IStatus", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.StatusToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
605
606
			addNumberToByteConverters(converterMap, integerFormat,
607
					integerClasses);
608
			addNumberToByteConverters(converterMap, numberFormat, floatClasses);
609
610
			addNumberToShortConverters(converterMap, integerFormat,
611
					integerClasses);
612
			addNumberToShortConverters(converterMap, numberFormat, floatClasses);
613
614
			addNumberToIntegerConverters(converterMap, integerFormat,
615
					integerClasses);
616
			addNumberToIntegerConverters(converterMap, numberFormat,
617
					floatClasses);
618
619
			addNumberToLongConverters(converterMap, integerFormat,
620
					integerClasses);
621
			addNumberToLongConverters(converterMap, numberFormat, floatClasses);
622
623
			addNumberToFloatConverters(converterMap, integerFormat,
624
					integerClasses);
625
			addNumberToFloatConverters(converterMap, numberFormat, floatClasses);
626
627
			addNumberToDoubleConverters(converterMap, integerFormat,
628
					integerClasses);
629
			addNumberToDoubleConverters(converterMap, numberFormat,
630
					floatClasses);
631
632
			addNumberToBigIntegerConverters(converterMap, integerFormat,
633
					integerClasses);
634
			addNumberToBigIntegerConverters(converterMap, numberFormat,
635
					floatClasses);
636
637
			addNumberToBigDecimalConverters(converterMap, integerFormat,
638
					integerClasses);
639
			addNumberToBigDecimalConverters(converterMap, numberFormat,
640
					floatClasses);
641
		}
642
643
		return converterMap;
644
	}
645
646
	private static final Class[] integerClasses = new Class[] { Byte.TYPE,
647
			Byte.class, Short.TYPE, Short.class, Integer.TYPE, Integer.class,
648
			Long.TYPE, Long.class, BigInteger.class };
649
650
	private static final Class[] floatClasses = new Class[] { Float.TYPE,
651
			Float.class, Double.TYPE, Double.class, BigDecimal.class };
652
653
	/**
654
	 * Registers converters to boxed and unboxed types from a list of from
655
	 * classes.
656
	 * 
657
	 * @param map
658
	 * @param numberFormat
659
	 * @param fromTypes
660
	 */
661
	private static void addNumberToByteConverters(Map map,
662
			NumberFormat numberFormat, Class[] fromTypes) {
663
664
		for (int i = 0; i < fromTypes.length; i++) {
665
			Class fromType = fromTypes[i];
666
			if (!fromType.equals(Byte.class) && !fromType.equals(Byte.TYPE)) {
667
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
668
						fromType, null) : fromType.getName();
669
670
				map
671
						.put(new Pair(fromName, BYTE_TYPE),
672
								new NumberToByteConverter(numberFormat,
673
										fromType, true));
674
				map
675
						.put(new Pair(fromName, Byte.class.getName()),
676
								new NumberToByteConverter(numberFormat,
677
										fromType, false));
678
			}
679
		}
680
	}
681
682
	/**
683
	 * Registers converters to boxed and unboxed types from a list of from
684
	 * classes.
685
	 * 
686
	 * @param map
687
	 * @param numberFormat
688
	 * @param fromTypes
689
	 */
690
	private static void addNumberToShortConverters(Map map,
691
			NumberFormat numberFormat, Class[] fromTypes) {
692
		for (int i = 0; i < fromTypes.length; i++) {
693
			Class fromType = fromTypes[i];
694
			if (!fromType.equals(Short.class) && !fromType.equals(Short.TYPE)) {
695
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
696
						fromType, null) : fromType.getName();
697
698
				map
699
						.put(new Pair(fromName, SHORT_TYPE),
700
								new NumberToShortConverter(numberFormat,
701
										fromType, true));
702
				map.put(new Pair(fromName, Short.class.getName()),
703
						new NumberToShortConverter(numberFormat, fromType,
704
								false));
705
			}
706
		}
707
	}
708
709
	/**
710
	 * Registers converters to boxed and unboxed types from a list of from
711
	 * classes.
712
	 * 
713
	 * @param map
714
	 * @param numberFormat
715
	 * @param fromTypes
716
	 */
717
	private static void addNumberToIntegerConverters(Map map,
718
			NumberFormat numberFormat, Class[] fromTypes) {
719
		for (int i = 0; i < fromTypes.length; i++) {
720
			Class fromType = fromTypes[i];
721
			if (!fromType.equals(Integer.class)
722
					&& !fromType.equals(Integer.TYPE)) {
723
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
724
						fromType, null) : fromType.getName();
725
726
				map.put(new Pair(fromName, INTEGER_TYPE),
727
						new NumberToIntegerConverter(numberFormat, fromType,
728
								true));
729
				map.put(new Pair(fromName, Integer.class.getName()),
730
						new NumberToIntegerConverter(numberFormat, fromType,
731
								false));
732
			}
733
		}
734
	}
735
736
	/**
737
	 * Registers converters to boxed and unboxed types from a list of from
738
	 * classes.
739
	 * 
740
	 * @param map
741
	 * @param numberFormat
742
	 * @param fromTypes
743
	 */
744
	private static void addNumberToLongConverters(Map map,
745
			NumberFormat numberFormat, Class[] fromTypes) {
746
		for (int i = 0; i < fromTypes.length; i++) {
747
			Class fromType = fromTypes[i];
748
			if (!fromType.equals(Long.class) && !fromType.equals(Long.TYPE)) {
749
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
750
						fromType, null) : fromType.getName();
751
752
				map
753
						.put(new Pair(fromName, LONG_TYPE),
754
								new NumberToLongConverter(numberFormat,
755
										fromType, true));
756
				map
757
						.put(new Pair(fromName, Long.class.getName()),
758
								new NumberToLongConverter(numberFormat,
759
										fromType, false));
760
			}
761
		}
762
	}
763
764
	/**
765
	 * Registers converters to boxed and unboxed types from a list of from
766
	 * classes.
767
	 * 
768
	 * @param map
769
	 * @param numberFormat
770
	 * @param fromTypes
771
	 */
772
	private static void addNumberToFloatConverters(Map map,
773
			NumberFormat numberFormat, Class[] fromTypes) {
774
		for (int i = 0; i < fromTypes.length; i++) {
775
			Class fromType = fromTypes[i];
776
			if (!fromType.equals(Float.class) && !fromType.equals(Float.TYPE)) {
777
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
778
						fromType, null) : fromType.getName();
779
780
				map
781
						.put(new Pair(fromName, FLOAT_TYPE),
782
								new NumberToFloatConverter(numberFormat,
783
										fromType, true));
784
				map.put(new Pair(fromName, Float.class.getName()),
785
						new NumberToFloatConverter(numberFormat, fromType,
786
								false));
787
			}
788
		}
789
	}
790
791
	/**
792
	 * Registers converters to boxed and unboxed types from a list of from
793
	 * classes.
794
	 * 
795
	 * @param map
796
	 * @param numberFormat
797
	 * @param fromTypes
798
	 */
799
	private static void addNumberToDoubleConverters(Map map,
800
			NumberFormat numberFormat, Class[] fromTypes) {
801
		for (int i = 0; i < fromTypes.length; i++) {
802
			Class fromType = fromTypes[i];
803
			if (!fromType.equals(Double.class) && !fromType.equals(Double.TYPE)) {
804
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
805
						fromType, null) : fromType.getName();
806
807
				map.put(new Pair(fromName, DOUBLE_TYPE),
808
						new NumberToDoubleConverter(numberFormat, fromType,
809
								true));
810
				map.put(new Pair(fromName, Double.class.getName()),
811
						new NumberToDoubleConverter(numberFormat, fromType,
812
								false));
813
			}
814
		}
815
	}
816
817
	/**
818
	 * Registers converters to boxed and unboxed types from a list of from
819
	 * classes.
820
	 * 
821
	 * @param map
822
	 * @param numberFormat
823
	 * @param fromTypes
824
	 */
825
	private static void addNumberToBigIntegerConverters(Map map,
826
			NumberFormat numberFormat, Class[] fromTypes) {
827
		for (int i = 0; i < fromTypes.length; i++) {
828
			Class fromType = fromTypes[i];
829
			if (!fromType.equals(BigInteger.class)) {
830
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
831
						fromType, null) : fromType.getName();
832
833
				map
834
						.put(new Pair(fromName, BigInteger.class.getName()),
835
								new NumberToBigIntegerConverter(numberFormat,
836
										fromType));
837
			}
838
		}
839
	}
840
841
	/**
842
	 * Registers converters to boxed and unboxed types from a list of from
843
	 * classes.
844
	 * 
845
	 * @param map
846
	 * @param numberFormat
847
	 * @param fromTypes
848
	 */
849
	private static void addNumberToBigDecimalConverters(Map map,
850
			NumberFormat numberFormat, Class[] fromTypes) {
851
		for (int i = 0; i < fromTypes.length; i++) {
852
			Class fromType = fromTypes[i];
853
			if (!fromType.equals(BigDecimal.class)) {
854
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(
855
						fromType, null) : fromType.getName();
856
857
				map
858
						.put(new Pair(fromName, BigDecimal.class.getName()),
859
								new NumberToBigDecimalConverter(numberFormat,
860
										fromType));
861
			}
862
		}
863
	}
864
865
	private static String getKeyForClass(Object originalValue,
866
			Class filteredValue) {
867
		if (originalValue instanceof Class) {
868
			Class originalClass = (Class) originalValue;
869
			if (originalClass.equals(Integer.TYPE)) {
870
				return INTEGER_TYPE;
871
			} else if (originalClass.equals(Byte.TYPE)) {
872
				return BYTE_TYPE;
873
			} else if (originalClass.equals(Boolean.TYPE)) {
874
				return BOOLEAN_TYPE;
875
			} else if (originalClass.equals(Double.TYPE)) {
876
				return DOUBLE_TYPE;
877
			} else if (originalClass.equals(Float.TYPE)) {
878
				return FLOAT_TYPE;
879
			} else if (originalClass.equals(Long.TYPE)) {
880
				return LONG_TYPE;
881
			} else if (originalClass.equals(Short.TYPE)) {
882
				return SHORT_TYPE;
883
			}
884
		}
885
		return filteredValue.getName();
886
	}
887
888
	/**
889
	 * @param fromType
890
	 * @param toType
891
	 * @return whether fromType is assignable to toType
892
	 */
893
	protected Boolean isAssignableFromTo(Object fromType, Object toType) {
894
		if (fromType instanceof Class && toType instanceof Class) {
895
			Class toClass = (Class) toType;
896
			if (toClass.isPrimitive()) {
897
				toClass = autoboxed(toClass);
898
			}
899
			Class fromClass = (Class) fromType;
900
			if (fromClass.isPrimitive()) {
901
				fromClass = autoboxed(fromClass);
902
			}
903
			return toClass.isAssignableFrom(fromClass) ? Boolean.TRUE
904
					: Boolean.FALSE;
905
		}
906
		return null;
907
	}
908
909
	/*
910
	 * Default converter implementation, does not perform any conversion.
911
	 */
912
	protected static final class DefaultConverter implements IConverter {
913
914
		private final Object toType;
915
916
		private final Object fromType;
917
918
		/**
919
		 * @param fromType
920
		 * @param toType
921
		 */
922
		DefaultConverter(Object fromType, Object toType) {
923
			this.toType = toType;
924
			this.fromType = fromType;
925
		}
926
927
		public Object convert(Object fromObject) {
928
			return fromObject;
929
		}
930
931
		public Object getFromType() {
932
			return fromType;
933
		}
934
935
		public Object getToType() {
936
			return toType;
937
		}
938
	}
939
}
(-)src/org/eclipse/jface/examples/databinding/snippets/Snippet000HelloWorld.java (-17 / +18 lines)
Lines 13-19 Link Here
13
package org.eclipse.jface.examples.databinding.snippets;
13
package org.eclipse.jface.examples.databinding.snippets;
14
14
15
import org.eclipse.core.databinding.DataBindingContext;
15
import org.eclipse.core.databinding.DataBindingContext;
16
import org.eclipse.core.databinding.beans.BeansObservables;
16
import org.eclipse.core.databinding.ValueBindingBuilder;
17
import org.eclipse.core.databinding.beans.PojoObservables;
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
19
import org.eclipse.jface.databinding.swt.SWTObservables;
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.SWT;
Lines 34-52 Link Here
34
		Display display = new Display();
35
		Display display = new Display();
35
		final ViewModel viewModel = new ViewModel();
36
		final ViewModel viewModel = new ViewModel();
36
37
37
		Realm.runWithDefault(SWTObservables.getRealm(display),
38
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
38
				new Runnable() {
39
			public void run() {
39
					public void run() {
40
				final Shell shell = new View(viewModel).createShell();
40
						final Shell shell = new View(viewModel).createShell();
41
				// The SWT event loop
41
						// The SWT event loop
42
				Display display = Display.getCurrent();
42
						Display display = Display.getCurrent();
43
				while (!shell.isDisposed()) {
43
						while (!shell.isDisposed()) {
44
					if (!display.readAndDispatch()) {
44
							if (!display.readAndDispatch()) {
45
						display.sleep();
45
								display.sleep();
46
							}
47
						}
48
					}
46
					}
49
				});
47
				}
48
			}
49
		});
50
		// Print the results
50
		// Print the results
51
		System.out.println("person.getName() = "
51
		System.out.println("person.getName() = "
52
				+ viewModel.getPerson().getName());
52
				+ viewModel.getPerson().getName());
Lines 90-95 Link Here
90
	// The GUI view
90
	// The GUI view
91
	static class View {
91
	static class View {
92
		private ViewModel viewModel;
92
		private ViewModel viewModel;
93
93
		private Text name;
94
		private Text name;
94
95
95
		public View(ViewModel viewModel) {
96
		public View(ViewModel viewModel) {
Lines 104-115 Link Here
104
			name = new Text(shell, SWT.BORDER);
105
			name = new Text(shell, SWT.BORDER);
105
106
106
			// Bind it
107
			// Bind it
107
			DataBindingContext bindingContext = new DataBindingContext();
108
			ValueBindingBuilder builder = ValueBindingBuilder.withDefaults()
109
					.dbc(new DataBindingContext());
108
			Person person = viewModel.getPerson();
110
			Person person = viewModel.getPerson();
109
111
110
			bindingContext.bindValue(SWTObservables.observeText(name,
112
			builder.bind(SWTObservables.observeText(name, SWT.Modify),
111
					SWT.Modify), BeansObservables.observeValue(person, "name"),
113
					PojoObservables.observeValue(person, "name"));
112
					null, null);
113
114
114
			// Open and return the Shell
115
			// Open and return the Shell
115
			shell.pack();
116
			shell.pack();

Return to bug 203492