| /******************************************************************************* |
| * Steven Spungin <steven@spungin.tv> - Ongoing maintenance |
| ******************************************************************************/ |
| |
| package org.eclipse.e4.tools.emf.ui.internal.common.component; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.databinding.UpdateValueStrategy; |
| import org.eclipse.core.databinding.conversion.Converter; |
| import org.eclipse.core.databinding.conversion.IConverter; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.emf.databinding.EMFUpdateValueStrategy; |
| import org.eclipse.emf.databinding.IEMFValueProperty; |
| import org.eclipse.emf.databinding.edit.IEMFEditValueProperty; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EFactory; |
| import org.eclipse.emf.edit.command.SetCommand; |
| |
| /** |
| * An updater to deal with unsettable primitive attributes on EMF objects. EMF's |
| * {@link IEMFEditValueProperty}/ {@link IEMFValueProperty} does an eGet to |
| * retrieve the attribute value, with no regard as to whether the attribute is |
| * unset. If the attribute is unset, then eGet() will return the default value. |
| * |
| * This implementation makes several assumptions: |
| * <ul> |
| * <li>Assumes that these unsettable attributes have a nonsensical default value |
| * that can be used to detect an eGet of an unset attribute.</li> |
| * <li>Assumes that we are using EMFEditObservables so that changes are |
| * described using {@link SetCommand}, such that we can provide |
| * {@link SetCommand#UNSET_VALUE} to remove a value.</li> |
| * </ul> |
| * See the following discussions for background details: |
| * <ul> |
| * <li><a href= |
| * "http://www.eclipse.org/forums/index.php?t=msg&th=165026/">Dynamic eGet for |
| * unsettable attributes</a></li> |
| * <li><a href= |
| * "http://www.eclipsezone.com/eclipse/forums/t114431.html?start=15"> Creating a |
| * ComboViewer for an EReference</a> particularly the later postings from Tom |
| * Schindl on handling null values</li> |
| * <li><a href="http://www.eclipse.org/forums/index.php?t=msg&th=174967/"> |
| * ObservableMapCellLabelProvider doesn't work well with unsettable |
| * features</a></li> |
| * </ul> |
| */ |
| public class UnsettableUpdateValueStrategy extends EMFUpdateValueStrategy { |
| @SuppressWarnings("rawtypes") |
| @Override |
| protected IConverter createConverter(Object fromType, Object toType) { |
| if (fromType == String.class) { |
| if (toType instanceof EAttribute) { |
| final EAttribute eAttribute = (EAttribute) toType; |
| final EDataType eDataType = eAttribute.getEAttributeType(); |
| final EFactory eFactory = eDataType.getEPackage().getEFactoryInstance(); |
| return new Converter(fromType, toType) { |
| @Override |
| public Object convert(Object fromObject) { |
| final String value = fromObject == null ? null : fromObject.toString(); |
| if (value == null || value.length() == 0) { |
| return SetCommand.UNSET_VALUE; |
| } |
| if (eAttribute.isMany()) { |
| final List<Object> result = new ArrayList<>(); |
| |
| for (final String element : value.split(" ")) { //$NON-NLS-1$ |
| result.add(eFactory.createFromString(eDataType, element)); |
| |
| } |
| return result; |
| } |
| return eFactory.createFromString(eDataType, value); |
| } |
| }; |
| } |
| } else if (toType == String.class) { |
| if (fromType instanceof EAttribute) { |
| final EAttribute eAttribute = (EAttribute) fromType; |
| final EDataType eDataType = eAttribute.getEAttributeType(); |
| final EFactory eFactory = eDataType.getEPackage().getEFactoryInstance(); |
| return new Converter(fromType, toType) { |
| @Override |
| public Object convert(Object fromObject) { |
| if (eAttribute.isMany()) { |
| final StringBuilder result = new StringBuilder(); |
| for (final Object value : (List<?>) fromObject) { |
| if (result.length() == 0) { |
| result.append(' '); |
| } |
| result.append(eFactory.convertToString(eDataType, value)); |
| } |
| return result.toString(); |
| } |
| // If the value |
| if (fromObject == SetCommand.UNSET_VALUE || fromObject == null |
| || fromObject.equals(eAttribute.getDefaultValue())) { |
| return ""; //$NON-NLS-1$ |
| } |
| return eFactory.convertToString(eDataType, fromObject); |
| } |
| }; |
| } |
| } |
| return super.createConverter(fromType, toType); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see |
| * org.eclipse.core.databinding.UpdateValueStrategy#doSet(org.eclipse.core |
| * .databinding.observable.value.IObservableValue, java.lang.Object) |
| */ |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| @Override |
| protected IStatus doSet(IObservableValue observableValue, Object value) { |
| // TODO Auto-generated method stub |
| return super.doSet(observableValue, value); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static <S, D> UpdateValueStrategy<S, D> create() { |
| return new UnsettableUpdateValueStrategy(); |
| } |
| } |