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/UpdateListStrategy.java (-11 / +38 lines)
Lines 12-20 Link Here
12
package org.eclipse.core.databinding;
12
package org.eclipse.core.databinding;
13
13
14
import org.eclipse.core.databinding.conversion.IConverter;
14
import org.eclipse.core.databinding.conversion.IConverter;
15
import org.eclipse.core.databinding.conversion.IConverterProvider;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.core.databinding.validation.ValidationStatus;
17
import org.eclipse.core.databinding.validation.ValidationStatus;
17
import org.eclipse.core.internal.databinding.BindingMessages;
18
import org.eclipse.core.internal.databinding.BindingMessages;
19
import org.eclipse.core.internal.databinding.DefaultConverterProvider;
18
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.core.runtime.Status;
21
import org.eclipse.core.runtime.Status;
20
22
Lines 36-43 Link Here
36
 * construction of the strategy (e.g. {@link #POLICY_NEVER},
38
 * construction of the strategy (e.g. {@link #POLICY_NEVER},
37
 * {@link #POLICY_ON_REQUEST}, {@link #POLICY_UPDATE}).
39
 * {@link #POLICY_ON_REQUEST}, {@link #POLICY_UPDATE}).
38
 * </p>
40
 * </p>
39
 * 
41
 *
40
 * 
42
 *
41
 * @see DataBindingContext#bindList(IObservableList, IObservableList,
43
 * @see DataBindingContext#bindList(IObservableList, IObservableList,
42
 *      UpdateListStrategy, UpdateListStrategy)
44
 *      UpdateListStrategy, UpdateListStrategy)
43
 * @see IConverter
45
 * @see IConverter
Lines 71-77 Link Here
71
	 * Helper method allowing API evolution of the above constant values. The
73
	 * Helper method allowing API evolution of the above constant values. The
72
	 * compiler will not inline constant values into client code if values are
74
	 * compiler will not inline constant values into client code if values are
73
	 * "computed" using this helper.
75
	 * "computed" using this helper.
74
	 * 
76
	 *
75
	 * @param i
77
	 * @param i
76
	 *            an integer
78
	 *            an integer
77
	 * @return the same integer
79
	 * @return the same integer
Lines 93-106 Link Here
93
	 * calling one of the setter methods.
95
	 * calling one of the setter methods.
94
	 */
96
	 */
95
	public UpdateListStrategy() {
97
	public UpdateListStrategy() {
96
		this(true, POLICY_UPDATE);
98
		this(true, POLICY_UPDATE,new DefaultConverterProvider());
99
	}
100
101
	/**
102
	 * @param provider
103
	 */
104
	public UpdateListStrategy(IConverterProvider provider) {
105
		this(true,POLICY_UPDATE,provider);
97
	}
106
	}
98
107
99
	/**
108
	/**
100
	 * Creates a new update list strategy with a configurable update policy. A
109
	 * Creates a new update list strategy with a configurable update policy. A
101
	 * default converter will be provided. The defaults can be changed by
110
	 * default converter will be provided. The defaults can be changed by
102
	 * calling one of the setter methods.
111
	 * calling one of the setter methods.
103
	 * 
112
	 *
104
	 * @param updatePolicy
113
	 * @param updatePolicy
105
	 *            one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST}, or
114
	 *            one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST}, or
106
	 *            {@link #POLICY_UPDATE}
115
	 *            {@link #POLICY_UPDATE}
Lines 110-120 Link Here
110
	}
119
	}
111
120
112
	/**
121
	/**
122
	 * @param updatePolicy
123
	 * @param provider
124
	 */
125
	public UpdateListStrategy(int updatePolicy,IConverterProvider provider) {
126
		this(true,updatePolicy,provider);
127
	}
128
129
	/**
113
	 * Creates a new update list strategy with a configurable update policy. A
130
	 * Creates a new update list strategy with a configurable update policy. A
114
	 * default converter will be provided if <code>provideDefaults</code> is
131
	 * default converter will be provided if <code>provideDefaults</code> is
115
	 * <code>true</code>. The defaults can be changed by calling one of the
132
	 * <code>true</code>. The defaults can be changed by calling one of the
116
	 * setter methods.
133
	 * setter methods.
117
	 * 
134
	 *
118
	 * @param provideDefaults
135
	 * @param provideDefaults
119
	 *            if <code>true</code>, default validators and a default
136
	 *            if <code>true</code>, default validators and a default
120
	 *            converter will be provided based on the observable list's
137
	 *            converter will be provided based on the observable list's
Lines 124-129 Link Here
124
	 *            {@link #POLICY_UPDATE}
141
	 *            {@link #POLICY_UPDATE}
125
	 */
142
	 */
126
	public UpdateListStrategy(boolean provideDefaults, int updatePolicy) {
143
	public UpdateListStrategy(boolean provideDefaults, int updatePolicy) {
144
		this(true,updatePolicy,new DefaultConverterProvider());
145
	}
146
147
	/**
148
	 * @param provideDefaults
149
	 * @param updatePolicy
150
	 * @param provider
151
	 */
152
	public UpdateListStrategy(boolean provideDefaults, int updatePolicy, IConverterProvider provider) {
153
		super(provider==null?new DefaultConverterProvider():provider);
127
		this.provideDefaults = provideDefaults;
154
		this.provideDefaults = provideDefaults;
128
		this.updatePolicy = updatePolicy;
155
		this.updatePolicy = updatePolicy;
129
	}
156
	}
Lines 136-142 Link Here
136
	 * {@link #setConverter(IConverter) converter} if one exists. If no
163
	 * {@link #setConverter(IConverter) converter} if one exists. If no
137
	 * converter exists no conversion occurs.
164
	 * converter exists no conversion occurs.
138
	 * </p>
165
	 * </p>
139
	 * 
166
	 *
140
	 * @param element
167
	 * @param element
141
	 * @return the converted element
168
	 * @return the converted element
142
	 */
169
	 */
Lines 145-151 Link Here
145
	}
172
	}
146
173
147
	/**
174
	/**
148
	 * 
175
	 *
149
	 * @param source
176
	 * @param source
150
	 * @param destination
177
	 * @param destination
151
	 */
178
	 */
Lines 180-186 Link Here
180
	/**
207
	/**
181
	 * Sets the converter to be invoked when converting added elements from the
208
	 * Sets the converter to be invoked when converting added elements from the
182
	 * source element type to the destination element type.
209
	 * source element type to the destination element type.
183
	 * 
210
	 *
184
	 * @param converter
211
	 * @param converter
185
	 * @return the receiver, to enable method call chaining
212
	 * @return the receiver, to enable method call chaining
186
	 */
213
	 */
Lines 192-198 Link Here
192
	/**
219
	/**
193
	 * Adds the given element at the given index to the given observable list.
220
	 * Adds the given element at the given index to the given observable list.
194
	 * Clients may extend but must call the super implementation.
221
	 * Clients may extend but must call the super implementation.
195
	 * 
222
	 *
196
	 * @param observableList
223
	 * @param observableList
197
	 * @param element
224
	 * @param element
198
	 * @param index
225
	 * @param index
Lines 213-219 Link Here
213
	/**
240
	/**
214
	 * Removes the element at the given index from the given observable list.
241
	 * Removes the element at the given index from the given observable list.
215
	 * Clients may extend but must call the super implementation.
242
	 * Clients may extend but must call the super implementation.
216
	 * 
243
	 *
217
	 * @param observableList
244
	 * @param observableList
218
	 * @param index
245
	 * @param index
219
	 * @return a status
246
	 * @return a status
(-)src/org/eclipse/core/databinding/UpdateStrategy.java (-480 / +28 lines)
Lines 11-87 Link Here
11
11
12
package org.eclipse.core.databinding;
12
package org.eclipse.core.databinding;
13
13
14
import java.math.BigDecimal;
15
import java.math.BigInteger;
16
import java.util.HashMap;
17
import java.util.Map;
18
14
19
import org.eclipse.core.databinding.conversion.IConverter;
15
import org.eclipse.core.databinding.conversion.IConverter;
20
import org.eclipse.core.databinding.conversion.NumberToStringConverter;
16
import org.eclipse.core.databinding.conversion.IConverterProvider;
21
import org.eclipse.core.databinding.conversion.StringToNumberConverter;
22
import org.eclipse.core.databinding.util.Policy;
23
import org.eclipse.core.internal.databinding.ClassLookupSupport;
24
import org.eclipse.core.internal.databinding.Pair;
25
import org.eclipse.core.internal.databinding.conversion.IdentityConverter;
26
import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter;
27
import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
28
import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
29
import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter;
30
import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter;
31
import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter;
32
import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
33
import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
34
import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
35
import org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter;
36
import org.eclipse.core.internal.databinding.conversion.StringToByteConverter;
37
import org.eclipse.core.internal.databinding.conversion.StringToShortConverter;
38
import org.eclipse.core.runtime.IStatus;
39
import org.eclipse.core.runtime.Status;
40
41
import com.ibm.icu.text.NumberFormat;
42
17
43
/**
18
/**
44
 * @since 1.0
19
 * @since 1.0
45
 * 
20
 *
46
 */
21
 */
47
/* package */class UpdateStrategy {
22
/* package */class UpdateStrategy {
23
	private IConverterProvider converterProvider;
48
24
49
	private static final String BOOLEAN_TYPE = "java.lang.Boolean.TYPE"; //$NON-NLS-1$
25
//	/**
50
	private static final String SHORT_TYPE = "java.lang.Short.TYPE"; //$NON-NLS-1$
26
//	 *
51
	private static final String BYTE_TYPE = "java.lang.Byte.TYPE"; //$NON-NLS-1$
27
//	 */
52
	private static final String DOUBLE_TYPE = "java.lang.Double.TYPE"; //$NON-NLS-1$
28
//	public UpdateStrategy() {
53
	private static final String FLOAT_TYPE = "java.lang.Float.TYPE"; //$NON-NLS-1$
29
//		this(new DefaultConverterProvider());
54
	private static final String INTEGER_TYPE = "java.lang.Integer.TYPE"; //$NON-NLS-1$
30
//	}
55
	private static final String LONG_TYPE = "java.lang.Long.TYPE"; //$NON-NLS-1$
56
	private static Map converterMap;
57
58
	private static Class autoboxed(Class clazz) {
59
		if (clazz == Float.TYPE)
60
			return Float.class;
61
		else if (clazz == Double.TYPE)
62
			return Double.class;
63
		else if (clazz == Short.TYPE)
64
			return Short.class;
65
		else if (clazz == Integer.TYPE)
66
			return Integer.class;
67
		else if (clazz == Long.TYPE)
68
			return Long.class;
69
		else if (clazz == Byte.TYPE)
70
			return Byte.class;
71
		else if (clazz == Boolean.TYPE)
72
			return Boolean.class;
73
		return clazz;
74
	}
75
31
76
	final protected void checkAssignable(Object toType, Object fromType,
32
	/**
77
			String errorString) {
33
	 * @param converterProvider the provider implementation used
78
		Boolean assignableFromModelToModelConverter = isAssignableFromTo(
34
	 */
79
				fromType, toType);
35
	public UpdateStrategy(IConverterProvider converterProvider) {
80
		if (assignableFromModelToModelConverter != null
36
		this.converterProvider = converterProvider;
81
				&& !assignableFromModelToModelConverter.booleanValue()) {
82
			throw new BindingException(errorString
83
					+ " Expected: " + fromType + ", actual: " + toType); //$NON-NLS-1$//$NON-NLS-2$
84
		}
85
	}
37
	}
86
38
87
	/**
39
	/**
Lines 89-509 Link Here
89
	 * fromType. Returns <code>null</code> if no converter could be created.
41
	 * fromType. Returns <code>null</code> if no converter could be created.
90
	 * Either toType or modelDescription can be <code>null</code>, but not
42
	 * Either toType or modelDescription can be <code>null</code>, but not
91
	 * both.
43
	 * both.
92
	 * 
44
	 *
93
	 * @param fromType
45
	 * @param fromType
94
	 * @param toType
46
	 * @param toType
95
	 * @return an IConverter, or <code>null</code> if unsuccessful
47
	 * @return an IConverter, or <code>null</code> if unsuccessful
96
	 */
48
	 */
97
	protected IConverter createConverter(Object fromType, Object toType) {
49
	protected IConverter createConverter(Object fromType, Object toType) {
98
		if (!(fromType instanceof Class) || !(toType instanceof Class)) {
50
		IConverter convert = converterProvider.createConverter(fromType, toType);
99
			return new DefaultConverter(fromType, toType);
51
		if( convert == null ) {
100
		}
52
			convert = new DefaultConverter(fromType,toType);
101
		Class toClass = (Class) toType;
102
		Class originalToClass = toClass;
103
		if (toClass.isPrimitive()) {
104
			toClass = autoboxed(toClass);
105
		}
106
		Class fromClass = (Class) fromType;
107
		Class originalFromClass = fromClass;
108
		if (fromClass.isPrimitive()) {
109
			fromClass = autoboxed(fromClass);
110
		}
111
		if (!((Class) toType).isPrimitive()
112
				&& toClass.isAssignableFrom(fromClass)) {
113
			return new IdentityConverter(originalFromClass, originalToClass);
114
		}
115
		if (((Class) fromType).isPrimitive() && ((Class) toType).isPrimitive()
116
				&& fromType.equals(toType)) {
117
			return new IdentityConverter(originalFromClass, originalToClass);
118
		}
119
		Map converterMap = getConverterMap();
120
		Class[] supertypeHierarchyFlattened = ClassLookupSupport
121
				.getTypeHierarchyFlattened(fromClass);
122
		for (int i = 0; i < supertypeHierarchyFlattened.length; i++) {
123
			Class currentFromClass = supertypeHierarchyFlattened[i];
124
			if (currentFromClass == toType) {
125
				// converting to toType is just a widening
126
				return new IdentityConverter(fromClass, toClass);
127
			}
128
			Pair key = new Pair(getKeyForClass(fromType, currentFromClass),
129
					getKeyForClass(toType, toClass));
130
			Object converterOrClassname = converterMap.get(key);
131
			if (converterOrClassname instanceof IConverter) {
132
				return (IConverter) converterOrClassname;
133
			} else if (converterOrClassname instanceof String) {
134
				String classname = (String) converterOrClassname;
135
				Class converterClass;
136
				try {
137
					converterClass = Class.forName(classname);
138
					IConverter result = (IConverter) converterClass
139
							.newInstance();
140
					converterMap.put(key, result);
141
					return result;
142
				} catch (Exception e) {
143
					Policy
144
							.getLog()
145
							.log(
146
									new Status(
147
											IStatus.ERROR,
148
											Policy.JFACE_DATABINDING,
149
											0,
150
											"Error while instantiating default converter", e)); //$NON-NLS-1$
151
				}
152
			}
153
		}
154
		// Since we found no converter yet, try a "downcast" converter;
155
		// the IdentityConverter will automatically check the actual types at
156
		// runtime.
157
		if (fromClass.isAssignableFrom(toClass)) {
158
			return new IdentityConverter(originalFromClass, originalToClass);
159
		}
160
		return new DefaultConverter(fromType, toType);
161
	}
162
163
	private static Map getConverterMap() {
164
		// using string-based lookup avoids loading of too many classes
165
		if (converterMap == null) {
166
			//NumberFormat to be shared across converters for the formatting of integer values
167
			NumberFormat integerFormat = NumberFormat.getIntegerInstance();
168
			//NumberFormat to be shared across converters for formatting non integer values
169
			NumberFormat numberFormat = NumberFormat.getNumberInstance();
170
			
171
			converterMap = new HashMap();
172
			converterMap
173
					.put(
174
							new Pair("java.util.Date", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.DateToStringConverter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
175
			converterMap
176
					.put(
177
							new Pair("java.lang.String", "java.lang.Boolean"), "org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
178
			converterMap
179
					.put(
180
							new Pair("java.lang.String", "java.lang.Byte"), StringToByteConverter.toByte(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
181
			converterMap
182
					.put(
183
							new Pair("java.lang.String", "java.lang.Character"), "org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
184
			converterMap
185
					.put(
186
							new Pair("java.lang.String", "java.util.Date"), "org.eclipse.core.internal.databinding.conversion.StringToDateConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
187
			converterMap
188
					.put(
189
							new Pair("java.lang.String", "java.lang.Short"), StringToShortConverter.toShort(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
190
			
191
			converterMap.put(new Pair("java.lang.String", "java.lang.Integer"), StringToNumberConverter.toInteger(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
192
			converterMap.put(new Pair("java.lang.String", "java.lang.Double"), StringToNumberConverter.toDouble(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
193
			converterMap.put(new Pair("java.lang.String", "java.lang.Long"), StringToNumberConverter.toLong(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
194
			converterMap.put(new Pair("java.lang.String", "java.lang.Float"), StringToNumberConverter.toFloat(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$			
195
			converterMap.put(new Pair("java.lang.String", "java.math.BigInteger"), StringToNumberConverter.toBigInteger(integerFormat));  //$NON-NLS-1$//$NON-NLS-2$			
196
			converterMap.put(new Pair("java.lang.Integer", "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
197
			converterMap.put(new Pair("java.lang.Long", "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
198
			converterMap.put(new Pair("java.lang.Double", "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
199
			converterMap.put(new Pair("java.lang.Float", "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
200
			converterMap.put(new Pair("java.math.BigInteger", "java.lang.String"), NumberToStringConverter.fromBigInteger(integerFormat));  //$NON-NLS-1$//$NON-NLS-2$
201
			converterMap.put(new Pair("java.lang.Byte", "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, false));   //$NON-NLS-1$//$NON-NLS-2$
202
			converterMap.put(new Pair("java.lang.Short", "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
203
			
204
			converterMap
205
					.put(
206
							new Pair("java.lang.Object", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
207
208
			// Integer.TYPE
209
			converterMap.put(new Pair("java.lang.String", INTEGER_TYPE), StringToNumberConverter.toInteger(integerFormat, true)); //$NON-NLS-1$
210
			converterMap
211
					.put(
212
							new Pair(INTEGER_TYPE, "java.lang.Integer"), new IdentityConverter(Integer.TYPE, Integer.class)); //$NON-NLS-1$
213
			converterMap
214
					.put(
215
							new Pair(INTEGER_TYPE, "java.lang.Object"), new IdentityConverter(Integer.TYPE, Object.class)); //$NON-NLS-1$
216
			converterMap.put(new Pair(INTEGER_TYPE, "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, true)); //$NON-NLS-1$
217
218
			// Byte.TYPE
219
			converterMap
220
					.put(
221
							new Pair("java.lang.String", BYTE_TYPE), StringToByteConverter.toByte(integerFormat, true)); //$NON-NLS-1$
222
			converterMap
223
					.put(
224
							new Pair(BYTE_TYPE, "java.lang.Byte"), new IdentityConverter(Byte.TYPE, Byte.class)); //$NON-NLS-1$
225
			converterMap
226
					.put(
227
							new Pair(BYTE_TYPE, "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, true)); //$NON-NLS-1$
228
			converterMap
229
					.put(
230
							new Pair(BYTE_TYPE, "java.lang.Object"), new IdentityConverter(Byte.TYPE, Object.class)); //$NON-NLS-1$
231
232
			// Double.TYPE
233
			converterMap.put(new Pair("java.lang.String", DOUBLE_TYPE), StringToNumberConverter.toDouble(numberFormat, true)); //$NON-NLS-1$
234
			converterMap.put(new Pair(DOUBLE_TYPE, "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, true)); //$NON-NLS-1$
235
			
236
			converterMap
237
					.put(
238
							new Pair(DOUBLE_TYPE, "java.lang.Double"), new IdentityConverter(Double.TYPE, Double.class)); //$NON-NLS-1$
239
			converterMap
240
					.put(
241
							new Pair(DOUBLE_TYPE, "java.lang.Object"), new IdentityConverter(Double.TYPE, Object.class)); //$NON-NLS-1$
242
243
			// Boolean.TYPE
244
			converterMap
245
					.put(
246
							new Pair("java.lang.String", BOOLEAN_TYPE), "org.eclipse.core.internal.databinding.conversion.StringToBooleanPrimitiveConverter"); //$NON-NLS-1$ //$NON-NLS-2$
247
			converterMap
248
					.put(
249
							new Pair(BOOLEAN_TYPE, "java.lang.Boolean"), new IdentityConverter(Boolean.TYPE, Boolean.class)); //$NON-NLS-1$
250
			converterMap
251
					.put(
252
							new Pair(BOOLEAN_TYPE, "java.lang.String"), new ObjectToStringConverter(Boolean.TYPE)); //$NON-NLS-1$
253
			converterMap
254
					.put(
255
							new Pair(BOOLEAN_TYPE, "java.lang.Object"), new IdentityConverter(Boolean.TYPE, Object.class)); //$NON-NLS-1$
256
257
			// Float.TYPE
258
			converterMap.put(new Pair("java.lang.String", FLOAT_TYPE), StringToNumberConverter.toFloat(numberFormat, true)); //$NON-NLS-1$
259
			converterMap.put(new Pair(FLOAT_TYPE, "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, true)); //$NON-NLS-1$
260
			converterMap
261
					.put(
262
							new Pair(FLOAT_TYPE, "java.lang.Float"), new IdentityConverter(Float.TYPE, Float.class)); //$NON-NLS-1$
263
			converterMap
264
					.put(
265
							new Pair(FLOAT_TYPE, "java.lang.Object"), new IdentityConverter(Float.TYPE, Object.class)); //$NON-NLS-1$		
266
267
			// Short.TYPE
268
			converterMap
269
					.put(
270
							new Pair("java.lang.String", SHORT_TYPE), StringToShortConverter.toShort(integerFormat, true)); //$NON-NLS-1$
271
			converterMap
272
					.put(
273
							new Pair(SHORT_TYPE, "java.lang.Short"), new IdentityConverter(Short.TYPE, Short.class)); //$NON-NLS-1$
274
			converterMap
275
					.put(
276
							new Pair(SHORT_TYPE, "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, true)); //$NON-NLS-1$
277
			converterMap
278
					.put(
279
							new Pair(SHORT_TYPE, "java.lang.Object"), new IdentityConverter(Short.TYPE, Object.class)); //$NON-NLS-1$		
280
281
			// Long.TYPE
282
			converterMap.put(new Pair("java.lang.String", LONG_TYPE), StringToNumberConverter.toLong(integerFormat, true)); //$NON-NLS-1$
283
			converterMap.put(new Pair(LONG_TYPE, "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, true)); //$NON-NLS-1$
284
			converterMap
285
					.put(
286
							new Pair(LONG_TYPE, "java.lang.Long"), new IdentityConverter(Long.TYPE, Long.class)); //$NON-NLS-1$
287
			converterMap
288
					.put(
289
							new Pair(LONG_TYPE, "java.lang.Object"), new IdentityConverter(Long.TYPE, Object.class)); //$NON-NLS-1$		
290
291
			converterMap
292
					.put(
293
							new Pair("org.eclipse.core.runtime.IStatus", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.StatusToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
294
			
295
			addNumberToByteConverters(converterMap, integerFormat, integerClasses);
296
			addNumberToByteConverters(converterMap, numberFormat, floatClasses);
297
			
298
			addNumberToShortConverters(converterMap, integerFormat, integerClasses);
299
			addNumberToShortConverters(converterMap, numberFormat, floatClasses);
300
			
301
			addNumberToIntegerConverters(converterMap, integerFormat, integerClasses);
302
			addNumberToIntegerConverters(converterMap, numberFormat, floatClasses);
303
			
304
			addNumberToLongConverters(converterMap, integerFormat, integerClasses);
305
			addNumberToLongConverters(converterMap, numberFormat, floatClasses);
306
			
307
			addNumberToFloatConverters(converterMap, integerFormat, integerClasses);
308
			addNumberToFloatConverters(converterMap, numberFormat, floatClasses);
309
			
310
			addNumberToDoubleConverters(converterMap, integerFormat, integerClasses);
311
			addNumberToDoubleConverters(converterMap, numberFormat, floatClasses);
312
			
313
			addNumberToBigIntegerConverters(converterMap, integerFormat, integerClasses);
314
			addNumberToBigIntegerConverters(converterMap, numberFormat, floatClasses);	
315
			
316
			addNumberToBigDecimalConverters(converterMap, integerFormat, integerClasses);
317
			addNumberToBigDecimalConverters(converterMap, numberFormat, floatClasses);
318
		}
319
320
		return converterMap;
321
	}
322
	
323
	private static final Class[] integerClasses = new Class[]{
324
		Byte.TYPE, Byte.class,
325
		Short.TYPE, Short.class, 
326
		Integer.TYPE, Integer.class,
327
		Long.TYPE, Long.class,
328
		BigInteger.class};
329
330
	private static final Class[] floatClasses = new Class[] {
331
		Float.TYPE, Float.class,
332
		Double.TYPE, Double.class,
333
		BigDecimal.class};
334
	
335
	/**
336
	 * Registers converters to boxed and unboxed types from a list of from classes.
337
	 * 
338
	 * @param map
339
	 * @param numberFormat
340
	 * @param fromTypes
341
	 */
342
	private static void addNumberToByteConverters(Map map,
343
			NumberFormat numberFormat, Class[] fromTypes) {
344
		
345
		for (int i = 0; i < fromTypes.length; i++) {
346
			Class fromType = fromTypes[i];
347
			if (!fromType.equals(Byte.class) && !fromType.equals(Byte.TYPE)) {
348
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
349
				
350
				map.put(new Pair(fromName, BYTE_TYPE), new NumberToByteConverter(numberFormat, fromType, true));
351
				map.put(new Pair(fromName, Byte.class.getName()), new NumberToByteConverter(numberFormat, fromType, false));
352
			}
353
		}
354
	}
355
	
356
	/**
357
	 * Registers converters to boxed and unboxed types from a list of from classes.
358
	 * 
359
	 * @param map
360
	 * @param numberFormat
361
	 * @param fromTypes
362
	 */
363
	private static void addNumberToShortConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
364
		for (int i = 0; i < fromTypes.length; i++) {
365
			Class fromType = fromTypes[i];
366
			if (!fromType.equals(Short.class) && !fromType.equals(Short.TYPE)) {
367
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
368
				
369
				map.put(new Pair(fromName, SHORT_TYPE), new NumberToShortConverter(numberFormat, fromType, true));
370
				map.put(new Pair(fromName, Short.class.getName()), new NumberToShortConverter(numberFormat, fromType, false));
371
			}
372
		}
373
	}
374
	
375
	/**
376
	 * Registers converters to boxed and unboxed types from a list of from classes.
377
	 * 
378
	 * @param map
379
	 * @param numberFormat
380
	 * @param fromTypes
381
	 */
382
	private static void addNumberToIntegerConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
383
		for (int i = 0; i < fromTypes.length; i++) {
384
			Class fromType = fromTypes[i];
385
			if (!fromType.equals(Integer.class) && !fromType.equals(Integer.TYPE)) {
386
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
387
				
388
				map.put(new Pair(fromName, INTEGER_TYPE), new NumberToIntegerConverter(numberFormat, fromType, true));
389
				map.put(new Pair(fromName, Integer.class.getName()), new NumberToIntegerConverter(numberFormat, fromType, false));
390
			}
391
		}
392
	}
393
	
394
	/**
395
	 * Registers converters to boxed and unboxed types from a list of from classes.
396
	 * 
397
	 * @param map
398
	 * @param numberFormat
399
	 * @param fromTypes
400
	 */
401
	private static void addNumberToLongConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
402
		for (int i = 0; i < fromTypes.length; i++) {
403
			Class fromType = fromTypes[i];
404
			if (!fromType.equals(Long.class) && !fromType.equals(Long.TYPE)) {
405
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
406
				
407
				map.put(new Pair(fromName, LONG_TYPE), new NumberToLongConverter(numberFormat, fromType, true));
408
				map.put(new Pair(fromName, Long.class.getName()), new NumberToLongConverter(numberFormat, fromType, false));
409
			}
410
		}
53
		}
411
	}
412
54
413
	/**
55
		return convert;
414
	 * Registers converters to boxed and unboxed types from a list of from classes.
415
	 * 
416
	 * @param map
417
	 * @param numberFormat
418
	 * @param fromTypes
419
	 */
420
	private static void addNumberToFloatConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
421
		for (int i = 0; i < fromTypes.length; i++) {
422
			Class fromType = fromTypes[i];
423
			if (!fromType.equals(Float.class) && !fromType.equals(Float.TYPE)) {
424
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
425
				
426
				map.put(new Pair(fromName, FLOAT_TYPE), new NumberToFloatConverter(numberFormat, fromType, true));
427
				map.put(new Pair(fromName, Float.class.getName()), new NumberToFloatConverter(numberFormat, fromType, false));
428
			}
429
		}
430
	}
431
	
432
	/**
433
	 * Registers converters to boxed and unboxed types from a list of from classes.
434
	 * 
435
	 * @param map
436
	 * @param numberFormat
437
	 * @param fromTypes
438
	 */
439
	private static void addNumberToDoubleConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
440
		for (int i = 0; i < fromTypes.length; i++) {
441
			Class fromType = fromTypes[i];
442
			if (!fromType.equals(Double.class) && !fromType.equals(Double.TYPE)) {
443
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
444
				
445
				map.put(new Pair(fromName, DOUBLE_TYPE), new NumberToDoubleConverter(numberFormat, fromType, true));
446
				map.put(new Pair(fromName, Double.class.getName()), new NumberToDoubleConverter(numberFormat, fromType, false));
447
			}
448
		}
449
	}
56
	}
450
57
451
	/**
58
	final protected void checkAssignable(Object toType, Object fromType,
452
	 * Registers converters to boxed and unboxed types from a list of from classes.
59
			String errorString) {
453
	 * 
60
		Boolean assignableFromModelToModelConverter = isAssignableFromTo(
454
	 * @param map
61
				fromType, toType);
455
	 * @param numberFormat
62
		if (assignableFromModelToModelConverter != null
456
	 * @param fromTypes
63
				&& !assignableFromModelToModelConverter.booleanValue()) {
457
	 */
64
			throw new BindingException(errorString
458
	private static void addNumberToBigIntegerConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
65
					+ " Expected: " + fromType + ", actual: " + toType); //$NON-NLS-1$//$NON-NLS-2$
459
		for (int i = 0; i < fromTypes.length; i++) {
460
			Class fromType = fromTypes[i];
461
			if (!fromType.equals(BigInteger.class)) {
462
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
463
				
464
				map.put(new Pair(fromName, BigInteger.class.getName()), new NumberToBigIntegerConverter(numberFormat, fromType));
465
			}
466
		}
467
	}
468
	
469
	/**
470
	 * Registers converters to boxed and unboxed types from a list of from classes.
471
	 * 
472
	 * @param map
473
	 * @param numberFormat
474
	 * @param fromTypes
475
	 */
476
	private static void addNumberToBigDecimalConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
477
		for (int i = 0; i < fromTypes.length; i++) {
478
			Class fromType = fromTypes[i];
479
			if (!fromType.equals(BigDecimal.class)) {
480
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
481
				
482
				map.put(new Pair(fromName, BigDecimal.class.getName()), new NumberToBigDecimalConverter(numberFormat, fromType));
483
			}
484
		}
485
	}
486
	
487
	private static String getKeyForClass(Object originalValue, Class filteredValue) {
488
		if (originalValue instanceof Class) {
489
			Class originalClass = (Class) originalValue;
490
			if (originalClass.equals(Integer.TYPE)) {
491
				return INTEGER_TYPE;
492
			} else if (originalClass.equals(Byte.TYPE)) {
493
				return BYTE_TYPE;
494
			} else if (originalClass.equals(Boolean.TYPE)) {
495
				return BOOLEAN_TYPE;
496
			} else if (originalClass.equals(Double.TYPE)) {
497
				return DOUBLE_TYPE;
498
			} else if (originalClass.equals(Float.TYPE)) {
499
				return FLOAT_TYPE;
500
			} else if (originalClass.equals(Long.TYPE)) {
501
				return LONG_TYPE;
502
			} else if (originalClass.equals(Short.TYPE)) {
503
				return SHORT_TYPE;
504
			}
505
		}
66
		}
506
		return filteredValue.getName();
507
	}
67
	}
508
68
509
	/**
69
	/**
Lines 512-530 Link Here
512
	 * @return whether fromType is assignable to toType
72
	 * @return whether fromType is assignable to toType
513
	 */
73
	 */
514
	protected Boolean isAssignableFromTo(Object fromType, Object toType) {
74
	protected Boolean isAssignableFromTo(Object fromType, Object toType) {
515
		if (fromType instanceof Class && toType instanceof Class) {
75
		return converterProvider.isAssignableFromTo(fromType, toType);
516
			Class toClass = (Class) toType;
517
			if (toClass.isPrimitive()) {
518
				toClass = autoboxed(toClass);
519
			}
520
			Class fromClass = (Class) fromType;
521
			if (fromClass.isPrimitive()) {
522
				fromClass = autoboxed(fromClass);
523
			}
524
			return toClass.isAssignableFrom(fromClass) ? Boolean.TRUE
525
					: Boolean.FALSE;
526
		}
527
		return null;
528
	}
76
	}
529
77
530
	/*
78
	/*
(-)src/org/eclipse/core/databinding/DataBindingContext.java (-23 / +42 lines)
Lines 16-21 Link Here
16
16
17
import java.util.Iterator;
17
import java.util.Iterator;
18
18
19
import org.eclipse.core.databinding.conversion.IConverterProvider;
19
import org.eclipse.core.databinding.observable.Observables;
20
import org.eclipse.core.databinding.observable.Observables;
20
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.list.IObservableList;
22
import org.eclipse.core.databinding.observable.list.IObservableList;
Lines 47-53 Link Here
47
 * could be aggregated to set the page status and fulfillment. Each page in the
48
 * could be aggregated to set the page status and fulfillment. Each page in the
48
 * <code>IWizard</code> would have its own context instance.
49
 * <code>IWizard</code> would have its own context instance.
49
 * </p>
50
 * </p>
50
 * 
51
 *
51
 * @since 1.0
52
 * @since 1.0
52
 */
53
 */
53
public class DataBindingContext {
54
public class DataBindingContext {
Lines 62-71 Link Here
62
63
63
	private Realm validationRealm;
64
	private Realm validationRealm;
64
65
66
	private IConverterProvider converterProvider;
67
65
	/**
68
	/**
66
	 * Creates a data binding context, using the current default realm for the
69
	 * Creates a data binding context, using the current default realm for the
67
	 * validation observables.
70
	 * validation observables.
68
	 * 
71
	 *
69
	 * @see Realm
72
	 * @see Realm
70
	 */
73
	 */
71
	public DataBindingContext() {
74
	public DataBindingContext() {
Lines 73-88 Link Here
73
	}
76
	}
74
77
75
	/**
78
	/**
79
	 * @param converterProvider
80
	 */
81
	public DataBindingContext(IConverterProvider converterProvider) {
82
		this(Realm.getDefault(),null);
83
	}
84
85
	/**
76
	 * Creates a data binding context using the given realm for the validation
86
	 * Creates a data binding context using the given realm for the validation
77
	 * observables.
87
	 * observables.
78
	 * 
88
	 *
79
	 * @param validationRealm
89
	 * @param validationRealm
80
	 *            the realm to be used for the validation observables
90
	 *            the realm to be used for the validation observables
81
	 * 
91
	 *
82
	 * @see Realm
92
	 * @see Realm
83
	 */
93
	 */
84
	public DataBindingContext(Realm validationRealm) {
94
	public DataBindingContext(Realm validationRealm) {
95
		this(validationRealm,null);
96
	}
97
98
	/**
99
	 * @param validationRealm
100
	 * @param converterProvider
101
	 */
102
	public DataBindingContext(Realm validationRealm,IConverterProvider converterProvider) {
85
		Assert.isNotNull(validationRealm);
103
		Assert.isNotNull(validationRealm);
104
		this.converterProvider = converterProvider;
86
		this.validationRealm = validationRealm;
105
		this.validationRealm = validationRealm;
87
		bindings = new WritableList(validationRealm);
106
		bindings = new WritableList(validationRealm);
88
107
Lines 97-103 Link Here
97
	 * validation and conversion can be employed to customize the process. For
116
	 * validation and conversion can be employed to customize the process. For
98
	 * specifics on the customization of the process see
117
	 * specifics on the customization of the process see
99
	 * {@link UpdateValueStrategy}.
118
	 * {@link UpdateValueStrategy}.
100
	 * 
119
	 *
101
	 * @param targetObservableValue
120
	 * @param targetObservableValue
102
	 *            target value, commonly a UI widget
121
	 *            target value, commonly a UI widget
103
	 * @param modelObservableValue
122
	 * @param modelObservableValue
Lines 109-115 Link Here
109
	 *            strategy to employ when the model is the source of the change
128
	 *            strategy to employ when the model is the source of the change
110
	 *            and the target is the destination
129
	 *            and the target is the destination
111
	 * @return created binding
130
	 * @return created binding
112
	 * 
131
	 *
113
	 * @see UpdateValueStrategy
132
	 * @see UpdateValueStrategy
114
	 */
133
	 */
115
	public final Binding bindValue(IObservableValue targetObservableValue,
134
	public final Binding bindValue(IObservableValue targetObservableValue,
Lines 131-166 Link Here
131
	/**
150
	/**
132
	 * Returns an update value strategy to be used for copying values from the
151
	 * Returns an update value strategy to be used for copying values from the
133
	 * from value to the to value. Clients may override.
152
	 * from value to the to value. Clients may override.
134
	 * 
153
	 *
135
	 * @param fromValue
154
	 * @param fromValue
136
	 * @param toValue
155
	 * @param toValue
137
	 * @return a update value strategy
156
	 * @return a update value strategy
138
	 */
157
	 */
139
	protected UpdateValueStrategy createModelToTargetUpdateValueStrategy(
158
	protected UpdateValueStrategy createModelToTargetUpdateValueStrategy(
140
			IObservableValue fromValue, IObservableValue toValue) {
159
			IObservableValue fromValue, IObservableValue toValue) {
141
		return new UpdateValueStrategy();
160
		return new UpdateValueStrategy(converterProvider);
142
	}
161
	}
143
162
144
	/**
163
	/**
145
	 * Returns an update value strategy to be used for copying values from the
164
	 * Returns an update value strategy to be used for copying values from the
146
	 * from value to the to value. Clients may override.
165
	 * from value to the to value. Clients may override.
147
	 * 
166
	 *
148
	 * @param fromValue
167
	 * @param fromValue
149
	 * @param toValue
168
	 * @param toValue
150
	 * @return a update value strategy
169
	 * @return a update value strategy
151
	 */
170
	 */
152
	protected UpdateValueStrategy createTargetToModelUpdateValueStrategy(
171
	protected UpdateValueStrategy createTargetToModelUpdateValueStrategy(
153
			IObservableValue fromValue, IObservableValue toValue) {
172
			IObservableValue fromValue, IObservableValue toValue) {
154
		return new UpdateValueStrategy();
173
		return new UpdateValueStrategy(converterProvider);
155
	}
174
	}
156
	
175
157
	/**
176
	/**
158
	 * Creates a {@link Binding} to synchronize the values of two
177
	 * Creates a {@link Binding} to synchronize the values of two
159
	 * {@link IObservableList observable lists}. During synchronization
178
	 * {@link IObservableList observable lists}. During synchronization
160
	 * validation and conversion can be employed to customize the process. For
179
	 * validation and conversion can be employed to customize the process. For
161
	 * specifics on the customization of the process see
180
	 * specifics on the customization of the process see
162
	 * {@link UpdateListStrategy}.
181
	 * {@link UpdateListStrategy}.
163
	 * 
182
	 *
164
	 * @param targetObservableList
183
	 * @param targetObservableList
165
	 *            target list, commonly a list representing a list in the UI
184
	 *            target list, commonly a list representing a list in the UI
166
	 * @param modelObservableList
185
	 * @param modelObservableList
Lines 172-178 Link Here
172
	 *            strategy to employ when the model is the source of the change
191
	 *            strategy to employ when the model is the source of the change
173
	 *            and the target is the destination
192
	 *            and the target is the destination
174
	 * @return created binding
193
	 * @return created binding
175
	 * 
194
	 *
176
	 * @see UpdateListStrategy
195
	 * @see UpdateListStrategy
177
	 */
196
	 */
178
	public final Binding bindList(IObservableList targetObservableList,
197
	public final Binding bindList(IObservableList targetObservableList,
Lines 203-220 Link Here
203
	protected UpdateListStrategy createModelToTargetUpdateListStrategy(
222
	protected UpdateListStrategy createModelToTargetUpdateListStrategy(
204
			IObservableList modelObservableList,
223
			IObservableList modelObservableList,
205
			IObservableList targetObservableList) {
224
			IObservableList targetObservableList) {
206
		return new UpdateListStrategy();
225
		return new UpdateListStrategy(converterProvider);
207
	}
226
	}
208
227
209
	/**
228
	/**
210
	 * @param targetObservableList
229
	 * @param targetObservableList
211
	 * @param modelObservableList
230
	 * @param modelObservableList
212
	 * @return an update list strategy 
231
	 * @return an update list strategy
213
	 */
232
	 */
214
	protected UpdateListStrategy createTargetToModelUpdateListStrategy(
233
	protected UpdateListStrategy createTargetToModelUpdateListStrategy(
215
			IObservableList targetObservableList,
234
			IObservableList targetObservableList,
216
			IObservableList modelObservableList) {
235
			IObservableList modelObservableList) {
217
		return new UpdateListStrategy();
236
		return new UpdateListStrategy(converterProvider);
218
	}
237
	}
219
238
220
	/**
239
	/**
Lines 231-237 Link Here
231
	/**
250
	/**
232
	 * Returns an unmodifiable observable list with elements of type
251
	 * Returns an unmodifiable observable list with elements of type
233
	 * {@link Binding}, ordered by time of addition.
252
	 * {@link Binding}, ordered by time of addition.
234
	 * 
253
	 *
235
	 * @return the observable list containing all bindings
254
	 * @return the observable list containing all bindings
236
	 */
255
	 */
237
	public final IObservableList getBindings() {
256
	public final IObservableList getBindings() {
Lines 243-249 Link Here
243
	 * statuses (type: {@link IStatus}). The keys of the map are the bindings
262
	 * statuses (type: {@link IStatus}). The keys of the map are the bindings
244
	 * returned by {@link #getBindings()}, and the values are the current
263
	 * returned by {@link #getBindings()}, and the values are the current
245
	 * validaion status objects for each binding.
264
	 * validaion status objects for each binding.
246
	 * 
265
	 *
247
	 * @return the observable map from bindings to status objects.
266
	 * @return the observable map from bindings to status objects.
248
	 */
267
	 */
249
	public final IObservableMap getValidationStatusMap() {
268
	public final IObservableMap getValidationStatusMap() {
Lines 252-258 Link Here
252
271
253
	/**
272
	/**
254
	 * Adds the given binding to this data binding context.
273
	 * Adds the given binding to this data binding context.
255
	 * 
274
	 *
256
	 * @param binding
275
	 * @param binding
257
	 *            The binding to add.
276
	 *            The binding to add.
258
	 */
277
	 */
Lines 263-269 Link Here
263
	/**
282
	/**
264
	 * Updates all model observable objects to reflect the current state of the
283
	 * Updates all model observable objects to reflect the current state of the
265
	 * target observable objects.
284
	 * target observable objects.
266
	 * 
285
	 *
267
	 */
286
	 */
268
	public final void updateModels() {
287
	public final void updateModels() {
269
		for (Iterator it = bindings.iterator(); it.hasNext();) {
288
		for (Iterator it = bindings.iterator(); it.hasNext();) {
Lines 275-281 Link Here
275
	/**
294
	/**
276
	 * Updates all target observable objects to reflect the current state of the
295
	 * Updates all target observable objects to reflect the current state of the
277
	 * model observable objects.
296
	 * model observable objects.
278
	 * 
297
	 *
279
	 */
298
	 */
280
	public final void updateTargets() {
299
	public final void updateTargets() {
281
		for (Iterator it = bindings.iterator(); it.hasNext();) {
300
		for (Iterator it = bindings.iterator(); it.hasNext();) {
Lines 286-292 Link Here
286
305
287
	/**
306
	/**
288
	 * Removes the given binding.
307
	 * Removes the given binding.
289
	 * 
308
	 *
290
	 * @param binding
309
	 * @param binding
291
	 * @return <code>true</code> if was associated with the context,
310
	 * @return <code>true</code> if was associated with the context,
292
	 *         <code>false</code> if not
311
	 *         <code>false</code> if not
Lines 297-303 Link Here
297
316
298
	/**
317
	/**
299
	 * Returns the validation realm.
318
	 * Returns the validation realm.
300
	 * 
319
	 *
301
	 * @return the realm for the validation observables
320
	 * @return the realm for the validation observables
302
	 * @see Realm
321
	 * @see Realm
303
	 */
322
	 */
(-)src/org/eclipse/core/databinding/UpdateValueStrategy.java (-20 / +47 lines)
Lines 15-24 Link Here
15
import java.util.HashMap;
15
import java.util.HashMap;
16
16
17
import org.eclipse.core.databinding.conversion.IConverter;
17
import org.eclipse.core.databinding.conversion.IConverter;
18
import org.eclipse.core.databinding.conversion.IConverterProvider;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.validation.IValidator;
20
import org.eclipse.core.databinding.validation.IValidator;
20
import org.eclipse.core.databinding.validation.ValidationStatus;
21
import org.eclipse.core.databinding.validation.ValidationStatus;
21
import org.eclipse.core.internal.databinding.BindingMessages;
22
import org.eclipse.core.internal.databinding.BindingMessages;
23
import org.eclipse.core.internal.databinding.DefaultConverterProvider;
22
import org.eclipse.core.internal.databinding.Pair;
24
import org.eclipse.core.internal.databinding.Pair;
23
import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
25
import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
24
import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
26
import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
Lines 87-93 Link Here
87
 * construction of the strategy (e.g. {@link #POLICY_NEVER},
89
 * construction of the strategy (e.g. {@link #POLICY_NEVER},
88
 * {@link #POLICY_CONVERT}, {@link #POLICY_ON_REQUEST}, {@link #POLICY_UPDATE}).
90
 * {@link #POLICY_CONVERT}, {@link #POLICY_ON_REQUEST}, {@link #POLICY_UPDATE}).
89
 * </p>
91
 * </p>
90
 * 
92
 *
91
 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
93
 * @see DataBindingContext#bindValue(IObservableValue, IObservableValue,
92
 *      UpdateValueStrategy, UpdateValueStrategy)
94
 *      UpdateValueStrategy, UpdateValueStrategy)
93
 * @see Binding#getValidationStatus()
95
 * @see Binding#getValidationStatus()
Lines 131-137 Link Here
131
	 * Helper method allowing API evolution of the above constant values. The
133
	 * Helper method allowing API evolution of the above constant values. The
132
	 * compiler will not inline constant values into client code if values are
134
	 * compiler will not inline constant values into client code if values are
133
	 * "computed" using this helper.
135
	 * "computed" using this helper.
134
	 * 
136
	 *
135
	 * @param i
137
	 * @param i
136
	 *            an integer
138
	 *            an integer
137
	 * @return the same integer
139
	 * @return the same integer
Lines 168-183 Link Here
168
	}
170
	}
169
171
170
	/**
172
	/**
173
	 * @param provider
174
	 */
175
	public UpdateValueStrategy(IConverterProvider provider) {
176
		this(true,POLICY_UPDATE,provider);
177
	}
178
179
	/**
171
	 * Creates a new update value strategy with a configurable update policy.
180
	 * Creates a new update value strategy with a configurable update policy.
172
	 * Default validators and a default converter will be provided. The defaults
181
	 * Default validators and a default converter will be provided. The defaults
173
	 * can be changed by calling one of the setter methods.
182
	 * can be changed by calling one of the setter methods.
174
	 * 
183
	 *
175
	 * @param updatePolicy
184
	 * @param updatePolicy
176
	 *            one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST},
185
	 *            one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST},
177
	 *            {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE}
186
	 *            {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE}
178
	 */
187
	 */
179
	public UpdateValueStrategy(int updatePolicy) {
188
	public UpdateValueStrategy(int updatePolicy) {
180
		this(true, updatePolicy);
189
		this(true, updatePolicy, new DefaultConverterProvider());
190
	}
191
192
	/**
193
	 * @param updatePolicy
194
	 * @param provider
195
	 */
196
	public UpdateValueStrategy(int updatePolicy,IConverterProvider provider) {
197
		this(true,updatePolicy,provider);
181
	}
198
	}
182
199
183
	/**
200
	/**
Lines 185-191 Link Here
185
	 * Default validators and a default converter will be provided if
202
	 * Default validators and a default converter will be provided if
186
	 * <code>provideDefaults</code> is <code>true</code>. The defaults can
203
	 * <code>provideDefaults</code> is <code>true</code>. The defaults can
187
	 * be changed by calling one of the setter methods.
204
	 * be changed by calling one of the setter methods.
188
	 * 
205
	 *
189
	 * @param provideDefaults
206
	 * @param provideDefaults
190
	 *            if <code>true</code>, default validators and a default
207
	 *            if <code>true</code>, default validators and a default
191
	 *            converter will be provided based on the observable value's
208
	 *            converter will be provided based on the observable value's
Lines 195-200 Link Here
195
	 *            {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE}
212
	 *            {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE}
196
	 */
213
	 */
197
	public UpdateValueStrategy(boolean provideDefaults, int updatePolicy) {
214
	public UpdateValueStrategy(boolean provideDefaults, int updatePolicy) {
215
		this(provideDefaults,updatePolicy,new DefaultConverterProvider());
216
	}
217
218
	/**
219
	 * @param provideDefaults
220
	 * @param updatePolicy
221
	 * @param provider
222
	 */
223
	public UpdateValueStrategy(boolean provideDefaults, int updatePolicy,IConverterProvider provider) {
224
		super(provider==null?new DefaultConverterProvider():provider);
198
		this.provideDefaults = provideDefaults;
225
		this.provideDefaults = provideDefaults;
199
		this.updatePolicy = updatePolicy;
226
		this.updatePolicy = updatePolicy;
200
	}
227
	}
Lines 206-212 Link Here
206
	 * {@link #setConverter(IConverter) converter} if one exists. If no
233
	 * {@link #setConverter(IConverter) converter} if one exists. If no
207
	 * converter exists no conversion occurs.
234
	 * converter exists no conversion occurs.
208
	 * </p>
235
	 * </p>
209
	 * 
236
	 *
210
	 * @param value
237
	 * @param value
211
	 * @return the converted value
238
	 * @return the converted value
212
	 */
239
	 */
Lines 218-224 Link Here
218
	 * Tries to create a validator that can validate values of type fromType.
245
	 * Tries to create a validator that can validate values of type fromType.
219
	 * Returns <code>null</code> if no validator could be created. Either
246
	 * Returns <code>null</code> if no validator could be created. Either
220
	 * toType or modelDescription can be <code>null</code>, but not both.
247
	 * toType or modelDescription can be <code>null</code>, but not both.
221
	 * 
248
	 *
222
	 * @param fromType
249
	 * @param fromType
223
	 * @param toType
250
	 * @param toType
224
	 * @return an IValidator, or <code>null</code> if unsuccessful
251
	 * @return an IValidator, or <code>null</code> if unsuccessful
Lines 243-249 Link Here
243
	 * attempt is made to default the
270
	 * attempt is made to default the
244
	 * {@link #validateAfterGet(Object) after get validator}. If a validator
271
	 * {@link #validateAfterGet(Object) after get validator}. If a validator
245
	 * cannot be defaulted it will be <code>null</code>.
272
	 * cannot be defaulted it will be <code>null</code>.
246
	 * 
273
	 *
247
	 * @param source
274
	 * @param source
248
	 * @param destination
275
	 * @param destination
249
	 */
276
	 */
Lines 316-322 Link Here
316
				}
343
				}
317
			} else if (converter instanceof NumberToNumberConverter) {
344
			} else if (converter instanceof NumberToNumberConverter) {
318
				result = (IValidator) validatorsByConverter.get(converter);
345
				result = (IValidator) validatorsByConverter.get(converter);
319
				
346
320
				if (result == null) {
347
				if (result == null) {
321
					if (converter instanceof NumberToByteConverter) {
348
					if (converter instanceof NumberToByteConverter) {
322
						result = new NumberToByteValidator((NumberToByteConverter) converter);
349
						result = new NumberToByteValidator((NumberToByteConverter) converter);
Lines 355-361 Link Here
355
	/**
382
	/**
356
	 * Sets the validator to be invoked after the source value is converted to
383
	 * Sets the validator to be invoked after the source value is converted to
357
	 * the type of the destination observable.
384
	 * the type of the destination observable.
358
	 * 
385
	 *
359
	 * @param validator
386
	 * @param validator
360
	 * @return the receiver, to enable method call chaining
387
	 * @return the receiver, to enable method call chaining
361
	 */
388
	 */
Lines 367-373 Link Here
367
	/**
394
	/**
368
	 * Sets the validator to be invoked after the source value is retrieved at
395
	 * Sets the validator to be invoked after the source value is retrieved at
369
	 * the beginning of the synchronization process.
396
	 * the beginning of the synchronization process.
370
	 * 
397
	 *
371
	 * @param validator
398
	 * @param validator
372
	 * @return the receiver, to enable method call chaining
399
	 * @return the receiver, to enable method call chaining
373
	 */
400
	 */
Lines 379-385 Link Here
379
	/**
406
	/**
380
	 * Sets the validator to be invoked before the value is to be set on the
407
	 * Sets the validator to be invoked before the value is to be set on the
381
	 * destination at the end of the synchronization process.
408
	 * destination at the end of the synchronization process.
382
	 * 
409
	 *
383
	 * @param validator
410
	 * @param validator
384
	 * @return the receiver, to enable method call chaining
411
	 * @return the receiver, to enable method call chaining
385
	 */
412
	 */
Lines 391-397 Link Here
391
	/**
418
	/**
392
	 * Sets the converter to be invoked when converting from the source type to
419
	 * Sets the converter to be invoked when converting from the source type to
393
	 * the destination type.
420
	 * the destination type.
394
	 * 
421
	 *
395
	 * @param converter
422
	 * @param converter
396
	 * @return the receiver, to enable method call chaining
423
	 * @return the receiver, to enable method call chaining
397
	 */
424
	 */
Lines 407-413 Link Here
407
	 * {@link #setAfterConvertValidator(IValidator) validator} if one exists. If
434
	 * {@link #setAfterConvertValidator(IValidator) validator} if one exists. If
408
	 * one does not exist no validation will occur.
435
	 * one does not exist no validation will occur.
409
	 * </p>
436
	 * </p>
410
	 * 
437
	 *
411
	 * @param value
438
	 * @param value
412
	 * @return an ok status
439
	 * @return an ok status
413
	 */
440
	 */
Lines 423-429 Link Here
423
	 * {@link #setAfterGetValidator(IValidator) validator} if one exists. If one
450
	 * {@link #setAfterGetValidator(IValidator) validator} if one exists. If one
424
	 * does not exist no validation will occur.
451
	 * does not exist no validation will occur.
425
	 * </p>
452
	 * </p>
426
	 * 
453
	 *
427
	 * @param value
454
	 * @param value
428
	 * @return an ok status
455
	 * @return an ok status
429
	 */
456
	 */
Lines 439-445 Link Here
439
	 * {@link #setBeforeSetValidator(IValidator) validator} if one exists. If
466
	 * {@link #setBeforeSetValidator(IValidator) validator} if one exists. If
440
	 * one does not exist no validation will occur.
467
	 * one does not exist no validation will occur.
441
	 * </p>
468
	 * </p>
442
	 * 
469
	 *
443
	 * @param value
470
	 * @param value
444
	 * @return an ok status
471
	 * @return an ok status
445
	 */
472
	 */
Lines 447-457 Link Here
447
		return beforeSetValidator == null ? Status.OK_STATUS
474
		return beforeSetValidator == null ? Status.OK_STATUS
448
				: beforeSetValidator.validate(value);
475
				: beforeSetValidator.validate(value);
449
	}
476
	}
450
	
477
451
	/**
478
	/**
452
	 * Sets the current value of the given observable to the given value.
479
	 * Sets the current value of the given observable to the given value.
453
	 * Clients may extend but must call the super implementation.
480
	 * Clients may extend but must call the super implementation.
454
	 * 
481
	 *
455
	 * @param observableValue
482
	 * @param observableValue
456
	 * @param value
483
	 * @param value
457
	 * @return status
484
	 * @return status
Lines 512-518 Link Here
512
		/**
539
		/**
513
		 * Associate a particular validator that can validate the conversion
540
		 * Associate a particular validator that can validate the conversion
514
		 * (fromClass, toClass)
541
		 * (fromClass, toClass)
515
		 * 
542
		 *
516
		 * @param fromClass
543
		 * @param fromClass
517
		 *            The Class to convert from
544
		 *            The Class to convert from
518
		 * @param toClass
545
		 * @param toClass
Lines 527-533 Link Here
527
554
528
		/**
555
		/**
529
		 * Return an IValidator for a specific fromClass and toClass.
556
		 * Return an IValidator for a specific fromClass and toClass.
530
		 * 
557
		 *
531
		 * @param fromClass
558
		 * @param fromClass
532
		 *            The Class to convert from
559
		 *            The Class to convert from
533
		 * @param toClass
560
		 * @param toClass
(-)src/org/eclipse/core/internal/databinding/DefaultConverterProvider.java (+518 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.internal.databinding;
13
14
import java.math.BigDecimal;
15
import java.math.BigInteger;
16
import java.util.HashMap;
17
import java.util.Map;
18
19
import org.eclipse.core.databinding.conversion.IConverter;
20
import org.eclipse.core.databinding.conversion.IConverterProvider;
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.internal.databinding.conversion.IdentityConverter;
25
import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter;
26
import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter;
27
import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter;
28
import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter;
29
import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter;
30
import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter;
31
import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter;
32
import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter;
33
import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter;
34
import org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter;
35
import org.eclipse.core.internal.databinding.conversion.StringToByteConverter;
36
import org.eclipse.core.internal.databinding.conversion.StringToShortConverter;
37
import org.eclipse.core.runtime.IStatus;
38
import org.eclipse.core.runtime.Status;
39
40
import com.ibm.icu.text.NumberFormat;
41
42
43
/**
44
 * @since 3.3
45
 *
46
 */
47
public class DefaultConverterProvider implements IConverterProvider {
48
	private static Map converterMap;
49
50
	private static final Class[] integerClasses = new Class[]{
51
		Byte.TYPE, Byte.class,
52
		Short.TYPE, Short.class,
53
		Integer.TYPE, Integer.class,
54
		Long.TYPE, Long.class,
55
		BigInteger.class};
56
57
	private static final Class[] floatClasses = new Class[] {
58
		Float.TYPE, Float.class,
59
		Double.TYPE, Double.class,
60
		BigDecimal.class};
61
62
	private static final String BOOLEAN_TYPE = "java.lang.Boolean.TYPE"; //$NON-NLS-1$
63
	private static final String SHORT_TYPE = "java.lang.Short.TYPE"; //$NON-NLS-1$
64
	private static final String BYTE_TYPE = "java.lang.Byte.TYPE"; //$NON-NLS-1$
65
	private static final String DOUBLE_TYPE = "java.lang.Double.TYPE"; //$NON-NLS-1$
66
	private static final String FLOAT_TYPE = "java.lang.Float.TYPE"; //$NON-NLS-1$
67
	private static final String INTEGER_TYPE = "java.lang.Integer.TYPE"; //$NON-NLS-1$
68
	private static final String LONG_TYPE = "java.lang.Long.TYPE"; //$NON-NLS-1$
69
70
71
	private static Class autoboxed(Class clazz) {
72
		if (clazz == Float.TYPE)
73
			return Float.class;
74
		else if (clazz == Double.TYPE)
75
			return Double.class;
76
		else if (clazz == Short.TYPE)
77
			return Short.class;
78
		else if (clazz == Integer.TYPE)
79
			return Integer.class;
80
		else if (clazz == Long.TYPE)
81
			return Long.class;
82
		else if (clazz == Byte.TYPE)
83
			return Byte.class;
84
		else if (clazz == Boolean.TYPE)
85
			return Boolean.class;
86
		return clazz;
87
	}
88
89
90
91
92
	/* (non-Javadoc)
93
	 * @see org.eclipse.core.databinding.conversion.IConverterProvider#createConverter(java.lang.Object, java.lang.Object)
94
	 */
95
	public IConverter createConverter(Object fromType, Object toType) {
96
		if (!(fromType instanceof Class) || !(toType instanceof Class)) {
97
			return null;
98
		}
99
		Class toClass = (Class) toType;
100
		Class originalToClass = toClass;
101
		if (toClass.isPrimitive()) {
102
			toClass = autoboxed(toClass);
103
		}
104
		Class fromClass = (Class) fromType;
105
		Class originalFromClass = fromClass;
106
		if (fromClass.isPrimitive()) {
107
			fromClass = autoboxed(fromClass);
108
		}
109
		if (!((Class) toType).isPrimitive()
110
				&& toClass.isAssignableFrom(fromClass)) {
111
			return new IdentityConverter(originalFromClass, originalToClass);
112
		}
113
		if (((Class) fromType).isPrimitive() && ((Class) toType).isPrimitive()
114
				&& fromType.equals(toType)) {
115
			return new IdentityConverter(originalFromClass, originalToClass);
116
		}
117
		Map converterMap = getConverterMap();
118
		Class[] supertypeHierarchyFlattened = ClassLookupSupport
119
				.getTypeHierarchyFlattened(fromClass);
120
		for (int i = 0; i < supertypeHierarchyFlattened.length; i++) {
121
			Class currentFromClass = supertypeHierarchyFlattened[i];
122
			if (currentFromClass == toType) {
123
				// converting to toType is just a widening
124
				return new IdentityConverter(fromClass, toClass);
125
			}
126
			Pair key = new Pair(getKeyForClass(fromType, currentFromClass),
127
					getKeyForClass(toType, toClass));
128
			Object converterOrClassname = converterMap.get(key);
129
			if (converterOrClassname instanceof IConverter) {
130
				return (IConverter) converterOrClassname;
131
			} else if (converterOrClassname instanceof String) {
132
				String classname = (String) converterOrClassname;
133
				Class converterClass;
134
				try {
135
					converterClass = Class.forName(classname);
136
					IConverter result = (IConverter) converterClass
137
							.newInstance();
138
					converterMap.put(key, result);
139
					return result;
140
				} catch (Exception e) {
141
					Policy
142
							.getLog()
143
							.log(
144
									new Status(
145
											IStatus.ERROR,
146
											Policy.JFACE_DATABINDING,
147
											0,
148
											"Error while instantiating default converter", e)); //$NON-NLS-1$
149
				}
150
			}
151
		}
152
		// Since we found no converter yet, try a "downcast" converter;
153
		// the IdentityConverter will automatically check the actual types at
154
		// runtime.
155
		if (fromClass.isAssignableFrom(toClass)) {
156
			return new IdentityConverter(originalFromClass, originalToClass);
157
		}
158
		return null;
159
	}
160
161
	/**
162
	 * Registers converters to boxed and unboxed types from a list of from classes.
163
	 *
164
	 * @param map
165
	 * @param numberFormat
166
	 * @param fromTypes
167
	 */
168
	private static void addNumberToByteConverters(Map map,
169
			NumberFormat numberFormat, Class[] fromTypes) {
170
171
		for (int i = 0; i < fromTypes.length; i++) {
172
			Class fromType = fromTypes[i];
173
			if (!fromType.equals(Byte.class) && !fromType.equals(Byte.TYPE)) {
174
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
175
176
				map.put(new Pair(fromName, BYTE_TYPE), new NumberToByteConverter(numberFormat, fromType, true));
177
				map.put(new Pair(fromName, Byte.class.getName()), new NumberToByteConverter(numberFormat, fromType, false));
178
			}
179
		}
180
	}
181
182
	/**
183
	 * Registers converters to boxed and unboxed types from a list of from classes.
184
	 *
185
	 * @param map
186
	 * @param numberFormat
187
	 * @param fromTypes
188
	 */
189
	private static void addNumberToShortConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
190
		for (int i = 0; i < fromTypes.length; i++) {
191
			Class fromType = fromTypes[i];
192
			if (!fromType.equals(Short.class) && !fromType.equals(Short.TYPE)) {
193
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
194
195
				map.put(new Pair(fromName, SHORT_TYPE), new NumberToShortConverter(numberFormat, fromType, true));
196
				map.put(new Pair(fromName, Short.class.getName()), new NumberToShortConverter(numberFormat, fromType, false));
197
			}
198
		}
199
	}
200
201
	/**
202
	 * Registers converters to boxed and unboxed types from a list of from classes.
203
	 *
204
	 * @param map
205
	 * @param numberFormat
206
	 * @param fromTypes
207
	 */
208
	private static void addNumberToIntegerConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
209
		for (int i = 0; i < fromTypes.length; i++) {
210
			Class fromType = fromTypes[i];
211
			if (!fromType.equals(Integer.class) && !fromType.equals(Integer.TYPE)) {
212
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
213
214
				map.put(new Pair(fromName, INTEGER_TYPE), new NumberToIntegerConverter(numberFormat, fromType, true));
215
				map.put(new Pair(fromName, Integer.class.getName()), new NumberToIntegerConverter(numberFormat, fromType, false));
216
			}
217
		}
218
	}
219
220
	/**
221
	 * Registers converters to boxed and unboxed types from a list of from classes.
222
	 *
223
	 * @param map
224
	 * @param numberFormat
225
	 * @param fromTypes
226
	 */
227
	private static void addNumberToLongConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
228
		for (int i = 0; i < fromTypes.length; i++) {
229
			Class fromType = fromTypes[i];
230
			if (!fromType.equals(Long.class) && !fromType.equals(Long.TYPE)) {
231
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
232
233
				map.put(new Pair(fromName, LONG_TYPE), new NumberToLongConverter(numberFormat, fromType, true));
234
				map.put(new Pair(fromName, Long.class.getName()), new NumberToLongConverter(numberFormat, fromType, false));
235
			}
236
		}
237
	}
238
239
	/**
240
	 * Registers converters to boxed and unboxed types from a list of from classes.
241
	 *
242
	 * @param map
243
	 * @param numberFormat
244
	 * @param fromTypes
245
	 */
246
	private static void addNumberToFloatConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
247
		for (int i = 0; i < fromTypes.length; i++) {
248
			Class fromType = fromTypes[i];
249
			if (!fromType.equals(Float.class) && !fromType.equals(Float.TYPE)) {
250
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
251
252
				map.put(new Pair(fromName, FLOAT_TYPE), new NumberToFloatConverter(numberFormat, fromType, true));
253
				map.put(new Pair(fromName, Float.class.getName()), new NumberToFloatConverter(numberFormat, fromType, false));
254
			}
255
		}
256
	}
257
258
	/**
259
	 * Registers converters to boxed and unboxed types from a list of from classes.
260
	 *
261
	 * @param map
262
	 * @param numberFormat
263
	 * @param fromTypes
264
	 */
265
	private static void addNumberToDoubleConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
266
		for (int i = 0; i < fromTypes.length; i++) {
267
			Class fromType = fromTypes[i];
268
			if (!fromType.equals(Double.class) && !fromType.equals(Double.TYPE)) {
269
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
270
271
				map.put(new Pair(fromName, DOUBLE_TYPE), new NumberToDoubleConverter(numberFormat, fromType, true));
272
				map.put(new Pair(fromName, Double.class.getName()), new NumberToDoubleConverter(numberFormat, fromType, false));
273
			}
274
		}
275
	}
276
277
	/**
278
	 * Registers converters to boxed and unboxed types from a list of from classes.
279
	 *
280
	 * @param map
281
	 * @param numberFormat
282
	 * @param fromTypes
283
	 */
284
	private static void addNumberToBigIntegerConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
285
		for (int i = 0; i < fromTypes.length; i++) {
286
			Class fromType = fromTypes[i];
287
			if (!fromType.equals(BigInteger.class)) {
288
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
289
290
				map.put(new Pair(fromName, BigInteger.class.getName()), new NumberToBigIntegerConverter(numberFormat, fromType));
291
			}
292
		}
293
	}
294
295
	/**
296
	 * Registers converters to boxed and unboxed types from a list of from classes.
297
	 *
298
	 * @param map
299
	 * @param numberFormat
300
	 * @param fromTypes
301
	 */
302
	private static void addNumberToBigDecimalConverters(Map map, NumberFormat numberFormat, Class[] fromTypes) {
303
		for (int i = 0; i < fromTypes.length; i++) {
304
			Class fromType = fromTypes[i];
305
			if (!fromType.equals(BigDecimal.class)) {
306
				String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName();
307
308
				map.put(new Pair(fromName, BigDecimal.class.getName()), new NumberToBigDecimalConverter(numberFormat, fromType));
309
			}
310
		}
311
	}
312
313
314
	private static String getKeyForClass(Object originalValue, Class filteredValue) {
315
		if (originalValue instanceof Class) {
316
			Class originalClass = (Class) originalValue;
317
			if (originalClass.equals(Integer.TYPE)) {
318
				return INTEGER_TYPE;
319
			} else if (originalClass.equals(Byte.TYPE)) {
320
				return BYTE_TYPE;
321
			} else if (originalClass.equals(Boolean.TYPE)) {
322
				return BOOLEAN_TYPE;
323
			} else if (originalClass.equals(Double.TYPE)) {
324
				return DOUBLE_TYPE;
325
			} else if (originalClass.equals(Float.TYPE)) {
326
				return FLOAT_TYPE;
327
			} else if (originalClass.equals(Long.TYPE)) {
328
				return LONG_TYPE;
329
			} else if (originalClass.equals(Short.TYPE)) {
330
				return SHORT_TYPE;
331
			}
332
		}
333
		return filteredValue.getName();
334
	}
335
336
	/**
337
	 * @param fromType
338
	 * @param toType
339
	 * @return whether fromType is assignable to toType
340
	 */
341
	public Boolean isAssignableFromTo(Object fromType, Object toType) {
342
		if (fromType instanceof Class && toType instanceof Class) {
343
			Class toClass = (Class) toType;
344
			if (toClass.isPrimitive()) {
345
				toClass = autoboxed(toClass);
346
			}
347
			Class fromClass = (Class) fromType;
348
			if (fromClass.isPrimitive()) {
349
				fromClass = autoboxed(fromClass);
350
			}
351
			return toClass.isAssignableFrom(fromClass) ? Boolean.TRUE
352
					: Boolean.FALSE;
353
		}
354
		return null;
355
	}
356
357
358
359
	private static Map getConverterMap() {
360
		// using string-based lookup avoids loading of too many classes
361
		if (converterMap == null) {
362
			//NumberFormat to be shared across converters for the formatting of integer values
363
			NumberFormat integerFormat = NumberFormat.getIntegerInstance();
364
			//NumberFormat to be shared across converters for formatting non integer values
365
			NumberFormat numberFormat = NumberFormat.getNumberInstance();
366
367
			converterMap = new HashMap();
368
			converterMap
369
					.put(
370
							new Pair("java.util.Date", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.DateToStringConverter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
371
			converterMap
372
					.put(
373
							new Pair("java.lang.String", "java.lang.Boolean"), "org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
374
			converterMap
375
					.put(
376
							new Pair("java.lang.String", "java.lang.Byte"), StringToByteConverter.toByte(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
377
			converterMap
378
					.put(
379
							new Pair("java.lang.String", "java.lang.Character"), "org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
380
			converterMap
381
					.put(
382
							new Pair("java.lang.String", "java.util.Date"), "org.eclipse.core.internal.databinding.conversion.StringToDateConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
383
			converterMap
384
					.put(
385
							new Pair("java.lang.String", "java.lang.Short"), StringToShortConverter.toShort(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$
386
387
			converterMap.put(new Pair("java.lang.String", "java.lang.Integer"), StringToNumberConverter.toInteger(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
388
			converterMap.put(new Pair("java.lang.String", "java.lang.Double"), StringToNumberConverter.toDouble(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
389
			converterMap.put(new Pair("java.lang.String", "java.lang.Long"), StringToNumberConverter.toLong(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
390
			converterMap.put(new Pair("java.lang.String", "java.lang.Float"), StringToNumberConverter.toFloat(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
391
			converterMap.put(new Pair("java.lang.String", "java.math.BigInteger"), StringToNumberConverter.toBigInteger(integerFormat));  //$NON-NLS-1$//$NON-NLS-2$
392
			converterMap.put(new Pair("java.lang.Integer", "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
393
			converterMap.put(new Pair("java.lang.Long", "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
394
			converterMap.put(new Pair("java.lang.Double", "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
395
			converterMap.put(new Pair("java.lang.Float", "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
396
			converterMap.put(new Pair("java.math.BigInteger", "java.lang.String"), NumberToStringConverter.fromBigInteger(integerFormat));  //$NON-NLS-1$//$NON-NLS-2$
397
			converterMap.put(new Pair("java.lang.Byte", "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, false));   //$NON-NLS-1$//$NON-NLS-2$
398
			converterMap.put(new Pair("java.lang.Short", "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, false));  //$NON-NLS-1$//$NON-NLS-2$
399
400
			converterMap
401
					.put(
402
							new Pair("java.lang.Object", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
403
404
			// Integer.TYPE
405
			converterMap.put(new Pair("java.lang.String", INTEGER_TYPE), StringToNumberConverter.toInteger(integerFormat, true)); //$NON-NLS-1$
406
			converterMap
407
					.put(
408
							new Pair(INTEGER_TYPE, "java.lang.Integer"), new IdentityConverter(Integer.TYPE, Integer.class)); //$NON-NLS-1$
409
			converterMap
410
					.put(
411
							new Pair(INTEGER_TYPE, "java.lang.Object"), new IdentityConverter(Integer.TYPE, Object.class)); //$NON-NLS-1$
412
			converterMap.put(new Pair(INTEGER_TYPE, "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, true)); //$NON-NLS-1$
413
414
			// Byte.TYPE
415
			converterMap
416
					.put(
417
							new Pair("java.lang.String", BYTE_TYPE), StringToByteConverter.toByte(integerFormat, true)); //$NON-NLS-1$
418
			converterMap
419
					.put(
420
							new Pair(BYTE_TYPE, "java.lang.Byte"), new IdentityConverter(Byte.TYPE, Byte.class)); //$NON-NLS-1$
421
			converterMap
422
					.put(
423
							new Pair(BYTE_TYPE, "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, true)); //$NON-NLS-1$
424
			converterMap
425
					.put(
426
							new Pair(BYTE_TYPE, "java.lang.Object"), new IdentityConverter(Byte.TYPE, Object.class)); //$NON-NLS-1$
427
428
			// Double.TYPE
429
			converterMap.put(new Pair("java.lang.String", DOUBLE_TYPE), StringToNumberConverter.toDouble(numberFormat, true)); //$NON-NLS-1$
430
			converterMap.put(new Pair(DOUBLE_TYPE, "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, true)); //$NON-NLS-1$
431
432
			converterMap
433
					.put(
434
							new Pair(DOUBLE_TYPE, "java.lang.Double"), new IdentityConverter(Double.TYPE, Double.class)); //$NON-NLS-1$
435
			converterMap
436
					.put(
437
							new Pair(DOUBLE_TYPE, "java.lang.Object"), new IdentityConverter(Double.TYPE, Object.class)); //$NON-NLS-1$
438
439
			// Boolean.TYPE
440
			converterMap
441
					.put(
442
							new Pair("java.lang.String", BOOLEAN_TYPE), "org.eclipse.core.internal.databinding.conversion.StringToBooleanPrimitiveConverter"); //$NON-NLS-1$ //$NON-NLS-2$
443
			converterMap
444
					.put(
445
							new Pair(BOOLEAN_TYPE, "java.lang.Boolean"), new IdentityConverter(Boolean.TYPE, Boolean.class)); //$NON-NLS-1$
446
			converterMap
447
					.put(
448
							new Pair(BOOLEAN_TYPE, "java.lang.String"), new ObjectToStringConverter(Boolean.TYPE)); //$NON-NLS-1$
449
			converterMap
450
					.put(
451
							new Pair(BOOLEAN_TYPE, "java.lang.Object"), new IdentityConverter(Boolean.TYPE, Object.class)); //$NON-NLS-1$
452
453
			// Float.TYPE
454
			converterMap.put(new Pair("java.lang.String", FLOAT_TYPE), StringToNumberConverter.toFloat(numberFormat, true)); //$NON-NLS-1$
455
			converterMap.put(new Pair(FLOAT_TYPE, "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, true)); //$NON-NLS-1$
456
			converterMap
457
					.put(
458
							new Pair(FLOAT_TYPE, "java.lang.Float"), new IdentityConverter(Float.TYPE, Float.class)); //$NON-NLS-1$
459
			converterMap
460
					.put(
461
							new Pair(FLOAT_TYPE, "java.lang.Object"), new IdentityConverter(Float.TYPE, Object.class)); //$NON-NLS-1$
462
463
			// Short.TYPE
464
			converterMap
465
					.put(
466
							new Pair("java.lang.String", SHORT_TYPE), StringToShortConverter.toShort(integerFormat, true)); //$NON-NLS-1$
467
			converterMap
468
					.put(
469
							new Pair(SHORT_TYPE, "java.lang.Short"), new IdentityConverter(Short.TYPE, Short.class)); //$NON-NLS-1$
470
			converterMap
471
					.put(
472
							new Pair(SHORT_TYPE, "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, true)); //$NON-NLS-1$
473
			converterMap
474
					.put(
475
							new Pair(SHORT_TYPE, "java.lang.Object"), new IdentityConverter(Short.TYPE, Object.class)); //$NON-NLS-1$
476
477
			// Long.TYPE
478
			converterMap.put(new Pair("java.lang.String", LONG_TYPE), StringToNumberConverter.toLong(integerFormat, true)); //$NON-NLS-1$
479
			converterMap.put(new Pair(LONG_TYPE, "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, true)); //$NON-NLS-1$
480
			converterMap
481
					.put(
482
							new Pair(LONG_TYPE, "java.lang.Long"), new IdentityConverter(Long.TYPE, Long.class)); //$NON-NLS-1$
483
			converterMap
484
					.put(
485
							new Pair(LONG_TYPE, "java.lang.Object"), new IdentityConverter(Long.TYPE, Object.class)); //$NON-NLS-1$
486
487
			converterMap
488
					.put(
489
							new Pair("org.eclipse.core.runtime.IStatus", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.StatusToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
490
491
			addNumberToByteConverters(converterMap, integerFormat, integerClasses);
492
			addNumberToByteConverters(converterMap, numberFormat, floatClasses);
493
494
			addNumberToShortConverters(converterMap, integerFormat, integerClasses);
495
			addNumberToShortConverters(converterMap, numberFormat, floatClasses);
496
497
			addNumberToIntegerConverters(converterMap, integerFormat, integerClasses);
498
			addNumberToIntegerConverters(converterMap, numberFormat, floatClasses);
499
500
			addNumberToLongConverters(converterMap, integerFormat, integerClasses);
501
			addNumberToLongConverters(converterMap, numberFormat, floatClasses);
502
503
			addNumberToFloatConverters(converterMap, integerFormat, integerClasses);
504
			addNumberToFloatConverters(converterMap, numberFormat, floatClasses);
505
506
			addNumberToDoubleConverters(converterMap, integerFormat, integerClasses);
507
			addNumberToDoubleConverters(converterMap, numberFormat, floatClasses);
508
509
			addNumberToBigIntegerConverters(converterMap, integerFormat, integerClasses);
510
			addNumberToBigIntegerConverters(converterMap, numberFormat, floatClasses);
511
512
			addNumberToBigDecimalConverters(converterMap, integerFormat, integerClasses);
513
			addNumberToBigDecimalConverters(converterMap, numberFormat, floatClasses);
514
		}
515
516
		return converterMap;
517
	}
518
}
(-)src/org/eclipse/core/databinding/conversion/IConverterProvider.java (+32 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.conversion;
13
14
/**
15
 * @since 3.3
16
 *
17
 */
18
public interface IConverterProvider {
19
	/**
20
	 * @param fromType
21
	 * @param toType
22
	 * @return the converter
23
	 */
24
	public IConverter createConverter(Object fromType, Object toType);
25
26
	/**
27
	 * @param fromType
28
	 * @param toType
29
	 * @return null
30
	 */
31
	public Boolean isAssignableFromTo(Object fromType, Object toType);
32
}

Return to bug 203492