/*******************************************************************************
* Copyright (c) 2008, 2012 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.eef.runtime.ui.widgets.settings;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.eef.runtime.impl.utils.EEFUtils;
/**
* @author glefur
* @since 1.0
*
*/
public class EEFEditorSettingsBuilder {
private EObject source;
private EStructuralFeature feature;
private List<NavigationStep> steps;
/**
* @param source
* @param feature
* @return a new instance of {@link EEFEditorSettingsBuilder}.
*/
public static EEFEditorSettingsBuilder create(EObject source, EStructuralFeature feature) {
return new EEFEditorSettingsBuilder(source, feature);
}
/**
* @param source
* @param feature
*/
private EEFEditorSettingsBuilder(EObject source, EStructuralFeature feature) {
this.source = source;
this.feature = feature;
steps = new ArrayList<NavigationStep>();
}
/**
* @param step
* @return
*/
public EEFEditorSettingsBuilder nextStep(NavigationStep step) {
steps.add(step);
return this;
}
/**
* @return
*/
public EEFEditorSettings build() {
for (NavigationStep step : steps) {
if (step.getReference().isMany() && step.getIndex() == NavigationStep.NOT_INITIALIZED) {
throw new IllegalStateException("Navigation step misconfigured : Reference " + step.getReference().getName() + " is mulivalued. You must define an index.");
}
}
return new EEFEditorSettingsImpl(source, feature, (List<NavigationStep>) Collections.unmodifiableList(steps));
}
/**
* @author glefur
*
*/
public class EEFEditorSettingsImpl implements EEFEditorSettings {
private EObject source;
private EStructuralFeature feature;
private List<NavigationStep> steps;
private EObject significantObject;
private EEFEditorSettingsImpl(EObject source, EStructuralFeature feature, List<NavigationStep> steps) {
this.source = source;
this.feature = feature;
this.steps = steps;
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#getValue()
*/
public Object getValue() {
EObject significantObject = getSignificantObject();
if (significantObject != null && significantObject.eResource() != null) {
return significantObject.eGet(feature);
} else {
return null;
}
}
/**
* Compute and cache the object to edit following the NavigationStep.
* @return object to edit.
*/
public EObject getSignificantObject() {
if (significantObject == null) {
EObject current = source;
for (NavigationStep step : EEFEditorSettingsImpl.this.steps) {
// reference *
if (step.getReference().isMany()) {
@SuppressWarnings("unchecked")
List<EObject> result = (List<EObject>)current.eGet(step.getReference());
List<EObject> result2 = new ArrayList<EObject>();
if (!result.isEmpty() && (!step.getFilters().isEmpty() || step.getDiscriminator() != null)) {
// add filters
if (!step.getFilters().isEmpty()) {
for (EEFFilter eefFilter : step.getFilters()) {
for (EObject eObject : result) {
if (eefFilter.select(eObject)) {
result2.add(eObject);
}
}
result = result2;
result2 = new ArrayList<EObject>();
}
}
// add discriminator
if (step.getDiscriminator() != null) {
for (EObject eObject : result) {
if (step.getDiscriminator().isInstance(eObject)) {
result2.add(eObject);
}
}
}
}
// Use init if result.isEmpty()
if (result.isEmpty()) {
return null;
}
if (step.getIndex() != NavigationStep.NOT_INITIALIZED && step.getIndex() < result.size()) {
current = result.get(step.getIndex());
// Use init if current == null
if (current == null) {
return null;
}
} else {
throw new IllegalStateException();
}
} else {
// reference 0 or 1
EObject current2 = current;
current = (EObject) current2.eGet(step.getReference());
if (current == null) {
return null;
}
}
}
significantObject = current;
}
return significantObject;
}
/**
* Compute and cache the object to edit following the NavigationStep.
* @return object to edit.
*/
public EObject getOrCreateSignificantObject() {
if (significantObject == null || (significantObject != null && significantObject.eResource() == null)) {
EObject current = source;
for (NavigationStep step : EEFEditorSettingsImpl.this.steps) {
// reference *
if (step.getReference().isMany()) {
@SuppressWarnings("unchecked")
List<EObject> result = (List<EObject>)current.eGet(step.getReference());
List<EObject> result2 = new ArrayList<EObject>();
if (!result.isEmpty() && (!step.getFilters().isEmpty() || step.getDiscriminator() != null)) {
// add filters
if (!step.getFilters().isEmpty()) {
for (EEFFilter eefFilter : step.getFilters()) {
for (EObject eObject : result) {
if (eefFilter.select(eObject)) {
result2.add(eObject);
}
}
result = result2;
result2 = new ArrayList<EObject>();
}
}
// add discriminator
if (step.getDiscriminator() != null) {
for (EObject eObject : result) {
if (step.getDiscriminator().isInstance(eObject)) {
result2.add(eObject);
}
}
result = result2;
result2 = new ArrayList<EObject>();
}
// no filter and no discriminator -> get step.reference
// } else {
// result2 = result;
}
// Use init if result.isEmpty()
if (result.isEmpty() && step.getInit() != null) {
result.add(step.getInit().init(current));
}
if (step.getIndex() != NavigationStep.NOT_INITIALIZED && step.getIndex() < result.size()) {
current = result.get(step.getIndex());
// Use init if current == null
if (current == null && step.getInit() != null) {
EObject current2 = current;
current = step.getInit().init(current2);
}
} else {
throw new IllegalStateException();
}
} else {
// reference 0 or 1
EObject current2 = current;
current = (EObject) current2.eGet(step.getReference());
if (current == null) {
if (step.getInit() != null) {
current = step.getInit().init(current2);
}
}
}
}
significantObject = current;
}
return significantObject;
}
public void setValue(Object newValue) {
getOrCreateSignificantObject().eSet(feature, newValue);
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#choiceOfValues(org.eclipse.emf.common.notify.AdapterFactory)
*/
public Object choiceOfValues(AdapterFactory adapterFactory) {
return feature instanceof EReference ? EEFUtils.choiceOfValues(source, feature) : null;
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#isAffectingFeature(org.eclipse.emf.ecore.EStructuralFeature)
*/
public boolean isAffectingFeature(EStructuralFeature feature) {
for (NavigationStep step : EEFEditorSettingsImpl.this.steps) {
if (step.getReference().equals(feature)) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#isAffectingEvent(org.eclipse.emf.common.notify.Notification)
*/
public boolean isAffectingEvent(Notification notification) {
if (
(notification.getFeature() instanceof EStructuralFeature && isAffectingFeature((EStructuralFeature) notification.getFeature()))) {
return true;
}
return false;
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#getSource()
*/
public EObject getSource() {
return source;
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#getEType()
*/
public EClassifier getEType() {
return feature.getEType();
}
/**
* {@inheritDoc}
* @see org.eclipse.emf.eef.runtime.ui.widgets.settings.EEFEditorSettings#getLastReference()
*/
public EReference getLastReference() {
if (feature instanceof EReference) {
return (EReference) feature;
} else if (EEFEditorSettingsImpl.this.steps.size() > 0) {
return EEFEditorSettingsImpl.this.steps.get(EEFEditorSettingsImpl.this.steps.size() - 1).getReference();
}
return null;
}
}
}