/*****************************************************************************
* Copyright (c) 2010 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.customization.properties.modelelement;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.papyrus.customization.properties.providers.ConstraintDescriptorContentProvider;
import org.eclipse.papyrus.customization.properties.providers.ContextLabelProvider;
import org.eclipse.papyrus.customization.properties.providers.DataContextElementContentProvider;
import org.eclipse.papyrus.customization.properties.providers.DependencyContentProvider;
import org.eclipse.papyrus.customization.properties.providers.EnvironmentContentProvider;
import org.eclipse.papyrus.customization.properties.providers.PropertyContentProvider;
import org.eclipse.papyrus.customization.properties.providers.PropertyEditorTypeContentProvider;
import org.eclipse.papyrus.customization.properties.providers.TabContentProvider;
import org.eclipse.papyrus.infra.constraints.ConstraintsPackage;
import org.eclipse.papyrus.infra.constraints.providers.ConstraintTypeContentProvider;
import org.eclipse.papyrus.infra.emf.providers.EMFGraphicalContentProvider;
import org.eclipse.papyrus.infra.emf.providers.strategy.ContainmentBrowseStrategy;
import org.eclipse.papyrus.infra.emf.providers.strategy.StrategyBasedContentProvider;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory;
import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider;
import org.eclipse.papyrus.infra.widgets.strategy.IStrategyBasedContentProvider;
import org.eclipse.papyrus.infra.widgets.strategy.ProviderBasedBrowseStrategy;
import org.eclipse.papyrus.infra.widgets.strategy.TreeBrowseStrategy;
import org.eclipse.papyrus.views.properties.contexts.Context;
import org.eclipse.papyrus.views.properties.contexts.ContextsPackage;
import org.eclipse.papyrus.views.properties.contexts.DataContextElement;
import org.eclipse.papyrus.views.properties.contexts.Section;
import org.eclipse.papyrus.views.properties.environment.EnvironmentPackage;
import org.eclipse.papyrus.views.properties.modelelement.AbstractModelElement;
import org.eclipse.papyrus.views.properties.modelelement.DataSource;
import org.eclipse.papyrus.views.properties.modelelement.EMFModelElement;
import org.eclipse.papyrus.views.properties.modelelement.ModelElement;
import org.eclipse.papyrus.views.properties.runtime.ConfigurationManager;
import org.eclipse.papyrus.views.properties.ui.PropertyEditor;
/**
* A {@link ModelElement} for customization specific properties
* For performance issues, the default EMF Content Providers cannot
* be used, as they usually load the whole ResourceSet, which is
* really expensive in a Context Model : most of the resources
* are XWT Files which are expensive to load, and never contain
* any referenceable object. Hence, this ModelElement replaces
* most EMF Content Providers by custom ones, much lighter. When such
* a content provider cannot be found, the default EMF one is used.
*
* @author Camille Letavernier
*/
public class CustomizationModelElement extends AbstractModelElement {
private EMFModelElement delegate;
private static Map<EClassifier, IStaticContentProvider> providers;
/**
* Constructs a new ModelElement.
*
* @param delegate
* If this model element cannot handle a given property, it will
* delegate the call to a standard EMF ModelElement
*/
public CustomizationModelElement(EMFModelElement delegate) {
this.delegate = delegate;
if(providers == null) {
initializeProviders();
}
}
private static void initializeProviders() {
providers = new HashMap<EClassifier, IStaticContentProvider>();
providers.put(EnvironmentPackage.eINSTANCE.getCompositeWidgetType(), new EnvironmentContentProvider(EnvironmentPackage.eINSTANCE.getEnvironment_CompositeWidgetTypes()));
providers.put(EnvironmentPackage.eINSTANCE.getStandardWidgetType(), new EnvironmentContentProvider(EnvironmentPackage.eINSTANCE.getEnvironment_WidgetTypes()));
providers.put(EnvironmentPackage.eINSTANCE.getLayoutType(), new EnvironmentContentProvider(EnvironmentPackage.eINSTANCE.getEnvironment_LayoutTypes()));
providers.put(EnvironmentPackage.eINSTANCE.getModelElementFactoryDescriptor(), new EnvironmentContentProvider(EnvironmentPackage.eINSTANCE.getEnvironment_ModelElementFactories()));
providers.put(EnvironmentPackage.eINSTANCE.getPropertyEditorType(), new EnvironmentContentProvider(EnvironmentPackage.eINSTANCE.getEnvironment_PropertyEditorTypes()));
providers.put(org.eclipse.papyrus.infra.constraints.environment.EnvironmentPackage.eINSTANCE.getConstraintType(), new ConstraintTypeContentProvider());
}
@Override
public IObservable doGetObservable(String propertyPath) {
EStructuralFeature feature = delegate.getFeature(propertyPath);
if(ContextsPackage.eINSTANCE.getSection_Name() == feature) {
return new SectionNameObservableValue(delegate.getSource(), feature, delegate.getDomain());
}
return delegate.getObservable(propertyPath);
}
@Override
public IStaticContentProvider getContentProvider(String propertyPath) {
EStructuralFeature feature = delegate.getFeature(propertyPath);
if(feature == null) {
return EmptyContentProvider.instance;
}
IStaticContentProvider provider = findProvider(feature);
if(provider == null) {
return delegate.getContentProvider(propertyPath);
}
if(provider instanceof ITreeContentProvider) {
IStrategyBasedContentProvider strategyProvider = getStrategyProvider((ITreeContentProvider)provider);
if(feature.getEType() == EnvironmentPackage.eINSTANCE.getPropertyEditorType()) {
return new PropertyEditorTypeContentProvider(strategyProvider, (PropertyEditor)delegate.getSource());
} else {
return new EMFGraphicalContentProvider(strategyProvider, ConfigurationManager.instance.getResourceSet(), "history_" + feature.getName());
}
}
return provider;
}
protected IStrategyBasedContentProvider getStrategyProvider(ITreeContentProvider provider) {
TreeBrowseStrategy browseStrategy = new ProviderBasedBrowseStrategy(provider);
TreeBrowseStrategy revealStrategy = new ContainmentBrowseStrategy(provider);
return new StrategyBasedContentProvider(browseStrategy, revealStrategy);
}
protected IStaticContentProvider findProvider(EStructuralFeature feature) {
EClassifier classifier = feature.getEType();
if(providers.containsKey(classifier)) {
return providers.get(classifier);
} else if(classifier == ContextsPackage.eINSTANCE.getProperty()) {
return new PropertyContentProvider(delegate.getSource());
} else if(classifier == ContextsPackage.eINSTANCE.getTab()) {
//Sections can only be moved to tabs from non-plugin contexts
boolean editableTabsOnly = delegate.getSource() instanceof Section;
return new TabContentProvider(delegate.getSource(), editableTabsOnly);
} else if(classifier instanceof EClass && EMFHelper.isSubclass((EClass)classifier, ConstraintsPackage.eINSTANCE.getConstraintDescriptor())) {
return new ConstraintDescriptorContentProvider(delegate.getSource(), (EClass)classifier);
} else if(isDataContextElement(classifier)) {
return new DataContextElementContentProvider((DataContextElement)delegate.getSource());
} else if(classifier == ContextsPackage.eINSTANCE.getContext()) {
return new DependencyContentProvider((Context)delegate.getSource());
}
return null;
}
private boolean isDataContextElement(EClassifier classifier) {
if(classifier == ContextsPackage.eINSTANCE.getDataContextElement()) {
return true;
}
if(classifier instanceof EClass) {
EClass eClass = (EClass)classifier;
return eClass.getEAllSuperTypes().contains(ContextsPackage.eINSTANCE.getDataContextElement());
}
return false;
}
@Override
public ILabelProvider getLabelProvider(String propertyPath) {
return new ContextLabelProvider();
}
@Override
public boolean isOrdered(String propertyPath) {
return delegate.isOrdered(propertyPath);
}
@Override
public boolean isUnique(String propertyPath) {
return delegate.isUnique(propertyPath);
}
@Override
public boolean isMandatory(String propertyPath) {
return delegate.isMandatory(propertyPath);
}
@Override
public boolean isEditable(String propertyPath) {
if(delegate.getFeature(propertyPath) == ContextsPackage.eINSTANCE.getSection_SectionFile()) {
return false;
}
return delegate.isEditable(propertyPath);
}
@Override
public ReferenceValueFactory getValueFactory(String propertyPath) {
return delegate.getValueFactory(propertyPath);
}
@Override
public boolean getDirectCreation(String propertyPath) {
return delegate.getDirectCreation(propertyPath);
}
@Override
public boolean forceRefresh(String localPropertyPath) {
return false;
}
@Override
public Object getDefaultValue(String propertyPath) {
return delegate.getDefaultValue(propertyPath);
}
@Override
public void setDataSource(DataSource source) {
delegate.setDataSource(source);
}
@Override
public void dispose() {
super.dispose();
delegate.dispose();
}
}