| /******************************************************************************* |
| * Copyright (c) 2015, 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.qvtd.compiler.internal.qvtr2qvtc; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.ocl.pivot.Variable; |
| import org.eclipse.ocl.pivot.utilities.ClassUtil; |
| import org.eclipse.ocl.pivot.utilities.PivotUtil; |
| import org.eclipse.qvtd.compiler.CompilerChainException; |
| import org.eclipse.qvtd.compiler.internal.qvtr2qvtc.analysis.RelationAnalysis; |
| import org.eclipse.qvtd.pivot.qvtbase.Domain; |
| import org.eclipse.qvtd.pivot.qvtbase.TypedModel; |
| import org.eclipse.qvtd.pivot.qvtcore.BottomPattern; |
| import org.eclipse.qvtd.pivot.qvtcore.CoreDomain; |
| import org.eclipse.qvtd.pivot.qvtcore.GuardPattern; |
| import org.eclipse.qvtd.pivot.qvtcore.Mapping; |
| import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil; |
| import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain; |
| import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil; |
| |
| /** |
| * Relation2AbstractMappings refines AbstractRelation2Mappings to support conversion of an abstract relation. |
| */ |
| /*public*/ class Relation2AbstractMappings extends AbstractRelation2Mappings |
| { |
| protected class RelationDomain2AbstractCoreMapping implements EnforceableRelationDomain2CoreMapping |
| { // FIXME share some minimal functionality |
| protected class OtherRelationDomain2AbstractCoreDomain implements OtherRelationDomain2CoreDomain |
| { |
| public OtherRelationDomain2AbstractCoreDomain(@NonNull RelationDomain rOtherDomain) { |
| TypedModel rOtherTypedModel = QVTrelationUtil.getTypedModel(rOtherDomain); |
| List<@NonNull Variable> rOtherRootVariables = QVTrelationUtil.getRootVariables(rOtherDomain); |
| // |
| TypedModel cOtherTypedModel = getCoreTypedModel(rOtherTypedModel); |
| CoreDomain cOtherDomain = createCoreDomain(cOtherTypedModel, false); |
| cOtherDomain.setIsCheckable(rOtherDomain.isIsCheckable()); |
| cOtherDomain.setIsEnforceable(false); |
| for (@NonNull Variable rVariable : rOtherRootVariables) { |
| Variable2Variable variableAnalysis = variablesAnalysis.getVariableAnalysis(rVariable); |
| variableAnalysis.setIsRoot(); |
| variableAnalysis.setOtherBound(rOtherTypedModel); |
| } |
| } |
| |
| @Override |
| public void synthesize() throws CompilerChainException {} |
| } |
| |
| // Relations |
| /** |
| * rd: The relation domain to be enforced |
| */ |
| protected final @NonNull RelationDomain rEnforcedDomain; |
| /** |
| * The TypedModel of the enforced domain: rEnforcedDomain.getTypedModel() |
| */ |
| protected final @NonNull TypedModel rEnforcedTypedModel; |
| |
| // Core |
| /** |
| * m: The resultant mapping |
| */ |
| protected final @NonNull Mapping cMapping; |
| /** |
| * mg: The resultant mapping guard pattern: cMapping.getOwnedGuardPattern() |
| */ |
| protected final @NonNull GuardPattern cMiddleGuardPattern; |
| /** |
| * mb : The resultant mapping bottom pattern: cMapping.getOwnedBottomPattern() |
| */ |
| protected final @NonNull BottomPattern cMiddleBottomPattern; |
| /** |
| * mdir: The resultant enforced typed model |
| */ |
| protected final @NonNull TypedModel cEnforcedTypedModel; |
| /** |
| * md: The resultant enforced domain |
| */ |
| protected final @NonNull CoreDomain cEnforcedDomain; |
| |
| /** |
| * The conversion for each other domains sharing the parent of this domain |
| */ |
| protected final @NonNull List<@NonNull OtherRelationDomain2CoreDomain> otherDomain2coreDomains; |
| /** |
| * The analysis of each viariable in the relation. |
| */ |
| protected final @NonNull Variables2Variables variablesAnalysis; |
| |
| public RelationDomain2AbstractCoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName) throws CompilerChainException { |
| // super(rEnforcedDomain, cMappingName); |
| this.rEnforcedDomain = rEnforcedDomain; |
| this.rEnforcedTypedModel = QVTrelationUtil.getTypedModel(rEnforcedDomain); |
| // |
| this.cEnforcedTypedModel = getCoreTypedModel(rEnforcedTypedModel); |
| this.cMapping = createCoreMapping(cMappingName); |
| this.cMiddleGuardPattern = ClassUtil.nonNullState(cMapping.getGuardPattern()); |
| this.cMiddleBottomPattern = ClassUtil.nonNullState(cMapping.getBottomPattern()); |
| this.cEnforcedDomain = createCoreDomain(cEnforcedTypedModel, true); |
| // this.cEnforcedGuardPattern = ClassUtil.nonNullState(cEnforcedDomain.getGuardPattern()); |
| // this.cEnforcedBottomPattern = ClassUtil.nonNullState(cEnforcedDomain.getBottomPattern()); |
| // |
| this.variablesAnalysis = new Variables2Variables(relationAnalysis, rEnforcedDomain, cEnforcedDomain, null, false, false); |
| // |
| this.otherDomain2coreDomains = new ArrayList<>(); |
| for (@NonNull Domain rDomain : ClassUtil.nullFree(rEnforcedDomain.getRule().getDomain())) { |
| if ((rDomain != rEnforcedDomain) && (rDomain instanceof RelationDomain)) { |
| RelationDomain rRelationDomain = (RelationDomain)rDomain; |
| otherDomain2coreDomains.add(new OtherRelationDomain2AbstractCoreDomain(rRelationDomain)); |
| } |
| } |
| } |
| |
| private @NonNull CoreDomain createCoreDomain(@NonNull TypedModel cTypedModel, boolean isEnforced) { |
| CoreDomain coreDomain = qvtr2qvtc.createCoreDomain(cTypedModel); |
| coreDomain.setIsCheckable(false); |
| coreDomain.setIsEnforceable(isEnforced); |
| coreDomain.setRule(cMapping); |
| return coreDomain; |
| } |
| |
| @Override |
| public @NonNull Mapping getCoreMapping() { |
| return cMapping; |
| } |
| |
| protected @NonNull TypedModel getCoreTypedModel(@NonNull TypedModel rTypedModel) { |
| String name = PivotUtil.getName(rTypedModel); |
| Iterable<org.eclipse.ocl.pivot.@NonNull Package> usedPackages = QVTrelationUtil.getUsedPackages(rTypedModel); |
| for (@NonNull TypedModel cTypedModel : QVTcoreUtil.getModelParameters(cTransformation)) { |
| if (name.equals(cTypedModel.getName())) { |
| assert cTypedModel.getUsedPackage().equals(usedPackages); |
| return cTypedModel; |
| } |
| } |
| return ClassUtil.nonNullState(null); |
| } |
| |
| protected void synthesize() throws CompilerChainException { |
| for (@NonNull Variable2Variable variableAnalysis : variablesAnalysis.getAnalyses()) { |
| variableAnalysis.getCoreVariable(); |
| } |
| } |
| } |
| |
| /** |
| * The per-typed model top relation conversions. |
| */ |
| protected @NonNull Map<@NonNull TypedModel, @NonNull RelationDomain2AbstractCoreMapping> typedModel2relationDomain2coreMapping = new HashMap<>(); |
| |
| public Relation2AbstractMappings(@NonNull RelationalTransformation2CoreTransformation relationalTransformation2coreTransformation, @NonNull RelationAnalysis relationAnalysis) { |
| super(relationalTransformation2coreTransformation, relationAnalysis); |
| assert rRelation.isIsAbstract(); |
| } |
| |
| private void addRelationDomain2coreMapping(@NonNull RelationDomain2AbstractCoreMapping relationDomain2coreMapping) { |
| RelationDomain rDomain = relationDomain2coreMapping.rEnforcedDomain; |
| TypedModel rTypedModel = QVTrelationUtil.getTypedModel(rDomain); |
| EnforceableRelationDomain2CoreMapping old = typedModel2relationDomain2coreMapping.put(rTypedModel, relationDomain2coreMapping); |
| assert old == null; |
| } |
| |
| /** |
| * Return the list of conversions, one for each possible enforced domain. |
| */ |
| @Override |
| public void analyze() throws CompilerChainException { |
| for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(rRelation)) { |
| if (rDomain.isIsEnforceable()) { |
| String coreMappingName = qvtr2qvtc.getNameGenerator().createMappingName(rDomain); |
| addRelationDomain2coreMapping(new RelationDomain2AbstractCoreMapping(rDomain, coreMappingName)); |
| } |
| } |
| } |
| |
| @Override |
| public @NonNull EnforceableRelationDomain2CoreMapping getWhenRelationDomain2CoreMapping(@NonNull TypedModel rEnforcedTypedModel) { |
| return ClassUtil.nonNullState(typedModel2relationDomain2coreMapping.get(rEnforcedTypedModel)); |
| } |
| |
| @Override |
| public @NonNull EnforceableRelationDomain2CoreMapping getWhereRelationDomain2CoreMapping(@NonNull TypedModel rEnforcedTypedModel) { |
| return ClassUtil.nonNullState(typedModel2relationDomain2coreMapping.get(rEnforcedTypedModel)); |
| } |
| |
| @Override |
| public void synthesize() throws CompilerChainException { |
| for (@NonNull RelationDomain2AbstractCoreMapping enforceableRelationDomain2coreMapping : typedModel2relationDomain2coreMapping.values()) { |
| enforceableRelationDomain2coreMapping.synthesize(); |
| enforceableRelationDomain2coreMapping.variablesAnalysis.check(); |
| } |
| } |
| } |