blob: b866483721f811fe24f6e2de1725282176410e27 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2011 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.operation.editor.xtext.scoping;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.papyrus.operation.editor.xtext.operation.FormalParameter;
import org.eclipse.papyrus.operation.editor.xtext.operation.Multiplicity;
import org.eclipse.papyrus.operation.editor.xtext.operation.OperationDeclaration;
import org.eclipse.papyrus.operation.editor.xtext.operation.OperationDefinitionOrStub;
import org.eclipse.papyrus.operation.editor.xtext.validation.OperationJavaValidator;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Reception;
import org.eclipse.uml2.uml.Signal;
import org.eclipse.uml2.uml.TemplateParameter;
import org.eclipse.uml2.uml.VisibilityKind;
public class OperationEditorScopingTool extends AbstractScopingTool {
private AlfPartialScope behaviorScope;
private AlfPartialScope classifierScope;
private AlfPartialScope packageScope;
private static List<EObject> removeDuplicateClassifiers(List<EObject> list) {
List<EObject> intermediateFilteredList = new ArrayList<EObject>();
HashMap<String, Classifier> classifiers = new HashMap<String, Classifier>();
HashMap<String, Classifier> elementImports = new HashMap<String, Classifier>();
for (EObject o : list) {
if (o instanceof Classifier) {
Classifier c = (Classifier) o;
if (classifiers.get(c.getQualifiedName()) == null) {
classifiers.put(c.getQualifiedName(), c);
intermediateFilteredList.add(c);
}
// else => nothing to be done, this is a duplicate
}
else if (o instanceof ElementImport) {
ElementImport e = (ElementImport) o;
Classifier c = (Classifier) e.getImportedElement();
if (elementImports.get(e.getAlias()) == null) {
elementImports.put(e.getAlias(), c);
intermediateFilteredList.add(e);
}
else {// need to check if element import aliases the same thing.
Classifier alreadyInTheList = elementImports.get(e.getAlias());
if (!alreadyInTheList.getQualifiedName().equals(c.getQualifiedName())) {
// The model is ill-formed, and there's no need to filter
intermediateFilteredList.add(e);
}
// else => nothing to be done, this is a duplicate
}
}
}
// needs to make a second pass on the filtered list, to remove cases where aliases and names are the same, and represent the same element
List<EObject> filteredList = new ArrayList<EObject>();
for (int i = 0; i < intermediateFilteredList.size(); i++) {
String classifierName = (intermediateFilteredList.get(i) instanceof Classifier) ?
((Classifier) intermediateFilteredList.get(i)).getName() :
((ElementImport) intermediateFilteredList.get(i)).getAlias();
String classifierQualifiedName = (intermediateFilteredList.get(i) instanceof Classifier) ?
((Classifier) intermediateFilteredList.get(i)).getQualifiedName() :
((Classifier) ((ElementImport) intermediateFilteredList.get(i)).getImportedElement()).getQualifiedName();
boolean duplicateFound = false;
for (int j = i + 1; j < intermediateFilteredList.size() && !duplicateFound; j++) {
String cddDuplicateClassifierName = (intermediateFilteredList.get(j) instanceof Classifier) ?
((Classifier) intermediateFilteredList.get(j)).getName() :
((ElementImport) intermediateFilteredList.get(j)).getAlias();
if (cddDuplicateClassifierName.equals(classifierName)) {
String cddDuplicateClassifierQualifiedName = (intermediateFilteredList.get(j) instanceof Classifier) ?
((Classifier) intermediateFilteredList.get(j)).getQualifiedName() :
((Classifier) ((ElementImport) intermediateFilteredList.get(j)).getImportedElement()).getQualifiedName();
if (cddDuplicateClassifierQualifiedName.equals(classifierQualifiedName)) {
duplicateFound = true;
}
}
}
if (!duplicateFound) {
filteredList.add(intermediateFilteredList.get(i));
}
}
return filteredList;
}
@Override
public AlfPartialScope getVisibleVariablesOrParametersOrProperties(EObject context) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new VariableOrParameterOrPropertyStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new VariableOrParameterOrPropertyStrategies().new BuildScopeStrategy();
AlfPartialScope variableOrParametersOrPropertiesScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
return variableOrParametersOrPropertiesScope;
}
@Override
public AlfPartialScope getVisibleOperationsOrBehaviors(EObject context) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new OperationAndBehaviorsStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new OperationAndBehaviorsStrategies().new BuildScopeStrategy();
AlfPartialScope operationScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
return operationScope;
}
@Override
public AlfPartialScope getVisibleBehaviors(EObject context) {
// if (behaviorScope == null) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new BehaviorsStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new BehaviorsStrategies().new BuildScopeStrategy();
behaviorScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
// }
return behaviorScope;
}
@Override
public AlfPartialScope getVisibleClassifiers(EObject context) {
// if (classifierScope == null) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new ClassifierStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new ClassifierStrategies().new BuildScopeStrategy();
classifierScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
// }
return classifierScope;
}
@Override
public AlfPartialScope getVisiblePackages(EObject context) {
if (context instanceof Package) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new PackagesStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new PackagesStrategies().new BuildScopeStrategy();
return new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
}
// if (packageScope == null) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new PackagesStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new PackagesStrategies().new BuildScopeStrategy();
packageScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
// }
return packageScope;
}
@Override
public boolean isAReturnStatementExpected(EObject context) {
EObject cddOperationDefinitionOrStub = context;
while (cddOperationDefinitionOrStub != null &&
!(cddOperationDefinitionOrStub instanceof OperationDefinitionOrStub)) {
cddOperationDefinitionOrStub = cddOperationDefinitionOrStub.eContainer();
}
if (cddOperationDefinitionOrStub == null) {
return false;
}
OperationDefinitionOrStub op = (OperationDefinitionOrStub) cddOperationDefinitionOrStub;
if (op.getDeclaration() != null && op.getDeclaration().getReturnType() != null) {
return true;
}
return false;
}
@Override
public TypeExpression getExpectedReturnType(EObject context) {
EObject cddOperationDefinitionOrStub = context;
while (!(cddOperationDefinitionOrStub instanceof OperationDefinitionOrStub)) {
cddOperationDefinitionOrStub = cddOperationDefinitionOrStub.eContainer();
}
OperationDefinitionOrStub op = (OperationDefinitionOrStub) cddOperationDefinitionOrStub;
if (op.getDeclaration() != null && op.getDeclaration().getReturnType() != null) {
QualifiedNameWithBinding expectedReturnType = op.getDeclaration().getReturnType().getTypeName().getQualifiedName();
TypeFacade type = TypeFacadeFactory.eInstance.createVoidFacade(expectedReturnType);
Multiplicity expectedReturnMultiplicity = op.getDeclaration().getReturnType().getMultiplicity();
int lower = 1;
int upper = 1;
boolean isUnique = true;
boolean isOrdered = false;
if (expectedReturnMultiplicity != null) {
MultiplicityFacade multiplicity = MultiplicityFacadeFactory.eInstance.createMultiplicityFacade(expectedReturnMultiplicity);
lower = multiplicity.getLowerBound();
upper = multiplicity.getUpperBound();
isUnique = multiplicity.isUnique();
isOrdered = multiplicity.isOrdered();
}
TypeExpression typeExp = TypeExpressionFactory.eInstance.createTypeExpression(type, lower, upper, isUnique, isOrdered);
return typeExp;
}
return null;
}
@Override
public AlfPartialScope getVisibleSignalReceptions(EObject context) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new ReceptionsStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new ReceptionsStrategies().new BuildScopeStrategy();
return new AlfPartialScope(nameStrategy, buildScopeStrategy, context);
}
/*
* Class encapsulating scoping strategies for this editor
*/
protected class OperationEditorScopingStrategies {
/*
* Strategies for operations
*/
protected class OperationAndBehaviorsStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof Operation) {
return ((Operation) element).getName();
} else if (element instanceof OperationDeclaration) {
return ((OperationDeclaration) element).getName();
} else if (element instanceof Behavior) {
return ((Behavior) element).getName();
} else if (element instanceof ElementImport) {
ElementImport eImport = (ElementImport) element;
if (eImport.getAlias() != null) {
return eImport.getAlias();
} else {
return ((Behavior) eImport.getImportedElement()).getName();
}
} else {
return "Unexpected element kind...";
}
}
};
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
// in the case where the context element is a Package or an ElementImport for a package, the scope can only contain behaviors
Package potentialContextPackage = null;
if (contextElement instanceof Package) {
potentialContextPackage = (Package) contextElement;
}
else if (contextElement instanceof ElementImport) {
ElementImport eImport = (ElementImport) contextElement;
if (eImport.getImportedElement() instanceof Package) {
potentialContextPackage = (Package) eImport.getImportedElement();
}
}
if (potentialContextPackage != null) {
// if (behaviorScope == null) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new BehaviorsStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new BehaviorsStrategies().new BuildScopeStrategy();
behaviorScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, contextElement);
// }
for (List<EObject> scope : behaviorScope.getScopeDetails()) {
nestedScopes.add(scope);
}
return nestedScopes;
}
// At this point, we have identified that the context element is not a package.
// First scoping levels concern operations
// retrieves the contextOperation (i.e., the operation edited by the current editor)
Operation contextOperation = (Operation) OperationJavaValidator.getContextElement();
// retrieves the contextClassier (i.e. the owner of the contextOperation, or contextElement)
Classifier contextClassifier;
if (contextElement instanceof Classifier) {
contextClassifier = (Classifier) contextElement;
}
else if (contextElement instanceof ElementImport && ((ElementImport) contextElement).getImportedElement() instanceof Classifier) {
contextClassifier = (Classifier) ((ElementImport) contextElement).getImportedElement();
}
else {
contextClassifier = (Classifier) contextOperation.getNamespace();
}
// add all the operations owned by the context classifier at the first scoping level
nestedList.addAll(contextClassifier.getOperations());
// if the contextElement is not a class
// removes the potential contextOperation, in order to replace it by the OperationDeclaration of the current editor
if (!((contextElement instanceof Classifier) || ((contextElement instanceof ElementImport && ((ElementImport) contextElement).getImportedElement() instanceof Classifier)))) {
nestedList.remove(contextOperation);
EObject cddOperationDefinitionOrStub = contextElement;
while (cddOperationDefinitionOrStub != null && !(cddOperationDefinitionOrStub instanceof OperationDefinitionOrStub)) {
cddOperationDefinitionOrStub = cddOperationDefinitionOrStub.eContainer();
}
if (cddOperationDefinitionOrStub != null) {
OperationDeclaration declaration = ((OperationDefinitionOrStub) cddOperationDefinitionOrStub).getDeclaration();
nestedList.add(declaration);
} else {
nestedList.add(contextOperation);
}
}
nestedScopes.add(nestedList);
// then builds other scoping levels based on context classifier inheritance hierarchy
List<Classifier> currentGenerals = new ArrayList<Classifier>();
currentGenerals.addAll(contextClassifier.getGenerals());
List<Classifier> nextGenerals;
while (!currentGenerals.isEmpty()) {
nextGenerals = new ArrayList<Classifier>();
nestedList = new ArrayList<EObject>();
for (Classifier general : currentGenerals) {
nextGenerals.addAll(general.getGenerals());
for (Operation o : general.getOperations()) {
nestedList.add(o);
}
}
nestedScopes.add(nestedList);
currentGenerals = nextGenerals;
}
// finally feeds last scoping levels with behaviors (only if contextElement is not a Class)
if (!((contextElement instanceof Classifier) || ((contextElement instanceof ElementImport && ((ElementImport) contextElement).getImportedElement() instanceof Classifier)))) {
if (behaviorScope == null) {
AlfPartialScope.IGetNameStrategy nameStrategy = new OperationEditorScopingStrategies().new BehaviorsStrategies().new NameStrategy();
AlfPartialScope.IBuildScopeStrategy buildScopeStrategy = new OperationEditorScopingStrategies().new BehaviorsStrategies().new BuildScopeStrategy();
behaviorScope = new AlfPartialScope(nameStrategy, buildScopeStrategy, contextElement);
}
for (List<EObject> scope : behaviorScope.getScopeDetails()) {
nestedScopes.add(scope);
}
}
return nestedScopes;
}
};
}
/*
* Strategies for Receptions
*/
protected class ReceptionsStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof Signal) {
return ((Signal) element).getName();
} else {
return "Unexpected element kind...";
}
}
};
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
// retrieves the contextOperation (i.e., the operation edited by the current editor)
Operation contextOperation = (Operation) OperationJavaValidator.getContextElement();
// retrieves the owner of the contextOperation
Classifier contextClassifier = (Classifier) contextOperation.getNamespace();
if (!(contextClassifier instanceof org.eclipse.uml2.uml.Class)) {
nestedScopes.add(nestedList);
return nestedScopes;
}
// add all the signals for which a Reception is defined
for (org.eclipse.uml2.uml.Feature f : contextClassifier.allFeatures()) {
if (f instanceof Reception) {
if (((Reception) f).getSignal() != null) {
nestedList.add(((Reception) f).getSignal());
}
}
}
nestedScopes.add(nestedList);
return nestedScopes;
}
};
}
/*
* Strategies for Variables, Parameters and Properties
*/
protected class VariableOrParameterOrPropertyStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof Property) {
return ((Property) element).getName();
} else if (element instanceof FormalParameter) {
String formalParameterName = ((FormalParameter) element).getName();
if (formalParameterName.startsWith("\'")) {
formalParameterName = formalParameterName.substring(1, formalParameterName.length() - 1);
}
return formalParameterName;
}
else if (element instanceof LocalNameDeclarationStatement) {
return ((LocalNameDeclarationStatement) element).getVarName();
}
else if (element instanceof InvocationOrAssignementOrDeclarationStatement) {
InvocationOrAssignementOrDeclarationStatement statement = (InvocationOrAssignementOrDeclarationStatement) element;
return statement.getVariableDeclarationCompletion() != null ?
statement.getVariableDeclarationCompletion().getVariableName() :
"";
}
else if (element instanceof LoopVariableDefinition) {
return ((LoopVariableDefinition) element).getName();
}
else if (element instanceof AcceptClause) {
return ((AcceptClause) element).getName();
}
else if (element instanceof AcceptStatement) {
return ((AcceptStatement) element).getClause().getName();
}
else if (element instanceof SequenceExpansionExpression) {
SequenceExpansionExpression expression = (SequenceExpansionExpression) element;
return expression.getName() != null ?
expression.getName() :
"";
}
return "unexpected kind ...";
}
}
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
// first checks if the context element is a Classifier
if (contextElement instanceof Classifier) {
// then builds a nested scope containing properties visible from this classifier (i.e., owned or inherited)
// following levels of scoping concern Properties visible from the context operation (i.e. those who belong to the context classifier or its parents)
Classifier contextClassifier = (Classifier) contextElement;
nestedList = new ArrayList<EObject>();
nestedList.addAll(contextClassifier.getAttributes());
nestedScopes.add(nestedList);
List<Classifier> currentGenerals = new ArrayList<Classifier>();
currentGenerals.addAll(contextClassifier.getGenerals());
List<Classifier> nextGenerals;
while (!currentGenerals.isEmpty()) {
nextGenerals = new ArrayList<Classifier>();
nestedList = new ArrayList<EObject>();
for (Classifier general : currentGenerals) {
nextGenerals.addAll(general.getGenerals());
for (Property p : general.getAttributes()) {
if (p.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
nestedList.add(p);
}
}
}
nestedScopes.add(nestedList);
currentGenerals = nextGenerals;
}
return nestedScopes;
}
// the first level of scoping contains SequenceExpansionExpression local variables, LocalVariableDefinitions and FormalParameters of the operation
// checks if the expression is nested inside a SequenceExpansionExpression
EObject cddContextExpression = contextElement;
boolean goOn = true;
do {
while (cddContextExpression != null && !(cddContextExpression instanceof Expression)) {
cddContextExpression = cddContextExpression.eContainer();
}
if (cddContextExpression != null) {
if (cddContextExpression.eContainer() instanceof SequenceExpansionExpression) {
nestedList.add(cddContextExpression.eContainer());
goOn = false;
}
else if (cddContextExpression.eContainer() instanceof TupleElement ||
cddContextExpression.eContainer() instanceof PropertyCallExpression ||
cddContextExpression.eContainer() instanceof ParenthesizedExpression) {
cddContextExpression = cddContextExpression.eContainer();
}
else {
goOn = false;
}
}
else {
goOn = false;
}
} while (goOn == true);
// Following statement address LocalVariableDefinitions
// First retrieve the inner most statement encapsulating the context eObject
EObject cddInnerMostStatement = contextElement;
Statement innerMostStatement;
while (cddInnerMostStatement != null && !(cddInnerMostStatement instanceof Statement)) {
cddInnerMostStatement = cddInnerMostStatement.eContainer();
}
if (cddInnerMostStatement != null) {
innerMostStatement = (Statement) cddInnerMostStatement;
DocumentedStatement owningDocumentedStatement = (DocumentedStatement) innerMostStatement.eContainer();
List<DocumentedStatement> containingListOfDocumentedStatement = new ArrayList<DocumentedStatement>();
if (owningDocumentedStatement.eContainer() instanceof NonEmptyStatementSequence) {
containingListOfDocumentedStatement.addAll(((NonEmptyStatementSequence) owningDocumentedStatement.eContainer()).getStatement());
}
else {
containingListOfDocumentedStatement.addAll(((StatementSequence) owningDocumentedStatement.eContainer()).getStatements());
}
for (int i = containingListOfDocumentedStatement.indexOf(owningDocumentedStatement) - 1; i >= 0; i--) {
DocumentedStatement previousDocumentStatement = containingListOfDocumentedStatement.get(i);
if (containsALocalNameDeclaration(previousDocumentStatement)) {
nestedList.add(previousDocumentStatement.getStatement());
}
}
// hierarchically navigates over the innermost statement to retrieve all local variable definitions
cddInnerMostStatement = innerMostStatement.eContainer().eContainer();
while (!(cddInnerMostStatement instanceof OperationDefinitionOrStub)) {
if (cddInnerMostStatement instanceof ForStatement) {
nestedList.addAll(((ForStatement) cddInnerMostStatement).getControl().getLoopVariableDefinition());
innerMostStatement = (Statement) cddInnerMostStatement;
owningDocumentedStatement = (DocumentedStatement) innerMostStatement.eContainer();
containingListOfDocumentedStatement = new ArrayList<DocumentedStatement>();
if (owningDocumentedStatement.eContainer() instanceof NonEmptyStatementSequence) {
containingListOfDocumentedStatement.addAll(((NonEmptyStatementSequence) owningDocumentedStatement.eContainer()).getStatement());
}
else {
containingListOfDocumentedStatement.addAll(((StatementSequence) owningDocumentedStatement.eContainer()).getStatements());
}
for (int i = containingListOfDocumentedStatement.indexOf(owningDocumentedStatement); i >= 0; i--) {
DocumentedStatement previousDocumentStatement = containingListOfDocumentedStatement.get(i);
if (containsALocalNameDeclaration(previousDocumentStatement)) {
nestedList.add(previousDocumentStatement.getStatement());
}
}
cddInnerMostStatement = innerMostStatement.eContainer();
}
else if (cddInnerMostStatement instanceof AcceptBlock) {
AcceptBlock acceptBlock = (AcceptBlock) cddInnerMostStatement;
if (acceptBlock.getClause().getName() != null) {
nestedList.add(acceptBlock.getClause());
}
}
else if (cddInnerMostStatement instanceof CompoundAcceptStatementCompletion) {
CompoundAcceptStatementCompletion completion = (CompoundAcceptStatementCompletion) cddInnerMostStatement;
AcceptStatement container = (AcceptStatement) completion.eContainer();
if (container.getClause().getName() != null) {
nestedList.add(container.getClause());
}
}
else if (cddInnerMostStatement instanceof Statement) {
innerMostStatement = (Statement) cddInnerMostStatement;
owningDocumentedStatement = (DocumentedStatement) innerMostStatement.eContainer();
containingListOfDocumentedStatement = new ArrayList<DocumentedStatement>();
if (owningDocumentedStatement.eContainer() instanceof NonEmptyStatementSequence) {
containingListOfDocumentedStatement.addAll(((NonEmptyStatementSequence) owningDocumentedStatement.eContainer()).getStatement());
}
else {
containingListOfDocumentedStatement.addAll(((StatementSequence) owningDocumentedStatement.eContainer()).getStatements());
}
for (int i = containingListOfDocumentedStatement.indexOf(owningDocumentedStatement); i >= 0; i--) {
DocumentedStatement previousDocumentStatement = containingListOfDocumentedStatement.get(i);
if (containsALocalNameDeclaration(previousDocumentStatement)) {
nestedList.add(previousDocumentStatement.getStatement());
}
}
cddInnerMostStatement = innerMostStatement.eContainer();
}
cddInnerMostStatement = cddInnerMostStatement.eContainer();
}
}
// Following statement address FormalParameters
// first retrieve the context OperationDeclaration from the edited text
OperationDeclaration declaration = ((OperationDefinitionOrStub) cddInnerMostStatement).getDeclaration();
if (declaration.getFormalParameters().getFormalParameterList() != null) {
for (FormalParameter p : declaration.getFormalParameters().getFormalParameterList().getFormalParameter()) {
nestedList.add(p);
}
}
nestedScopes.add(nestedList);
// following levels of scoping concern Properties visible from the context operation (i.e. those who belong to the context classifier or its parents)
Operation contextOperation = (Operation) OperationJavaValidator.getContextElement();
Classifier contextClassifier = (Classifier) contextOperation.getNamespace();
nestedList = new ArrayList<EObject>();
nestedList.addAll(contextClassifier.getAttributes());
nestedScopes.add(nestedList);
List<Classifier> currentGenerals = new ArrayList<Classifier>();
currentGenerals.addAll(contextClassifier.getGenerals());
List<Classifier> nextGenerals;
while (!currentGenerals.isEmpty()) {
nextGenerals = new ArrayList<Classifier>();
nestedList = new ArrayList<EObject>();
for (Classifier general : currentGenerals) {
nextGenerals.addAll(general.getGenerals());
for (Property p : general.getAttributes()) {
if (p.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
nestedList.add(p);
}
}
}
nestedScopes.add(nestedList);
currentGenerals = nextGenerals;
}
return nestedScopes;
}
}
public boolean containsALocalNameDeclaration(DocumentedStatement previousDocumentStatement) {
Statement statement = previousDocumentStatement.getStatement();
if (statement instanceof LocalNameDeclarationStatement) {
return true;
}
if (statement instanceof InvocationOrAssignementOrDeclarationStatement) {
// TODO : handle cases with implicit declarations, e.g., v = 14 ; // v is a variable of type Integer
InvocationOrAssignementOrDeclarationStatement cddDclStatement = (InvocationOrAssignementOrDeclarationStatement) statement;
if (cddDclStatement.getVariableDeclarationCompletion() != null) {
return true;
}
}
if (statement instanceof AcceptStatement) {
AcceptStatement cddDclStatement = (AcceptStatement) statement;
if (cddDclStatement.getSimpleAccept() != null && cddDclStatement.getClause().getName() != null) {
return true;
}
}
return false;
}
}
/*
* Strategies for Classifiers
*/
protected class ClassifierStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof Classifier) {
return ((Classifier) element).getName();
} else if (element instanceof ElementImport) {
ElementImport imported = (ElementImport) element;
return imported.getAlias() != null ? imported.getAlias() : ((Classifier) imported.getImportedElement()).getName();
} else {
return "Unexpected element kind...";
}
}
};
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
// first checks if contextElement represents a Package. In this case, builds a scope containing all classifiers visible from this package
Package potentialContextPackage = null;
if (contextElement instanceof Package) {
potentialContextPackage = (Package) contextElement;
} else if (contextElement instanceof ElementImport) {
ElementImport eImport = (ElementImport) contextElement;
if (eImport.getImportedElement() instanceof Package) {
potentialContextPackage = (Package) eImport.getImportedElement();
}
}
if (potentialContextPackage != null) {
List<EObject> importedClassifiers = processPublicallyImportedClassifiers(potentialContextPackage);
importedClassifiers = removeDuplicateClassifiers(importedClassifiers);
nestedScopes.add(importedClassifiers);
return nestedScopes;
}
// retrieves the contextOperation (i.e., the operation edited by the current editor)
Operation contextOperation = (Operation) OperationJavaValidator.getContextElement();
// retrieves the owner of the contextOperation
Classifier contextClassifier = (Classifier) contextOperation.getNamespace();
// add the context classifier at the first scoping level
nestedList.add(contextClassifier);
// retrieves all package imports, and add all classifiers available at the root of this package
for (PackageImport i : contextClassifier.getPackageImports()) {
Package importedPackage = i.getImportedPackage();
nestedList.addAll(processPublicallyImportedClassifiers(importedPackage));
}
// retrieves all element imports. For those which concern a Classifier, either add the classifier if no alias is defined, or the element import if an alias is defined
for (ElementImport i : contextClassifier.getElementImports()) {
PackageableElement e = i.getImportedElement();
if (e instanceof Classifier) {
if (i.getAlias() != null) {
nestedList.add(i);
} else {
nestedList.add(e);
}
}
}
nestedList = removeDuplicateClassifiers(nestedList);
nestedScopes.add(nestedList);
// Then process the implicit import of alf library
nestedList = new ArrayList<EObject>();
if (AlfJavaValidator.getAlfStandardLibrary() != null) {
List<EObject> importedClassifiers = processPublicallyImportedClassifiers(AlfJavaValidator.getAlfStandardLibrary());
/**
* to be uncommented when templates are supported
* importedClassifiers.add(TypeUtils._Collection.extractActualType()) ;
* importedClassifiers.add(TypeUtils._Set.extractActualType()) ;
* importedClassifiers.add(TypeUtils._Bag.extractActualType()) ;
* importedClassifiers.add(TypeUtils._Queue.extractActualType()) ;
* importedClassifiers.add(TypeUtils._OrderedSet.extractActualType()) ;
* importedClassifiers.add(TypeUtils._List.extractActualType()) ;
* importedClassifiers.add(TypeUtils._Deque.extractActualType()) ;
* importedClassifiers.add(TypeUtils._Map.extractActualType()) ;
* importedClassifiers.add(TypeUtils._Entry.extractActualType()) ;
*/
nestedList.addAll(removeDuplicateClassifiers(importedClassifiers));
nestedScopes.add(nestedList);
}
return nestedScopes;
}
private List<EObject> processPublicallyImportedClassifiers(Package p) {
List<EObject> importedClassifiers = new ArrayList<EObject>();
for (NamedElement n : p.getOwnedMembers()) {
if (n instanceof Classifier) {
if (((Classifier) n).getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
importedClassifiers.add(n);
}
}
}
for (ElementImport eImport : p.getElementImports()) {
if (eImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
PackageableElement element = eImport.getImportedElement();
if (element instanceof Classifier) {
if (eImport.getAlias() != null) {
importedClassifiers.add(eImport);
}
else {
importedClassifiers.add(element);
}
}
}
}
for (PackageImport pImport : p.getPackageImports()) {
if (pImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
importedClassifiers.addAll(processPublicallyImportedClassifiers(pImport.getImportedPackage()));
}
}
return importedClassifiers;
}
};
}
/*
* Strategies for Packages
*/
protected class PackagesStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof Namespace) {
return ((Namespace) element).getName();
} else if (element instanceof ElementImport) {
ElementImport eImport = (ElementImport) element;
return eImport.getAlias() != null ? eImport.getAlias() : eImport.getImportedElement().getName();
} else {
return "Unexpected element kind...";
}
}
}
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
if (contextElement instanceof Package) { // if the context element is a package, returns the scope related to this package.
nestedScopes.add(processPublicallyImportedPackages((Package) contextElement));
return nestedScopes;
}
Package root = (Package) OperationJavaValidator.getModel();
// first process packages directly imported by the context classifier (either package import or element import)
Operation contextOperation = (Operation) OperationJavaValidator.getContextElement();
Classifier contextClassifier = (Classifier) contextOperation.getNamespace();
nestedList.addAll(processPublicallyImportedPackages(contextClassifier));
nestedScopes.add(nestedList);
// Then process the implicit import of alf library
nestedList = new ArrayList<EObject>();
if (AlfJavaValidator.getAlfStandardLibrary() != null) {
nestedList.add(AlfJavaValidator.getAlfStandardLibrary());
nestedList.addAll(processPublicallyImportedPackages(AlfJavaValidator.getAlfStandardLibrary()));
nestedScopes.add(nestedList);
}
// finally processes the root package
nestedList = new ArrayList<EObject>();
nestedList.add(root);
nestedScopes.add(nestedList);
return nestedScopes;
}
private List<EObject> processPublicallyImportedPackages(Namespace namespace) {
List<EObject> importedPackages = new ArrayList<EObject>();
for (NamedElement ownedMember : namespace.getOwnedMembers()) {
if (ownedMember.getVisibility() != VisibilityKind.PRIVATE_LITERAL && ownedMember instanceof Package) {
importedPackages.add(ownedMember);
}
}
for (ElementImport eImport : namespace.getElementImports()) {
if (eImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
PackageableElement importedElement = eImport.getImportedElement();
if (importedElement instanceof Package) {
if (eImport.getAlias() != null) {
importedPackages.add(eImport);
} else {
importedPackages.add(importedElement);
}
}
}
}
for (PackageImport pImport : namespace.getPackageImports()) {
if (pImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
importedPackages.addAll(processPublicallyImportedPackages(pImport.getImportedPackage()));
}
}
return importedPackages;
}
}
}
/*
* Strategies for Behaviors
*/
protected class BehaviorsStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof Behavior) {
return ((Behavior) element).getName();
} else if (element instanceof ElementImport) {
ElementImport imported = (ElementImport) element;
return imported.getAlias() != null ? imported.getAlias() : ((Behavior) imported.getImportedElement()).getName();
} else {
return "Unexpected element kind...";
}
}
};
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
// first checks if contextElement represents a Package. In this case, builds a scope containing all behaviors visible from this package
Package potentialContextPackage = null;
if (contextElement instanceof Package) {
potentialContextPackage = (Package) contextElement;
} else if (contextElement instanceof ElementImport) {
ElementImport eImport = (ElementImport) contextElement;
if (eImport.getImportedElement() instanceof Package) {
potentialContextPackage = (Package) eImport.getImportedElement();
}
}
if (potentialContextPackage != null) {
nestedScopes.add(processPublicallyImportedBehaviors(potentialContextPackage));
return nestedScopes;
}
// retrieves the contextOperation (i.e., the operation edited by the current editor)
Operation contextOperation = (Operation) OperationJavaValidator.getContextElement();
// retrieves the owner of the contextOperation
Classifier contextClassifier = (Classifier) contextOperation.getNamespace();
// retrieves all package imports, and add all behaviors available at the root of this package
for (PackageImport i : contextClassifier.getPackageImports()) {
Package importedPackage = i.getImportedPackage();
nestedList.addAll(processPublicallyImportedBehaviors(importedPackage));
}
// retrieves all element imports. For those which concern a Behavior, either add the behavior if no alias is defined, or the element import if an alias is defined
for (ElementImport i : contextClassifier.getElementImports()) {
PackageableElement e = i.getImportedElement();
if (e instanceof Classifier) {
if (i.getAlias() != null) {
nestedList.add(i);
} else {
nestedList.add(e);
}
}
}
nestedList = removeDuplicateClassifiers(nestedList);
nestedScopes.add(nestedList);
// Then process the implicit import of alf library
nestedList = new ArrayList<EObject>();
if (AlfJavaValidator.getAlfStandardLibrary() != null) {
List<EObject> importedClassifiers = processPublicallyImportedBehaviors(AlfJavaValidator.getAlfStandardLibrary());
importedClassifiers = removeDuplicateClassifiers(importedClassifiers);
nestedList.addAll(importedClassifiers);
nestedScopes.add(nestedList);
}
return nestedScopes;
}
private List<EObject> processPublicallyImportedBehaviors(Package p) {
List<EObject> importedBehaviors = new ArrayList<EObject>();
for (NamedElement n : p.getOwnedMembers()) {
if (n instanceof Behavior) {
if (((Behavior) n).getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
importedBehaviors.add(n);
}
}
else if (n instanceof Package) {
importedBehaviors.addAll(processPublicallyImportedBehaviors((Package) n));
}
}
for (ElementImport eImport : p.getElementImports()) {
if (eImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
PackageableElement element = eImport.getImportedElement();
if (element instanceof Behavior) {
if (eImport.getAlias() != null) {
importedBehaviors.add(eImport);
} else {
importedBehaviors.add(element);
}
}
}
}
for (PackageImport pImport : p.getPackageImports()) {
if (pImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
importedBehaviors.addAll(processPublicallyImportedBehaviors(pImport.getImportedPackage()));
}
}
return importedBehaviors;
}
};
}
/*
* Strategies for Template Parameters
*/
protected class TemplateParameterStrategies {
protected class NameStrategy implements AlfPartialScope.IGetNameStrategy {
public String getName(EObject element) {
if (element instanceof TemplateParameter) {
TemplateParameter param = (TemplateParameter) element;
Classifier classifierParam = (Classifier) param.getParameteredElement();
if (classifierParam != null) {
return classifierParam.getName();
}
}
return "Unexpected element kind...";
}
}
protected class BuildScopeStrategy implements AlfPartialScope.IBuildScopeStrategy {
public List<List<EObject>> buildScope(EObject contextElement) {
List<List<EObject>> nestedScopes = new ArrayList<List<EObject>>();
List<EObject> nestedList = new ArrayList<EObject>();
if (contextElement instanceof Classifier) {
Classifier classifierParam = (Classifier) contextElement;
// TODO classifierParam.get
return nestedScopes;
}
// else
nestedScopes.add(nestedList);
return nestedScopes;
}
private List<EObject> processPublicallyImportedPackages(Namespace namespace) {
List<EObject> importedPackages = new ArrayList<EObject>();
for (NamedElement ownedMember : namespace.getOwnedMembers()) {
if (ownedMember.getVisibility() != VisibilityKind.PRIVATE_LITERAL && ownedMember instanceof Package) {
importedPackages.add(ownedMember);
}
}
for (ElementImport eImport : namespace.getElementImports()) {
if (eImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
PackageableElement importedElement = eImport.getImportedElement();
if (importedElement instanceof Package) {
if (eImport.getAlias() != null) {
importedPackages.add(eImport);
} else {
importedPackages.add(importedElement);
}
}
}
}
for (PackageImport pImport : namespace.getPackageImports()) {
if (pImport.getVisibility() != VisibilityKind.PRIVATE_LITERAL) {
importedPackages.addAll(processPublicallyImportedPackages(pImport.getImportedPackage()));
}
}
return importedPackages;
}
}
}
}
@Override
public AlfPartialScope getVisibleFormalParameters(TypeFacade context) {
// TODO Auto-generated method stub
return null;
}
}