/*******************************************************************************
* Copyright (c) 2012, 2015 Willink Transformations and others.
* 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:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.xtext.essentialocl.attributes;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.utilities.FeatureFilter;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.xtext.basecs.PathElementCS;
import org.eclipse.ocl.xtext.basecs.PathNameCS;
import org.eclipse.ocl.xtext.essentialoclcs.AbstractNameExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.ExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.InfixExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.NameExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.NavigatingArgCS;
import org.eclipse.ocl.xtext.essentialoclcs.NavigationRole;
import org.eclipse.ocl.xtext.essentialoclcs.OperatorExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.RoundBracketedClauseCS;
public class NavigationUtil
{
/**
* Return the NavigationOperatorCS for which csExp is the left node of the navigation operator's argument tree.
*/
public static @Nullable InfixExpCS getNavigationInfixExp(@NonNull AbstractNameExpCS csExp) {
EObject eContainer = csExp.eContainer();
if (eContainer instanceof NameExpCS) {
csExp = (NameExpCS) eContainer;
}
for (ExpCS csChild = csExp; true; csChild = csChild.getLocalParent()) {
if (csChild == null) {
return null;
}
OperatorExpCS csOperator = csChild.getLocalParent();
if (csOperator == null) {
return null;
}
ExpCS csSource = csOperator.getSource();
if (csSource == csChild) { // e.g. ... -> (X... -> ...)
;
}
else if (isNavigationInfixExp(csOperator)) { // e.g ... -> X
return (InfixExpCS) csOperator;
}
else { // e.g. ... and X
return null;
}
}
}
public static boolean isIteration(@NonNull PivotMetamodelManager metamodelManager, @NonNull RoundBracketedClauseCS csRoundBracketedClause, @NonNull CollectionType type) {
for (NavigatingArgCS csArg : csRoundBracketedClause.getOwnedArguments()) {
if (csArg.getRole() != NavigationRole.EXPRESSION) {
return true;
}
}
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
PathNameCS pathName = csNameExp.getOwnedPathName();
List<PathElementCS> path = pathName.getOwnedPathElements();
if (path.size() != 1) {
return false;
}
PathElementCS csPathElement = path.get(0);
Element unresolvedElement = csPathElement.basicGetReferredElement();
if ((unresolvedElement != null) && !unresolvedElement.eIsProxy()) {
return unresolvedElement instanceof Iteration;
}
String name = csPathElement.toString();
assert name != null;
for (Operation operation : metamodelManager.getAllOperations(type, FeatureFilter.SELECT_NON_STATIC, name)) {
return operation instanceof Iteration; // mixed overload are not allowed
}
return false;
}
public static boolean isNavigationInfixExp(@Nullable EObject eObject) {
if (eObject instanceof InfixExpCS) {
String name = ((InfixExpCS)eObject).getName();
return isNavigationOperator(name);
}
else {
return false;
}
}
public static boolean isNavigationOperator(String name) { // FIXME Use the grammar production
return PivotConstants.OBJECT_NAVIGATION_OPERATOR.equals(name)
|| PivotConstants.AGGREGATE_NAVIGATION_OPERATOR.equals(name)
|| PivotConstants.SAFE_OBJECT_NAVIGATION_OPERATOR.equals(name)
|| PivotConstants.SAFE_AGGREGATE_NAVIGATION_OPERATOR.equals(name)
|| "^".equals(name)
|| "^^".equals(name);
}
}