Skip to content

Package: ExpectedValueControlRenderer$ModelToTargetUpdateStrategy

ExpectedValueControlRenderer$ModelToTargetUpdateStrategy

nameinstructionbranchcomplexitylinemethod
ExpectedValueControlRenderer.ModelToTargetUpdateStrategy(ExpectedValueControlRenderer)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
convert(Object)
M: 13 C: 42
76%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 3 C: 11
79%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2013 EclipseSource Muenchen GmbH and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * Eugen Neufeld - initial API and implementation
13: ******************************************************************************/
14:
15: package org.eclipse.emf.ecp.view.internal.editor.controls;
16:
17: import java.lang.reflect.Constructor;
18: import java.lang.reflect.InvocationTargetException;
19:
20: import org.eclipse.core.databinding.Binding;
21: import org.eclipse.core.databinding.DataBindingContext;
22: import org.eclipse.core.databinding.UpdateValueStrategy;
23: import org.eclipse.core.databinding.observable.IObserving;
24: import org.eclipse.core.databinding.observable.value.IObservableValue;
25: import org.eclipse.emf.common.util.EList;
26: import org.eclipse.emf.common.util.Enumerator;
27: import org.eclipse.emf.databinding.EMFUpdateValueStrategy;
28: import org.eclipse.emf.ecore.EAttribute;
29: import org.eclipse.emf.ecore.EEnumLiteral;
30: import org.eclipse.emf.ecore.EObject;
31: import org.eclipse.emf.ecore.EStructuralFeature;
32: import org.eclipse.emf.ecore.EcorePackage;
33: import org.eclipse.emf.ecore.InternalEObject;
34: import org.eclipse.emf.ecore.impl.EEnumImpl;
35: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
36: import org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTControlSWTRenderer;
37: import org.eclipse.emf.ecp.view.spi.model.VControl;
38: import org.eclipse.emf.ecp.view.spi.provider.ECPTooltipModifierHelper;
39: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
40: import org.eclipse.emfforms.spi.common.report.ReportService;
41: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
42: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedReport;
43: import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding;
44: import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
45: import org.eclipse.jface.dialogs.InputDialog;
46: import org.eclipse.jface.dialogs.MessageDialog;
47: import org.eclipse.jface.layout.GridDataFactory;
48: import org.eclipse.jface.layout.GridLayoutFactory;
49: import org.eclipse.jface.viewers.ArrayContentProvider;
50: import org.eclipse.jface.viewers.LabelProvider;
51: import org.eclipse.jface.window.Window;
52: import org.eclipse.swt.SWT;
53: import org.eclipse.swt.events.SelectionAdapter;
54: import org.eclipse.swt.events.SelectionEvent;
55: import org.eclipse.swt.layout.GridData;
56: import org.eclipse.swt.widgets.Button;
57: import org.eclipse.swt.widgets.Composite;
58: import org.eclipse.swt.widgets.Control;
59: import org.eclipse.swt.widgets.Label;
60: import org.eclipse.swt.widgets.Shell;
61: import org.eclipse.ui.dialogs.ListDialog;
62:
63: /**
64: * A control for defining an value in a leaf condition.
65: *
66: * @author Eugen Neufeld
67: *
68: */
69: // APITODO no api yet
70: public abstract class ExpectedValueControlRenderer extends SimpleControlSWTControlSWTRenderer {
71:
72:         /**
73:          * Default constructor.
74:          *
75:          * @param vElement the view model element to be rendered
76:          * @param viewContext the view context
77:          * @param reportService The {@link ReportService}
78:          * @param databindingService The {@link EMFFormsDatabinding}
79:          * @param labelProvider The {@link EMFFormsLabelProvider}
80:          * @param viewTemplateProvider The {@link VTViewTemplateProvider}
81:          */
82:         public ExpectedValueControlRenderer(VControl vElement, ViewModelContext viewContext,
83:                 ReportService reportService, EMFFormsDatabinding databindingService, EMFFormsLabelProvider labelProvider,
84:                 VTViewTemplateProvider viewTemplateProvider) {
85:                 super(vElement, viewContext, reportService, databindingService, labelProvider, viewTemplateProvider);
86:         }
87:
88:         private Label text;
89:         private Shell shell;
90:
91:         private String getTextVariantID() {
92:                 return "org_eclipse_emf_ecp_view_editor_controls_ruleattribute"; //$NON-NLS-1$
93:         }
94:
95:         @Override
96:         public void finalizeRendering(Composite parent) {
97:                 super.finalizeRendering(parent);
98:                 shell = parent.getShell();
99:         }
100:
101:         /**
102:          * {@inheritDoc}
103:          *
104:          * @see org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTControlSWTRenderer#createSWTControl(org.eclipse.swt.widgets.Composite)
105:          */
106:         @Override
107:         protected Control createSWTControl(Composite parent) {
108:                 final Composite composite = new Composite(parent, SWT.NONE);
109:                 GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
110:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(composite);
111:                 final Button bSelectObject = new Button(composite, SWT.PUSH);
112:                 bSelectObject.setText("Select Object"); //$NON-NLS-1$
113:
114:                 text = new Label(composite, SWT.SINGLE | SWT.BORDER);
115:                 text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
116:                 text.setData(CUSTOM_VARIANT, getTextVariantID());
117:
118:                 bSelectObject.addSelectionListener(new SelectionAdapter() {
119:
120:                         @Override
121:                         public void widgetSelected(SelectionEvent e) {
122:                                 super.widgetSelected(e);
123:                                 onSelectButton(text);
124:                         }
125:                 });
126:                 return text;
127:         }
128:
129:         /**
130:          * {@inheritDoc}
131:          *
132:          * @see org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTControlSWTRenderer#createBindings(org.eclipse.swt.widgets.Control,
133:          * org.eclipse.emf.ecore.EStructuralFeature.Setting)
134:          */
135:         @Override
136:         protected Binding[] createBindings(Control control) throws DatabindingFailedException {
137:                 final Label text = (Label) control;
138:                 final TargetToModelUpdateStrategy targetToModelUpdateStrategy = new TargetToModelUpdateStrategy();
139:                 final ModelToTargetUpdateStrategy modelToTargetUpdateStrategy = new ModelToTargetUpdateStrategy();
140:
141:                 final IObservableValue value = org.eclipse.jface.databinding.swt.typed.WidgetProperties.text().observe(text);
142:
143:                 final Binding binding = getDataBindingContext().bindValue(value, getModelValue(),
144:                         withPreSetValidation(targetToModelUpdateStrategy), modelToTargetUpdateStrategy);
145:                 return new Binding[] { binding };
146:         }
147:
148:         /**
149:          * Creates a tooltip binding for this control.
150:          *
151:          * @param text the {@link Text} to bind
152:          * @param modelValue the {@link IObservableValue} to bind
153:          * @param dataBindingContext the {@link DataBindingContext} to use
154:          * @param targetToModel the {@link UpdateValueStrategy} from target to Model
155:          * @param modelToTarget the {@link UpdateValueStrategy} from model to target
156:          * @return the created {@link Binding}
157:          */
158:         protected Binding createTooltipBinding(Control text, IObservableValue modelValue,
159:                 DataBindingContext dataBindingContext, UpdateValueStrategy targetToModel, UpdateValueStrategy modelToTarget) {
160:                 final IObservableValue toolTip = org.eclipse.jface.databinding.swt.typed.WidgetProperties.tooltipText()
161:                         .observe(text);
162:                 return dataBindingContext.bindValue(toolTip, modelValue, targetToModel, modelToTarget);
163:         }
164:
165:         /**
166:          * Lets the user select an object and returns the selection.
167:          *
168:          * @param attribute the attribute for which an object is needed
169:          * @return the object
170:          */
171:         protected Object getSelectedObject(EAttribute attribute) {
172:                 Object object = null;
173:                 // final EAttribute attribute = (EAttribute) structuralFeature;
174:                 if (attribute == null) {
175:                         showError(shell, "Missing Attribute", //$NON-NLS-1$
176:                                 "Please select an attribute before attempting to select its value."); //$NON-NLS-1$
177:                         return object;
178:                 }
179:                 Class<?> attribuetClazz = attribute.getEAttributeType().getInstanceClass();
180:
181:                 if (attribuetClazz == null) {
182:                         if (EcorePackage.eINSTANCE.getEEnum().isInstance(attribute.getEType())) {
183:                                 attribuetClazz = Enum.class;
184:                                 final EList<EEnumLiteral> eLiterals = EEnumImpl.class.cast(attribute.getEType()).getELiterals();
185:                                 final Object[] enumValues = eLiterals.toArray();
186:                                 final ListDialog ld = new ListDialog(shell);
187:                                 ld.setLabelProvider(new LabelProvider());
188:                                 ld.setContentProvider(ArrayContentProvider.getInstance());
189:                                 ld.setInput(enumValues);
190:                                 ld.setInitialSelections(new Object[] { enumValues[0] });
191:                                 ld.setMessage("Please select the enum value to set."); //$NON-NLS-1$
192:                                 ld.setTitle("Select a value"); //$NON-NLS-1$
193:                                 final int enumSelectionResult = ld.open();
194:                                 if (Window.OK == enumSelectionResult) {
195:                                         object = EEnumLiteral.class.cast(ld.getResult()[0]).getLiteral();
196:                                 }
197:                         } else {
198:                                 return null;
199:                         }
200:                 } else {
201:                         if (attribuetClazz.isPrimitive()) {
202:                                 attribuetClazz = getAttributeClass(attribuetClazz);
203:                         }
204:                         if (Enum.class.isAssignableFrom(attribuetClazz)) {
205:                                 final Object[] enumValues = attribuetClazz.getEnumConstants();
206:                                 final ListDialog ld = new ListDialog(shell);
207:                                 ld.setLabelProvider(new LabelProvider());
208:                                 ld.setContentProvider(ArrayContentProvider.getInstance());
209:                                 ld.setInput(enumValues);
210:                                 ld.setInitialSelections(new Object[] { enumValues[0] });
211:                                 ld.setMessage("Please select the enum value to set."); //$NON-NLS-1$
212:                                 ld.setTitle("Select a value"); //$NON-NLS-1$
213:                                 final int enumSelectionResult = ld.open();
214:                                 if (Window.OK == enumSelectionResult) {
215:                                         object = Enumerator.class.cast(ld.getResult()[0]).getLiteral();
216:                                 }
217:                         } else if (String.class.isAssignableFrom(attribuetClazz)
218:                                 || Number.class.isAssignableFrom(attribuetClazz)
219:                                 || Boolean.class.isAssignableFrom(attribuetClazz)) {
220:                                 object = promptForValue(shell, object, attribuetClazz);
221:                         } else {
222:                                 showError(shell, "Not primitive Attribute selected", //$NON-NLS-1$
223:                                         "The selected attribute has a not primitive type. We can't provide you support for it!"); //$NON-NLS-1$
224:                         }
225:                 }
226:                 return object;
227:         }
228:
229:         /**
230:          * Shows an error message to the user.
231:          *
232:          * @param shell The Shell to show the error on
233:          * @param title The title of the error message
234:          * @param description The error description
235:          */
236:         protected void showError(Shell shell, String title, String description) {
237:                 MessageDialog.openError(shell, title, description);
238:         }
239:
240:         /**
241:          * Prompts the user to input a value. Return the original object if the input is cancelled.
242:          *
243:          * @param shell The Shell on which an input dialog will be opened
244:          * @param object The current value
245:          * @param attributeClazz The Class for which we want a value
246:          * @return the prompted value, or the input object if the prompt was cancelled
247:          */
248:         Object promptForValue(Shell shell, Object object, Class<?> attributeClazz) {
249:                 try {
250:                         final Constructor<?> constructor = attributeClazz.getConstructor(String.class);
251:                         final InputDialog id = new InputDialog(
252:                                 shell,
253:                                 "Insert the value", //$NON-NLS-1$
254:                                 "The value must be parseable by the " //$NON-NLS-1$
255:                                         + attributeClazz.getSimpleName()
256:                                         + " class. For a double value please use the #.# format. For boolean values 'true' or 'false'.", //$NON-NLS-1$
257:                                 null, null);
258:                         final int inputResult = id.open();
259:                         if (Window.OK == inputResult) {
260:                                 object = constructor.newInstance(id.getValue());
261:                         }
262:                         if (Boolean.class.isAssignableFrom(attributeClazz) && !Boolean.class.cast(object)
263:                                 && !"false".equalsIgnoreCase(id.getValue())) { //$NON-NLS-1$
264:                                 showError(shell, "Invalid boolean value", //$NON-NLS-1$
265:                                         "You have entered an invalid value. False has been chosen instead."); //$NON-NLS-1$
266:                         }
267:                 } catch (final IllegalArgumentException ex) {
268:                         openInvalidValueMessage();
269:                 } catch (final SecurityException ex) {
270:                         openInvalidValueMessage();
271:                 } catch (final NoSuchMethodException ex) {
272:                         openInvalidValueMessage();
273:                 } catch (final InstantiationException ex) {
274:                         openInvalidValueMessage();
275:                 } catch (final IllegalAccessException ex) {
276:                         openInvalidValueMessage();
277:                 } catch (final InvocationTargetException ex) {
278:                         openInvalidValueMessage();
279:                 }
280:                 return object;
281:         }
282:
283:         private Class<?> getAttributeClass(Class<?> attributeClazz) {
284:                 if (int.class.isAssignableFrom(attributeClazz)) {
285:                         attributeClazz = Integer.class;
286:                 } else if (long.class.isAssignableFrom(attributeClazz)) {
287:                         attributeClazz = Long.class;
288:                 } else if (float.class.isAssignableFrom(attributeClazz)) {
289:                         attributeClazz = Float.class;
290:                 } else if (double.class.isAssignableFrom(attributeClazz)) {
291:                         attributeClazz = Double.class;
292:                 } else if (boolean.class.isAssignableFrom(attributeClazz)) {
293:                         attributeClazz = Boolean.class;
294:                 } else if (char.class.isAssignableFrom(attributeClazz)) {
295:                         attributeClazz = Character.class;
296:                 }
297:                 return attributeClazz;
298:         }
299:
300:         private void openInvalidValueMessage() {
301:                 MessageDialog.openError(shell, "Invalid value", //$NON-NLS-1$
302:                         "You have entered an invalid value. The previsous value will be kept."); //$NON-NLS-1$
303:         }
304:
305:         /**
306:          * Called when the select value button is pressed.
307:          *
308:          * @param text the label which should be used to set the value
309:          */
310:         protected abstract void onSelectButton(Label text);
311:
312:         /**
313:          * Returns the model object representing the value for this renderer's domain model reference.
314:          *
315:          * @return the EObject
316:          * @throws DatabindingFailedException if the databinding fails
317:          */
318:         protected EObject getObservedEObject() throws DatabindingFailedException {
319:                 final IObservableValue observableValue = getEMFFormsDatabinding()
320:                         .getObservableValue(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
321:                 final EObject result = (EObject) ((IObserving) observableValue).getObserved();
322:                 observableValue.dispose();
323:                 return result;
324:         }
325:
326:         /**
327:          * {@inheritDoc}
328:          *
329:          * @see org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTRenderer#getUnsetText()
330:          */
331:         @Override
332:         protected String getUnsetText() {
333:                 // TODO Auto-generated method stub
334:                 return null;
335:         }
336:
337:         /**
338:          * The strategy to convert from model to target.
339:          *
340:          * @author Eugen Neufeld
341:          *
342:          */
343:         protected class ModelToTargetUpdateStrategy extends EMFUpdateValueStrategy {
344:
345:                 @Override
346:                 public Object convert(Object value) {
347:                         final Object converted = value.toString();
348:•                        if (String.class.isInstance(converted)) {
349:                                 IObservableValue observableValue;
350:                                 try {
351:                                         observableValue = getEMFFormsDatabinding()
352:                                                 .getObservableValue(getVElement().getDomainModelReference(),
353:                                                         getViewModelContext().getDomainModel());
354:                                 } catch (final DatabindingFailedException ex) {
355:                                         getReportService().report(new DatabindingFailedReport(ex));
356:                                         return converted;
357:                                 }
358:                                 final InternalEObject internalEObject = (InternalEObject) ((IObserving) observableValue).getObserved();
359:                                 final EStructuralFeature structuralFeature = (EStructuralFeature) observableValue.getValueType();
360:                                 observableValue.dispose();
361:                                 return ECPTooltipModifierHelper.modifyString(String.class.cast(converted),
362:                                         internalEObject.eSetting(structuralFeature));
363:                         }
364:                         return converted;
365:                 }
366:
367:         }
368:
369:         /**
370:          * The strategy to convert from target to model.
371:          *
372:          * @author Eugen
373:          *
374:          */
375:         protected class TargetToModelUpdateStrategy extends EMFUpdateValueStrategy {
376:
377:                 /**
378:                  * Constructor for indicating whether a value is unsettable.
379:                  */
380:                 public TargetToModelUpdateStrategy() {
381:                 }
382:
383:                 /**
384:                  * {@inheritDoc}
385:                  */
386:                 @Override
387:                 public Object convert(Object value) {
388:                         return value;
389:                 }
390:         }
391:
392: }