| /******************************************************************************* |
| * Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| * 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: |
| <<<<<<< HEAD |
| * Pierre Allard - initial API and implementation |
| * Regent L'Archeveque |
| * |
| ======= |
| * Pierre Allard, |
| * Regent L'Archeveque - initial API and implementation |
| * |
| >>>>>>> refs/heads/eclipse_pa |
| * SPDX-License-Identifier: EPL-1.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.apogy.common.emf.databinding; |
| |
| import org.eclipse.apogy.common.emf.AbstractFeatureNode; |
| import org.eclipse.apogy.common.emf.AbstractFeatureSpecifier; |
| import org.eclipse.apogy.common.emf.ApogyCommonEMFFactory; |
| import org.eclipse.apogy.common.emf.ApogyCommonEMFPackage; |
| import org.eclipse.apogy.common.emf.FeatureNodeAdapter; |
| import org.eclipse.core.databinding.observable.value.AbstractObservableValue; |
| import org.eclipse.core.databinding.observable.value.IValueChangeListener; |
| import org.eclipse.core.databinding.observable.value.ValueDiff; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EObject; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class FeatureNodeObservableValue extends AbstractObservableValue<Object> { |
| private static final Logger Logger = LoggerFactory.getLogger(FeatureNodeObservableValue.class); |
| |
| private Adapter adapter = null; |
| @SuppressWarnings("unused") |
| private EObject eObject; |
| |
| private AbstractFeatureNode featureNode; |
| private FeatureNodeAdapter featureNodeAdapter = null; |
| private boolean resolved = false; |
| |
| public FeatureNodeObservableValue(EObject eObject, AbstractFeatureNode featureNode) { |
| setEObject(eObject); |
| setFeatureNode(featureNode); |
| |
| setResolved(getFeatureNodeAdapter().isResolved()); |
| } |
| |
| public void setEObject(EObject eObject) { |
| this.eObject = eObject; |
| getFeatureNodeAdapter().setSourceObject(eObject); |
| } |
| |
| public void setFeatureNode(AbstractFeatureNode featureNode) { |
| this.featureNode = featureNode; |
| getFeatureNodeAdapter().setFeatureNode(featureNode); |
| } |
| |
| @Override |
| public Object getValueType() { |
| if (this.featureNode instanceof AbstractFeatureNode) { |
| AbstractFeatureSpecifier featureSpecifier = (AbstractFeatureSpecifier) this.featureNode; |
| |
| if (featureSpecifier.getStructuralFeature().getEType() instanceof EEnum) { |
| return featureSpecifier.getStructuralFeature().getEType(); |
| } else if (featureSpecifier.getStructuralFeature().getEType() instanceof EClass) { |
| return featureSpecifier.getStructuralFeature().getEType(); |
| } else { |
| return featureSpecifier.getStructuralFeature().getEType().getInstanceClass(); |
| } |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Method called when the resolution status of the ObservableValue changes. This |
| * method could be overloaded by clients. |
| * |
| * @param newValue The new value of the resolved flag. |
| */ |
| public void resolved(boolean newValue) { |
| } |
| |
| public boolean isResolved() { |
| return this.resolved; |
| } |
| |
| protected void setResolved(boolean newResolved) { |
| this.resolved = newResolved; |
| |
| try { |
| resolved(newResolved); |
| } catch (Throwable t) { |
| Logger.error(t.getMessage(), t); |
| } |
| } |
| |
| @Override |
| protected Object doGetValue() { |
| return getFeatureNodeAdapter().getCurrentValue(); |
| } |
| |
| @Override |
| public synchronized void removeValueChangeListener(IValueChangeListener<Object> listener) { |
| super.removeValueChangeListener(listener); |
| |
| // Dispose of FeatureNodeAdapter if no one is listening anymore. |
| if (!hasListeners()) { |
| dispose(); |
| } |
| } |
| |
| protected FeatureNodeAdapter getFeatureNodeAdapter() { |
| if (this.featureNodeAdapter == null) { |
| this.featureNodeAdapter = ApogyCommonEMFFactory.eINSTANCE.createFeatureNodeAdapter(); |
| this.featureNodeAdapter.eAdapters().add(getAdapter()); |
| } |
| |
| return this.featureNodeAdapter; |
| } |
| |
| private Adapter getAdapter() { |
| if (this.adapter == null) { |
| this.adapter = new AdapterImpl() { |
| @Override |
| public void notifyChanged(Notification notification) { |
| if (notification.getFeatureID( |
| FeatureNodeAdapter.class) == ApogyCommonEMFPackage.FEATURE_NODE_ADAPTER__CURRENT_VALUE) { |
| final Object oldValue = notification.getOldValue(); |
| final Object newValue = notification.getNewValue(); |
| |
| // Fire a Value Change |
| getRealm().asyncExec(new Runnable() { |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| @Override |
| public void run() { |
| ValueDiff valueDiff = new DefaultValueDiff(oldValue, newValue); |
| fireValueChange(valueDiff); |
| } |
| }); |
| } else if (notification.getFeatureID( |
| FeatureNodeAdapter.class) == ApogyCommonEMFPackage.FEATURE_NODE_ADAPTER__RESOLVED) { |
| if (notification.getOldBooleanValue() != notification.getNewBooleanValue()) { |
| setResolved(notification.getNewBooleanValue()); |
| } |
| } |
| } |
| }; |
| } |
| |
| return this.adapter; |
| } |
| |
| @Override |
| public synchronized void dispose() { |
| // Removes adapter on FeatureNodeAdapter. |
| getFeatureNodeAdapter().eAdapters().remove(getAdapter()); |
| |
| // Removes references to Source and FeatureNode. |
| setEObject(null); |
| setFeatureNode(null); |
| |
| this.adapter = null; |
| this.featureNodeAdapter = null; |
| super.dispose(); |
| } |
| } |