blob: 7942497b476276d0957187e885b5b5c22e7142ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2017 Willink Transformations 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 - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.xtext.base.cs2as;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.pivot.AnyType;
import org.eclipse.ocl.pivot.DataType;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.LambdaType;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.Parameter;
import org.eclipse.ocl.pivot.PivotPackage;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.TemplateParameter;
import org.eclipse.ocl.pivot.TemplateableElement;
import org.eclipse.ocl.pivot.TupleType;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.internal.executor.ExecutorTuplePart;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.xtext.base.utilities.ElementUtil;
import org.eclipse.ocl.xtext.basecs.AnnotationCS;
import org.eclipse.ocl.xtext.basecs.ClassCS;
import org.eclipse.ocl.xtext.basecs.ConstraintCS;
import org.eclipse.ocl.xtext.basecs.DataTypeCS;
import org.eclipse.ocl.xtext.basecs.DocumentationCS;
import org.eclipse.ocl.xtext.basecs.EnumerationCS;
import org.eclipse.ocl.xtext.basecs.EnumerationLiteralCS;
import org.eclipse.ocl.xtext.basecs.LambdaTypeCS;
import org.eclipse.ocl.xtext.basecs.ModelElementCS;
import org.eclipse.ocl.xtext.basecs.ModelElementRefCS;
import org.eclipse.ocl.xtext.basecs.MultiplicityBoundsCS;
import org.eclipse.ocl.xtext.basecs.MultiplicityStringCS;
import org.eclipse.ocl.xtext.basecs.NamedElementCS;
import org.eclipse.ocl.xtext.basecs.OperationCS;
import org.eclipse.ocl.xtext.basecs.PackageCS;
import org.eclipse.ocl.xtext.basecs.PackageOwnerCS;
import org.eclipse.ocl.xtext.basecs.ParameterCS;
import org.eclipse.ocl.xtext.basecs.PathElementCS;
import org.eclipse.ocl.xtext.basecs.PathNameCS;
import org.eclipse.ocl.xtext.basecs.PrimitiveTypeRefCS;
import org.eclipse.ocl.xtext.basecs.StructuralFeatureCS;
import org.eclipse.ocl.xtext.basecs.StructuredClassCS;
import org.eclipse.ocl.xtext.basecs.TemplateBindingCS;
import org.eclipse.ocl.xtext.basecs.TemplateParameterSubstitutionCS;
import org.eclipse.ocl.xtext.basecs.TemplateSignatureCS;
import org.eclipse.ocl.xtext.basecs.TuplePartCS;
import org.eclipse.ocl.xtext.basecs.TupleTypeCS;
import org.eclipse.ocl.xtext.basecs.TypeParameterCS;
import org.eclipse.ocl.xtext.basecs.TypeRefCS;
import org.eclipse.ocl.xtext.basecs.TypedRefCS;
import org.eclipse.ocl.xtext.basecs.TypedTypeRefCS;
import org.eclipse.ocl.xtext.basecs.WildcardTypeRefCS;
import org.eclipse.ocl.xtext.basecs.util.AbstractExtendingBaseCSVisitor;
import org.eclipse.ocl.xtext.basecs.util.VisitableCS;
public class BaseCSPreOrderVisitor extends AbstractExtendingBaseCSVisitor<Continuation<?>, @NonNull CS2ASConversion>
{
protected static class ClassSupersContinuation extends SingleContinuation<StructuredClassCS>
{
private static @NonNull Dependency[] computeDependencies(@NonNull CS2ASConversion context, @NonNull StructuredClassCS csElement) {
List<TypedRefCS> csSuperTypes = csElement.getOwnedSuperTypes();
if (csSuperTypes.isEmpty()) {
return null;
}
List<@NonNull Dependency> dependencies = new ArrayList<>();
for (TypedRefCS csSuperType : csSuperTypes) {
if (csSuperType != null) {
dependencies.add(new PivotDependency(csSuperType));
}
}
return dependencies.toArray(new @NonNull Dependency[dependencies.size()]);
}
public ClassSupersContinuation(@NonNull CS2ASConversion context, org.eclipse.ocl.pivot.Class pivotParent, @NonNull StructuredClassCS csElement) {
super(context, pivotParent, null, csElement, computeDependencies(context, csElement));
}
@Override
public BasicContinuation<?> execute() {
org.eclipse.ocl.pivot.Class pivotElement = PivotUtil.getPivot(org.eclipse.ocl.pivot.Class.class, csElement);
if (pivotElement != null) {
List<org.eclipse.ocl.pivot.@NonNull Class> superClasses = ClassUtil.nullFree(pivotElement.getSuperClasses());
context.refreshList(org.eclipse.ocl.pivot.Class.class, superClasses, csElement.getOwnedSuperTypes());
if (superClasses.isEmpty()) {
org.eclipse.ocl.pivot.Class oclElementType = context.getStandardLibrary().getOclElementType();
pivotElement.getSuperClasses().add(oclElementType);
}
}
return null;
}
}
protected static class LambdaContinuation extends SingleContinuation<LambdaTypeCS>
{
private static @NonNull Dependency @NonNull [] computeDependencies(@NonNull CS2ASConversion context, @NonNull LambdaTypeCS csElement) {
TypedRefCS ownedContextType = ClassUtil.nonNullState(csElement.getOwnedContextType());
TypedRefCS ownedResultType = ClassUtil.nonNullState(csElement.getOwnedResultType());
List<TypedRefCS> csParameterTypes = csElement.getOwnedParameterTypes();
int iMax = csParameterTypes.size();
@NonNull Dependency @NonNull [] dependencies = new @NonNull Dependency[2 + iMax];
dependencies[0] = new PivotDependency(ownedContextType);
dependencies[1] = new PivotDependency(ownedResultType);
for (int i = 0; i < iMax; i++) {
TypedRefCS csParameterType = ClassUtil.nonNullState(csParameterTypes.get(i));
dependencies[i+2] = new PivotDependency(csParameterType);
}
return dependencies;
}
public LambdaContinuation(@NonNull CS2ASConversion context, @NonNull LambdaTypeCS csElement) {
super(context, null, null, csElement, computeDependencies(context, csElement));
}
@Override
public BasicContinuation<?> execute() {
Type contextType = PivotUtil.getPivot(Type.class, csElement.getOwnedContextType());
Type resultType = PivotUtil.getPivot(Type.class, csElement.getOwnedResultType());
String name = csElement.getName();
if ((contextType != null) && (resultType != null) && (name != null)) {
List<@NonNull Type> parameterTypes = new ArrayList<>();
for (TypedRefCS csParameterType : csElement.getOwnedParameterTypes()) {
Type parameterType = PivotUtil.getPivot(Type.class, csParameterType);
if (parameterType != null) {
parameterTypes.add(parameterType);
}
}
LambdaType lambdaType = context.getMetamodelManager().getCompleteModel().getLambdaType(name, contextType, parameterTypes, resultType, null);
context.installPivotTypeWithMultiplicity(lambdaType, csElement);
}
return null;
}
}
protected static abstract class OperatorExpContinuation<T extends NamedElementCS> extends SingleContinuation<T>
{
public OperatorExpContinuation(@NonNull CS2ASConversion context, @NonNull T csElement) {
super(context, null, null, csElement);
context.getOperatorsHavePrecedenceInterDependency().addDependency(this);
}
@Override
public BasicContinuation<?> execute() {
context.getOperatorsHavePrecedenceInterDependency().setSatisfied(this);
return null;
}
}
protected static class ParameterContinuation extends SingleContinuation<ParameterCS>
{
public ParameterContinuation(@NonNull CS2ASConversion context, @NonNull ParameterCS csElement) {
super(context, null, null, csElement);
}
@Override
public boolean canExecute() {
if (!super.canExecute()) {
return false;
}
TypedRefCS ownedType = csElement.getOwnedType();
Element pivot = ownedType != null ? ownedType.getPivot() : null;
if (pivot == null) {
return false;
}
return true;
}
@Override
public BasicContinuation<?> execute() {
Parameter parameter = PivotUtil.getPivot(Parameter.class, csElement);
if (parameter != null) {
context.refreshRequiredType(parameter, csElement);
TypedRefCS ownedType = csElement.getOwnedType();
boolean isTypeof = false;
if (ownedType instanceof TypedTypeRefCS) {
isTypeof = ((TypedTypeRefCS)ownedType).isIsTypeof();
}
parameter.setIsTypeof(isTypeof);
}
return null;
}
}
protected static class PrimitiveTypeRefContinuation extends TypedRefContinuation<PrimitiveTypeRefCS>
{
public PrimitiveTypeRefContinuation(@NonNull CS2ASConversion context, @NonNull PrimitiveTypeRefCS csElement) {
super(context, csElement);
}
@Override
public BasicContinuation<?> execute() {
String name = csElement.getName();
if (name != null) {
Type pivotType = context.getStandardLibrary().getLibraryType(name);
context.installPivotTypeWithMultiplicity(pivotType, csElement);
}
return null;
}
}
protected static class SpecializedTypeRefContinuation1 extends SingleContinuation<TypedTypeRefCS>
{
public SpecializedTypeRefContinuation1(@NonNull CS2ASConversion context, @NonNull TypedTypeRefCS csElement) {
super(context, null, null, csElement, context.getTypesHaveSignaturesInterDependency());
assert csElement.getOwnedBinding() != null;
}
@Override
public BasicContinuation<?> execute() {
@SuppressWarnings("unused")
Element pivotType = csElement.getReferredType();
return new SpecializedTypeRefContinuation2(context, csElement);
}
}
protected static class SpecializedTypeRefContinuation2 extends TypedRefContinuation<TypedTypeRefCS>
{
private static Dependency[] computeDependencies(@NonNull CS2ASConversion context, @NonNull TypedTypeRefCS csElement) {
List<@NonNull Dependency> dependencies = new ArrayList<>();
TemplateBindingCS csTemplateBinding = csElement.getOwnedBinding();
if (csTemplateBinding != null) {
for (TemplateParameterSubstitutionCS csTemplateParameterSubstitution : csTemplateBinding.getOwnedSubstitutions()) {
TypeRefCS csTemplateParameter = csTemplateParameterSubstitution.getOwnedActualParameter();
if (csTemplateParameter != null) {
dependencies.add(new PivotDependency(csTemplateParameter));
}
}
for (TemplateParameterSubstitutionCS csTemplateParameterSubstitution : csTemplateBinding.getOwnedSubstitutions()) {
TypeRefCS csActualParameter = csTemplateParameterSubstitution.getOwnedActualParameter();
if (csActualParameter != null) {
dependencies.add(new PivotDependency(csActualParameter)); // FIXME may be a redundant duplicate
}
}
}
dependencies.add(new PivotHasSuperClassesDependency(csElement));
return dependencies.toArray(new Dependency[dependencies.size()]);
}
public SpecializedTypeRefContinuation2(@NonNull CS2ASConversion context, @NonNull TypedTypeRefCS csElement) {
super(context, csElement, computeDependencies(context, csElement));
assert csElement.getOwnedBinding() != null;
}
@Override
public boolean canExecute() {
if (!super.canExecute()) {
return false;
}
if (context.isInReturnTypeWithUnresolvedParameters(csElement)) {
return false;
}
Type pivotType = csElement.getReferredType();
if (pivotType instanceof org.eclipse.ocl.pivot.Class) {
if (((org.eclipse.ocl.pivot.Class)pivotType).getSuperClasses().size() <= 0) {
return false;
}
TemplateBindingCS csTemplateBinding = csElement.getOwnedBinding();
if (csTemplateBinding != null) {
for (TemplateParameterSubstitutionCS csTemplateParameterSubstitution : csTemplateBinding.getOwnedSubstitutions()) {
TypeRefCS ownedActualParameter = csTemplateParameterSubstitution.getOwnedActualParameter();
if (ownedActualParameter instanceof WildcardTypeRefCS) {
return true;
}
Type actualParameterClass = (Type) ownedActualParameter.getPivot();
if (actualParameterClass == null) {
return false;
}
}
}
}
return true;
}
@Override
public BasicContinuation<?> execute() {
Type pivotType = csElement.getReferredType();
if (pivotType != null) {
TemplateBindingCS csTemplateBinding = csElement.getOwnedBinding();
if ((csTemplateBinding != null) && ElementUtil.isSpecialization(csTemplateBinding)) {
pivotType = (Type) context.specializeTemplates(csElement);
// TemplateBinding pivotTemplateBinding = PivotUtil.getPivot(TemplateBinding.class, csTemplateBinding);
// pivotType = pivotTemplateBinding.getBoundElement();
}
if (pivotType != null) {
context.installPivotTypeWithMultiplicity(pivotType, csElement);
}
}
return null;
}
}
protected static class TypeParameterContinuation extends SingleContinuation<TypeParameterCS>
{
public TypeParameterContinuation(@NonNull CS2ASConversion context, @NonNull TypeParameterCS csElement) {
super(context, null, null, csElement);
}
@Override
public boolean canExecute() {
if (!super.canExecute()) {
return false;
}
for (TypedRefCS csExtend : csElement.getOwnedExtends()) {
org.eclipse.ocl.pivot.Class asExtend = PivotUtil.getPivot(org.eclipse.ocl.pivot.Class.class, csExtend);
if (asExtend == null) {
return false;
}
}
return true;
}
@Override
public BasicContinuation<?> execute() {
TemplateParameter pivotElement = PivotUtil.getPivot(TemplateParameter.class, csElement);
if (pivotElement != null) {
List<TypedRefCS> csExtends = csElement.getOwnedExtends();
List<org.eclipse.ocl.pivot.@NonNull Class> asExtends = new ArrayList<>();
for (TypedRefCS csExtend : csExtends) {
org.eclipse.ocl.pivot.Class asExtend = PivotUtil.getPivot(org.eclipse.ocl.pivot.Class.class, csExtend);
if (asExtend != null) {
asExtends.add(asExtend);
}
}
PivotUtilInternal.refreshList(pivotElement.getConstrainingClasses(), asExtends);
}
return null;
}
}
protected static class TemplateSignatureContinuation extends SingleContinuation<ClassCS>
{
public TemplateSignatureContinuation(@NonNull CS2ASConversion context, NamedElement pivotParent, @NonNull ClassCS csElement) {
super(context, pivotParent, PivotPackage.Literals.TEMPLATEABLE_ELEMENT__OWNED_SIGNATURE, csElement);
context.getTypesHaveSignaturesInterDependency().addDependency(this);
}
@Override
public BasicContinuation<?> execute() {
Type pivotElement = PivotUtil.getPivot(Type.class, csElement);
if (pivotElement != null) {
if (pivotElement instanceof TemplateableElement) {
context.refreshTemplateSignature(csElement, (TemplateableElement)pivotElement);
}
context.getTypesHaveSignaturesInterDependency().setSatisfied(this);
}
return null;
}
}
protected static class TupleContinuation extends TypedRefContinuation<TupleTypeCS>
{
public TupleContinuation(@NonNull CS2ASConversion context, @NonNull TupleTypeCS csElement) {
super(context, csElement);
}
@Override
public boolean canExecute() {
if (!super.canExecute()) {
return false;
}
for (TuplePartCS csTuplePart : csElement.getOwnedParts()) {
TypedRefCS ownedType = csTuplePart.getOwnedType();
Element pivot = ownedType.getPivot();
if (pivot == null) {
return false;
}
}
if (context.isInReturnTypeWithUnresolvedParameters(csElement)) {
return false;
}
return true;
}
@Override
public BasicContinuation<?> execute() {
String name = csElement.getName();
if (name != null) {
List<@NonNull TypedElement> parts = new ArrayList<>();
for (@SuppressWarnings("null")@NonNull TuplePartCS csTuplePart : csElement.getOwnedParts()) {
String partName = csTuplePart.getName();
if (partName != null) {
Type partType = PivotUtil.getPivot(Type.class, csTuplePart.getOwnedType());
if (partType != null) {
parts.add(new ExecutorTuplePart(partType, partName));
}
}
}
TupleType tupleType = context.getMetamodelManager().getCompleteModel().getTupleType(name, parts, null);
context.installPivotTypeWithMultiplicity(tupleType, csElement);
List<Property> tupleParts = tupleType.getOwnedProperties();
for (TuplePartCS csTuplePart : csElement.getOwnedParts()) {
String partName = csTuplePart.getName();
Property tuplePart = NameUtil.getNameable(tupleParts, partName);
if (tuplePart != null) {
context.installPivotUsage(csTuplePart, tuplePart);
}
}
}
return null;
}
}
protected static abstract class TypedRefContinuation<T extends TypedRefCS> extends SingleContinuation<T>
{
public TypedRefContinuation(@NonNull CS2ASConversion context, @NonNull T csElement, Dependency... dependencies) {
super(context, null, null, csElement);
}
}
protected static class UnspecializedTypeRefContinuation extends TypedRefContinuation<TypedTypeRefCS>
{
public UnspecializedTypeRefContinuation(@NonNull CS2ASConversion context, @NonNull TypedTypeRefCS csElement) {
super(context, csElement, context.getTypesHaveSignaturesInterDependency());
assert csElement.getOwnedBinding() == null;
}
@Override
public BasicContinuation<?> execute() {
Type pivotType = csElement.getReferredType();
context.installPivotTypeWithMultiplicity(pivotType, csElement);
return null;
}
}
public BaseCSPreOrderVisitor(@NonNull CS2ASConversion context) {
super(context);
}
@Override
public Continuation<?> visiting(@NonNull VisitableCS visitable) {
throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for CS2AS PreOrder pass");
}
@Override
public Continuation<?> visitAnnotationCS(@NonNull AnnotationCS object) {
return null;
}
@Override
public Continuation<?> visitConstraintCS(@NonNull ConstraintCS csConstraint) {
return null;
}
@Override
public Continuation<?> visitDataTypeCS(@NonNull DataTypeCS csDataType) {
DataType pivotElement = PivotUtil.getPivot(DataType.class, csDataType);
if (pivotElement != null) {
List<org.eclipse.ocl.pivot.Class> pivotSuperClasses = pivotElement.getSuperClasses();
pivotSuperClasses.clear();
org.eclipse.ocl.pivot.Class oclElementType = context.getStandardLibrary().getOclElementType();
pivotSuperClasses.add(oclElementType);
}
return null;
}
@Override
public Continuation<?> visitDocumentationCS(@NonNull DocumentationCS object) {
return null;
}
@Override
public Continuation<?> visitEnumerationCS(@NonNull EnumerationCS csEnumeration) {
org.eclipse.ocl.pivot.Enumeration pivotElement = PivotUtil.getPivot(org.eclipse.ocl.pivot.Enumeration.class, csEnumeration);
if (pivotElement != null) {
List<org.eclipse.ocl.pivot.Class> pivotSuperClasses = pivotElement.getSuperClasses();
pivotSuperClasses.clear();
org.eclipse.ocl.pivot.Class oclElementType = context.getStandardLibrary().getOclElementType();
pivotSuperClasses.add(oclElementType);
}
return null;
}
@Override
public Continuation<?> visitEnumerationLiteralCS(@NonNull EnumerationLiteralCS csEnumerationLiteral) {
return null;
}
@Override
public Continuation<?> visitLambdaTypeCS(@NonNull LambdaTypeCS csLambdaType) {
return new LambdaContinuation(context, csLambdaType);
}
@Override
public Continuation<?> visitModelElementCS(@NonNull ModelElementCS csModelElement) {
return null;
}
@Override
public Continuation<?> visitModelElementRefCS(@NonNull ModelElementRefCS csModelElementRef) {
return null;
}
@Override
public Continuation<?> visitMultiplicityBoundsCS(@NonNull MultiplicityBoundsCS object) {
return null;
}
@Override
public Continuation<?> visitMultiplicityStringCS(@NonNull MultiplicityStringCS object) {
return null;
}
@Override
public Continuation<?> visitOperationCS(@NonNull OperationCS csOperation) {
return null;
}
@Override
public Continuation<?> visitPackageCS(@NonNull PackageCS csPackage) {
return null;
}
@Override
public Continuation<?> visitPackageOwnerCS(@NonNull PackageOwnerCS object) {
return null;
};
@Override
public Continuation<?> visitParameterCS(@NonNull ParameterCS csParameter) {
return new ParameterContinuation(context, csParameter);
}
@Override
public Continuation<?> visitPathElementCS(@NonNull PathElementCS csElement) {
return null;
}
@Override
public Continuation<?> visitPathNameCS(@NonNull PathNameCS csElement) {
return null;
}
@Override
public Continuation<?> visitPrimitiveTypeRefCS(@NonNull PrimitiveTypeRefCS csPrimitiveTypeRef) {
return new PrimitiveTypeRefContinuation(context, csPrimitiveTypeRef);
}
@Override
public Continuation<?> visitStructuredClassCS(@NonNull StructuredClassCS csClass) {
org.eclipse.ocl.pivot.Class pivotElement = PivotUtil.getPivot(org.eclipse.ocl.pivot.Class.class, csClass);
if (pivotElement == null) {
return null;
}
Continuations continuations = new Continuations();
if (csClass.getOwnedSignature() != null) {
continuations.add(new TemplateSignatureContinuation(context, pivotElement, csClass));
}
else {
pivotElement.setOwnedSignature(null);
}
if (!(pivotElement instanceof AnyType)) {
continuations.add(new ClassSupersContinuation(context, pivotElement, csClass));
}
return continuations.getContinuation();
}
@Override
public Continuation<?> visitStructuralFeatureCS(@NonNull StructuralFeatureCS csStructuralFeature) {
return null;
}
@Override
public Continuation<?> visitTemplateBindingCS(@NonNull TemplateBindingCS csTemplateBinding) {
return null;
}
@Override
public Continuation<?> visitTemplateSignatureCS(@NonNull TemplateSignatureCS csTemplateSignature) {
return null;
}
@Override
public Continuation<?> visitTupleTypeCS(@NonNull TupleTypeCS csTupleType) {
return new TupleContinuation(context, csTupleType);
}
@Override
public Continuation<?> visitTypeParameterCS(@NonNull TypeParameterCS csTypeParameter) {
TemplateParameter pivotElement = PivotUtil.getPivot(TemplateParameter.class, csTypeParameter);
if (pivotElement == null) {
return null;
}
if (csTypeParameter.getOwnedExtends().size() > 0) {
return new TypeParameterContinuation(context, csTypeParameter);
}
else {
pivotElement.getConstrainingClasses().clear();
return null;
}
}
@Override
public Continuation<?> visitTypedTypeRefCS(@NonNull TypedTypeRefCS csTypedTypeRef) {
if (csTypedTypeRef.getOwnedBinding() == null) {
return new UnspecializedTypeRefContinuation(context, csTypedTypeRef);
}
else {
return new SpecializedTypeRefContinuation1(context, csTypedTypeRef);
}
}
@Override
public Continuation<?> visitWildcardTypeRefCS(@NonNull WildcardTypeRefCS csWildcardTypeRef) {
return null;
}
}