| /******************************************************************************* |
| * Copyright (c) 2013, 2017 CEA LIST 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(CEA LIST) - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ocl.examples.codegen.oclinecore; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.emf.codegen.ecore.genmodel.GenModel; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.ETypedElement; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor; |
| import org.eclipse.ocl.examples.codegen.analyzer.BoxingAnalyzer; |
| import org.eclipse.ocl.examples.codegen.analyzer.CodeGenAnalyzer; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGOperation; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGPackage; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGProperty; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement; |
| import org.eclipse.ocl.examples.codegen.java.JavaCodeGenerator; |
| import org.eclipse.ocl.pivot.AnyType; |
| 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.Constraint; |
| import org.eclipse.ocl.pivot.Element; |
| import org.eclipse.ocl.pivot.ExpressionInOCL; |
| import org.eclipse.ocl.pivot.IfExp; |
| import org.eclipse.ocl.pivot.LetExp; |
| import org.eclipse.ocl.pivot.LetVariable; |
| import org.eclipse.ocl.pivot.LoopExp; |
| import org.eclipse.ocl.pivot.OCLExpression; |
| import org.eclipse.ocl.pivot.Operation; |
| import org.eclipse.ocl.pivot.OperationCallExp; |
| import org.eclipse.ocl.pivot.PrimitiveLiteralExp; |
| import org.eclipse.ocl.pivot.PrimitiveType; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.PropertyCallExp; |
| import org.eclipse.ocl.pivot.StandardLibrary; |
| import org.eclipse.ocl.pivot.TupleLiteralExp; |
| import org.eclipse.ocl.pivot.TupleLiteralPart; |
| import org.eclipse.ocl.pivot.TupleType; |
| import org.eclipse.ocl.pivot.TypeExp; |
| import org.eclipse.ocl.pivot.Variable; |
| import org.eclipse.ocl.pivot.VariableDeclaration; |
| import org.eclipse.ocl.pivot.VariableExp; |
| import org.eclipse.ocl.pivot.ids.OperationId; |
| import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal; |
| import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal; |
| 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.utilities.ClassUtil; |
| import org.eclipse.ocl.pivot.utilities.NameUtil; |
| import org.eclipse.ocl.pivot.utilities.PivotConstants; |
| import org.eclipse.ocl.pivot.utilities.PivotHelper; |
| import org.eclipse.ocl.pivot.utilities.PivotUtil; |
| |
| /** |
| * OCLinEcoreCodeGenerator supports generation of the inline OCL-defined content of a Ecore *Impl file. |
| */ |
| public class OCLinEcoreCodeGenerator extends JavaCodeGenerator |
| { |
| public static class EcoreBoxingAnalyzer extends BoxingAnalyzer |
| { |
| private EcoreBoxingAnalyzer(@NonNull CodeGenAnalyzer analyzer) { |
| super(analyzer); |
| } |
| |
| @Override |
| public @Nullable Object visitCGOperation(@NonNull CGOperation cgOperation) { |
| super.visitCGOperation(cgOperation); |
| Element asOperation = cgOperation.getAst(); |
| if (asOperation instanceof Operation) { |
| EObject eObject = ((Operation)asOperation).getESObject(); |
| if (eObject instanceof ETypedElement) { |
| EClassifier eType = ((ETypedElement)eObject).getEType(); |
| if (eType != null) { |
| rewriteAsEcore(cgOperation.getBody(), eType); |
| } |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public @Nullable Object visitCGProperty(@NonNull CGProperty cgProperty) { |
| super.visitCGProperty(cgProperty); |
| Element asProperty = cgProperty.getAst(); |
| if (asProperty instanceof Property) { |
| EObject eObject = ((Property)asProperty).getESObject(); |
| if (eObject instanceof ETypedElement) { |
| EClassifier eType = ((ETypedElement)eObject).getEType(); |
| if (eType != null) { |
| rewriteAsEcore(cgProperty.getBody(), eType); |
| } |
| } |
| } |
| return null; |
| } |
| } |
| |
| /** |
| * StatusAnalyzer traverses an OCLExpression tree identifying those nodes that create status and can be rewritten. |
| * |
| * During the visit a Boolean return signals: |
| * true - is a Boolean Tuple.status that can be rewritten as OclAny. |
| * false - is a Boolean Tuple.status that cannot be rewritten as OclAny. |
| * null- is not a Boolean Tuple.status |
| */ |
| protected static class StatusAnalyzer extends AbstractExtendingVisitor<@Nullable Boolean, @NonNull OCLinEcoreCodeGenerator> |
| { |
| protected final @NonNull StandardLibrary standardLibrary; |
| private @NonNull Map<@NonNull VariableDeclaration, @Nullable Boolean> variable2verdict = new HashMap<>(); |
| private @NonNull List<@NonNull OCLExpression> canBeOclAnyExpressions = new ArrayList<>(); |
| private @NonNull List<@NonNull OperationCallExp> impliesExpressions = new ArrayList<>(); |
| private @NonNull List<@NonNull PropertyCallExp> statusAccesses = new ArrayList<>(); |
| |
| protected StatusAnalyzer(@NonNull OCLinEcoreCodeGenerator context) { |
| super(context); |
| this.standardLibrary = context.getEnvironmentFactory().getStandardLibrary(); |
| } |
| |
| protected @Nullable Boolean visit(/*@NonNull*/ OCLExpression object) { |
| Boolean itemVerdict = object.accept(this); |
| if (itemVerdict == Boolean.TRUE) { |
| assert !(object instanceof TupleLiteralExp); |
| assert !canBeOclAnyExpressions.contains(object); |
| canBeOclAnyExpressions.add(object); |
| } |
| return itemVerdict; |
| } |
| |
| @Override |
| public @Nullable Boolean visiting(@NonNull Visitable visitable) { |
| throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName()); |
| } |
| |
| // @Override |
| // public @Nullable Boolean visitBooleanLiteralExp(@NonNull BooleanLiteralExp object) { |
| // return true; |
| // } |
| |
| @Override |
| public @Nullable Boolean visitCallExp(@NonNull CallExp object) { |
| if (!context.booleanType.conformsTo(standardLibrary, PivotUtil.getType(object))) { |
| return null; |
| } |
| OCLExpression asSource = PivotUtil.getOwnedSource(object); |
| Boolean sourceVerdict = visit(asSource); |
| if (sourceVerdict == null) { |
| return sourceVerdict; |
| } |
| return true; |
| } |
| |
| @Override |
| public @Nullable Boolean visitCollectionItem(@NonNull CollectionItem object) { |
| return visit(object); |
| } |
| |
| @Override |
| public @Nullable Boolean visitCollectionLiteralExp(@NonNull CollectionLiteralExp object) { |
| boolean canBeOclAny = true; |
| for (@NonNull CollectionLiteralPart part : PivotUtil.getOwnedParts(object)) { |
| Boolean itemVerdict = visit(part); |
| if (itemVerdict == null) { |
| return null; |
| } |
| if (itemVerdict == false) { |
| canBeOclAny = false; |
| } |
| } |
| return canBeOclAny; |
| } |
| |
| @Override |
| public @Nullable Boolean visitCollectionRange(@NonNull CollectionRange object) { |
| return null; |
| } |
| |
| @Override |
| public @Nullable Boolean visitExpressionInOCL(@NonNull ExpressionInOCL object) { |
| return visit(object.getOwnedBody()); |
| } |
| |
| @Override |
| public @Nullable Boolean visitIfExp(@NonNull IfExp object) { |
| Boolean thenVerdict = visit(object.getOwnedThen()); |
| Boolean elseVerdict = visit(object.getOwnedElse()); |
| if ((thenVerdict == null) || (elseVerdict == null)) { |
| return null; |
| } |
| return thenVerdict && elseVerdict; |
| } |
| |
| @Override |
| public @Nullable Boolean visitLetExp(@NonNull LetExp object) { |
| object.getOwnedVariable().accept(this); |
| return visit(object.getOwnedIn()); |
| } |
| |
| @Override |
| public @Nullable Boolean visitLetVariable(@NonNull LetVariable object) { |
| Boolean verdict = visit(object.getOwnedInit()); |
| variable2verdict.put(object, verdict); |
| return verdict; |
| } |
| |
| @Override |
| public @Nullable Boolean visitLoopExp(@NonNull LoopExp object) { |
| return null; |
| } |
| |
| @Override |
| public @Nullable Boolean visitOCLExpression(@NonNull OCLExpression object) { |
| System.out.println("Unsupported " + object.eClass().getName() + " for " + getClass().getSimpleName()); |
| return null; |
| } |
| |
| // |
| // An OperationCallExp propagates a Tuple status if it is an implies guard for a Tyuple status |
| // |
| @Override |
| public @Nullable Boolean visitOperationCallExp(@NonNull OperationCallExp object) { |
| Operation referredOperation = PivotUtil.getReferredOperation(object); |
| if (referredOperation.getOperationId() == OperationId.BOOLEAN_IMPLIES) { |
| OCLExpression argument = PivotUtil.getOwnedArgument(object, 0); |
| Boolean argumentVerdict = visit(argument); |
| if (argumentVerdict != null) { |
| impliesExpressions.add(object); |
| } |
| return argumentVerdict; |
| |
| } |
| /* |
| // - it can return a Boolean |
| // - one of more of source/arguments are a Tuple status passable as OclAny |
| //-- which is almost nothing |
| if (!context.booleanType.conformsTo(standardLibrary, PivotUtil.getType(object))) { |
| return null; |
| } |
| OCLExpression asSource = PivotUtil.getOwnedSource(object); |
| Boolean sourceVerdict = visit(asSource); |
| if (sourceVerdict == null) { // ?? ==null |
| return null; |
| } |
| boolean canBeStatusExpression = false; |
| boolean canBeOclAnyExpression = sourceVerdict.booleanValue(); |
| Type owningClass = PivotUtil.getOwningClass(referredOperation); |
| if (!context.oclAnyType.conformsTo(standardLibrary, owningClass)) { |
| canBeOclAnyExpression = false; |
| } |
| if (context.booleanType.conformsTo(standardLibrary, owningClass)) { |
| canBeStatusExpression = true; |
| } |
| Iterable<@NonNull Parameter> ownedParameters = PivotUtil.getOwnedParameters(referredOperation); |
| Iterable<@NonNull OCLExpression> ownedArguments = PivotUtil.getOwnedArguments(object); |
| Iterator<@NonNull Parameter> itParameter = ownedParameters.iterator(); |
| Iterator<@NonNull OCLExpression> itArgument = ownedArguments.iterator(); |
| while (itParameter.hasNext() && itArgument.hasNext()) { |
| Parameter asParameter = itParameter.next(); |
| OCLExpression asArgument = itArgument.next(); |
| Boolean argumentVerdict = visit(asArgument); |
| if (argumentVerdict == null) { |
| return argumentVerdict; |
| } |
| Type parameterClass = PivotUtil.getType(asParameter); |
| if (!context.oclAnyType.conformsTo(standardLibrary, parameterClass)) { |
| canBeOclAnyExpression = false; |
| } |
| if (context.booleanType.conformsTo(standardLibrary, parameterClass)) { |
| canBeStatusExpression = true; |
| } |
| } |
| if (!canBeStatusExpression) { |
| return null; |
| } |
| return canBeOclAnyExpression; */ |
| return null; |
| } |
| |
| @Override |
| public @Nullable Boolean visitPrimitiveLiteralExp(@NonNull PrimitiveLiteralExp object) { |
| return null; |
| } |
| |
| // |
| // A PropertyCallExp can return a Tuple status if the source is a TupleLiteralExp and the status property is accessed. |
| // |
| @Override |
| public @Nullable Boolean visitPropertyCallExp(@NonNull PropertyCallExp object) { |
| OCLExpression ownedSource = object.getOwnedSource(); |
| if (ownedSource instanceof TupleLiteralExp){ |
| TupleLiteralExp tupleLiteralExp = (TupleLiteralExp)ownedSource; |
| TupleType tupleType = PivotUtil.getType(tupleLiteralExp); |
| Property statusPart = PivotUtilInternal.getStatusTupleTypeStatusPart(tupleType); |
| if (statusPart != null){ |
| statusAccesses.add(object); |
| return true; |
| } |
| } |
| // Boolean superVerdict = super.visitPropertyCallExp(object); |
| // if (superVerdict != Boolean.TRUE) { |
| // return superVerdict; |
| // } |
| return null; |
| } |
| |
| @Override |
| public @Nullable Boolean visitTupleLiteralExp(@NonNull TupleLiteralExp object) { |
| Property statusPart = PivotUtilInternal.getStatusTupleTypeStatusPart(PivotUtil.getType(object)); |
| if (statusPart != null){ |
| return true; |
| } |
| return null; |
| } |
| |
| @Override |
| public @Nullable Boolean visitTypeExp(@NonNull TypeExp object) { |
| return null; |
| } |
| |
| @Override |
| public @Nullable Boolean visitVariableExp(@NonNull VariableExp object) { |
| return variable2verdict.get(object.getReferredVariable()); |
| } |
| } |
| |
| public static void generatePackage(@NonNull GenPackage genPackage, |
| @NonNull Map<String, String> uri2body, @NonNull Map<GenPackage, String> constantsTexts) { |
| Resource genResource = ClassUtil.nonNullState(genPackage.eResource()); |
| EnvironmentFactoryInternal environmentFactory = PivotUtilInternal.getEnvironmentFactory(genResource); |
| OCLinEcoreCodeGenerator generator = new OCLinEcoreCodeGenerator(environmentFactory, genPackage); |
| generator.generate(uri2body, constantsTexts); |
| } |
| |
| protected final @NonNull OCLinEcoreGlobalContext globalContext; |
| protected final @NonNull StandardLibraryInternal standardLibrary; |
| protected final @NonNull CodeGenAnalyzer cgAnalyzer; |
| protected final @NonNull GenPackage genPackage; |
| protected final @NonNull PivotHelper asHelper; |
| protected final @NonNull AnyType oclAnyType; |
| protected final @NonNull PrimitiveType booleanType; |
| protected final @NonNull PrimitiveType integerType; |
| private @Nullable Map<@NonNull ExpressionInOCL, @NonNull ExpressionInOCL> newQuery2oldQuery = null; |
| |
| protected OCLinEcoreCodeGenerator(@NonNull EnvironmentFactoryInternal environmentFactory, @NonNull GenPackage genPackage) { |
| super(environmentFactory); |
| this.standardLibrary = environmentFactory.getStandardLibrary(); |
| GenModel genModel = ClassUtil.nonNullModel(genPackage.getGenModel()); |
| genModel.reconcile(); |
| metamodelManager.addGenModel(genModel); |
| getOptions().setUseNullAnnotations(OCLinEcoreGenModelGeneratorAdapter.useNullAnnotations(genModel)); |
| this.cgAnalyzer = new CodeGenAnalyzer(this); |
| this.genPackage = genPackage; |
| this.globalContext = new OCLinEcoreGlobalContext(this, genPackage); |
| asHelper = new PivotHelper(environmentFactory); |
| this.oclAnyType = standardLibrary.getOclAnyType(); |
| this.integerType = standardLibrary.getIntegerType(); |
| this.booleanType = standardLibrary.getBooleanType(); |
| // CommonSubexpressionEliminator.CSE_BUILD.setState(true); |
| // CommonSubexpressionEliminator.CSE_PLACES.setState(true); |
| // CommonSubexpressionEliminator.CSE_PRUNE.setState(true); |
| // CommonSubexpressionEliminator.CSE_PULL_UP.setState(true); |
| // CommonSubexpressionEliminator.CSE_PUSH_UP.setState(true); |
| // CommonSubexpressionEliminator.CSE_REWRITE.setState(true); |
| } |
| |
| @Override |
| public @NonNull BoxingAnalyzer createBoxingAnalyzer() { |
| return new EcoreBoxingAnalyzer(cgAnalyzer); |
| } |
| |
| protected void generate(@NonNull Map<String, String> uri2body, @NonNull Map<GenPackage, String> constantsTexts) { |
| Map<@NonNull ExpressionInOCL, @NonNull ExpressionInOCL> newQuery2oldQuery2 = newQuery2oldQuery = new HashMap<>(); |
| try { |
| EPackage ecorePackage = genPackage.getEcorePackage(); |
| org.eclipse.ocl.pivot.Package asPackage = metamodelManager.getASOfEcore(org.eclipse.ocl.pivot.Package.class, ecorePackage); |
| assert asPackage != null; |
| AS2CGVisitor as2cgVisitor = new OCLinEcoreAS2CGVisitor(cgAnalyzer, globalContext); |
| CGPackage cgPackage = (CGPackage) ClassUtil.nonNullState(asPackage.accept(as2cgVisitor)); |
| optimize(cgPackage); |
| OCLinEcoreCG2JavaVisitor cg2java = new OCLinEcoreCG2JavaVisitor(this, genPackage, cgPackage); |
| Map<String, String> results = cg2java.generateBodies(); |
| for (Map.Entry<String, String> entry : results.entrySet()) { |
| uri2body.put(entry.getKey(), entry.getValue()); |
| } |
| Iterable<@NonNull CGValuedElement> sortedGlobals = prepareGlobals(); |
| String constantsText = cg2java.generateConstants(sortedGlobals); |
| constantsTexts.put(genPackage, constantsText); |
| } |
| finally { |
| for (Map.Entry<@NonNull ExpressionInOCL, @NonNull ExpressionInOCL> entry : newQuery2oldQuery2.entrySet()) { |
| ExpressionInOCL newQuery = entry.getKey(); |
| ExpressionInOCL oldQuery = entry.getValue(); |
| Constraint eContainer = (Constraint) newQuery.eContainer(); |
| PivotUtilInternal.resetContainer(newQuery); |
| eContainer.setOwnedSpecification(oldQuery); |
| } |
| newQuery2oldQuery = null; |
| } |
| } |
| |
| @Override |
| public @NonNull CodeGenAnalyzer getAnalyzer() { |
| return cgAnalyzer; |
| } |
| |
| @Override |
| public @NonNull OCLinEcoreGlobalContext getGlobalContext() { |
| return globalContext; |
| } |
| |
| protected @NonNull ExpressionInOCL rewriteQuery(@NonNull ExpressionInOCL oldQuery, @NonNull String qualifiedConstraintName) { |
| OCLExpression oldBody = oldQuery.getOwnedBody(); |
| if ((oldBody instanceof BooleanLiteralExp) && ((BooleanLiteralExp)oldBody).isBooleanSymbol()) { |
| return oldQuery; // Unconditionally true (typically obsolete) constraint needs no added complexity |
| } |
| ExpressionInOCL asSynthesizedQuery = EcoreUtil.copy(oldQuery); |
| StatusAnalyzer statusAnalyzer = new StatusAnalyzer(this); |
| Boolean verdict = asSynthesizedQuery.accept(statusAnalyzer); |
| if (verdict == Boolean.TRUE) { |
| for (@NonNull PropertyCallExp asPropertyCallExp : statusAnalyzer.statusAccesses) { |
| TupleLiteralExp asTupleValue = (TupleLiteralExp)asPropertyCallExp.getOwnedSource(); |
| assert asTupleValue != null; |
| OCLExpression asExpression = rewriteTupleLiteralExp(asTupleValue); |
| EObject eContainer = asPropertyCallExp.eContainer(); |
| EReference eContainmentFeature = asPropertyCallExp.eContainmentFeature(); |
| PivotUtilInternal.resetContainer(asPropertyCallExp); |
| eContainer.eSet(eContainmentFeature, asExpression); // FIXME isMany |
| } |
| for (@NonNull OCLExpression asExpression : statusAnalyzer.canBeOclAnyExpressions) { |
| if (asExpression.eContainer() != null) { |
| asExpression.setType(oclAnyType); |
| } |
| } |
| for (@NonNull OperationCallExp impliesExpression : statusAnalyzer.impliesExpressions) { |
| OCLExpression conditionExpression = PivotUtil.getOwnedSource(impliesExpression); |
| OCLExpression thenExpression = PivotUtil.getOwnedArgument(impliesExpression, 0); |
| OCLExpression elseExpression = asHelper.createBooleanLiteralExp(true); |
| PivotUtilInternal.resetContainer(conditionExpression); |
| PivotUtilInternal.resetContainer(thenExpression); |
| OCLExpression ifExpression = asHelper.createIfExp(conditionExpression, thenExpression, elseExpression); |
| EObject eContainer = impliesExpression.eContainer(); |
| EReference eContainmentFeature = impliesExpression.eContainmentFeature(); |
| PivotUtilInternal.resetContainer(impliesExpression); |
| eContainer.eSet(eContainmentFeature, ifExpression); // FIXME isMany |
| } |
| asSynthesizedQuery.setBody(null); |
| } |
| Variable asSelfVariable = ClassUtil.nonNullState(asSynthesizedQuery.getOwnedContext()); |
| Variable asDiagnosticsVariable = asHelper.createParameterVariable("diagnostics", oclAnyType, false); |
| asSynthesizedQuery.getOwnedParameters().add(asDiagnosticsVariable); |
| Variable asContextVariable = asHelper.createParameterVariable("context", oclAnyType, false); |
| asSynthesizedQuery.getOwnedParameters().add(asContextVariable); |
| // |
| // Cache the result in a let-variable |
| // |
| OCLExpression asResultVariableInit = asSynthesizedQuery.getOwnedBody(); |
| assert asResultVariableInit != null; |
| LetVariable asResultVariable = asHelper.createLetVariable("result", asResultVariableInit); |
| // |
| // Cache the severity in a let-variable |
| // |
| OCLExpression asSeverityVariableInit = asHelper.createOperationCallExp(asHelper.createStringLiteralExp(qualifiedConstraintName), "getSeverity"); |
| LetVariable asSeverityVariable = asHelper.createLetVariable("severity", integerType, asSeverityVariableInit.isIsRequired(), asSeverityVariableInit); |
| // |
| // Build from the bottom, starting with logging the status. |
| // |
| OCLExpression asLogExpression = asHelper.createOperationCallExp(asHelper.createStringLiteralExp(qualifiedConstraintName), "logDiagnostic", |
| asHelper.createVariableExp(asSelfVariable), asHelper.createNullLiteralExp(), |
| asHelper.createVariableExp(asDiagnosticsVariable), asHelper.createVariableExp(asContextVariable), |
| asHelper.createNullLiteralExp()/*asMessageExp*/, asHelper.createVariableExp(asSeverityVariable), |
| asHelper.createVariableExp(asResultVariable), asHelper.createIntegerLiteralExp(0)); |
| // |
| // Wrapped in the status let-variable |
| // |
| OCLExpression asResultExpression = asHelper.createLetExp(asResultVariable, asLogExpression); |
| // |
| // Wrapped in an interesting severity guard |
| // |
| OCLExpression asCondition = asHelper.createOperationCallExp(asHelper.createVariableExp(asSeverityVariable), "<=", asHelper.createIntegerLiteralExp(0)); |
| OCLExpression asSeverityExpression = asHelper.createIfExp(asCondition, asHelper.createBooleanLiteralExp(true), asResultExpression); |
| // |
| // Wrapped in the severity let-variable |
| // |
| asSynthesizedQuery.setOwnedBody(asHelper.createLetExp(asSeverityVariable, asSeverityExpression)); |
| // |
| // Install replacment query in the original Constraint. |
| // |
| Constraint eContainer = (Constraint) oldQuery.eContainer(); |
| PivotUtilInternal.resetContainer(oldQuery); |
| eContainer.setOwnedSpecification(asSynthesizedQuery); |
| Map<@NonNull ExpressionInOCL, @NonNull ExpressionInOCL> newQuery2oldQuery2 = newQuery2oldQuery; |
| assert newQuery2oldQuery2 != null; |
| newQuery2oldQuery2.put(asSynthesizedQuery, oldQuery); |
| return asSynthesizedQuery; |
| } |
| |
| private @NonNull OCLExpression rewriteTupleLiteralExp(@NonNull TupleLiteralExp asTupleLiteralExp) { |
| Iterable<@NonNull TupleLiteralPart> asTupleParts = PivotUtil.getOwnedParts(asTupleLiteralExp); |
| LetVariable asStatusVariable = null; |
| TupleLiteralPart asStatusPart = NameUtil.getNameable(asTupleParts, PivotConstants.STATUS_PART_NAME); |
| if (asStatusPart == null) { |
| return asTupleLiteralExp; |
| } |
| OCLExpression asStatusInit = asStatusPart.getOwnedInit(); |
| if (asStatusInit == null) { |
| return asTupleLiteralExp; |
| } |
| // |
| // Cache the status in a let-variable |
| // |
| PivotUtilInternal.resetContainer(asStatusInit); |
| asStatusVariable = asHelper.createLetVariable("status", standardLibrary.getBooleanType(), asStatusInit.isIsRequired(), asStatusInit); |
| asStatusPart.setOwnedInit(asHelper.createVariableExp(asStatusVariable)); |
| // |
| // Wrap the tuple in a status guard for failure. |
| // |
| PivotUtilInternal.resetContainer(asTupleLiteralExp); |
| OCLExpression asCondition = asHelper.createOperationCallExp(asHelper.createVariableExp(asStatusVariable), "=", asHelper.createBooleanLiteralExp(true)); |
| OCLExpression asStatusExp = asHelper.createIfExp(asCondition, asHelper.createBooleanLiteralExp(true), asTupleLiteralExp); |
| return asHelper.createLetExp(asStatusVariable, asStatusExp); |
| } |
| } |