/******************************************************************************* * Copyright (c) 2010, 2015 IBM Corporation 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: * IBM - Initial API and implementation * E.D. Willink - Robustness enhancements (null-proofing) * Adolfo Sanchez- Barbudo Herrera - 228841 Fix NPE in VariableExp *******************************************************************************/ package org.eclipse.ocl.pivot.utilities; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.Annotation; import org.eclipse.ocl.pivot.AnyType; import org.eclipse.ocl.pivot.AssociationClassCallExp; import org.eclipse.ocl.pivot.BooleanLiteralExp; import org.eclipse.ocl.pivot.CollectionItem; import org.eclipse.ocl.pivot.CollectionLiteralExp; import org.eclipse.ocl.pivot.CollectionLiteralPart; import org.eclipse.ocl.pivot.CollectionRange; import org.eclipse.ocl.pivot.CollectionType; import org.eclipse.ocl.pivot.Comment; import org.eclipse.ocl.pivot.CompleteClass; import org.eclipse.ocl.pivot.CompletePackage; import org.eclipse.ocl.pivot.Constraint; import org.eclipse.ocl.pivot.Detail; import org.eclipse.ocl.pivot.MapLiteralExp; import org.eclipse.ocl.pivot.MapLiteralPart; import org.eclipse.ocl.pivot.MapType; import org.eclipse.ocl.pivot.ShadowExp; import org.eclipse.ocl.pivot.ShadowPart; import org.eclipse.ocl.pivot.Element; import org.eclipse.ocl.pivot.ElementExtension; import org.eclipse.ocl.pivot.EnumLiteralExp; import org.eclipse.ocl.pivot.EnumerationLiteral; import org.eclipse.ocl.pivot.ExpressionInOCL; import org.eclipse.ocl.pivot.FeatureCallExp; import org.eclipse.ocl.pivot.IfExp; import org.eclipse.ocl.pivot.Import; import org.eclipse.ocl.pivot.IntegerLiteralExp; import org.eclipse.ocl.pivot.InvalidLiteralExp; import org.eclipse.ocl.pivot.InvalidType; import org.eclipse.ocl.pivot.IterateExp; import org.eclipse.ocl.pivot.Iteration; import org.eclipse.ocl.pivot.IteratorExp; import org.eclipse.ocl.pivot.LambdaType; import org.eclipse.ocl.pivot.LetExp; import org.eclipse.ocl.pivot.MessageExp; import org.eclipse.ocl.pivot.Model; import org.eclipse.ocl.pivot.NamedElement; import org.eclipse.ocl.pivot.NavigationCallExp; 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.Parameter; 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.RealLiteralExp; import org.eclipse.ocl.pivot.StateExp; 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.TupleLiteralExp; import org.eclipse.ocl.pivot.TupleLiteralPart; import org.eclipse.ocl.pivot.TupleType; import org.eclipse.ocl.pivot.Type; import org.eclipse.ocl.pivot.TypeExp; import org.eclipse.ocl.pivot.StereotypeExtender; import org.eclipse.ocl.pivot.TypedElement; import org.eclipse.ocl.pivot.UnlimitedNaturalLiteralExp; import org.eclipse.ocl.pivot.UnspecifiedValueExp; import org.eclipse.ocl.pivot.Variable; import org.eclipse.ocl.pivot.VariableExp; import org.eclipse.ocl.pivot.VoidType; import org.eclipse.ocl.pivot.WildcardType; import org.eclipse.ocl.pivot.ids.IdManager; import org.eclipse.ocl.pivot.ids.TypeId; import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal; import org.eclipse.ocl.pivot.resource.ASResource; import org.eclipse.ocl.pivot.util.AbstractExtendingVisitor; import org.eclipse.ocl.pivot.util.Visitable; import org.eclipse.ocl.pivot.values.Unlimited; /** * Converts an OCL expression to a string for debugging. This is not intended to * be used by client applications as an AST-to-text transformation. * * @author Edith Schonberg (edith) * @author Christian W. Damus (cdamus) * @author Edward Willink (ewillink) */ public class ToStringVisitor extends AbstractExtendingVisitor<@Nullable String, @NonNull StringBuilder> { private static final Logger logger = Logger.getLogger(ToStringVisitor.class); public static interface Factory { @NonNull ToStringVisitor createToStringVisitor(@NonNull StringBuilder s); @NonNull EPackage getEPackage(); } private static @NonNull Map<EPackage, Factory> factoryMap = new HashMap<EPackage, Factory>(); public static synchronized void addFactory(@NonNull Factory factory) { factoryMap.put(factory.getEPackage(), factory); } public static @Nullable Factory getFactory(@NonNull EObject eObject) { EPackage ePackage = eObject.eClass().getEPackage(); Factory factory = factoryMap.get(ePackage); if (factory == null) { logger.error("No ToStringVisitor Factory registered for " + ePackage.getName()); } return factory; } public static String toString(@NonNull Element asElement) { Resource resource = asElement.eResource(); if (resource instanceof ASResource) { StringBuilder s = new StringBuilder(); ToStringVisitor v = ((ASResource)resource).getASResourceFactory().createToStringVisitor(s); asElement.accept(v); return s.toString(); } Factory factory = getFactory(asElement); if (factory == null) { return NULL_PLACEHOLDER; } StringBuilder s = new StringBuilder(); ToStringVisitor v = factory.createToStringVisitor(s); asElement.accept(v); return s.toString(); } protected static class AS2StringFactory implements ToStringVisitor.Factory { protected AS2StringFactory() { ToStringVisitor.addFactory(this); // FACTORY.getClass(); // This is redundant for this class but needed by derived classes } @Override public @NonNull ToStringVisitor createToStringVisitor(@NonNull StringBuilder s) { return new ToStringVisitor(s); } @Override public @NonNull EPackage getEPackage() { PivotPackage eInstance = PivotPackage.eINSTANCE; assert eInstance != null; return eInstance; } } public static ToStringVisitor.@NonNull Factory FACTORY = new AS2StringFactory(); /** * Indicates where a required element in the AST was <code>null</code>, so * that it is evident in the debugger that something was missing. We don't * want just <code>"null"</code> because that would look like the OclVoid * literal. */ protected static @NonNull String NULL_PLACEHOLDER = "\"<null>\""; //$NON-NLS-1$ /** * Initializes me. */ public ToStringVisitor(@NonNull StringBuilder s) { super(s); } /* * protected List<? extends EObject> getConstrainedElements(Constraint * constraint) { if (uml == null) { return Collections.emptyList(); } else { * return uml.getConstrainedElements(constraint); } } * * protected String getStereotype(Constraint constraint) { return (uml == * null)? null : uml.getStereotype(constraint); } * * @Override protected ExpressionInOCL getSpecification(Constraint * constraint) { return (uml == null)? null : * uml.getSpecification(constraint); } */ protected void append(Number number) { if (number != null) { context.append(number.toString()); } else { context.append(NULL_PLACEHOLDER); } } protected void append(String string) { if (string != null) { context.append(string); } else { context.append(NULL_PLACEHOLDER); } } protected void appendAtPre(FeatureCallExp mpc) { if (mpc.isIsPre()) { append("@pre"); //$NON-NLS-1$ } } protected void appendElementType(@Nullable TypedElement typedElement) { if (typedElement == null) { append(NULL_PLACEHOLDER); } else { Type type = typedElement.getType(); safeVisit(type); if (!typedElement.isIsRequired()) { append("[?]"); } else if (!(type instanceof CollectionType)) { append("[1]"); } } } protected void appendName(Nameable object) { if (object == null) { context.append(NULL_PLACEHOLDER); } else { context.append(object.getName()); } } protected void appendOperationSignature(Operation operation) { appendName(operation); append("("); boolean comma = false; for (java.util.Iterator<Parameter> iter = operation .getOwnedParameters().iterator(); iter.hasNext();) { Parameter parm = iter.next(); if (comma) { append(", "); //$NON-NLS-1$ } else { comma = true; } appendName(parm); append(" : "); //$NON-NLS-1$ if (parm.getType() != null) { boolean isTypeof = parm.isIsTypeof(); if (isTypeof) { append("typeof("); } appendElementType(parm); if (isTypeof) { append(")"); } } else { append(TypeId.OCL_VOID_NAME); } } append(") :"); //$NON-NLS-1$ if (operation.getType() != null) { append(" "); boolean isTypeof = operation.isIsTypeof(); if (isTypeof) { append("typeof("); } appendElementType(operation); if (isTypeof) { append(")"); } } } protected void appendPropertyCallExp(@NonNull NavigationCallExp pc, Property property) { // source is null when the property call expression is an // association class navigation qualifier OCLExpression source = pc.getOwnedSource(); safeVisit(source); Type sourceType = source != null ? source.getType() : null; append(PivotUtil.getNavigationOperator(pc.isIsSafe(), PivotUtil.isAggregate(sourceType))); appendName(property); appendAtPre(pc); List<OCLExpression> qualifiers = pc.getQualifiers(); if (!qualifiers.isEmpty()) { append("["); //$NON-NLS-1$ String prefix = ""; //$NON-NLS-1$ for (OCLExpression qualifier : qualifiers) { append(prefix); safeVisit(qualifier); prefix = ", "; //$NON-NLS-1$ } append("]"); } } protected void appendPropertySignature(Property property) { appendName(property); if (property.getType() != null) { append(" : "); appendElementType(property); } } protected void appendQualifiedName(NamedElement parent, String separator, NamedElement child) { if (parent != null) { appendQualifiedName(parent); append(separator); } appendName(child); } protected void appendQualifiedName(@Nullable NamedElement object) { if (object == null) { context.append(NULL_PLACEHOLDER); } else { EObject container = object.eContainer(); if ((container != null) && (!(container instanceof Model) && (container instanceof NamedElement) && (!(container.eContainer() instanceof Model) || !PivotConstants.OCL_NAME.equals(((NamedElement)container).getName())))) { appendQualifiedName((NamedElement) container); append("::"); //$NON-NLS-1$ } appendName(object); if (object instanceof TemplateableElement) { TemplateableElement templateableElement = (TemplateableElement) object; appendTemplateBindings(templateableElement.getOwnedBindings(), null); appendTemplateSignature(templateableElement.getOwnedSignature()); } } } protected void appendTemplateBindings(List<TemplateBinding> templateBindings, @Nullable CollectionType collectionType) { if (templateBindings.size() > 0) { append("("); String prefix = ""; //$NON-NLS-1$ for (TemplateBinding templateBinding : templateBindings) { for (TemplateParameterSubstitution templateParameterSubstitution : templateBinding.getOwnedSubstitutions()) { append(prefix); safeVisit(templateParameterSubstitution.getActual()); prefix = ","; } } if (collectionType != null) { Number lower = collectionType.getLower(); Number upper = collectionType.getUpper(); long lowerValue = lower != null ? lower.longValue() : 0l; // FIXME Handle BigInteger long upperValue = (upper != null) && !(upper instanceof Unlimited) ? upper.longValue() : -1l; if ((lowerValue != 0) || (upperValue != -1) || collectionType.isIsNullFree()) { StringUtil.appendMultiplicity(context, lowerValue, upperValue, collectionType.isIsNullFree()); } } append(")"); } } protected void appendTemplateSignature(TemplateSignature templateSignature) { if (templateSignature != null) { List<TemplateParameter> templateParameters = templateSignature.getOwnedParameters(); if (!templateParameters.isEmpty()) { append("("); String prefix = ""; //$NON-NLS-1$ for (TemplateParameter templateParameter : templateParameters) { append(prefix); appendName(templateParameter); prefix = ","; } append(")"); } } } protected void appendType(Type type) { if ((type != null) && (type.eClass() == PivotPackage.Literals.CLASS) // i.e. by pass AnyType, PrimitiveType, ... && (type.eContainer() instanceof NamedElement)) { appendQualifiedName((NamedElement) type.eContainer()); append("::"); } appendName(type); } /** * A null-safe visitation of the specified visitable, appending any generted text to the toStringVisitor context. * * @param v a visitable, or <code>null</code> * @return <code>null</code> */ @Override public @Nullable String safeVisit(org.eclipse.ocl.pivot.util.@Nullable Visitable v) { if (v == null) { append(NULL_PLACEHOLDER); } else { v.accept(this); } return null; } @Override public String toString() { return context.toString(); } @Override public @Nullable String visitAnnotation(@NonNull Annotation object) { appendName(object); return null; } @Override public String visitAnyType(@NonNull AnyType object) { appendName(object); return null; } /** * Callback for an AssociationClassCallExp visit. * * @param ac * the association class expression * @return string source.ref */ @Override public String visitAssociationClassCallExp(@NonNull AssociationClassCallExp ac) { safeVisit(ac.getOwnedSource()); append("."); //$NON-NLS-1$ appendName(ac.getReferredAssociationClass()); //$NON-NLS-1$ appendAtPre(ac); List<OCLExpression> qualifiers = ac.getQualifiers(); if (!qualifiers.isEmpty()) { append("["); safeVisit(qualifiers.get(0)); append("]"); } return null; } /** * Callback for a BooleanLiteralExp visit. * * @param bl * -- boolean literal expression * @return the value of the boolean literal as a java.lang.Boolean. */ @Override public String visitBooleanLiteralExp(@NonNull BooleanLiteralExp bl) { append(Boolean.toString(bl.isBooleanSymbol())); return null; } @Override public String visitClass(org.eclipse.ocl.pivot.@NonNull Class cls) { org.eclipse.ocl.pivot.Package pkg = cls.getOwningPackage(); if (pkg == null) { append("null::"); appendName(cls); } else if (!(pkg.eContainer() instanceof Model) || !IdManager.METAMODEL.equals(pkg.getPackageId())) { appendQualifiedName(pkg, "::", cls); } else { appendName(cls); } appendTemplateBindings(cls.getOwnedBindings(), null); appendTemplateSignature(cls.getOwnedSignature()); return null; } /** * Visits the item's item expression. */ @Override public String visitCollectionItem(@NonNull CollectionItem item) { safeVisit(item.getOwnedItem()); return null; } /** * Visits the collection literal's parts. */ @Override public String visitCollectionLiteralExp(@NonNull CollectionLiteralExp cl) { // construct the appropriate collection from the parts // based on the collection kind. switch (cl.getKind()) { case SET : append("Set{");//$NON-NLS-1$ break; case ORDERED_SET : append("OrderedSet{");//$NON-NLS-1$ break; case BAG : append("Bag{");//$NON-NLS-1$ break; case SEQUENCE : append("Sequence{");//$NON-NLS-1$ break; default : append("Collection{");//$NON-NLS-1$ break; } boolean isFirst = true; for (CollectionLiteralPart part : cl.getOwnedParts()) { if (!isFirst) { append(", "); } safeVisit(part); isFirst = false; } append("}"); return null; } /** * Visits the range's first and last expressions. */ @Override public String visitCollectionRange(@NonNull CollectionRange range) { safeVisit(range.getOwnedFirst()); append(" .. "); safeVisit(range.getOwnedLast()); return null; } @Override public String visitCollectionType(@NonNull CollectionType object) { appendName(object); appendTemplateBindings(object.getOwnedBindings(), object); appendTemplateSignature(object.getOwnedSignature()); // Number lower = object.getLower(); // Number upper = object.getUpper(); // long lowerValue = lower != null ? lower.longValue() : 0l; // FIXME Handle BigInteger // long upperValue = (upper != null) && !(upper instanceof Unlimited) ? upper.longValue() : -1l; // if ((lowerValue != 0) || (upperValue != -1)) { // StringUtil.appendMultiplicity(context, lowerValue, upperValue, object.isIsNullFree()); // } return null; } @Override public String visitComment(@NonNull Comment comment) { append("/* "); append(comment.getBody()); append(" */"); return null; } @Override public @Nullable String visitCompleteClass(@NonNull CompleteClass object) { appendName(object); append("*"); append(object.getPartialClasses().size()); return null; } @Override public @Nullable String visitCompletePackage(@NonNull CompletePackage object) { appendName(object); append("*"); append(object.getPartialPackages().size()); append(" : "); append(object.getURI()); return null; } /** * Renders a constraint with its context and expression. */ @Override public String visitConstraint(@NonNull Constraint constraint) { List<? extends EObject> constrained = constraint.getConstrainedElements(); if (!constrained.isEmpty()) { EObject elem = constrained.get(0); append("context "); //$NON-NLS-1$ if (elem instanceof Type) { appendName((NamedElement) elem); } else if (elem instanceof Operation) { Operation oper = (Operation) elem; appendOperationSignature(oper); } else if (elem instanceof Property) { Property prop = (Property) elem; appendPropertySignature(prop); } append(" "); } String stereo = PivotUtilInternal.getStereotype(constraint); append(stereo); //$NON-NLS-1$ String name = constraint.getName(); if (name != null) { append(" "); //$NON-NLS-1$ append(name); } append(": "); //$NON-NLS-1$ /* FIXME def context EObject elem = constrained.get(1); if (elem instanceof Operation) { appendOperationSignature((Operation) elem); } else if (elem instanceof Property) { appendPropertySignature((Property) elem); } append(" = "); //$NON-NLS-1$ */ safeVisit(constraint.getOwnedSpecification()); return null; } @Override public @Nullable String visitDetail(@NonNull Detail object) { appendName(object); append(" = "); boolean first = true; for (String value : object.getValues()) { if (!first) { append(", "); } append(value); first = false; } return null; } @Override public String visitElementExtension(@NonNull ElementExtension as) { appendName(as); return null; } /** * Callback for an EnumLiteralExp visit. * * @param el * the enumeration literal expresion * @return the enumeration literal toString() */ @Override public String visitEnumLiteralExp(@NonNull EnumLiteralExp el) { appendQualifiedName(el.getReferredLiteral()); return null; } @Override public String visitEnumerationLiteral(@NonNull EnumerationLiteral el) { appendQualifiedName(el.getOwningEnumeration(), "::", el); return null; } /** * Renders an ExpressionInOCL with its context variables and body. */ @Override public String visitExpressionInOCL(@NonNull ExpressionInOCL expression) { OCLExpression bodyExpression = expression.getOwnedBody(); if (bodyExpression != null) { return safeVisit(bodyExpression); } else { append(expression.getBody()); return null; } } /** * Callback for an IfExp visit. * * @param ifExp * an IfExp * @return the string representation */ @Override public String visitIfExp(@NonNull IfExp ifExp) { append("if "); //$NON-NLS-1$ safeVisit(ifExp.getOwnedCondition()); append(" then "); //$NON-NLS-1$ safeVisit(ifExp.getOwnedThen()); append(" else "); //$NON-NLS-1$ safeVisit(ifExp.getOwnedElse()); append(" endif"); //$NON-NLS-1$ return null; } @Override public @Nullable String visitImport(@NonNull Import object) { appendName(object); append(" : "); appendQualifiedName(object.getImportedNamespace()); return null; } /** * Callback for an IntegerLiteralExp visit. * * @param il * -- integer literal expression * @return String */ @Override public String visitIntegerLiteralExp(@NonNull IntegerLiteralExp il) { append(il.getIntegerSymbol()); return null; } @Override public String visitInvalidLiteralExp(@NonNull InvalidLiteralExp il) { append("invalid"); return null; } @Override public String visitInvalidType(@NonNull InvalidType object) { appendName(object); return null; } /** * Callback for an IterateExp visit. * * @param callExp * an iterate expression * @return the string representation */ @Override public String visitIterateExp(@NonNull IterateExp callExp) { safeVisit(callExp.getOwnedSource()); append(PivotUtil.getNavigationOperator(callExp.isIsSafe(), true)); appendName(callExp.getReferredIteration()); append("("); //$NON-NLS-1$ boolean isFirst = true; for (Variable variable : callExp.getOwnedIterators()) { if (!isFirst) { append(", "); } safeVisit(variable); isFirst = false; } append("; "); safeVisit(callExp.getOwnedResult()); append(" | "); safeVisit(callExp.getOwnedBody()); append(")");//$NON-NLS-1$ return null; } @Override public String visitIteration(@NonNull Iteration iteration) { appendQualifiedName(iteration.getOwningClass(), ".", iteration); appendTemplateBindings(iteration.getOwnedBindings(), null); appendTemplateSignature(iteration.getOwnedSignature()); append("("); boolean isFirst = true; for (Parameter parameter : iteration.getOwnedIterators()) { if (!isFirst) { append(", "); } appendElementType(parameter); isFirst = false; } isFirst = true; for (Parameter accumulator : iteration.getOwnedAccumulators()) { if (!isFirst) { append(", "); } else { append("; "); } appendElementType(accumulator); isFirst = false; } isFirst = true; for (Parameter parameter : iteration.getOwnedParameters()) { if (!isFirst) { append(", "); } else { append(" | "); } appendElementType(parameter); isFirst = false; } append(") : "); appendElementType(iteration); return null; } /** * Callback for an IteratorExp visit. * * @param callExp * an iterator expression * @return the string representation */ @Override public String visitIteratorExp(@NonNull IteratorExp callExp) { safeVisit(callExp.getOwnedSource()); append(PivotUtil.getNavigationOperator(callExp.isIsSafe(), true)); appendName(callExp.getReferredIteration()); append("("); //$NON-NLS-1$ boolean isFirst = true; for (Variable variable : callExp.getOwnedIterators()) { if (!isFirst) { append(", "); } safeVisit(variable); isFirst = false; } append(" | "); safeVisit(callExp.getOwnedBody()); append(")");//$NON-NLS-1$ return null; } @Override public String visitLambdaType(@NonNull LambdaType lambda) { appendName(lambda); Type contextType = lambda.getContextType(); if (contextType != null) { append(" "); appendType(contextType); appendTemplateSignature(lambda.getOwnedSignature()); append("("); boolean isFirst = true; for (Type parameterType : lambda.getParameterType()) { if (!isFirst) { append(","); } appendType(parameterType); isFirst = false; } append(") : "); appendType(lambda.getResultType()); } return null; } /** * Callback for LetExp visit. * * @param letExp * a let expression * @return the string representation */ @Override public String visitLetExp(@NonNull LetExp letExp) { append("let "); //$NON-NLS-1$ safeVisit(letExp.getOwnedVariable()); append(" in "); //$NON-NLS-1$ safeVisit(letExp.getOwnedIn()); return null; } /** * Visits the map literal's parts. */ @Override public String visitMapLiteralExp(@NonNull MapLiteralExp mapLiteralExp) { append("Map{");//$NON-NLS-1$ boolean isFirst = true; for (MapLiteralPart part : mapLiteralExp.getOwnedParts()) { if (!isFirst) { append(", "); } safeVisit(part); isFirst = false; } append("}"); return null; } /** * Visits the range's first and last expressions. */ @Override public String visitMapLiteralPart(@NonNull MapLiteralPart mapLiteralPart) { safeVisit(mapLiteralPart.getOwnedKey()); append(" <- "); safeVisit(mapLiteralPart.getOwnedValue()); return null; } @Override public String visitMapType(@NonNull MapType object) { appendName(object); appendTemplateBindings(object.getOwnedBindings(), null); appendTemplateSignature(object.getOwnedSignature()); return null; } /** * Visits the message expression's target and then its arguments. */ @Override public String visitMessageExp(@NonNull MessageExp messageExp) { safeVisit(messageExp.getOwnedTarget()); append((messageExp.getType() instanceof CollectionType) ? "^^" : "^"); //$NON-NLS-1$//$NON-NLS-2$ if (messageExp.getOwnedCalledOperation() != null) { appendName(messageExp.getOwnedCalledOperation().getOperation()); } else if (messageExp.getOwnedSentSignal() != null) { appendName(messageExp.getOwnedSentSignal().getSignal()); } append("("); String prefix = ""; for (OCLExpression argument : messageExp.getOwnedArguments()) { append(prefix); safeVisit(argument); prefix = ", "; //$NON-NLS-1$ } append(")"); return null; } @Override public String visitNullLiteralExp(@NonNull NullLiteralExp il) { append("null"); return null; } @Override public String visitOperation(@NonNull Operation operation) { appendQualifiedName(operation.getOwningClass(), "::", operation); appendTemplateBindings(operation.getOwnedBindings(), null); appendTemplateSignature(operation.getOwnedSignature()); append("("); boolean isFirst = true; for (Parameter parameter : operation.getOwnedParameters()) { if (!isFirst) { append(","); } appendElementType(parameter); isFirst = false; } append(") : "); appendElementType(operation); return null; } /** * Callback for an OperationCallExp visit. * * Look at the source to determine operator ( -> or . ) * * @param oc * the operation call expression * @return string */ @Override public String visitOperationCallExp(@NonNull OperationCallExp oc) { OCLExpression source = oc.getOwnedSource(); safeVisit(source); Operation oper = oc.getReferredOperation(); if (oper != null) { Type sourceType = source != null ? source.getType() : null; append(PivotUtil.getNavigationOperator(oc.isIsSafe(), PivotUtil.isAggregate(sourceType))); appendName(oper); } else { append(PivotUtil.getNavigationOperator(false, false)); appendName(oc); } append("("); String prefix = "";//$NON-NLS-1$ for (OCLExpression argument : oc.getOwnedArguments()) { append(prefix); safeVisit(argument); prefix = ", ";//$NON-NLS-1$ } append(")"); appendAtPre(oc); return null; } /** * Callback for an OppositePropertyCallExp visit. * * @param pc * the property call expression * @return string source.ref */ @Override public String visitOppositePropertyCallExp(@NonNull OppositePropertyCallExp pc) { Property referredOppositeProperty = pc.getReferredProperty(); Property referredProperty = referredOppositeProperty != null ? referredOppositeProperty.getOpposite() : null; appendPropertyCallExp(pc, referredProperty); return null; } @Override public String visitPackage(org.eclipse.ocl.pivot.@NonNull Package pkg) { appendQualifiedName(pkg.getOwningPackage(), "::", pkg); return null; } @Override public String visitParameter(@NonNull Parameter parameter) { appendQualifiedName((NamedElement) parameter.eContainer(), ".", parameter); return null; } @Override public String visitPrecedence(@NonNull Precedence precedence) { appendName(precedence); append("(" + precedence.getOrder() + ")"); return null; } @Override public String visitPrimitiveType(@NonNull PrimitiveType object) { appendName(object); return null; } @Override public String visitProfileApplication(@NonNull ProfileApplication object) { appendQualifiedName(object.getAppliedProfile()); append(" applied-to "); appendQualifiedName(object.getOwningPackage()); return null; } @Override public String visitProperty(@NonNull Property property) { appendQualifiedName(property.getOwningClass(), "::", property); return null; } /** * Callback for an PropertyCallExp visit. * * @param pc * the property call expression * @return string source.ref */ @Override public String visitPropertyCallExp(@NonNull PropertyCallExp pc) { Property property = pc.getReferredProperty(); appendPropertyCallExp(pc, property); return null; } /** * Callback for a RealLiteralExp visit. * * @param rl * -- real literal expression * @return the value of the real literal as a java.lang.Double. */ @Override public String visitRealLiteralExp(@NonNull RealLiteralExp rl) { append(rl.getRealSymbol()); return null; } @Override public String visitModel(@NonNull Model root) { append(root.getExternalURI()); return null; } /** * Callback for a ShadowExp visit. * * @param shadowExp * shadow expression * @return the string representation */ @Override public String visitShadowExp(@NonNull ShadowExp shadowExp) { appendQualifiedName(shadowExp.getType()); append("{");//$NON-NLS-1$ String prefix = ""; for (ShadowPart part : shadowExp.getOwnedParts()) { append(prefix); safeVisit(part); prefix = ", ";//$NON-NLS-1$ } append("}"); return null; } /** * Visits the tuple shadow part's value, if any. */ @Override public String visitShadowPart(@NonNull ShadowPart part) { appendName(part.getReferredProperty()); OCLExpression initExpression = part.getOwnedInit(); if (initExpression != null) { append(" = "); safeVisit(initExpression); } return null; } @Override public String visitStateExp(@NonNull StateExp s) { appendName(s); return null; } @Override public String visitStereotypeExtender(@NonNull StereotypeExtender object) { appendQualifiedName(object.getClass_()); append(" extended-by "); appendQualifiedName(object.getOwningStereotype()); return null; } /** * Callback for a StringLiteralExp visit. * * @param sl * -- string literal expression * @return the value of the string literal as a java.lang.String. */ @Override public String visitStringLiteralExp(@NonNull StringLiteralExp sl) { append("'"); append(sl.getStringSymbol()); append("'"); return null; } @Override public String visitTemplateBinding(@NonNull TemplateBinding object) { // s.append(getQualifiedName(object.getFormal(), "/", (NamedElement) // object.getActual())); appendTemplateBindings(Collections.singletonList(object), null); return null; } @Override public String visitTemplateParameter(@NonNull TemplateParameter object) { TemplateSignature signature = object.getOwningSignature(); appendName(signature != null ? (NamedElement) signature.getOwningElement() : null); append("."); appendName(object); return null; } @Override public String visitTemplateParameterSubstitution(@NonNull TemplateParameterSubstitution object) { TemplateParameter formal = object.getFormal(); appendName(formal != null ? formal : null); append("/"); safeVisit(object.getActual()); return null; } @Override public String visitTemplateSignature(@NonNull TemplateSignature object) { // s.append(getQualifiedName(object.getFormal(), "/", (NamedElement) // object.getActual())); appendTemplateSignature(object); return null; } /** * Callback for a TupleLiteralExp visit. * * @param literalExp * tuple literal expression * @return the string representation */ @Override public String visitTupleLiteralExp(@NonNull TupleLiteralExp literalExp) { append("Tuple{");//$NON-NLS-1$ String prefix = ""; for (TupleLiteralPart part : literalExp.getOwnedParts()) { append(prefix); safeVisit(part); prefix = ", ";//$NON-NLS-1$ } append("}"); return null; } /** * Visits the tuple literal part's value, if any. */ @Override public String visitTupleLiteralPart(@NonNull TupleLiteralPart part) { appendName(part); Type type = part.getType(); if (type != null) { append(" : "); appendElementType(part); } OCLExpression initExpression = part.getOwnedInit(); if (initExpression != null) { append(" = "); safeVisit(initExpression); } return null; } @Override public String visitTupleType(@NonNull TupleType object) { appendName(object); append("("); String prefix = ""; for (TypedElement part : object.getOwnedProperties()) { append(prefix); appendName(part); append(":"); appendElementType(part); prefix = ","; } append(")"); return null; } @Override public String visitTypeExp(@NonNull TypeExp t) { appendQualifiedName(t.getReferredType()); return null; } /** * Callback for an UnlimitedNaturalLiteralExp visit. * * @param unl * -- unlimited natural literal expression * @return String */ @Override public String visitUnlimitedNaturalLiteralExp(@NonNull UnlimitedNaturalLiteralExp unl) { append(unl.getUnlimitedNaturalSymbol()); return null; } @Override public String visitWildcardType(@NonNull WildcardType object) { appendName(object); return null; } /** * Callback for an UnspecifiedValueExp visit. * * @param uv * - UnspecifiedValueExp * @return the string representation */ @Override public String visitUnspecifiedValueExp(@NonNull UnspecifiedValueExp uv) { append("?"); //$NON-NLS-1$ if (uv.getType() != null && !(uv.getType() instanceof VoidType)) { append(" : "); //$NON-NLS-1$ appendName(uv.getType()); } return null; } /** * Visits the variable's initialization expression (if any). */ @Override public String visitVariable(@NonNull Variable variable) { appendName(variable); Type type = variable.getType(); if (type != null) { append(" : "); appendElementType(variable); } OCLExpression initExpression = variable.getOwnedInit(); if (initExpression != null) { append(" = "); safeVisit(initExpression); } return null; } /** * Callback for a VariableExp visit. * * @param v * the variable expression * @return the variable name */ @Override public String visitVariableExp(@NonNull VariableExp v) { appendName(v.getReferredVariable()); return null; } @Override public String visitVoidType(@NonNull VoidType object) { appendName(object); return null; } @Override public String visiting(@NonNull Visitable visitable) { append(visitable.getClass().getName()); return null; } } // ToStringVisitorImpl