blob: d01df054c6660c1c59630a08102801b8571432e7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.utilities;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Annotation;
import org.eclipse.ocl.pivot.BooleanLiteralExp;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionLiteralPart;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.Constraint;
import org.eclipse.ocl.pivot.Detail;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.EnumLiteralExp;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.Feature;
import org.eclipse.ocl.pivot.FinalState;
import org.eclipse.ocl.pivot.IfExp;
import org.eclipse.ocl.pivot.IntegerLiteralExp;
import org.eclipse.ocl.pivot.InvalidLiteralExp;
import org.eclipse.ocl.pivot.IteratorExp;
import org.eclipse.ocl.pivot.LambdaType;
import org.eclipse.ocl.pivot.LetExp;
import org.eclipse.ocl.pivot.LoopExp;
import org.eclipse.ocl.pivot.MapLiteralExp;
import org.eclipse.ocl.pivot.MapLiteralPart;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.NullLiteralExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.OppositePropertyCallExp;
import org.eclipse.ocl.pivot.PivotPackage;
import org.eclipse.ocl.pivot.Precedence;
import org.eclipse.ocl.pivot.PrimitiveType;
import org.eclipse.ocl.pivot.ProfileApplication;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.PropertyCallExp;
import org.eclipse.ocl.pivot.Pseudostate;
import org.eclipse.ocl.pivot.RealLiteralExp;
import org.eclipse.ocl.pivot.ShadowExp;
import org.eclipse.ocl.pivot.State;
import org.eclipse.ocl.pivot.StereotypeExtender;
import org.eclipse.ocl.pivot.StringLiteralExp;
import org.eclipse.ocl.pivot.TemplateBinding;
import org.eclipse.ocl.pivot.TemplateParameter;
import org.eclipse.ocl.pivot.TemplateParameterSubstitution;
import org.eclipse.ocl.pivot.TemplateSignature;
import org.eclipse.ocl.pivot.TemplateableElement;
import org.eclipse.ocl.pivot.Transition;
import org.eclipse.ocl.pivot.TupleLiteralExp;
import org.eclipse.ocl.pivot.TupleType;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
import org.eclipse.ocl.pivot.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.internal.utilities.AS2Moniker;
import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.util.AbstractExtendingVisitor;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.values.Unlimited;
public class AS2MonikerVisitor extends AbstractExtendingVisitor<Object, AS2Moniker> implements PivotConstantsInternal
{
private static boolean initialized = false;
@Deprecated // The TPS policy pursued here is suspect
private static @Nullable Map<TemplateParameter, Type> getAllTemplateParameterSubstitutions(@Nullable Map<TemplateParameter, Type> map,
@Nullable TemplateableElement templateableElement) {
for (EObject eObject = templateableElement; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof TemplateableElement) {
for (TemplateBinding templateBinding : ((TemplateableElement) eObject).getOwnedBindings()) {
for (TemplateParameterSubstitution templateParameterSubstitution : templateBinding.getOwnedSubstitutions()) {
if (map == null) {
map = new HashMap<TemplateParameter, Type>();
}
map.put(templateParameterSubstitution.getFormal(), templateParameterSubstitution.getActual());
}
}
}
if (eObject instanceof org.eclipse.ocl.pivot.Class) {
for (org.eclipse.ocl.pivot.Class superType : ((org.eclipse.ocl.pivot.Class)eObject).getSuperClasses()) {
map = getAllTemplateParameterSubstitutions(map, superType);
}
}
}
return map;
}
public static void initialize() {
if (!initialized) {
initialized = true;
roleNames.put(PivotPackage.Literals.LOOP_EXP__OWNED_BODY, "argument");
// roleNames.put(PivotPackage.Literals.EXPRESSION_IN_OCL__BODY_EXPRESSION, "ownedExpression");
/* roleNames.put(PivotPackage.Literals.CALL_EXP__SOURCE, "s");
roleNames.put(PivotPackage.Literals.CONSTRAINT__SPECIFICATION, "z");
roleNames.put(PivotPackage.Literals.EXPRESSION_IN_OCL__BODY_EXPRESSION, "x");
roleNames.put(PivotPackage.Literals.IF_EXP__CONDITION, "q");
roleNames.put(PivotPackage.Literals.IF_EXP__THEN_EXPRESSION, "t");
roleNames.put(PivotPackage.Literals.IF_EXP__ELSE_EXPRESSION, "f");
roleNames.put(PivotPackage.Literals.LET_EXP__IN, "i");
roleNames.put(PivotPackage.Literals.LET_EXP__VARIABLE, "v");
roleNames.put(PivotPackage.Literals.LOOP_EXP__BODY, "b");
roleNames.put(PivotPackage.Literals.LOOP_EXP__ITERATOR, "i");
roleNames.put(PivotPackage.Literals.OPERATION_CALL_EXP__ARGUMENT, "a");
roleNames.put(PivotPackage.Literals.VARIABLE__INIT_EXPRESSION, "i");
*/ }
}
protected final @Nullable Map<TemplateParameter, Type> templateBindings;
public AS2MonikerVisitor(@NonNull AS2Moniker context) {
super(context);
templateBindings = null;
if (!initialized) {
initialize();
}
}
public AS2MonikerVisitor(@NonNull AS2Moniker context, @Nullable Map<TemplateParameter, Type> templateBindings) {
super(context);
this.templateBindings = templateBindings;
}
public void appendExpPrefix(@NonNull NamedElement object) {
EObject parent = object.eContainer();
if (parent instanceof CallExp) {
CallExp callExpParent = (CallExp)parent;
if (callExpParent.isIsImplicit()) {
if (callExpParent instanceof IteratorExp) { // Bypass implicit collect
if (callExpParent.getOwnedSource() == object) {
context.appendElement(((IteratorExp)callExpParent).getOwnedBody());
context.append(MONIKER_SCOPE_SEPARATOR);
context.appendRole(object);
context.append(MONIKER_OPERATOR_SEPARATOR);
return;
}
else {
context.appendParent(callExpParent, MONIKER_SCOPE_SEPARATOR);
context.appendRole(callExpParent);
context.append(MONIKER_OPERATOR_SEPARATOR);
return;
}
}
else if (callExpParent.getOwnedSource() == object) {
object = callExpParent;
}
}
}
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendRole(object);
context.append(MONIKER_OPERATOR_SEPARATOR);
}
@Override
public String toString() {
return context.toString();
}
@Override
public Object visitAnnotation(@NonNull Annotation object) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.append(ANNOTATION_QUOTE);
context.append(String.valueOf(object.getName()));
context.append(ANNOTATION_QUOTE);
Object container = object.eContainer().eGet(object.eContainingFeature());
if (container instanceof List<?>) {
int index = 0;
for (Object element : (List<?>)container) {
if (element == object) {
break;
}
if ((element instanceof Annotation) && (((Annotation)element).getName().equals(object.getName()))) {
index++;
}
}
if (index > 0) {
context.append(index);
}
}
return true;
}
@Override
public Object visitBooleanLiteralExp(@NonNull BooleanLiteralExp object) {
appendExpPrefix(object);
context.append(Boolean.toString(object.isBooleanSymbol()));
return true;
}
@Override
public Object visitClass(org.eclipse.ocl.pivot.@NonNull Class object) {
if (!object.getOwnedBindings().isEmpty()) {
Type templateableClass = PivotUtil.getUnspecializedTemplateableElement(object);
context.appendParent(templateableClass, MONIKER_SCOPE_SEPARATOR);
context.appendName(templateableClass);
context.appendTemplateBindings(object, templateBindings);
}
else if (object.eContainer() instanceof TemplateParameterSubstitution) {
TemplateParameter formal = ((TemplateParameterSubstitution)object.eContainer()).getFormal();
int index = formal.getOwningSignature().getOwnedParameters().indexOf(formal);
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.append(WILDCARD_INDICATOR + index);
}
else {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
context.appendTemplateParameters(object);
}
return true;
}
@Override
public Object visitCollectionLiteralExp(@NonNull CollectionLiteralExp object) {
appendExpPrefix(object);
context.appendName(object.getType());
return true;
}
@Override
public Object visitCollectionLiteralPart(@NonNull CollectionLiteralPart object) {
context.appendParent(object, MONIKER_PART_SEPARATOR);
context.appendIndex(object);
return true;
}
@Override
public Object visitCollectionType(@NonNull CollectionType object) {
super.visitCollectionType(object);
Number lower = object.getLower();
Number upper = object.getUpper();
if ((lower.longValue() != 0) || !(upper instanceof Unlimited)) {
context.append("_" + lower);
if (!(upper instanceof Unlimited)) {
context.append("_" + upper);
}
}
if (!object.isIsNullFree()) {
context.append(COLLECTION_ELEMENT_SEPARATOR);
context.append("1");
}
return true;
}
@Override
public Object visitConstraint(@NonNull Constraint object) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.append(PivotUtilInternal.getStereotype(object));
Object container = object.eContainer().eGet(object.eContainingFeature());
if (container instanceof List<?>) {
int index = 0;
String name2 = object.getName();
for (Object content : (List<?>)container) {
if (content == object) {
break;
}
if (content instanceof Constraint) {
Constraint sibling = (Constraint) content;
if (PivotUtilInternal.getStereotype(sibling).equals(PivotUtilInternal.getStereotype(object))) {
String name1 = sibling.getName();
if (name1 != name2) {
if ((name1 == null) || !name1.equals(name2)) {
break;
}
}
index++;
}
}
}
context.append(MONIKER_OPERATOR_SEPARATOR);
if (name2 != null) {
context.append(name2);
}
if (index != 0) {
context.append(MONIKER_OPERATOR_SEPARATOR);
context.append(index);
}
}
return true;
}
@Override
public Object visitDetail(@NonNull Detail object) {
context.appendParent(object, BINDINGS_PREFIX);
context.append(object.getName());
return true;
}
@Override
public Object visitEnumLiteralExp(@NonNull EnumLiteralExp object) {
appendExpPrefix(object);
context.appendName(object.getReferredLiteral());
return true;
}
@Override
public Object visitExpressionInOCL(@NonNull ExpressionInOCL object) {
if (object.eContainer() != null) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendRole(object);
}
else {
context.append(MONIKER_ROOT_EXP);
}
return true;
}
@Override
public Object visitFinalState(@NonNull FinalState object) {
context.appendParent(object, MONIKER_PART_SEPARATOR);
context.append("FS");
context.append(MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
return true;
}
@Override
public Object visitIfExp(@NonNull IfExp object) {
appendExpPrefix(object);
context.append(MONIKER_IF_EXP);
return true;
}
@Override
public Object visitIntegerLiteralExp(@NonNull IntegerLiteralExp object) {
appendExpPrefix(object);
context.append(object.getIntegerSymbol().toString());
return true;
}
@Override
public Object visitInvalidLiteralExp(@NonNull InvalidLiteralExp object) {
appendExpPrefix(object);
context.append(MONIKER_INVALID_LITERAL_EXP);
return true;
}
@Override
public Object visitLambdaType(@NonNull LambdaType object) {
context.append(object.getName());
// context.appendTemplateParameters(object);
Map<TemplateParameter, Type> bindings = getAllTemplateParameterSubstitutions(null, object);
context.appendLambdaType(object.getContextType(), object.getParameterType(), object.getResultType(), bindings);
return true;
}
@Override
public Object visitLetExp(@NonNull LetExp object) {
appendExpPrefix(object);
context.append(MONIKER_LET_EXP);
return true;
}
@Override
public Object visitLoopExp(@NonNull LoopExp object) {
appendExpPrefix(object);
if (object.isIsImplicit()) {
OCLExpression body = object.getOwnedBody();
if (body instanceof CallExp) {
Feature referredFeature = PivotUtil.getReferredFeature((CallExp) body);
context.appendName(referredFeature);
return true;
}
}
context.appendName(object.getReferredIteration());
return true;
}
@Override
public Object visitMapLiteralExp(@NonNull MapLiteralExp object) {
appendExpPrefix(object);
context.appendName(object.getType());
return true;
}
@Override
public Object visitMapLiteralPart(@NonNull MapLiteralPart object) {
context.appendParent(object, MONIKER_PART_SEPARATOR);
context.appendIndex(object);
return true;
}
@Override
public Object visitModel(@NonNull Model object) {
context.append(MONIKER_ROOT);
return true;
}
@Override
public Object visitNamedElement(@NonNull NamedElement object) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
return true;
}
@Override
public Object visitNullLiteralExp(@NonNull NullLiteralExp object) {
appendExpPrefix(object);
context.append(MONIKER_NULL_LITERAL_EXP);
return true;
}
@Override
public Object visitOperation(@NonNull Operation object) {
if (!object.getOwnedBindings().isEmpty()) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
Map<TemplateParameter, Type> bindings = getAllTemplateParameterSubstitutions(null, object);
if (templateBindings != null) {
if (bindings == null) {
bindings = templateBindings;
}
else {
// FIXME merge templateBindings
}
}
context.appendTemplateBindings(object, bindings);
context.appendParameters(object, bindings);
return true;
}
else {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
context.appendTemplateParameters(object);
context.appendParameters(object, null);
}
return true;
}
@Override
public Object visitOperationCallExp(@NonNull OperationCallExp object) {
appendExpPrefix(object);
context.appendName(object.getReferredOperation());
return true;
}
@Override
public Object visitOppositePropertyCallExp(@NonNull OppositePropertyCallExp object) {
appendExpPrefix(object);
context.append("~");
context.appendName(object.getReferredProperty());
return true;
}
@SuppressWarnings("deprecation")
@Override
public Object visitPackage(org.eclipse.ocl.pivot.@NonNull Package object) {
// if (!object.hasMoniker()) {
// throw new IllegalStateException("No moniker has been configured for " + object);
// }
context.append(PivotUtilInternal.getNsURI(object));
return true;
}
@Override
public Object visitPrecedence(@NonNull Precedence object) {
context.appendParent(object, PRECEDENCE_PREFIX);
context.appendName(object);
return true;
}
@Override
public Object visitPrimitiveType(@NonNull PrimitiveType object) {
context.appendName(object);
return true;
}
@Override
public Object visitProfileApplication(@NonNull ProfileApplication object) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
context.appendElement(object.getAppliedProfile());
return true;
}
@Override
public Object visitPropertyCallExp(@NonNull PropertyCallExp object) {
appendExpPrefix(object);
context.appendName(object.getReferredProperty());
return true;
}
@Override
public Object visitPseudostate(@NonNull Pseudostate object) {
context.appendParent(object, MONIKER_PART_SEPARATOR);
context.append("PS");
context.append(MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
return true;
}
@Override
public Object visitRealLiteralExp(@NonNull RealLiteralExp object) {
appendExpPrefix(object);
context.append(object.getRealSymbol().toString());
return true;
}
@Override
public String visitShadowExp(@NonNull ShadowExp shadowExp) {
appendExpPrefix(shadowExp);
context.append(MONIKER_TUPLE_LITERAL_EXP);
// appendQualifiedName(constructorExp.getReferredType());
// append("{");//$NON-NLS-1$
// String prefix = "";
// for (TupleLiteralPart part : constructorExp.getPart()) {
// append(prefix);
// safeVisit(part);
// prefix = ", ";//$NON-NLS-1$
// }
// append("}");
return null;
}
@Override
public Object visitState(@NonNull State object) {
context.appendParent(object, MONIKER_PART_SEPARATOR);
context.append("S");
context.append(MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
return true;
}
@Override
public Object visitStereotypeExtender(@NonNull StereotypeExtender object) {
context.appendElement(object.getClass_());
context.append(MONIKER_SCOPE_SEPARATOR);
context.append("X");
context.append(MONIKER_PART_SEPARATOR);
context.appendElement((Element) object.eContainer());
return true;
}
@Override
public Object visitStringLiteralExp(@NonNull StringLiteralExp object) {
appendExpPrefix(object);
context.append(MONIKER_STRING_LITERAL_EXP);
return true;
}
@Override
public Object visitTemplateBinding(@NonNull TemplateBinding object) {
TemplateSignature signature = object.getTemplateSignature();
if (signature != null) {
context.appendElement(signature.getOwningElement());
}
context.append(BINDINGS_PREFIX);
return true;
}
@Override
public Object visitTemplateParameter(@NonNull TemplateParameter object) {
TemplateableElement owningTemplateElement = object.getOwningSignature().getOwningElement();
context.appendElement(owningTemplateElement);
context.append(TEMPLATE_PARAMETER_PREFIX);
context.appendName(object);
return true;
}
@Override
public Object visitTemplateParameterSubstitution(@NonNull TemplateParameterSubstitution object) {
context.appendElement(object.getOwningBinding());
context.appendName(object.getFormal());
return true;
}
@Override
public Object visitTemplateSignature(@NonNull TemplateSignature object) {
context.appendParent(object, MONIKER_SCOPE_SEPARATOR);
return true;
}
@Override
public Object visitTransition(@NonNull Transition object) {
context.appendParent(object, MONIKER_PART_SEPARATOR);
context.append("T");
context.append(MONIKER_SCOPE_SEPARATOR);
context.appendName(object);
return true;
}
@Override
public Object visitTupleLiteralExp(@NonNull TupleLiteralExp object) {
appendExpPrefix(object);
context.append(MONIKER_TUPLE_LITERAL_EXP);
return true;
}
@Override
public Object visitTupleType(@NonNull TupleType object) {
List<Property> ownedAttributes = object.getOwnedProperties();
if (ownedAttributes.isEmpty()) {
super.visitTupleType(object);
}
else {
context.appendName(object);
context.appendTupleType(ownedAttributes);
}
return true;
}
@Override
public Object visitTypeExp(@NonNull TypeExp object) {
appendExpPrefix(object);
context.appendName(object.getReferredType());
return true;
}
@Override
public Object visitUnlimitedNaturalLiteralExp(@NonNull UnlimitedNaturalLiteralExp object) {
appendExpPrefix(object);
Number unlimitedNaturalSymbol = object.getUnlimitedNaturalSymbol();
context.append(unlimitedNaturalSymbol.toString());
return true;
}
@Override
public Object visitVariable(@NonNull Variable object) {
appendExpPrefix(object);
context.appendName(object);
return true;
}
@Override
public Object visitVariableExp(@NonNull VariableExp object) {
appendExpPrefix(object);
context.appendName(object.getReferredVariable());
return true;
}
@Override
public Object visiting(@NonNull Visitable visitable) {
throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
}
}