blob: 6fafded588f52631d040dfea838a27793214e4d6 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}