/** * Copyright (c) 2011 BestSolution.at and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation */ package org.eclipse.emf.databinding.internal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.IProperty; import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.SimplePropertyEvent; import org.eclipse.core.databinding.property.list.IListProperty; import org.eclipse.core.databinding.property.value.SimpleValueProperty; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.databinding.IEMFListProperty.ListElementAccess; import org.eclipse.emf.databinding.IEMFListProperty.ListElementAccess.WriteData; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; /** */ public class EMFListValueProperty extends SimpleValueProperty { private final EStructuralFeature eStructuralFeature; @SuppressWarnings("rawtypes") private final ListElementAccess elementAccess; private final IListProperty delegate; /** * @param delegate * @param eStructuralFeature * @param elementAccess */ public EMFListValueProperty(IListProperty delegate, EStructuralFeature eStructuralFeature, ListElementAccess<?> elementAccess) { this.delegate = delegate; this.eStructuralFeature = eStructuralFeature; this.elementAccess = elementAccess; } public Object getValueType() { return eStructuralFeature; } @Override protected Object doGetValue(Object source) { List< ? > list = listFromDelegate(source); @SuppressWarnings("unchecked") int idx = elementAccess.getReadValueIndex(list); if (idx != WriteData.NO_INDEX) { return list.get(idx); } return null; } @SuppressWarnings("unchecked") private List<?> listFromDelegate(Object source) { List<?> list = Collections.EMPTY_LIST; if (source != null) { // we can't use IListProperty#getList(Object) because our lower bound is DB 1.2 if( delegate instanceof EMFListProperty ) { list = ((EMFListProperty)delegate).doGetList(source); } else { IObservableList observable = delegate.observe(source); try { list = new ArrayList<Object>(observable); } finally { observable.dispose(); } } } return list; } @SuppressWarnings("unchecked") @Override protected void doSetValue(Object source, Object value) { IObservableList list = delegate.observe(source); try { WriteData data = elementAccess.getWriteValueData(list); if (data != null) { doSetListValue((EObject)source, list, data, value); } } finally { list.dispose(); } } /** * @param source * @param targetList * @param data * @param value */ protected void doSetListValue(EObject source, List<Object> targetList, WriteData data, Object value) { if (data.insert) { if (data.index == WriteData.NO_INDEX) { targetList.add(value); } else { targetList.add(data.index, value); } } else { targetList.set(data.index, value); } } @Override public INativePropertyListener adaptListener(final ISimplePropertyListener listener) { return new EMFPropertyListener() { @Override public void notifyChanged(Notification msg) { if (msg.getFeature() == getFeature() && !msg.isTouch()) { Object newValue = doGetValue(msg.getNotifier()); //TODO Can we be smarter here and find out if the value really changed instead of passing null getListener().handleEvent( new SimplePropertyEvent(SimplePropertyEvent.CHANGE, msg.getNotifier(), getOwner(), Diffs.createValueDiff(null, newValue))); } } @Override protected IProperty getOwner() { return EMFListValueProperty.this; } @Override protected ISimplePropertyListener getListener() { return listener; } @Override protected EStructuralFeature getFeature() { return eStructuralFeature; } }; } }