/*****************************************************************************
* 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.uml.tools.providers;
import java.util.List;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.NotFoundException;
import org.eclipse.papyrus.infra.core.resource.uml.UmlUtils;
import org.eclipse.papyrus.infra.emf.providers.strategy.SemanticEMFContentProvider;
import org.eclipse.papyrus.infra.widgets.Activator;
import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Stereotype;
/**
* A semantic Hierarchic Content Provider for UML
*
* @author Camille Letavernier
*/
public class SemanticUMLContentProvider extends SemanticEMFContentProvider {
public SemanticUMLContentProvider(EObject editedEObject, EStructuralFeature feature, EObject[] roots) {
super(editedEObject, feature, roots);
}
public SemanticUMLContentProvider(EObject editedEObject, EStructuralFeature feature) {
this(editedEObject, feature, findRoots(editedEObject));
}
public SemanticUMLContentProvider(EObject[] roots) {
super(roots);
}
public SemanticUMLContentProvider(ResourceSet root) {
this(null, null, root);
}
public SemanticUMLContentProvider(EObject editedEObject, EStructuralFeature feature, ResourceSet root) {
this(editedEObject, feature, getRoots(root));
}
protected static EObject[] findRoots(EObject source) {
if(source.eResource() == null || source.eResource().getResourceSet() == null) {
return SemanticEMFContentProvider.findRoots(source);
}
//We have a full resourceSet : we return its contents
return getRoots(source.eResource().getResourceSet());
}
protected static EObject[] getRoots(ResourceSet root) {
if(root instanceof ModelSet) {
ModelSet modelSet = (ModelSet)root;
//TODO : Find all semantic roots, including Models and Libraries
//This is related to the ModelSet evolution
try {
return new EObject[]{ UmlUtils.getUmlModel(modelSet).lookupRoot() };
} catch (NotFoundException ex) {
Activator.log.error(ex);
}
}
return SemanticEMFContentProvider.getRoots(root);
}
@Override
protected boolean isCompatibleMetaclass(Object containerElement, Object metaclass) {
Element semanticElement = UMLUtil.resolveUMLElement(containerElement);
if(semanticElement == null) {
return false;
}
if(metaclass instanceof Stereotype) {
Stereotype stereotype = (Stereotype)metaclass;
boolean res = semanticElement.getAppliedStereotype(stereotype.getQualifiedName()) != null;
if (!res) {
EClass definition = stereotype.getDefinition();
for (EObject e : semanticElement.getStereotypeApplications()){
EClass c = e.eClass();
if (definition != null && definition.isSuperTypeOf(c)){
res = true ;
break ;
}
}
}
return res;
}
//TODO : We should use super.isCompatibleMetaclass(), but the super-implementation
//may not be compatible with our implementation of getAdaptedValue()
if(metaclass instanceof EClassifier) {
return ((EClassifier)metaclass).isInstance(semanticElement);
}
return false;
}
/**
* This method should return either the StereotypeApplication (For Sto - Sto associations),
* or the UML Element (For Sto - UML associations)
*
* This depends on the wanted metaclass.
*/
//TODO : In some cases, we may have a filter based on both a UML Metaclass and a Stereotype
//In such a specific case, a specific implementation is probably needed
//
//This case may especially occur in the case of dynamic creation of stereotype associations.
@Override
public Object getAdaptedValue(Object containerElement) {
Object semanticElement = super.getAdaptedValue(containerElement);
if(semanticElement instanceof Element) {
Element element = (Element)semanticElement;
//Looks for a compatible Stereotype application
for(Object metaclassWanted : getWantedMetaclasses()) {
if(metaclassWanted instanceof Stereotype) {
EObject stereotypeApplication = null;
stereotypeApplication = element.getStereotypeApplication((Stereotype)metaclassWanted);
if(stereotypeApplication == null) {
List<Stereotype> subStereotypes = element.getAppliedSubstereotypes((Stereotype)metaclassWanted);
for(Stereotype subSteretoype : subStereotypes) {
stereotypeApplication = element.getStereotypeApplication(subSteretoype);
if(stereotypeApplication != null) {
break;
}
}
}
if(stereotypeApplication != null) {
return stereotypeApplication;
}
}
}
}
//If no stereotype application is found, return the UML Element
return semanticElement;
}
}