/*****************************************************************************
* 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:
* CEA LIST - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.textedit.state.xtext.scoping;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.papyrus.uml.textedit.state.xtext.umlState.QualifiedName;
import org.eclipse.papyrus.uml.textedit.state.xtext.umlState.SubmachineRule;
import org.eclipse.papyrus.uml.textedit.state.xtext.validation.UmlStateJavaValidator;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.StateMachine;
import org.eclipse.xtext.gmf.glue.edit.part.PopupXtextEditorHelper;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.eclipse.xtext.scoping.impl.SimpleScope;
/**
* This class contains custom scoping description.
*
* see : http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping
* on how and when to use it
*
*/
public class UmlStateScopeProvider extends AbstractDeclarativeScopeProvider {
/**
* Rule for computing the scope of PropertyRule
* @param ctx
* @param ref
* @return scope
*/
public IScope scope_SubmachineRule_submachine(SubmachineRule ctx, EReference ref) {
return create___SubmachineRule_submachine___Scope(ctx) ;
}
private IScope create___SubmachineRule_submachine___Scope(SubmachineRule ctx) {
if (ctx.getPath() == null) {
Iterator<EObject> i = PopupXtextEditorHelper.context.eResource().getAllContents() ;
List<EObject> allContent = new ArrayList<EObject>() ;
while (i.hasNext()) {
EObject object = i.next() ;
if (object instanceof StateMachine)
allContent.add(object) ;
}
Iterable<IEObjectDescription> visibleParameterBoxes = Scopes.scopedElementsFor(allContent) ;
return new SimpleScope(visibleParameterBoxes) ;
}
else {
// In the case where a path (qualified name prefix) has been specified,
// retrieves visible elements from this name space
List<Element> tmpVisibleElementsFromPath = new ArrayList<Element>() ;
if (ctx.getPath() != null) {
QualifiedName qualifiedName = ctx.getPath() ;
while (qualifiedName.getRemaining() != null) {
qualifiedName = qualifiedName.getRemaining() ;
}
Namespace nearestNamespace = qualifiedName.getPath() ;
if (nearestNamespace != null) {
List<Element> tmpVisiblePropertiesFromPath = new ArrayList<Element>() ;
tmpVisiblePropertiesFromPath.addAll(new Visitor_GetOwnedAndImportedStatemachines().visit(nearestNamespace)) ;
for (Element e : tmpVisiblePropertiesFromPath) {
tmpVisibleElementsFromPath.add(e) ;
}
}
}
// builds the nested scope based on hierarchy and then inheritance
SimpleScope resultScope = null;
Iterable<IEObjectDescription> iterableIEobjectDescriptions ;
if (! tmpVisibleElementsFromPath.isEmpty()) {
iterableIEobjectDescriptions = Scopes.scopedElementsFor(tmpVisibleElementsFromPath) ;
resultScope = resultScope != null ? new SimpleScope(resultScope, iterableIEobjectDescriptions) : new SimpleScope(iterableIEobjectDescriptions) ;
}
return resultScope != null ? resultScope : new SimpleScope(Scopes.scopedElementsFor(new ArrayList<Element>())) ;
}
}
/**
* @param ctx
* @param ref
* @return scope
*/
public IScope scope_QualifiedName_path (QualifiedName ctx, EReference ref) {
List<Namespace> visibleNamespaces = new ArrayList<Namespace>() ;
if (ctx != null && ctx.eContainer() != null && ctx.eContainer() instanceof QualifiedName) {
Namespace parentNameSpace = ((QualifiedName)ctx.eContainer()).getPath() ;
visibleNamespaces.addAll(new Visitor_GetOwnedNamespacesAndImportedNamespaces().visit(parentNameSpace)) ;
}
else {
visibleNamespaces.add(UmlStateJavaValidator.getModel()) ;
visibleNamespaces.addAll(new Visitor_GetImportedNamespaces().visit(UmlStateJavaValidator.getModel())) ;
}
Iterable<IEObjectDescription> iterableIEobjectDescription = Scopes.scopedElementsFor(visibleNamespaces) ;
return new SimpleScope(iterableIEobjectDescription) ;
}
private class Visitor_GetImportedNamespaces {
public List<Namespace> visit(Namespace visited) {
List<Namespace> namespaces = new ArrayList<Namespace>() ;
// retrieves imported namespaces
for (PackageImport pImport : visited.getPackageImports()) {
namespaces.add(pImport.getImportedPackage()) ;
}
for (ElementImport eImport : visited.getElementImports()) {
if (eImport.getImportedElement() instanceof Namespace)
namespaces.add((Namespace)eImport.getImportedElement()) ;
}
return namespaces;
}
}
private class Visitor_GetOwnedNamespacesAndImportedNamespaces extends Visitor_GetImportedNamespaces {
@Override
public List<Namespace> visit(Namespace visited) {
List<Namespace> namespaces = new ArrayList<Namespace>() ;
// first retrieves imported namespaces
namespaces.addAll(super.visit(visited)) ;
// then retrieves owned namespaces
for (NamedElement n : visited.getOwnedMembers()) {
if (n instanceof Namespace)
namespaces.add((Namespace)n) ;
}
return namespaces;
}
}
private class Visitor_GetOwnedAndImportedStatemachines {
public List<Element> visit(Namespace visited) {
List<Element> visibleElements = new ArrayList<Element>() ;
// first retrieves imported statemachines
for (ElementImport eImport : visited.getElementImports()) {
if (eImport.getImportedElement() instanceof StateMachine)
visibleElements.add(eImport.getImportedElement()) ;
}
// then retrieves owned statemachines
for (Element n : visited.getOwnedElements()) {
if (n instanceof StateMachine)
visibleElements.add(n) ;
}
return visibleElements;
}
}
}