| /******************************************************************************* |
| * Copyright (c) 2022 Willink Transformation 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.examples.codegen.calling; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.examples.codegen.analyzer.BoxingAnalyzer; |
| import org.eclipse.ocl.examples.codegen.analyzer.CodeGenAnalyzer; |
| import org.eclipse.ocl.examples.codegen.calling.AbstractOperationCallingConvention.CGParameterStyle; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGBodiedProperty; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGClass; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGModelFactory; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGNavigationCallExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGParameter; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGProperty; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGPropertyAssignment; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement; |
| import org.eclipse.ocl.examples.codegen.java.CG2JavaVisitor; |
| import org.eclipse.ocl.examples.codegen.java.JavaStream; |
| import org.eclipse.ocl.examples.codegen.naming.ExecutableNameManager; |
| import org.eclipse.ocl.examples.codegen.utilities.CGUtil; |
| import org.eclipse.ocl.pivot.ExpressionInOCL; |
| import org.eclipse.ocl.pivot.LanguageExpression; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.TupleType; |
| import org.eclipse.ocl.pivot.Variable; |
| import org.eclipse.ocl.pivot.ids.PropertyId; |
| import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension; |
| import org.eclipse.ocl.pivot.utilities.ParserException; |
| import org.eclipse.ocl.pivot.utilities.PivotUtil; |
| import org.eclipse.ocl.pivot.utilities.ValueUtil; |
| |
| /** |
| * AbstractPropertyCallingConvention defines the default support for a property declaration or call. |
| */ |
| public abstract class AbstractPropertyCallingConvention extends AbstractCallingConvention implements PropertyCallingConvention |
| { |
| protected void createCGParameters(@NonNull ExecutableNameManager propertyNameManager, @Nullable ExpressionInOCL initExpression) {} |
| |
| protected @NonNull CGProperty createCGProperty(@NonNull CodeGenAnalyzer analyzer, @NonNull Property asProperty) { |
| return CGModelFactory.eINSTANCE.createCGConstrainedProperty(); |
| } |
| |
| @Override |
| public void createImplementation(@NonNull CodeGenAnalyzer analyzer, @NonNull CGProperty cgProperty) { |
| // assert (this instanceof StereotypePropertyCallingConvention) |
| // || (this instanceof ConstrainedPropertyCallingConvention) |
| // || (this instanceof NativePropertyCallingConvention) |
| // || (this instanceof ForeignPropertyCallingConvention); |
| ExecutableNameManager propertyNameManager = analyzer.getGlobalNameManager().usePropertyNameManager(cgProperty); |
| Property asProperty = CGUtil.getAST(cgProperty); |
| cgProperty.setRequired(asProperty.isIsRequired()); |
| LanguageExpression specification = asProperty.getOwnedExpression(); |
| if (specification != null) { |
| try { |
| EnvironmentFactoryInternalExtension environmentFactory = (EnvironmentFactoryInternalExtension)analyzer.getCodeGenerator().getEnvironmentFactory(); |
| ExpressionInOCL query = environmentFactory.parseSpecification(specification); |
| Variable contextVariable = query.getOwnedContext(); |
| if (contextVariable != null) { |
| CGParameter selfParameter = propertyNameManager.getSelfParameter(); |
| assert selfParameter.getAst() == contextVariable; |
| } |
| ((CGBodiedProperty)cgProperty).setBody(analyzer.createCGElement(CGValuedElement.class, query.getOwnedBody())); |
| } catch (ParserException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); // XXX |
| } |
| } |
| } |
| |
| @Override |
| public @NonNull CGProperty createProperty(@NonNull CodeGenAnalyzer analyzer, @NonNull Property asProperty, @Nullable ExpressionInOCL asExpressionInOCL) { |
| CGProperty cgProperty = createCGProperty(analyzer, asProperty); |
| assert cgProperty.getCallingConvention() == null; |
| cgProperty.setCallingConvention(this); |
| assert cgProperty.getAst() == null; |
| analyzer.initAst(cgProperty, asProperty, true); |
| ExecutableNameManager propertyNameManager = analyzer.getPropertyNameManager(cgProperty, asProperty); |
| createCGParameters(propertyNameManager, asExpressionInOCL); |
| assert cgProperty.eContainer() == null; |
| CGClass cgClass = analyzer.getCGClass(PivotUtil.getOwningClass(asProperty)); |
| cgClass.getProperties().add(cgProperty); |
| return cgProperty; |
| } |
| |
| @Override |
| public boolean generateEcoreBody(@NonNull CG2JavaVisitor cg2javaVisitor, @NonNull CGProperty cgProperty) { |
| // throw new UnsupportedOperationException("Unexpected " + this + " for an Ecore Property " + cgProperty); |
| // cg2javaVisitor.getJavaStream().append("Unexpected " + this + " for the Ecore Property for " + cgProperty); |
| return false; // requires manual implementation |
| } |
| |
| @Override |
| public boolean generateJavaAssignment(@NonNull CG2JavaVisitor cg2javaVisitor, @NonNull CGPropertyAssignment cgPropertyAssignment) { |
| JavaStream js = cg2javaVisitor.getJavaStream(); |
| CGProperty cgProperty = CGUtil.getReferredProperty(cgPropertyAssignment); |
| Property asProperty = CGUtil.getAST(cgProperty); |
| js.append("«"); |
| js.append(getClass().getSimpleName()); |
| js.append(".generateJavaAssignment "); // XXX debugging - change to abstract |
| js.append(asProperty.getOwningClass().getOwningPackage().getName()); |
| js.append("::"); |
| js.append(asProperty.getOwningClass().getName()); |
| js.append("::"); |
| js.append(asProperty.getName()); |
| js.append("»\n"); |
| return false; |
| } |
| |
| @Override |
| public boolean generateJavaDeclaration(@NonNull CG2JavaVisitor cg2javaVisitor, @NonNull CGProperty cgProperty) { |
| JavaStream js = cg2javaVisitor.getJavaStream(); |
| Property asProperty = CGUtil.getAST(cgProperty); |
| js.append("«"); |
| js.append(getClass().getSimpleName()); |
| js.append(".generateJavaDeclaration "); // XXX debugging - change to abstract |
| js.append(asProperty.getOwningClass().getOwningPackage().getName()); |
| js.append("::"); |
| js.append(asProperty.getOwningClass().getName()); |
| js.append("::"); |
| js.append(asProperty.getName()); |
| js.append("»\n"); |
| return true; |
| } |
| |
| @Override |
| public boolean generateJavaInitialization(@NonNull CG2JavaVisitor cg2javaVisitor, @NonNull CGProperty cgProperty) { |
| JavaStream js = cg2javaVisitor.getJavaStream(); |
| Property asProperty = CGUtil.getAST(cgProperty); |
| js.append("«"); |
| js.append(getClass().getSimpleName()); |
| js.append(".generateJavaInitialization "); // XXX debugging - change to abstract |
| js.append(asProperty.getOwningClass().getOwningPackage().getName()); |
| js.append("::"); |
| js.append(asProperty.getOwningClass().getName()); |
| js.append("::"); |
| js.append(asProperty.getName()); |
| js.append("»\n"); |
| return true; |
| } |
| |
| @Override |
| public void initCGParameter(@NonNull ExecutableNameManager propertyNameManager) { |
| propertyNameManager.createCGPropertyParameter(CGParameterStyle.SELF); |
| } |
| |
| @Override |
| public boolean isInlined() { |
| return false; |
| } |
| |
| @Override |
| public void rewriteWithBoxingAndGuards(@NonNull BoxingAnalyzer boxingAnalyzer, @NonNull CGProperty cgProperty) { |
| } |
| |
| @Override |
| public void rewriteWithBoxingAndGuards(@NonNull BoxingAnalyzer boxingAnalyzer, @NonNull CGNavigationCallExp cgNavigationCallExp) { |
| Property referredProperty = cgNavigationCallExp.getAsProperty(); |
| String referredPropertyName; |
| if (referredProperty == null) { |
| referredPropertyName = "unknown"; |
| } |
| else if (referredProperty.eContainer() instanceof TupleType) { |
| referredPropertyName = referredProperty.getName(); |
| } |
| else { |
| PropertyId referredPropertyId = referredProperty.getPropertyId(); |
| referredPropertyName = ValueUtil.getElementIdName(referredPropertyId); |
| } |
| boxingAnalyzer.rewriteAsGuarded(cgNavigationCallExp.getSource(), boxingAnalyzer.isSafe(cgNavigationCallExp), "source for '" + referredPropertyName + "'"); |
| rewriteWithSourceBoxing(boxingAnalyzer, cgNavigationCallExp); |
| rewriteWithResultBoxing(boxingAnalyzer, cgNavigationCallExp); |
| } |
| |
| @Override |
| public void rewriteWithBoxingAndGuards(@NonNull BoxingAnalyzer boxingAnalyzer, @NonNull CGPropertyAssignment cgPropertyAssignment) { |
| // XXX change to abstract to mandate handling |
| } |
| |
| protected void rewriteWithResultBoxing(@NonNull BoxingAnalyzer boxingAnalyzer, @NonNull CGNavigationCallExp cgNavigationCallExp) { |
| // XXX change to abstract to mandate handling |
| } |
| |
| protected void rewriteWithSourceBoxing(@NonNull BoxingAnalyzer boxingAnalyzer, @NonNull CGNavigationCallExp cgNavigationCallExp) { |
| // XXX change to abstract to mandate handling |
| } |
| } |