/***************************************************************************** * Copyright (c) 2012 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.infra.emf.providers.strategy; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.eclipse.emf.common.notify.AdapterFactory; 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.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.facet.infra.browser.uicore.CustomizableModelContentProvider; import org.eclipse.papyrus.infra.emf.Activator; import org.eclipse.papyrus.infra.emf.utils.EMFHelper; import org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider; import org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider; import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; public class SemanticEMFContentProvider extends CustomizableModelContentProvider implements IAdaptableContentProvider, IHierarchicContentProvider, IStaticContentProvider { protected EObject[] roots; protected List<?> metaclasses = new LinkedList<Object>(); protected List<?> notWantedMetaclasses = new LinkedList<Object>(); protected EObject eObject; protected EStructuralFeature feature; protected AdapterFactory factory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); public SemanticEMFContentProvider(EObject editedEObject, EStructuralFeature feature, EObject[] roots) { super(Activator.getDefault().getCustomizationManager()); this.roots = roots; configureMetaclasses(feature); this.eObject = editedEObject; this.feature = feature; } protected void configureMetaclasses(EStructuralFeature feature) { if(feature != null) { setWantedMetaclasses(Collections.singletonList(feature.getEType())); } } public SemanticEMFContentProvider(EObject editedEObject, EStructuralFeature feature) { this(editedEObject, feature, findRoots(editedEObject)); } public SemanticEMFContentProvider(EObject[] roots) { this(null, null, roots); } public SemanticEMFContentProvider(ResourceSet root) { this(null, null, root); } public SemanticEMFContentProvider(EObject editedEObject, EStructuralFeature feature, ResourceSet root) { this(editedEObject, feature, getRoots(root)); } protected static EObject[] getRoots(ResourceSet root) { List<EObject> roots = new LinkedList<EObject>(); if(root != null) { for(Resource resource : root.getResources()) { roots.addAll(resource.getContents()); } } return roots.toArray(new EObject[roots.size()]); } protected static EObject[] findRoots(EObject source) { //The EObject is not contained in a resource : we return the top-level EObject if(source.eResource() == null) { while(source.eContainer() != null) { source = source.eContainer(); } return new EObject[]{ source }; } //The resource is not contained in a resource set : we return the resource's contents if(source.eResource().getResourceSet() == null) { return source.eResource().getContents().toArray(new EObject[0]); } //We have a full resourceSet : we return its contents return getRoots(source.eResource().getResourceSet()); } @Override public EObject[] getRootElements(final Object inputElement) { return roots; } public Object getAdaptedValue(Object containerElement) { return EMFHelper.getEObject(containerElement); } @Override public boolean hasChildren(Object parent) { //May be expensive Object[] children = getChildren(parent); return children != null && children.length > 0; } public boolean isValidValue(Object containerElement) { // get the semantic object form the element Object semanticObject = getAdaptedValue(containerElement); //return false for EReference and non-semantic objects if(semanticObject instanceof EReference || semanticObject == null) { return false; } //Tests whether the element is compatible with at least one metaclass if(metaclasses != null && !metaclasses.isEmpty()) { boolean compatible = false; for(Object metaclass : metaclasses) { if(isCompatibleMetaclass(containerElement, metaclass)) { compatible = true; break; } } if(!compatible) { return false; } } //If the element is compatible with at least one metaclass from notWanted, then it is not valid for(Object metaclass : notWantedMetaclasses) { if(isCompatibleMetaclass(containerElement, metaclass)) { return false; } } return true; } protected boolean isCompatibleMetaclass(Object containerElement, Object metaclass) { if(metaclass instanceof EClassifier) { Object semanticElement = getAdaptedValue(containerElement); return ((EClassifier)metaclass).isInstance(semanticElement); } return false; } public void setWantedMetaclasses(List<?> metaclasses) { this.metaclasses = metaclasses; } public void setNotWantedMetaclasses(List<?> notWantedMetaclasses) { this.notWantedMetaclasses = notWantedMetaclasses; } public Object[] getElements() { return super.getElements(null); } public List<?> getWantedMetaclasses() { return metaclasses; } public List<?> getNotWantedMetaclasses() { return notWantedMetaclasses; } }