| /******************************************************************************* |
| * Copyright (c) 2016, 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.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.pivot.BooleanLiteralExp; |
| import org.eclipse.ocl.pivot.CallExp; |
| 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.Element; |
| import org.eclipse.ocl.pivot.EnumLiteralExp; |
| import org.eclipse.ocl.pivot.EnumerationLiteral; |
| import org.eclipse.ocl.pivot.ExpressionInOCL; |
| 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.IterateExp; |
| import org.eclipse.ocl.pivot.Iteration; |
| import org.eclipse.ocl.pivot.IteratorExp; |
| import org.eclipse.ocl.pivot.IteratorVariable; |
| import org.eclipse.ocl.pivot.LetExp; |
| import org.eclipse.ocl.pivot.LetVariable; |
| import org.eclipse.ocl.pivot.MapLiteralExp; |
| import org.eclipse.ocl.pivot.MapLiteralPart; |
| import org.eclipse.ocl.pivot.MapType; |
| import org.eclipse.ocl.pivot.NamedElement; |
| import org.eclipse.ocl.pivot.Namespace; |
| 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.Package; |
| import org.eclipse.ocl.pivot.Parameter; |
| import org.eclipse.ocl.pivot.ParameterVariable; |
| import org.eclipse.ocl.pivot.PivotFactory; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.PropertyCallExp; |
| import org.eclipse.ocl.pivot.RealLiteralExp; |
| import org.eclipse.ocl.pivot.ResultVariable; |
| import org.eclipse.ocl.pivot.SelfType; |
| import org.eclipse.ocl.pivot.ShadowExp; |
| import org.eclipse.ocl.pivot.ShadowPart; |
| import org.eclipse.ocl.pivot.StandardLibrary; |
| import org.eclipse.ocl.pivot.StringLiteralExp; |
| import org.eclipse.ocl.pivot.TemplateParameter; |
| 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.TypedElement; |
| import org.eclipse.ocl.pivot.UnlimitedNaturalLiteralExp; |
| import org.eclipse.ocl.pivot.Variable; |
| import org.eclipse.ocl.pivot.VariableDeclaration; |
| import org.eclipse.ocl.pivot.VariableExp; |
| import org.eclipse.ocl.pivot.ids.TypeId; |
| import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager; |
| import org.eclipse.ocl.pivot.internal.manager.TemplateParameterSubstitutionHelper; |
| import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal; |
| import org.eclipse.ocl.pivot.library.LibraryFeature; |
| import org.eclipse.ocl.pivot.values.TemplateParameterSubstitutions; |
| |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Lists; |
| |
| /** |
| * PivotHelper provides helper routines to assist creation of Pivot model elements. |
| * @since 1.3 |
| */ |
| public class PivotHelper |
| { |
| protected final @NonNull EnvironmentFactory environmentFactory; |
| protected final @NonNull StandardLibrary standardLibrary; |
| private final @NonNull PivotMetamodelManager metamodelManager; |
| |
| public PivotHelper(@NonNull EnvironmentFactory environmentFactory) { |
| this.environmentFactory = environmentFactory; |
| this.standardLibrary = environmentFactory.getStandardLibrary(); |
| this.metamodelManager = (PivotMetamodelManager) environmentFactory.getMetamodelManager(); // FIXME avoid this cast; |
| } |
| |
| public @NonNull BooleanLiteralExp createBooleanLiteralExp(boolean booleanSymbol) { |
| BooleanLiteralExp asBoolean = PivotFactory.eINSTANCE.createBooleanLiteralExp(); |
| asBoolean.setBooleanSymbol(booleanSymbol); |
| asBoolean.setType(standardLibrary.getBooleanType()); |
| asBoolean.setIsRequired(true); |
| return asBoolean; |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| public @NonNull OCLExpression createCoercionCallExp(@NonNull OCLExpression asExpression, @NonNull Operation coercion) { |
| if (asExpression instanceof IntegerLiteralExp) { |
| IntegerLiteralExp asIntegerLiteralExp = (IntegerLiteralExp)asExpression; |
| Number integerSymbol = asIntegerLiteralExp.getIntegerSymbol(); |
| if (integerSymbol.longValue() >= 0) { |
| org.eclipse.ocl.pivot.Class integerType = standardLibrary.getIntegerType(); |
| Operation asCoercion = NameUtil.getNameable(integerType.getOwnedOperations(), "toUnlimitedNatural"); |
| if (coercion == asCoercion) { |
| return createUnlimitedNaturalLiteralExp(integerSymbol); |
| } |
| } |
| } |
| OperationCallExp asCoercionCallExp = PivotFactory.eINSTANCE.createOperationCallExp(); |
| asCoercionCallExp.setOwnedSource(asExpression); |
| asCoercionCallExp.setReferredOperation(coercion); |
| asCoercionCallExp.setType(coercion.getType()); |
| asCoercionCallExp.setIsRequired(coercion.isIsRequired()); |
| return asCoercionCallExp; |
| } |
| |
| public @NonNull CollectionItem createCollectionItem(@NonNull OCLExpression asItem) { |
| CollectionItem collectionItem = PivotFactory.eINSTANCE.createCollectionItem(); |
| collectionItem.setOwnedItem(asItem); |
| collectionItem.setType(asItem.getType()); |
| collectionItem.setIsRequired(asItem.isIsRequired()); |
| return collectionItem; |
| } |
| |
| public @NonNull CollectionLiteralExp createCollectionLiteralExp(@NonNull CollectionType asType, @NonNull Iterable<CollectionLiteralPart> asParts) { |
| CollectionLiteralExp collectionLiteralExp = PivotFactory.eINSTANCE.createCollectionLiteralExp(); |
| Iterables.addAll(collectionLiteralExp.getOwnedParts(), asParts); |
| collectionLiteralExp.setType(asType); |
| collectionLiteralExp.setKind(TypeUtil.getCollectionKind(asType)); |
| collectionLiteralExp.setIsRequired(true); |
| return collectionLiteralExp; |
| } |
| |
| public @NonNull CollectionRange createCollectionRange(@NonNull OCLExpression asFirst, @NonNull OCLExpression asLast) { |
| CollectionRange collectionRange = PivotFactory.eINSTANCE.createCollectionRange(); |
| collectionRange.setOwnedFirst(asFirst); |
| collectionRange.setOwnedLast(asLast); |
| collectionRange.setType(standardLibrary.getIntegerType()); |
| collectionRange.setIsRequired(true); |
| return collectionRange; |
| } |
| |
| public @NonNull Comment createComment(@NonNull String comment) { |
| Comment asComment = PivotFactory.eINSTANCE.createComment(); |
| asComment.setBody(comment); |
| return asComment; |
| } |
| |
| /** |
| * @since 1.10 |
| */ |
| public @NonNull EnumLiteralExp createEnumLiteralExp(@NonNull EnumerationLiteral value) { |
| EnumLiteralExp asEnumLiteralExp = PivotFactory.eINSTANCE.createEnumLiteralExp(); |
| asEnumLiteralExp.setReferredLiteral(value); |
| asEnumLiteralExp.setType(value.getOwningEnumeration()); |
| asEnumLiteralExp.setIsRequired(true); |
| return asEnumLiteralExp; |
| } |
| |
| public @NonNull IfExp createIfExp(@NonNull OCLExpression asCondition, @NonNull OCLExpression asThen, @NonNull OCLExpression asElse) { |
| Type commonType = metamodelManager.getCommonType(ClassUtil.nonNullState(asThen.getType()), TemplateParameterSubstitutions.EMPTY, |
| ClassUtil.nonNullState(asElse.getType()), TemplateParameterSubstitutions.EMPTY); |
| IfExp asIf = PivotFactory.eINSTANCE.createIfExp(); |
| asIf.setOwnedCondition(asCondition); |
| asIf.setOwnedThen(asThen); |
| asIf.setOwnedElse(asElse); |
| asIf.setType(commonType); |
| asIf.setIsRequired(asThen.isIsRequired() && asElse.isIsRequired()); |
| return asIf; |
| } |
| |
| public @NonNull Import createImport(@Nullable String name, @NonNull Namespace namespace) { |
| Import asImport = PivotFactory.eINSTANCE.createImport(); |
| asImport.setName(name); |
| asImport.setImportedNamespace(namespace); |
| asImport.setXmiidVersion(PivotConstants.XMIIDS_CURRENT); |
| return asImport; |
| } |
| |
| public @NonNull IntegerLiteralExp createIntegerLiteralExp(@NonNull Number integerSymbol) { |
| IntegerLiteralExp asInteger = PivotFactory.eINSTANCE.createIntegerLiteralExp(); |
| asInteger.setIntegerSymbol(integerSymbol); |
| asInteger.setType(standardLibrary.getIntegerType()); |
| asInteger.setIsRequired(true); |
| return asInteger; |
| } |
| |
| public @NonNull InvalidLiteralExp createInvalidExpression(/*Object object, String boundMessage, Throwable e*/) { |
| InvalidLiteralExp invalidLiteralExp = PivotFactory.eINSTANCE.createInvalidLiteralExp(); |
| invalidLiteralExp.setType(standardLibrary.getOclInvalidType()); |
| // invalidLiteralExp.setObject(object); |
| // invalidLiteralExp.setReason(boundMessage); |
| // invalidLiteralExp.setThrowable(e); |
| return invalidLiteralExp; |
| } |
| |
| public @NonNull IterateExp createIterateExp(@NonNull OCLExpression asSource, @NonNull Iteration asIteration, @NonNull List<@NonNull ? extends Variable> asIterators, @NonNull Variable asResult, @NonNull OCLExpression asBody) { |
| IterateExp asCallExp = PivotFactory.eINSTANCE.createIterateExp(); |
| asCallExp.setReferredIteration(asIteration); |
| asCallExp.setName(asIteration.getName()); |
| asCallExp.setOwnedSource(asSource); |
| asCallExp.getOwnedIterators().addAll(asIterators); |
| asCallExp.setOwnedResult(asResult); |
| asCallExp.setOwnedBody(asBody); |
| setOperationReturnType(asCallExp, asIteration); |
| return asCallExp; |
| } |
| |
| public @NonNull IteratorExp createIteratorExp(@NonNull OCLExpression asSource, @NonNull Iteration asIteration, @NonNull List<@NonNull ? extends Variable> asIterators, @NonNull OCLExpression asBody) { |
| IteratorExp asCallExp = PivotFactory.eINSTANCE.createIteratorExp(); |
| asCallExp.setReferredIteration(asIteration); |
| asCallExp.setName(asIteration.getName()); |
| asCallExp.setOwnedSource(asSource); |
| asCallExp.getOwnedIterators().addAll(asIterators); |
| asCallExp.setOwnedBody(asBody); |
| setOperationReturnType(asCallExp, asIteration); |
| return asCallExp; |
| } |
| |
| public @NonNull IteratorVariable createIteratorVariable(@NonNull String name, @NonNull Type asType, boolean isRequired) { |
| IteratorVariable asVariable = PivotFactory.eINSTANCE.createIteratorVariable(); |
| asVariable.setName(name); |
| asVariable.setType(asType); |
| asVariable.setIsRequired(isRequired); |
| return asVariable; |
| } |
| |
| public @NonNull LetExp createLetExp(@NonNull Variable asVariable, @NonNull OCLExpression asInExpression) { |
| LetExp asLetExp = PivotFactory.eINSTANCE.createLetExp(); |
| asLetExp.setOwnedVariable(asVariable); |
| asLetExp.setOwnedIn(asInExpression);; |
| asLetExp.setType(asInExpression.getType()); |
| asLetExp.setIsRequired(asInExpression.isIsRequired()); |
| asLetExp.setOwnedVariable(asVariable); |
| return asLetExp; |
| } |
| |
| public @NonNull LetVariable createLetVariable(@NonNull String name, @NonNull OCLExpression asInitExpression) { |
| LetVariable asVariable = PivotFactory.eINSTANCE.createLetVariable(); |
| asVariable.setName(name); |
| asVariable.setType(asInitExpression.getType()); |
| asVariable.setIsRequired(asInitExpression.isIsRequired()); |
| asVariable.setOwnedInit(asInitExpression); |
| return asVariable; |
| } |
| |
| public @NonNull LetVariable createLetVariable(@NonNull String name, @NonNull Type asType, boolean isRequired) { |
| LetVariable asVariable = PivotFactory.eINSTANCE.createLetVariable(); |
| asVariable.setName(name); |
| asVariable.setType(asType); |
| asVariable.setIsRequired(isRequired); |
| return asVariable; |
| } |
| |
| public @NonNull LetVariable createLetVariable(@NonNull String name, @NonNull Type asType, boolean isRequired, @NonNull OCLExpression asInitExpression) { |
| LetVariable asVariable = PivotFactory.eINSTANCE.createLetVariable(); |
| asVariable.setName(name); |
| asVariable.setType(asType); |
| asVariable.setIsRequired(isRequired); |
| asVariable.setOwnedInit(asInitExpression); |
| return asVariable; |
| } |
| |
| public @NonNull OCLExpression createMapLiteralExp(@NonNull MapType asType, @NonNull Iterable<MapLiteralPart> asParts) { |
| MapLiteralExp mapLiteralExp = PivotFactory.eINSTANCE.createMapLiteralExp(); |
| Iterables.addAll(mapLiteralExp.getOwnedParts(), asParts); |
| mapLiteralExp.setType(asType); |
| mapLiteralExp.setIsRequired(true); |
| return mapLiteralExp; |
| } |
| |
| public @NonNull MapLiteralPart createMapLiteralPart(@NonNull OCLExpression asKey, @NonNull OCLExpression asValue) { |
| MapLiteralPart mapLiteralPart = PivotFactory.eINSTANCE.createMapLiteralPart(); |
| mapLiteralPart.setOwnedKey(asKey); |
| mapLiteralPart.setOwnedValue(asValue); |
| // mapLiteralPart.setType(asItem.getType()); |
| // mapLiteralPart.setIsRequired(true); |
| return mapLiteralPart; |
| } |
| |
| @SuppressWarnings("deprecation") |
| public @NonNull NavigationCallExp createNavigationCallExp(@NonNull OCLExpression asSourceExpression, @NonNull Property asProperty) { |
| return PivotUtil.createNavigationCallExp(asSourceExpression, asProperty); |
| } |
| |
| public @NonNull NullLiteralExp createNullLiteralExp() { |
| NullLiteralExp asNull = PivotFactory.eINSTANCE.createNullLiteralExp(); |
| asNull.setType(standardLibrary.getOclVoidType()); |
| asNull.setIsRequired(false); |
| return asNull; |
| } |
| |
| public @NonNull OperationCallExp createOperationCallExp(@NonNull OCLExpression asSourceExpression, @NonNull String opName, @NonNull OCLExpression... asArguments) { |
| Type asType = ClassUtil.nonNullState(asSourceExpression.getType()); |
| CompleteClass completeClass = environmentFactory.getCompleteModel().getCompleteClass(asType); |
| int argumentCount = asArguments != null ? asArguments.length : 0; |
| int bestMatches = -1; |
| Operation bestOperation = null; |
| for (@NonNull Operation asOperation : completeClass.getOperations(FeatureFilter.SELECT_NON_STATIC, opName)) { |
| List<@NonNull ? extends TypedElement> asParameters = ClassUtil.nullFree(asOperation.getOwnedParameters()); |
| if ((asParameters.size() == argumentCount) && (asArguments != null)) { |
| int exactMatches = 0; |
| boolean gotOne = true; |
| for (int i = 0; i < argumentCount; i++) { |
| Type asParameterType = ClassUtil.nonNullState(asParameters.get(i).getType()); |
| if (asParameterType instanceof SelfType) { |
| Type asArgumentType = asArguments[i].getType(); |
| if (asArgumentType.conformsTo(standardLibrary, asType) && asType.conformsTo(standardLibrary, asArgumentType)) { |
| exactMatches++; |
| } |
| } |
| else { |
| Type asArgumentType = asArguments[i].getType(); |
| if (!asArgumentType.conformsTo(standardLibrary, asParameterType)) { |
| gotOne = false; |
| break; |
| } |
| if (asParameterType.conformsTo(standardLibrary, asArgumentType)) { |
| exactMatches++; |
| } |
| } |
| } |
| if (gotOne) { |
| if (exactMatches > bestMatches) { |
| bestMatches = exactMatches; |
| bestOperation = asOperation; |
| } |
| else if (exactMatches > bestMatches) { |
| bestOperation = null; |
| } |
| } |
| } |
| } |
| if (bestMatches < 0) { |
| throw new IllegalStateException("No match found for " + opName); |
| } |
| if (bestOperation == null) { |
| throw new IllegalStateException("Ambiguous match found for " + opName); |
| } |
| return createOperationCallExp(asSourceExpression, bestOperation, asArguments != null ? Lists.newArrayList(asArguments) : null); |
| } |
| |
| // public @NonNull OperationCallExp createOperationCallExp(@Nullable OCLExpression asSourceExpression, @NonNull Operation asOperation, @NonNull OCLExpression... asArguments) { |
| // return createOperationCallExp(asSourceExpression, asOperation, asArguments != null ? Lists.newArrayList(asArguments) : null); |
| // } |
| |
| public @NonNull OperationCallExp createOperationCallExp(@Nullable OCLExpression asSourceExpression, @NonNull Operation asOperation, @Nullable List<@NonNull OCLExpression> asArguments) { |
| OperationCallExp asOperationCallExp = PivotFactory.eINSTANCE.createOperationCallExp(); |
| asOperationCallExp.setOwnedSource(asSourceExpression); |
| asOperationCallExp.setReferredOperation(asOperation); |
| asOperationCallExp.setName(asOperation.getName()); |
| if (asArguments != null) { |
| asOperationCallExp.getOwnedArguments().addAll(asArguments); |
| } |
| setOperationReturnType(asOperationCallExp, asOperation); |
| return asOperationCallExp; |
| } |
| |
| public org.eclipse.ocl.pivot.@NonNull Package createPackage(@NonNull String name, @Nullable String nsPrefix, @Nullable String nsURI) { |
| Package asPackage = PivotFactory.eINSTANCE.createPackage(); |
| asPackage.setName(name); |
| if (nsPrefix != null) { |
| asPackage.setNsPrefix(nsPrefix); |
| } |
| if (nsURI != null) { |
| asPackage.setURI(nsURI); |
| } |
| return asPackage; |
| } |
| |
| public @NonNull Parameter createParameter(@NonNull TypedElement typedElement) { |
| String name = ClassUtil.nonNullState(typedElement.getName()); |
| Type type = ClassUtil.nonNullState(typedElement.getType()); |
| Parameter asParameter = PivotUtil.createParameter(name, type, typedElement.isIsRequired()); |
| return asParameter; |
| } |
| |
| /** |
| * @since 1.11 |
| */ |
| public @NonNull Parameter createParameter(@NonNull String name, @NonNull Type asType, boolean isRequired) { |
| return PivotUtil.createParameter(name, asType, isRequired); |
| } |
| |
| @Deprecated /* supply a representedParameter */ |
| public @NonNull ParameterVariable createParameterVariable(@NonNull String name, @NonNull Type asType, boolean isRequired) { |
| ParameterVariable asVariable = PivotFactory.eINSTANCE.createParameterVariable(); |
| asVariable.setName(name); |
| asVariable.setType(asType); |
| asVariable.setIsRequired(isRequired); |
| return asVariable; |
| } |
| |
| /** |
| * @since 1.10 |
| */ |
| public @NonNull ParameterVariable createParameterVariable(@NonNull Parameter asParameter) { |
| ParameterVariable asParameterVariable = PivotFactory.eINSTANCE.createParameterVariable(); |
| asParameterVariable.setName(asParameter.getName()); |
| asParameterVariable.setType(asParameter.getType()); |
| asParameterVariable.setIsRequired(asParameter.isIsRequired()); |
| asParameterVariable.setRepresentedParameter(asParameter); |
| return asParameterVariable; |
| } |
| |
| /** |
| * @since 1.11 |
| */ |
| public @NonNull PropertyCallExp createPropertyCallExp(@NonNull OCLExpression asSource, @NonNull Property asProperty) { |
| return PivotUtil.createPropertyCallExp(asSource, asProperty); |
| } |
| |
| public @NonNull RealLiteralExp createRealLiteralExp(@NonNull Number realSymbol) { |
| RealLiteralExp asReal = PivotFactory.eINSTANCE.createRealLiteralExp(); |
| asReal.setRealSymbol(realSymbol); |
| asReal.setType(standardLibrary.getRealType()); |
| asReal.setIsRequired(true); |
| return asReal; |
| } |
| |
| public @NonNull ResultVariable createResultVariable(@NonNull String name, @NonNull Type asType, boolean isRequired, @NonNull OCLExpression asInitExpression) { |
| ResultVariable asVariable = PivotFactory.eINSTANCE.createResultVariable(); |
| asVariable.setName(name); |
| asVariable.setType(asType); |
| asVariable.setIsRequired(isRequired); |
| asVariable.setOwnedInit(asInitExpression); |
| return asVariable; |
| } |
| |
| public @NonNull OCLExpression createShadowExp(org.eclipse.ocl.pivot.@NonNull Class asClass, @NonNull Iterable<ShadowPart> asParts) { |
| ShadowExp shadowExp = PivotFactory.eINSTANCE.createShadowExp(); |
| Iterables.addAll(shadowExp.getOwnedParts(), asParts); |
| shadowExp.setType(asClass); |
| shadowExp.setIsRequired(true); |
| return shadowExp; |
| } |
| |
| public @NonNull ShadowPart createShadowPart(@NonNull Property asProperty, @NonNull OCLExpression asValue) { |
| ShadowPart shadowPart = PivotFactory.eINSTANCE.createShadowPart(); |
| shadowPart.setReferredProperty(asProperty); |
| shadowPart.setType(asProperty.getType()); |
| shadowPart.setIsRequired(asProperty.isIsRequired()); |
| shadowPart.setOwnedInit(asValue); |
| return shadowPart; |
| } |
| |
| public @NonNull StringLiteralExp createStringLiteralExp(@NonNull String stringSymbol) { |
| StringLiteralExp asString = PivotFactory.eINSTANCE.createStringLiteralExp(); |
| asString.setStringSymbol(stringSymbol); |
| asString.setType(standardLibrary.getStringType()); |
| asString.setIsRequired(true); |
| return asString; |
| } |
| |
| public @NonNull TupleLiteralExp createTupleLiteralExp(@NonNull TupleType asType, @NonNull Iterable<TupleLiteralPart> asParts) { |
| TupleLiteralExp tupleLiteralExp = PivotFactory.eINSTANCE.createTupleLiteralExp(); |
| Iterables.addAll(tupleLiteralExp.getOwnedParts(), asParts); |
| tupleLiteralExp.setType(asType); |
| tupleLiteralExp.setIsRequired(true); |
| return tupleLiteralExp; |
| } |
| |
| public @NonNull TupleLiteralPart createTupleLiteralPart(@NonNull String name, @NonNull Type asType, boolean isRequired, @NonNull OCLExpression asValue) { |
| TupleLiteralPart tupleLiteralPart = PivotFactory.eINSTANCE.createTupleLiteralPart(); |
| tupleLiteralPart.setName(name); |
| tupleLiteralPart.setType(asType); |
| tupleLiteralPart.setIsRequired(isRequired); |
| tupleLiteralPart.setOwnedInit(asValue); |
| return tupleLiteralPart; |
| } |
| |
| public @NonNull TypeExp createTypeExp(@NonNull Type type) { |
| TypeExp asTypeExp = PivotFactory.eINSTANCE.createTypeExp(); |
| asTypeExp.setIsRequired(true); |
| asTypeExp.setReferredType(type); |
| asTypeExp.setName(type.getName()); |
| asTypeExp.setType(type instanceof TemplateParameter ? metamodelManager.getOclType("TemplateParameter") : standardLibrary.getClassType()); |
| asTypeExp.setTypeValue(type); |
| return asTypeExp; |
| } |
| |
| public @NonNull UnlimitedNaturalLiteralExp createUnlimitedNaturalLiteralExp(@NonNull Number unlimitedNaturalSymbol) { |
| UnlimitedNaturalLiteralExp asUnlimitedNatural = PivotFactory.eINSTANCE.createUnlimitedNaturalLiteralExp(); |
| asUnlimitedNatural.setUnlimitedNaturalSymbol(unlimitedNaturalSymbol); |
| asUnlimitedNatural.setType(standardLibrary.getUnlimitedNaturalType()); |
| asUnlimitedNatural.setIsRequired(true); |
| return asUnlimitedNatural; |
| } |
| |
| /** @deprecated Use appropriate derived Variable */ |
| @Deprecated |
| public @NonNull Variable createVariable(@NonNull String name, @NonNull OCLExpression asInitExpression) { |
| Variable asVariable = PivotUtil.createVariable(name, asInitExpression); |
| return asVariable; |
| } |
| |
| /** @deprecated Use appropriate derived Variable */ |
| @Deprecated |
| public @NonNull Variable createVariable(@NonNull String name, @NonNull Type asType, boolean isRequired, @Nullable OCLExpression asInitExpression) { |
| Variable asVariable = PivotUtil.createVariable(name, asType, isRequired, asInitExpression); |
| return asVariable; |
| } |
| |
| /** @deprecated Use appropriate derived Variable */ |
| @Deprecated |
| public @NonNull Variable createVariable(@NonNull TypedElement typedElement) { |
| String name = ClassUtil.nonNullState(typedElement.getName()); |
| Type type = ClassUtil.nonNullState(typedElement.getType()); |
| Variable asVariable = PivotUtil.createVariable(name, type, typedElement.isIsRequired(), null); |
| return asVariable; |
| } |
| |
| public @NonNull VariableExp createVariableExp(@NonNull VariableDeclaration asVariable) { |
| VariableExp asVariableExp = PivotUtil.createVariableExp(asVariable); |
| return asVariableExp; |
| } |
| |
| public org.eclipse.ocl.pivot.@NonNull Class getDataTypeClass() { |
| return ClassUtil.nonNullState(metamodelManager.getASClass(TypeId.DATA_TYPE_NAME)); |
| } |
| |
| public @NonNull Property getDataTypeValueProperty() { |
| return ClassUtil.nonNullState(NameUtil.getNameable(getDataTypeClass().getOwnedProperties(), PivotConstants.DATA_TYPE_VALUE_NAME)); |
| } |
| |
| public @NonNull EnvironmentFactory getEnvironmentFactory() { |
| return environmentFactory; |
| } |
| |
| protected @NonNull PivotMetamodelManager getMetamodelManager() { |
| return metamodelManager; |
| } |
| |
| public @NonNull StandardLibrary getStandardLibrary() { |
| return standardLibrary; |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| public <T extends EObject> void refreshList(@Nullable List<? super T> oldElements, @Nullable List<? extends T> newElements) { |
| PivotUtilInternal.refreshList(oldElements, newElements); |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| public void refreshName(@NonNull NamedElement pivotNamedElement, @Nullable String newName) { |
| String oldName = pivotNamedElement.getName(); |
| if ((newName != oldName) && ((newName == null) || !newName.equals(oldName))) { |
| pivotNamedElement.setName(newName); |
| } |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| public void refreshNsURI(org.eclipse.ocl.pivot.@NonNull Package pivotPackage, String newNsURI) { |
| String oldNsURI = pivotPackage.getURI(); |
| if ((newNsURI != oldNsURI) && ((newNsURI == null) || !newNsURI.equals(oldNsURI))) { |
| pivotPackage.setURI(newNsURI); |
| } |
| } |
| |
| /** |
| * Rewrite asTree and all its descendants to replace all "?." and "?->" navigations by their safe counterparts. |
| * @since 1.3 |
| */ |
| public void rewriteSafeNavigations(@NonNull Element asTree) { |
| // |
| // Locate all unsafe calls first to avoid CME from concurrent locate/rewrite. |
| // |
| List<@NonNull CallExp> unsafeCallExps = null; |
| if (asTree instanceof CallExp) { |
| unsafeCallExps = rewriteUnsafeCallExp_Gather(unsafeCallExps, (CallExp)asTree); |
| } |
| for (TreeIterator<EObject> tit = asTree.eAllContents(); tit.hasNext(); ) { |
| EObject eObject = tit.next(); |
| if (eObject instanceof CallExp) { |
| unsafeCallExps = rewriteUnsafeCallExp_Gather(unsafeCallExps, (CallExp)eObject); |
| } |
| } |
| // |
| // Rewrite the unsafe calls |
| // |
| if (unsafeCallExps != null) { |
| org.eclipse.ocl.pivot.Class oclAnyType = standardLibrary.getOclAnyType(); |
| Operation oclEqualsOperation = NameUtil.getNameable(oclAnyType.getOwnedOperations(), "="); |
| assert oclEqualsOperation != null; |
| org.eclipse.ocl.pivot.Class collectionType = standardLibrary.getCollectionType(); |
| Operation excludingOperation = NameUtil.getNameable(collectionType.getOwnedOperations(), "excluding"); |
| assert excludingOperation != null; |
| for (CallExp unsafeCallExp : unsafeCallExps) { |
| OCLExpression source = unsafeCallExp.getOwnedSource(); |
| assert source != null; |
| if (source.getType() instanceof CollectionType) { |
| rewriteUnsafeCollectionCallExp(metamodelManager, excludingOperation, unsafeCallExp); |
| } |
| else { |
| rewriteUnsafeObjectCallExp(metamodelManager, oclEqualsOperation, unsafeCallExp); |
| } |
| } |
| } |
| } |
| |
| private @Nullable List<@NonNull CallExp> rewriteUnsafeCallExp_Gather(@Nullable List<@NonNull CallExp> unsafeCallExps, @NonNull CallExp callExp) { |
| OCLExpression source = callExp.getOwnedSource(); |
| if ((source != null) && callExp.isIsSafe()) { |
| if (unsafeCallExps == null) { |
| unsafeCallExps = new ArrayList<@NonNull CallExp>(); |
| } |
| unsafeCallExps.add(callExp); |
| } |
| return unsafeCallExps; |
| } |
| |
| private void rewriteUnsafeCollectionCallExp(@NonNull PivotMetamodelManager metamodelManager, @NonNull Operation excludingOperation, @NonNull CallExp unsafeCollectionCallExp) { |
| unsafeCollectionCallExp.setIsSafe(false); |
| EObject eContainer = unsafeCollectionCallExp.eContainer(); |
| EReference eContainmentFeature = unsafeCollectionCallExp.eContainmentFeature(); |
| PivotUtilInternal.resetContainer(unsafeCollectionCallExp); |
| // |
| OCLExpression nullExpression = metamodelManager.createNullLiteralExp(); |
| OCLExpression safeCollectionCallExp = createOperationCallExp(unsafeCollectionCallExp, excludingOperation, Collections.singletonList(nullExpression)); |
| // |
| eContainer.eSet(eContainmentFeature, safeCollectionCallExp); |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| private void rewriteUnsafeObjectCallExp(@NonNull PivotMetamodelManager metamodelManager, @NonNull Operation oclEqualsOperation, @NonNull CallExp unsafeObjectCallExp) { |
| unsafeObjectCallExp.setIsSafe(false); |
| EObject eContainer = unsafeObjectCallExp.eContainer(); |
| EReference eContainmentFeature = unsafeObjectCallExp.eContainmentFeature(); |
| PivotUtilInternal.resetContainer(unsafeObjectCallExp); |
| OCLExpression oldSourceExpression = unsafeObjectCallExp.getOwnedSource(); |
| assert oldSourceExpression != null; |
| // |
| LetVariable unsafeSourceVariable = createLetVariable("unsafe", oldSourceExpression); |
| OCLExpression unsafeSourceExpression1 = createVariableExp(unsafeSourceVariable); |
| unsafeObjectCallExp.setOwnedSource(unsafeSourceExpression1); |
| // |
| OCLExpression unsafeSourceExpression2 = createVariableExp(unsafeSourceVariable); |
| OCLExpression nullExpression = metamodelManager.createNullLiteralExp(); |
| OCLExpression isUnsafeExpression = createOperationCallExp(unsafeSourceExpression2, oclEqualsOperation, Collections.singletonList(nullExpression)); |
| // |
| OCLExpression thenExpression = metamodelManager.createNullLiteralExp(); |
| OCLExpression safeObjectCallExp = metamodelManager.createIfExp(isUnsafeExpression, thenExpression, unsafeObjectCallExp); |
| // |
| LetExp safeExp = createLetExp(unsafeSourceVariable, safeObjectCallExp); |
| // |
| eContainer.eSet(eContainmentFeature, safeExp); |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| @Deprecated /* @deprecated not used -doesn't set behavioral type */ |
| public void setBehavioralType(@NonNull TypedElement targetElement, @NonNull TypedElement sourceElement) { |
| if (!sourceElement.eIsProxy()) { |
| Type type = PivotUtil.getBehavioralType(sourceElement); |
| if ((type != null) && type.eIsProxy()) { |
| type = null; |
| } |
| boolean isRequired = sourceElement.isIsRequired(); |
| setType(targetElement, type, isRequired); |
| } |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| public void setContextVariable(@NonNull ExpressionInOCL pivotSpecification, @NonNull String selfVariableName, @Nullable Type contextType, @Nullable Type contextInstance) { |
| Variable contextVariable = pivotSpecification.getOwnedContext(); |
| if (contextVariable == null) { |
| @NonNull ParameterVariable nonNullContextVariable = PivotFactory.eINSTANCE.createParameterVariable(); |
| contextVariable = nonNullContextVariable; |
| pivotSpecification.setOwnedContext(contextVariable); |
| if (contextType == null) { |
| contextType = standardLibrary.getOclVoidType(); |
| } |
| } |
| refreshName(contextVariable, selfVariableName); |
| setType(contextVariable, contextType, contextVariable.isIsRequired(), contextInstance); |
| } |
| |
| /** |
| * Set the operation/iteration return type and nullity in the asCallExp. This may involve creating a specialization |
| * of the operation/iteration return type and may require the use of a TemplateParameterSubstitutionHelper to |
| * compute inadequately modelled unique/ordered/size/nullity. |
| * |
| * @since 1.4 |
| */ |
| public void setOperationReturnType(@NonNull CallExp asCallExp, @NonNull Operation asOperation) { |
| OCLExpression asSourceExpression = asCallExp.getOwnedSource(); |
| Type sourceType; |
| Type sourceTypeValue; |
| if (asSourceExpression != null) { |
| sourceType = asSourceExpression.getType(); |
| sourceTypeValue = asSourceExpression.getTypeValue(); |
| } |
| else { |
| sourceType = null; |
| sourceTypeValue = null; |
| } |
| Type returnType = null; |
| Type formalType = asOperation.getType(); |
| boolean isTypeof = asOperation.isIsTypeof(); |
| boolean returnIsRequired = asOperation.isIsRequired(); |
| if ((formalType != null) && (sourceType != null)) { |
| if (isTypeof) { |
| returnType = metamodelManager.specializeType(formalType, asCallExp, sourceType, null); |
| } |
| else { |
| returnType = metamodelManager.specializeType(formalType, asCallExp, sourceType, sourceTypeValue); |
| } |
| } |
| // |
| // The flattening of collect() and consequently implicit-collect is not modelled accurately. |
| // Other library operations have subtle non-null/size computations. |
| // Therefore allow an operation-specific TemplateParameterSubstitutionHelper to adjust the regular functionality above. |
| // |
| LibraryFeature implementationClass = asOperation.getImplementation(); |
| if (implementationClass != null) { |
| Class<? extends LibraryFeature> libraryClass = implementationClass.getClass(); |
| TemplateParameterSubstitutionHelper substitutionHelper = TemplateParameterSubstitutionHelper.getHelper(libraryClass); |
| if (substitutionHelper != null) { |
| returnType = substitutionHelper.resolveReturnType(metamodelManager, asCallExp, returnType); |
| returnIsRequired = substitutionHelper.resolveReturnNullity(metamodelManager, asCallExp, returnIsRequired); |
| } |
| } |
| Type returnTypeValue; |
| if (isTypeof) { |
| returnTypeValue = returnType; |
| returnType = standardLibrary.getClassType(); |
| } |
| else { |
| returnTypeValue = null; |
| } |
| setType(asCallExp, returnType, returnIsRequired, returnTypeValue); |
| } |
| |
| public void setType(@NonNull OCLExpression asExpression, Type type, boolean isRequired, @Nullable Type typeValue) { |
| setType(asExpression, type, isRequired); |
| Type primaryTypeValue = typeValue != null ? metamodelManager.getPrimaryType(typeValue) : null; |
| if (primaryTypeValue != asExpression.getTypeValue()) { |
| asExpression.setTypeValue(primaryTypeValue); |
| } |
| } |
| |
| /** |
| * @since 1.4 |
| */ |
| public void setType(@NonNull VariableDeclaration asVariable, Type type, boolean isRequired, @Nullable Type typeValue) { |
| setType(asVariable, type, isRequired); |
| Type primaryTypeValue = typeValue != null ? metamodelManager.getPrimaryType(typeValue) : null; |
| if (primaryTypeValue != asVariable.getTypeValue()) { |
| asVariable.setTypeValue(primaryTypeValue); |
| } |
| } |
| |
| public void setType(@NonNull TypedElement asTypedElement, Type type, boolean isRequired) { |
| Type primaryType = type != null ? metamodelManager.getPrimaryType(type) : null; |
| if (primaryType != asTypedElement.getType()) { |
| asTypedElement.setType(primaryType); |
| } |
| boolean wasRequired = asTypedElement.isIsRequired(); |
| if (wasRequired != isRequired) { |
| asTypedElement.setIsRequired(isRequired); |
| } |
| if (primaryType != null) { |
| PivotUtil.debugWellContainedness(primaryType); |
| } |
| } |
| } |