Skip to content

Commit c488881

Browse files
committed
Correct doSet() signature in UpdateValueStrategy
The "value" that is passed as to the doSet() method must match the source type, not the target type. Otherwise a ClassCastException is thrown when a typified UpdateValueStrategy is used. Example: IObservableValue<Integer> source = ... IObservableValue<Boolean> target = ... UpdateValueStrategy<Integer, Boolean> strategy = ... context.bindValue(target, source, null, strategy); A change to "source" will always produce a ClassCastException, because an Integer is passed to the doSet() method, which is then casted to a Boolean by the Java runtime. This renders the strategy unusable, unless raw types are used. Closes #3008
1 parent b141132 commit c488881

File tree

5 files changed

+47
-5
lines changed

5 files changed

+47
-5
lines changed

bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/UpdateValueStrategy.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,9 +476,10 @@ public IStatus validateBeforeSet(D value) {
476476
* @param value new value to set
477477
* @return status
478478
*/
479-
protected IStatus doSet(IObservableValue<? super D> observableValue, D value) {
479+
@SuppressWarnings("unchecked")
480+
protected IStatus doSet(IObservableValue<? super D> observableValue, S value) {
480481
try {
481-
observableValue.setValue(value);
482+
observableValue.setValue((D) value);
482483
} catch (Exception ex) {
483484
return logErrorWhileSettingValue(ex);
484485
}

bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/ValueBinding.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ private <S, D1, D2 extends D1> void doUpdate(final IObservableValue<S> source,
203203
updatingModel = true;
204204
}
205205
try {
206-
IStatus setterStatus = updateValueStrategy.doSet(destination, convertedValue);
206+
IStatus setterStatus = updateValueStrategy.doSet(destination, value);
207207

208208
mergeStatus(multiStatus, setterStatus);
209209
} finally {

examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/nestedselection/TestMasterDetail.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public class TestMasterDetail {
5959
*/
6060
private static final class CustomUpdateValueStrategy<S, D> extends UpdateValueStrategy<S, D> {
6161
@Override
62-
protected IStatus doSet(IObservableValue<? super D> observableValue, D value) {
62+
protected IStatus doSet(IObservableValue<? super D> observableValue, S value) {
6363
IStatus result = super.doSet(observableValue, value);
6464
if (result.isOK()) {
6565
Object changed = observableValue;

tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/UpdateValueStrategyTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package org.eclipse.core.tests.databinding;
1717

18+
import static org.junit.Assert.assertEquals;
1819
import static org.junit.Assert.assertNotNull;
1920
import static org.junit.Assert.assertSame;
2021
import static org.junit.Assert.assertThrows;
@@ -25,6 +26,7 @@
2526
import java.util.Date;
2627

2728
import org.eclipse.core.databinding.BindingException;
29+
import org.eclipse.core.databinding.DataBindingContext;
2830
import org.eclipse.core.databinding.UpdateValueStrategy;
2931
import org.eclipse.core.databinding.observable.value.IObservableValue;
3032
import org.eclipse.core.databinding.observable.value.WritableValue;
@@ -44,6 +46,8 @@
4446
import org.eclipse.core.internal.databinding.validation.StringToIntegerValidator;
4547
import org.eclipse.core.internal.databinding.validation.StringToLongValidator;
4648
import org.eclipse.core.internal.databinding.validation.StringToShortValidator;
49+
import org.eclipse.core.runtime.IStatus;
50+
import org.eclipse.core.runtime.Status;
4751
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
4852
import org.junit.Test;
4953

@@ -181,6 +185,43 @@ public void testDefaultValidatorForNumberToBigDecimal() throws Exception {
181185
NumberToUnboundedNumberValidator.class);
182186
}
183187

188+
@Test
189+
public void testUpdateValueWithStrategy() throws Exception {
190+
WritableValue<Integer> model = WritableValue.withValueType(Integer.class);
191+
WritableValue<Boolean> target = WritableValue.withValueType(Boolean.class);
192+
193+
/*
194+
UpdateValueStrategy strategy1 = new UpdateValueStrategy() {
195+
@Override
196+
protected IStatus doSet(IObservableValue observableValue, Object value) {
197+
Integer modelValue = (Integer) value;
198+
if (modelValue != null && modelValue != 0) {
199+
return super.doSet(observableValue, true);
200+
}
201+
return super.doSet(observableValue, false);
202+
}
203+
};
204+
*/
205+
206+
UpdateValueStrategy<Integer, Boolean> strategy2 = new UpdateValueStrategy<>() {
207+
@Override
208+
protected IStatus doSet(IObservableValue<? super Boolean> observableValue, Integer value) {
209+
if (value != null && value != 0) {
210+
observableValue.setValue(true);
211+
} else {
212+
observableValue.setValue(false);
213+
}
214+
return Status.OK_STATUS;
215+
}
216+
};
217+
218+
DataBindingContext context = new DataBindingContext();
219+
context.bindValue(target, model, null, strategy2);
220+
221+
model.setValue(1);
222+
assertEquals(target.getValue(), true);
223+
}
224+
184225
@Test
185226
public void testCachesDefaultedValidators() throws Exception {
186227
WritableValue<String> source = WritableValue.withValueType(String.class);

tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/databinding/ValueBindingTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public void testCancelStatusInValidationDoesNotUpdateModel()
189189
public void testStatusesFromEveryPhaseAreReturned() throws Exception {
190190
UpdateValueStrategy<Object, String> strategy = new UpdateValueStrategy<>() {
191191
@Override
192-
protected IStatus doSet(IObservableValue<? super String> observableValue, String value) {
192+
protected IStatus doSet(IObservableValue<? super String> observableValue, Object value) {
193193
super.doSet(observableValue, value);
194194
return ValidationStatus.info("");
195195
}

0 commit comments

Comments
 (0)