KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > databinding > internal > ValueBinding


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 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 package org.eclipse.jface.internal.databinding.internal;
12
13 import org.eclipse.jface.internal.databinding.provisional.BindSpec;
14 import org.eclipse.jface.internal.databinding.provisional.Binding;
15 import org.eclipse.jface.internal.databinding.provisional.BindingEvent;
16 import org.eclipse.jface.internal.databinding.provisional.BindingException;
17 import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
18 import org.eclipse.jface.internal.databinding.provisional.conversion.IConverter;
19 import org.eclipse.jface.internal.databinding.provisional.observable.Diffs;
20 import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
21 import org.eclipse.jface.internal.databinding.provisional.observable.value.IValueChangeListener;
22 import org.eclipse.jface.internal.databinding.provisional.observable.value.IValueChangingListener;
23 import org.eclipse.jface.internal.databinding.provisional.observable.value.IVetoableValue;
24 import org.eclipse.jface.internal.databinding.provisional.observable.value.ValueDiff;
25 import org.eclipse.jface.internal.databinding.provisional.observable.value.WritableValue;
26 import org.eclipse.jface.internal.databinding.provisional.validation.IDomainValidator;
27 import org.eclipse.jface.internal.databinding.provisional.validation.IValidator;
28 import org.eclipse.jface.internal.databinding.provisional.validation.ValidationError;
29
30 /**
31  * @since 1.0
32  *
33  */

34 public class ValueBinding extends Binding {
35
36     private final IObservableValue target;
37
38     private final IObservableValue model;
39
40     private IValidator targetValidator;
41
42     private IConverter targetToModelConverter;
43
44     private IConverter modelToTargetConverter;
45
46     private IDomainValidator domainValidator;
47
48     private boolean updating = false;
49
50     private WritableValue partialValidationErrorObservable = new WritableValue(
51             ValidationError.class, null);
52
53     private WritableValue validationErrorObservable = new WritableValue(
54             ValidationError.class, null);
55
56     /**
57      * @param context
58      * @param target
59      * @param model
60      * @param bindSpec
61      */

62     public ValueBinding(DataBindingContext context, IObservableValue target,
63             IObservableValue model, BindSpec bindSpec) {
64         super(context);
65         this.target = target;
66         this.model = model;
67         if (bindSpec.updateTarget()) {
68             modelToTargetConverter = bindSpec.getModelToTargetConverter();
69             if (modelToTargetConverter == null) {
70                 throw new BindingException(
71                         "Missing model to target converter from " + model.getValueType() + " to " + target.getValueType()); //$NON-NLS-1$ //$NON-NLS-2$
72
}
73             if (!context.isAssignableFromTo(model.getValueType(),
74                     modelToTargetConverter.getFromType())) {
75                 throw new BindingException(
76                         "model to target converter does not convert from model type. Expected: " + model.getValueType() + ", actual: " + modelToTargetConverter.getFromType()); //$NON-NLS-1$ //$NON-NLS-2$
77
}
78             if (!context.isAssignableFromTo(modelToTargetConverter.getToType(),
79                     target.getValueType())) {
80                 throw new BindingException(
81                         "model to target converter does convert to target type. Expected: " + target.getValueType() + ", actual: " + modelToTargetConverter.getToType()); //$NON-NLS-1$ //$NON-NLS-2$
82
}
83             model.addValueChangeListener(modelChangeListener);
84         }
85         if (bindSpec.updateModel()) {
86             targetToModelConverter = bindSpec.getTargetToModelConverter();
87             if (targetToModelConverter == null) {
88                 throw new BindingException(
89                         "Missing target to model converter from " + target.getValueType() + " to " + model.getValueType()); //$NON-NLS-1$ //$NON-NLS-2$
90
}
91             if (!context.isAssignableFromTo(target.getValueType(),
92                     targetToModelConverter.getFromType())) {
93                 throw new BindingException(
94                         "target to model converter does not convert from target type. Expected: " + target.getValueType() + ", actual: " + targetToModelConverter.getFromType()); //$NON-NLS-1$ //$NON-NLS-2$
95
}
96             if (!context.isAssignableFromTo(targetToModelConverter.getToType(),
97                     model.getValueType())) {
98                 throw new BindingException(
99                         "target to model converter does convert to model type. Expected: " + model.getValueType() + ", actual: " + targetToModelConverter.getToType()); //$NON-NLS-1$ //$NON-NLS-2$
100
}
101             targetValidator = bindSpec.getTypeConversionValidator();
102             if (targetValidator == null) {
103                 throw new BindingException("Missing validator"); //$NON-NLS-1$
104
}
105             domainValidator = bindSpec.getDomainValidator();
106             target.addValueChangeListener(targetChangeListener);
107             if (target instanceof IVetoableValue) {
108                 ((IVetoableValue) target)
109                         .addValueChangingListener(targetChangingListener);
110             }
111         }
112         updateTargetFromModel();
113     }
114
115     private final IValueChangingListener targetChangingListener = new IValueChangingListener() {
116         public boolean handleValueChanging(IVetoableValue source, ValueDiff diff) {
117             if (updating)
118                 return true;
119             // we are notified of a pending change, do validation
120
// and veto the change if it is not valid
121
Object JavaDoc value = diff.getNewValue();
122             ValidationError partialValidationError = targetValidator
123                     .isPartiallyValid(value);
124             partialValidationErrorObservable.setValue(partialValidationError);
125             return partialValidationError == null;
126         }
127     };
128
129     private final IValueChangeListener targetChangeListener = new IValueChangeListener() {
130         public void handleValueChange(IObservableValue source, ValueDiff diff) {
131             if (updating)
132                 return;
133             // the target (usually a widget) has changed, validate
134
// the value and update the source
135
updateModelFromTarget(diff);
136         }
137     };
138
139     private IValueChangeListener modelChangeListener = new IValueChangeListener() {
140         public void handleValueChange(IObservableValue source, ValueDiff diff) {
141             if (updating)
142                 return;
143             // The model has changed so we must update the target
144
doUpdateTargetFromModel(diff);
145         }
146     };
147
148     /**
149      * This also does validation.
150      *
151      * @param diff
152      *
153      * @param changeEvent
154      * TODO
155      */

156     public void updateModelFromTarget(ValueDiff diff) {
157         BindingEvent e = new BindingEvent(model, target, diff,
158                 BindingEvent.EVENT_COPY_TO_MODEL,
159                 BindingEvent.PIPELINE_AFTER_GET) {
160         };
161         e.originalValue = target.getValue();
162         if (failure(errMsg(fireBindingEvent(e)))) {
163             return;
164         }
165
166         ValidationError validationError = doValidate(e.originalValue);
167         if (validationError != null) {
168             return;
169         }
170         e.pipelinePosition = BindingEvent.PIPELINE_AFTER_VALIDATE;
171         if (failure(errMsg(fireBindingEvent(e)))) {
172             return;
173         }
174
175         try {
176             updating = true;
177
178             e.convertedValue = targetToModelConverter.convert(e.originalValue);
179             e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CONVERT;
180             if (failure(errMsg(fireBindingEvent(e)))) {
181                 return;
182             }
183
184             validationError = doDomainValidation(e.convertedValue);
185             if (validationError != null) {
186                 return;
187             }
188             e.pipelinePosition = BindingEvent.PIPELINE_AFTER_BUSINESS_VALIDATE;
189             if (failure(errMsg(fireBindingEvent(e)))) {
190                 return;
191             }
192
193             model.setValue(e.convertedValue);
194             e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CHANGE;
195             fireBindingEvent(e);
196         } catch (Exception JavaDoc ex) {
197             ValidationError error = ValidationError.error(BindingMessages
198                     .getString("ValueBinding_ErrorWhileSettingValue")); //$NON-NLS-1$
199
validationErrorObservable.setValue(error);
200         } finally {
201             updating = false;
202         }
203     }
204
205     /**
206      * @param convertedValue
207      * @return String
208      */

209     private ValidationError doDomainValidation(Object JavaDoc convertedValue) {
210         if (domainValidator == null) {
211             return null;
212         }
213         ValidationError validationError = domainValidator
214                 .isValid(convertedValue);
215         return errMsg(validationError);
216     }
217
218     private ValidationError doValidate(Object JavaDoc value) {
219         if (targetValidator == null)
220             return null;
221         ValidationError validationError = targetValidator.isValid(value);
222         return errMsg(validationError);
223     }
224
225     private ValidationError errMsg(ValidationError validationError) {
226         partialValidationErrorObservable.setValue(null);
227         validationErrorObservable.setValue(validationError);
228         return validationError;
229     }
230
231     private boolean failure(ValidationError errorMessage) {
232         // FIXME: Need to fire a BindingEvent here
233
if (errorMessage != null
234                 && errorMessage.status == ValidationError.ERROR) {
235             return true;
236         }
237         return false;
238     }
239
240     public void updateTargetFromModel() {
241         doUpdateTargetFromModel(null);
242     }
243
244     /**
245      * @param diff
246      */

247     public void doUpdateTargetFromModel(ValueDiff diff) {
248         try {
249             updating = true;
250             BindingEvent e = new BindingEvent(model, target, diff,
251                     BindingEvent.EVENT_COPY_TO_TARGET,
252                     BindingEvent.PIPELINE_AFTER_GET) {
253             };
254             e.originalValue = model.getValue();
255             if (failure(errMsg(fireBindingEvent(e)))) {
256                 return;
257             }
258
259             e.convertedValue = modelToTargetConverter.convert(e.originalValue);
260             e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CONVERT;
261             if (failure(errMsg(fireBindingEvent(e)))) {
262                 return;
263             }
264
265             target.setValue(e.convertedValue);
266             e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CHANGE;
267             if (failure(errMsg(fireBindingEvent(e)))) {
268                 return;
269             }
270
271             doValidate(target.getValue());
272             e.pipelinePosition = BindingEvent.PIPELINE_AFTER_VALIDATE;
273             fireBindingEvent(e);
274         } finally {
275             updating = false;
276         }
277     }
278
279     public IObservableValue getValidationError() {
280         return validationErrorObservable;
281     }
282
283     public IObservableValue getPartialValidationError() {
284         return partialValidationErrorObservable;
285     }
286
287     public void updateModelFromTarget() {
288         updateModelFromTarget(Diffs.createValueDiff(target.getValue(), target
289                 .getValue()));
290     }
291 }
292
Popular Tags