blob: 80a40831963c44295afbadd8f4774ebd8791b07a [file] [log] [blame]
/*******************************************************************************
* 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
}
}