| /******************************************************************************* |
| * Copyright (c) 2010, 2019 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.qvtd.xtext.qvtcore.cs2as; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.ocl.pivot.Import; |
| import org.eclipse.ocl.pivot.Operation; |
| import org.eclipse.ocl.pivot.PivotPackage; |
| import org.eclipse.ocl.pivot.Property; |
| import org.eclipse.ocl.pivot.Variable; |
| import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal; |
| import org.eclipse.ocl.pivot.utilities.ClassUtil; |
| import org.eclipse.ocl.pivot.utilities.PivotUtil; |
| import org.eclipse.ocl.xtext.base.cs2as.BasicContinuation; |
| import org.eclipse.ocl.xtext.base.cs2as.CS2AS; |
| import org.eclipse.ocl.xtext.base.cs2as.CS2ASConversion; |
| import org.eclipse.ocl.xtext.base.cs2as.Continuation; |
| import org.eclipse.ocl.xtext.base.cs2as.SingleContinuation; |
| import org.eclipse.ocl.xtext.base.utilities.BaseCSResource; |
| import org.eclipse.ocl.xtext.basecs.PathNameCS; |
| import org.eclipse.ocl.xtext.essentialoclcs.ExpCS; |
| import org.eclipse.ocl.xtext.essentialoclcs.NameExpCS; |
| import org.eclipse.qvtd.pivot.qvtbase.Function; |
| import org.eclipse.qvtd.pivot.qvtbase.FunctionParameter; |
| import org.eclipse.qvtd.pivot.qvtbase.Predicate; |
| import org.eclipse.qvtd.pivot.qvtbase.QVTbasePackage; |
| import org.eclipse.qvtd.pivot.qvtbase.Rule; |
| import org.eclipse.qvtd.pivot.qvtbase.Target; |
| import org.eclipse.qvtd.pivot.qvtbase.Transformation; |
| import org.eclipse.qvtd.pivot.qvtbase.TypedModel; |
| import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil; |
| import org.eclipse.qvtd.pivot.qvtcore.Assignment; |
| import org.eclipse.qvtd.pivot.qvtcore.BottomPattern; |
| import org.eclipse.qvtd.pivot.qvtcore.BottomVariable; |
| import org.eclipse.qvtd.pivot.qvtcore.CoreDomain; |
| import org.eclipse.qvtd.pivot.qvtcore.CoreModel; |
| import org.eclipse.qvtd.pivot.qvtcore.EnforcementOperation; |
| import org.eclipse.qvtd.pivot.qvtcore.GuardPattern; |
| import org.eclipse.qvtd.pivot.qvtcore.GuardVariable; |
| import org.eclipse.qvtd.pivot.qvtcore.Mapping; |
| import org.eclipse.qvtd.pivot.qvtcore.QVTcoreFactory; |
| import org.eclipse.qvtd.pivot.qvtcore.QVTcorePackage; |
| import org.eclipse.qvtd.pivot.qvtcore.RealizedVariable; |
| import org.eclipse.qvtd.pivot.qvtcore.VariableAssignment; |
| import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreHelper; |
| import org.eclipse.qvtd.xtext.qvtbasecs.JavaClassCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.BottomPatternCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.DirectionCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.DomainCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.EnforcementOperationCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.GuardPatternCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.MappingCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.ParamDeclarationCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.PredicateCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.PredicateOrAssignmentCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.QueryCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.RealizedVariableCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.TopLevelCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.TransformationCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.UnrealizedVariableCS; |
| import org.eclipse.qvtd.xtext.qvtcorecs.util.AbstractQVTcoreCSContainmentVisitor; |
| |
| import com.google.common.collect.Iterables; |
| |
| public class QVTcoreCSContainmentVisitor extends AbstractQVTcoreCSContainmentVisitor |
| { |
| protected static class IsAssignmentPredicate implements com.google.common.base.Predicate<PredicateOrAssignmentCS> |
| { |
| public final static @NonNull IsAssignmentPredicate INSTANCE = new IsAssignmentPredicate(); |
| |
| @Override |
| public boolean apply(PredicateOrAssignmentCS csAssignment) { |
| return csAssignment.getOwnedInitExpression() != null; |
| } |
| } |
| |
| protected static class IsPredicatePredicate implements com.google.common.base.Predicate<PredicateOrAssignmentCS> |
| { |
| public final static @NonNull IsPredicatePredicate INSTANCE = new IsPredicatePredicate(); |
| |
| @Override |
| public boolean apply(PredicateOrAssignmentCS csAssignment) { |
| return csAssignment.getOwnedInitExpression() == null; |
| } |
| } |
| |
| protected static class DirectionContentContinuation extends SingleContinuation<DirectionCS> |
| { |
| private DirectionContentContinuation(@NonNull CS2ASConversion context, @NonNull DirectionCS csElement) { |
| super(context, null, null, csElement); |
| } |
| |
| @Override |
| public BasicContinuation<?> execute() { |
| TypedModel pTypedModel = PivotUtil.getPivot(TypedModel.class, csElement); |
| if (pTypedModel != null) { |
| PivotUtilInternal.refreshList(pTypedModel.getUsedPackage(), csElement.getImports()); |
| PivotUtilInternal.refreshList(pTypedModel.getDependsOn(), csElement.getUses()); |
| // PivotUtilInternal.refreshList(pTypedModel.getIterates(), csElement.getUses()); |
| } |
| return null; |
| } |
| } |
| |
| protected static class DomainContentContinuation extends SingleContinuation<DomainCS> |
| { |
| private DomainContentContinuation(@NonNull CS2ASConversion context, @NonNull DomainCS csElement) { |
| super(context, null, null, csElement); |
| } |
| |
| @Override |
| public BasicContinuation<?> execute() { |
| CoreDomain pDomain = PivotUtil.getPivot(CoreDomain.class, csElement); |
| if (pDomain != null) { |
| TypedModel direction = csElement.getDirection(); |
| if (direction == null) { |
| Transformation transformation = QVTbaseUtil.basicGetContainingTransformation(pDomain); |
| if (transformation != null) { |
| direction = transformation.getModelParameter(null); |
| } |
| } |
| pDomain.setTypedModel(direction); |
| } |
| return null; |
| } |
| } |
| |
| public QVTcoreCSContainmentVisitor(@NonNull CS2ASConversion context) { |
| super(context); |
| } |
| |
| protected @NonNull QVTcoreHelper getHelper() { |
| return (QVTcoreHelper)helper; |
| } |
| |
| protected void resolveTransformationMappings(@NonNull Iterable<? extends @NonNull MappingCS> csMappings) { |
| Map<@NonNull Transformation, List<@NonNull Mapping>> tx2mappings = new HashMap<@NonNull Transformation, List<@NonNull Mapping>>(); |
| for (@NonNull MappingCS csMapping : csMappings) { |
| PathNameCS csInPathName = csMapping.getOwnedInPathName(); |
| if (csInPathName != null) { |
| Transformation asTransformation = lookupTransformation(csMapping, csInPathName, null); |
| if (asTransformation != null) { |
| Mapping asMapping = PivotUtil.getPivot(Mapping.class, csMapping); |
| if (asMapping != null) { |
| List<@NonNull Mapping> asMappings = tx2mappings.get(asTransformation); |
| if (asMappings == null) { |
| asMappings = new ArrayList<@NonNull Mapping>(); |
| tx2mappings.put(asTransformation, asMappings); |
| } |
| asMappings.add(asMapping); |
| } |
| } |
| } |
| } |
| for (@NonNull Transformation asTransformation : tx2mappings.keySet()) { |
| List<@NonNull Mapping> asMappings = tx2mappings.get(asTransformation); |
| List<Rule> asRules = asTransformation.getRule(); |
| if (asMappings != null) { |
| PivotUtilInternal.refreshList(asRules, asMappings); |
| } |
| else { |
| asRules.clear(); |
| } |
| } |
| } |
| |
| protected void resolveTransformationQueries(@NonNull Iterable<@NonNull QueryCS> csQueries) { |
| Map<@NonNull Transformation, List<@NonNull Function>> tx2qMap = new HashMap<@NonNull Transformation, List<@NonNull Function>>(); |
| for (@NonNull QueryCS csQuery : csQueries) { |
| Transformation asTransformation = csQuery.getTransformation(); |
| if (asTransformation != null) { |
| Function asQuery = PivotUtil.getPivot(Function.class, csQuery); |
| if (asQuery != null) { |
| List<@NonNull Function> asQueries = tx2qMap.get(asTransformation); |
| if (asQueries == null) { |
| asQueries = new ArrayList<@NonNull Function>(); |
| tx2qMap.put(asTransformation, asQueries); |
| } |
| asQueries.add(asQuery); |
| } |
| } |
| } |
| for (Transformation asTransformation : tx2qMap.keySet()) { |
| List<@NonNull Function> asQueries = tx2qMap.get(asTransformation); |
| List<Operation> asOperations = asTransformation.getOwnedOperations(); |
| if (asQueries != null) { |
| PivotUtilInternal.refreshList(asOperations, asQueries); |
| } |
| else { |
| asOperations.clear(); |
| } |
| } |
| } |
| |
| @Override |
| public Continuation<?> visitBottomPatternCS(@NonNull BottomPatternCS csElement) { |
| BottomPattern pBottomPattern = context.refreshModelElement(BottomPattern.class, QVTcorePackage.Literals.BOTTOM_PATTERN, csElement); |
| context.refreshPivotList(RealizedVariable.class, pBottomPattern.getRealizedVariable(), csElement.getOwnedRealizedVariables()); |
| context.refreshPivotList(Variable.class, pBottomPattern.getOwnedVariables(), csElement.getOwnedUnrealizedVariables()); |
| context.refreshPivotList(EnforcementOperation.class, pBottomPattern.getEnforcementOperation(), csElement.getOwnedEnforcementOperations()); |
| context.refreshPivotList(Assignment.class, pBottomPattern.getAssignment(), Iterables.filter(csElement.getOwnedConstraints(), IsAssignmentPredicate.INSTANCE)); |
| context.refreshPivotList(Predicate.class, pBottomPattern.getPredicate(), Iterables.filter(csElement.getOwnedConstraints(), IsPredicatePredicate.INSTANCE)); |
| context.refreshComments(pBottomPattern, csElement); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitDirectionCS(@NonNull DirectionCS csElement) { |
| TypedModel asTypedModel = refreshNamedElement(TypedModel.class, QVTbasePackage.Literals.TYPED_MODEL, csElement); |
| if (csElement.getName() == null) { |
| asTypedModel.setIsTrace(true); |
| } |
| return new DirectionContentContinuation(context, csElement); |
| } |
| |
| @Override |
| public Continuation<?> visitDomainCS(@NonNull DomainCS csElement) { |
| EObject eContainer = csElement.eContainer(); |
| if ((eContainer instanceof MappingCS) && (((MappingCS)eContainer).getOwnedMiddle() == csElement)) { |
| return null; |
| } |
| CoreDomain pivotElement = context.refreshModelElement(CoreDomain.class, QVTcorePackage.Literals.CORE_DOMAIN, csElement); |
| pivotElement.setIsCheckable(csElement.isIsCheck() || csElement.isIsEnforce()); |
| pivotElement.setIsEnforceable(csElement.isIsEnforce()); |
| pivotElement.setBottomPattern(PivotUtil.getPivot(BottomPattern.class, csElement.getOwnedBottomPattern())); |
| pivotElement.setGuardPattern(PivotUtil.getPivot(GuardPattern.class, csElement.getOwnedGuardPattern())); |
| context.refreshComments(pivotElement, csElement); |
| return new DomainContentContinuation(context, csElement); |
| } |
| |
| @Override |
| public Continuation<?> visitEnforcementOperationCS(@NonNull EnforcementOperationCS csElement) { |
| context.refreshModelElement(EnforcementOperation.class, QVTcorePackage.Literals.ENFORCEMENT_OPERATION, csElement); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitGuardPatternCS(@NonNull GuardPatternCS csElement) { |
| @NonNull GuardPattern pGuardPattern = context.refreshModelElement(GuardPattern.class, QVTcorePackage.Literals.GUARD_PATTERN, csElement); |
| context.refreshPivotList(Variable.class, pGuardPattern.getOwnedVariables(), csElement.getOwnedUnrealizedVariables()); |
| context.refreshPivotList(Predicate.class, pGuardPattern.getPredicate(), csElement.getOwnedPredicates()); |
| context.refreshComments(pGuardPattern, csElement); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitMappingCS(@NonNull MappingCS csElement) { |
| if (csElement.eContainer() instanceof TopLevelCS) { |
| if (csElement.getName() == null) { |
| context.addError(csElement, "top level mapping must be named"); |
| } |
| } |
| else { |
| if (csElement.getName() != null) { |
| context.addError(csElement, "composed mapping must be unnamed"); |
| } |
| } |
| @NonNull Mapping pivotElement = refreshNamedElement(Mapping.class, QVTcorePackage.Literals.MAPPING, csElement); |
| DomainCS csMiddle = csElement.getOwnedMiddle(); |
| if (csMiddle != null) { |
| pivotElement.setBottomPattern(PivotUtil.getPivot(BottomPattern.class, csMiddle.getOwnedBottomPattern())); |
| pivotElement.setGuardPattern(PivotUtil.getPivot(GuardPattern.class, csMiddle.getOwnedGuardPattern())); |
| } |
| else { |
| BottomPattern bottomPattern = pivotElement.getBottomPattern(); |
| if (bottomPattern == null) { |
| bottomPattern = QVTcoreFactory.eINSTANCE.createBottomPattern(); |
| bottomPattern.getAssignment().clear(); |
| bottomPattern.getBindsTo().clear(); |
| bottomPattern.getEnforcementOperation().clear(); |
| bottomPattern.getPredicate().clear(); |
| bottomPattern.getRealizedVariable().clear(); |
| bottomPattern.getOwnedVariables().clear(); |
| pivotElement.setBottomPattern(bottomPattern); |
| } |
| GuardPattern guardPattern = pivotElement.getGuardPattern(); |
| if (guardPattern == null) { |
| guardPattern = QVTcoreFactory.eINSTANCE.createGuardPattern(); |
| guardPattern.getBindsTo().clear(); |
| guardPattern.getPredicate().clear(); |
| guardPattern.getOwnedVariables().clear(); |
| pivotElement.setGuardPattern(guardPattern); |
| } |
| } |
| context.refreshPivotList(CoreDomain.class, pivotElement.getDomain(), csElement.getOwnedDomains()); |
| context.refreshPivotList(Mapping.class, pivotElement.getLocal(), csElement.getOwnedComposedMappings()); |
| pivotElement.setIsAbstract(csElement.isIsAbstract()); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitParamDeclarationCS(@NonNull ParamDeclarationCS csElement) { |
| refreshNamedElement(FunctionParameter.class, QVTbasePackage.Literals.FUNCTION_PARAMETER, csElement); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitPredicateCS(@NonNull PredicateCS csElement) { |
| context.refreshModelElement(Predicate.class, QVTbasePackage.Literals.PREDICATE, csElement); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitPredicateOrAssignmentCS(@NonNull PredicateOrAssignmentCS csElement) { |
| ExpCS csTarget = csElement.getOwnedTarget(); |
| if (csElement.getOwnedInitExpression() == null) { |
| context.refreshModelElement(Predicate.class, QVTbasePackage.Literals.PREDICATE, csElement); |
| } |
| else if (csTarget instanceof NameExpCS) { |
| VariableAssignment asAssignment = context.refreshModelElement(VariableAssignment.class, QVTcorePackage.Literals.VARIABLE_ASSIGNMENT, csElement); |
| asAssignment.setIsPartial(csElement.isIsPartial()); |
| } |
| else { |
| // QVTcorePackage.Literals.PROPERTY_ASSIGNMENT must wait till isIsImplicit determines if an OPPOSITE_PROPERTY_ASSIGNMENT |
| } |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitQueryCS(@NonNull QueryCS csElement) { |
| PathNameCS pathName = csElement.getOwnedPathName(); |
| if (pathName != null) { |
| CS2AS.setElementType(pathName, QVTbasePackage.Literals.TRANSFORMATION, csElement, null); |
| } |
| @NonNull Function pivotElement = refreshNamedElement(Function.class, QVTbasePackage.Literals.FUNCTION, csElement); |
| // pivotElement.setIsStatic(true); |
| pivotElement.setIsTransient(csElement.isIsTransient()); |
| JavaClassCS csJavaClass = csElement.getImplementation(); |
| pivotElement.setImplementationClass(csJavaClass != null ? csJavaClass.getName() : null); |
| context.refreshPivotList(FunctionParameter.class, pivotElement.getOwnedParameters(), csElement.getOwnedParameters()); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitRealizedVariableCS(@NonNull RealizedVariableCS csElement) { |
| refreshNamedElement(RealizedVariable.class, QVTcorePackage.Literals.REALIZED_VARIABLE, csElement); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitTopLevelCS(@NonNull TopLevelCS csElement) { |
| importPackages(csElement); |
| @NonNull CoreModel asModel = refreshRoot(CoreModel.class, QVTcorePackage.Literals.CORE_MODEL, csElement); |
| installPackageStructure(asModel, ClassUtil.nullFree(csElement.getOwnedPackages()), ClassUtil.nullFree(csElement.getOwnedTransformations())); |
| context.refreshPivotList(Import.class, asModel.getOwnedImports(), csElement.getOwnedImports()); |
| // |
| Resource eResource = csElement.eResource(); |
| if (eResource instanceof BaseCSResource) { |
| context.installRootElement((BaseCSResource)eResource, asModel); // Ensure containment viable for imported library type references |
| // importPackages(csElement); // FIXME This has to be after refreshPackage which is irregular and prevents local realization of ImportCS etc |
| } |
| resolveTransformationMappings(ClassUtil.nullFree(csElement.getOwnedMappings())); |
| resolveTransformationQueries(ClassUtil.nullFree(csElement.getOwnedQueries())); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitTransformationCS(@NonNull TransformationCS csElement) { |
| PathNameCS pathName = csElement.getOwnedPathName(); |
| if (pathName != null) { |
| CS2AS.setElementType(pathName, PivotPackage.Literals.NAMESPACE, csElement, null); |
| } |
| @SuppressWarnings("null") @NonNull EClass eClass = QVTbasePackage.Literals.TRANSFORMATION; |
| Transformation asTransformation = refreshNamedElement(Transformation.class, eClass, csElement); |
| refreshClassifier(asTransformation, csElement); |
| List<TypedModel> newModelParameters = new ArrayList<>(); |
| context.refreshPivotList(TypedModel.class, newModelParameters, csElement.getOwnedDirections()); |
| newModelParameters.add(0, getHelper().createPrimitiveTypedModel()); |
| newModelParameters.add(1, getHelper().createThisTypedModel()); |
| PivotUtilInternal.refreshList(asTransformation.getModelParameter(), newModelParameters); |
| context.refreshPivotList(Property.class, asTransformation.getOwnedProperties(), csElement.getOwnedProperties()); |
| context.refreshPivotList(Target.class, asTransformation.getOwnedTargets(), csElement.getOwnedTargets()); |
| QVTbaseUtil.getContextVariable(standardLibrary, asTransformation); |
| return null; |
| } |
| |
| @Override |
| public Continuation<?> visitUnrealizedVariableCS(@NonNull UnrealizedVariableCS csElement) { |
| if (csElement.eContainer() instanceof GuardPatternCS) { |
| refreshNamedElement(GuardVariable.class, QVTcorePackage.Literals.GUARD_VARIABLE, csElement); |
| } |
| else { |
| refreshNamedElement(BottomVariable.class, QVTcorePackage.Literals.BOTTOM_VARIABLE, csElement); |
| } |
| return null; |
| } |
| } |