blob: 1e213d8c569201244236b3e0c8a347253e4bb166 [file] [log] [blame]
/*******************************************************************************
* 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.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.qvtd.compiler.CompilerChainException;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtcore.Mapping;
import org.eclipse.qvtd.pivot.qvtrelation.Relation;
import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp;
import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain;
import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil;
import com.google.common.collect.Iterables;
/**
* InvokedRelationToMappingForEnforcement refines AbstractQVTr2QVTcRelations to support conversion of an invoked relation.
*/
/*public*/ class InvokedRelationToMappingForEnforcement extends AbstractQVTr2QVTcRelations
{
/**
* InvokedEnforceableRelationDomain2CoreMapping refines AbstractEnforceableRelationDomain2CoreMapping to support conversion of an invoked enforced domain.
*/
protected abstract class InvokedEnforceableRelationDomain2CoreMapping extends AbstractEnforceableRelationDomain2CoreMapping
{
/**
* InvokedOtherRelationDomain2CoreDomain refines AbstractOtherRelationDomain2CoreDomain to support conversion of an invoked not-enforced domain.
*/
protected class InvokedOtherRelationDomain2CoreDomain extends AbstractOtherRelationDomain2CoreDomain
{
public InvokedOtherRelationDomain2CoreDomain(@NonNull RelationDomain rOtherDomain) {
super(rOtherDomain);
}
/* // body of IROppositeDomainsToMappingForEnforcement
@Override
public void synthesize() throws CompilerChainException { // FIXME unify with TopLevel
// Set<@NonNull Variable> rOtherDomainVariables = new HashSet<@NonNull Variable>();
// gatherReferredVariables(rOtherDomainVariables, rOtherDomain); //ClassUtil.nullFree(rOtherDomainPattern.getBindsTo());
// assert rOtherDomainVariables.equals(Sets.newHashSet(getDomainVariables(rOtherDomain)));
// List<@NonNull Variable> rOtherRootVariables = getRootVariables(rOtherDomain);
//
// Set<@NonNull Variable> rOtherGuardVariables = new HashSet<@NonNull Variable>(rOtherDomainVariables);
// rOtherGuardVariables.retainAll(rWhenVariables);
// rOtherGuardVariables.addAll(rOtherRootVariables);
//
// Set<@NonNull Variable> rOtherBottomVariables = new HashSet<@NonNull Variable>(rOtherDomainVariables);
// rOtherBottomVariables.removeAll(rWhenVariables);
// rOtherBottomVariables.removeAll(rSharedVariables);
// rOtherBottomVariables.removeAll(rOtherRootVariables);
//
// Set<@NonNull Variable> rMiddleBottomVariables = new HashSet<@NonNull Variable>(rOtherDomainVariables);
// rMiddleBottomVariables.removeAll(rWhenVariables);
// rMiddleBottomVariables.retainAll(rSharedVariables);
// rMiddleBottomVariables.removeAll(rOtherRootVariables);
//
// mapVariables(rOtherGuardVariables, cOtherGuardPattern);
// mapVariables(rOtherBottomVariables, cOtherBottomPattern);
// mapVariables(rMiddleBottomVariables, cMiddleBottomPattern);
//
super.synthesize();
} */
}
public InvokedEnforceableRelationDomain2CoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName) throws CompilerChainException {
super(rEnforcedDomain, cMappingName);
}
@Override
protected @NonNull AbstractOtherRelationDomain2CoreDomain createOtherDomain2CoreDomain( @NonNull RelationDomain rRelationDomain) {
return new InvokedOtherRelationDomain2CoreDomain(rRelationDomain);
}
@Override
protected @NonNull Set<@NonNull Variable> getEnforcedBottomDomainVariables() { // FIXME unify with TopLevel
Set<@NonNull Variable> rEnforcedBottomDomainVariables = new HashSet<@NonNull Variable>(rEnforcedReferredVariables);
rEnforcedBottomDomainVariables.removeAll(rWhenVariable2rTypedModel.keySet());
rEnforcedBottomDomainVariables.removeAll(rSharedVariables);
rEnforcedBottomDomainVariables.removeAll(rEnforcedRootVariables);
return rEnforcedBottomDomainVariables;
}
private @NonNull VariableDeclaration getOverriddenParameter(@NonNull Relation rOverride, @NonNull Variable rParameter) {
if (rOverride == rRelation) {
return rParameter;
}
RelationDomain rootVariableDomain = QVTrelationUtil.getRootVariableDomain(rParameter);
List<@NonNull Variable> rootVariables = QVTrelationUtil.getRootVariables(rootVariableDomain);
int index = rootVariables.indexOf(rParameter);
assert index >= 0;
TypedModel rTypedModel = QVTrelationUtil.getTypedModel(rootVariableDomain);
RelationDomain overriddenRootVariableDomain = QVTrelationUtil.getRelationDomain(rOverride, rTypedModel);
List<@NonNull Variable> overriddenRootVariables = QVTrelationUtil.getRootVariables(overriddenRootVariableDomain);
assert index <= overriddenRootVariables.size();
return overriddenRootVariables.get(index);
}
// @Override
// protected @NonNull Set<@NonNull Variable> getEnforcedDomainGuardVariables(@NonNull Set<@NonNull Variable> rEnforcedBottomDomainVariables) { // FIXME unify with TopLevel
// Set<@NonNull Variable> rEnforcedDomainGuardVariables = new HashSet<@NonNull Variable>(rEnforcedReferredVariables);
// rEnforcedDomainGuardVariables.retainAll(rWhenVariables);
// rEnforcedDomainGuardVariables.addAll(rEnforcedRootVariables);
// return rEnforcedDomainGuardVariables;
// }
// RInvokerToMGuard
@Override
protected void mapIncomingInvocation() throws CompilerChainException {
Type invokingSignatureClass = null; // ?? invocation
Relation rOverride = rRelation;
for (; rOverride != null; rOverride = QVTrelationUtil.basicGetOverridden(rOverride)) {
invokingSignatureClass = qvtr2qvtc.basicGetSignatureClass(rOverride);
if (invokingSignatureClass != null) {
// qvtr2qvtc.get
break;
}
}
assert rOverride != null;
if (invokingSignatureClass == null) {
invokingSignatureClass = qvtr2qvtc.getSignatureClass(rRelation); // ?? invocation
}
Variable cInvocationVariable/*vd*/ = variablesAnalysis.addCoreGuardVariable("from_" + invokingSignatureClass.getName(), invokingSignatureClass);
org.eclipse.ocl.pivot.Class cInvocationType = QVTrelationUtil.getClass(cInvocationVariable);
assert cInvocationType == invokingSignatureClass; // FIXME
// List<@NonNull OCLExpression> rArguments = QVTrelationUtil.Internal.getOwnedArgumentsList(rInvocation);
List<@NonNull Variable> rParameters = qvtr2qvtc.getRootVariables(rRelation);
// int iSize = rArguments.size();
int iSize = rParameters.size();
// assert iSize == rParameters.size();
for (int i = 0; i < iSize; i++) {
Variable rParameter = rParameters.get(i);
// OCLExpression rArgument = rArguments.get(i);
// VariableExp rArgumentVariableExp = (VariableExp)rArgument;
// RInvokerToMGuardPredicate
// Variable rArgumentVariable = QVTrelationUtil.getReferredVariable(rArgumentVariableExp);
Variable cParameter = variablesAnalysis.getCoreVariable(rParameter);
Property cProperty = qvtr2qvtc.getSignatureProperty(cInvocationType, getOverriddenParameter(rOverride, rParameter));
NavigationCallExp cInvocationValue = createNavigationCallExp(createVariableExp(cInvocationVariable), cProperty);
variablesAnalysis.addConditionPredicate(cMiddleGuardPattern, cInvocationValue, createVariableExp(cParameter));
}
}
}
/**
* The per-typed model when invocation conversions.
*/
private @NonNull Map<@NonNull TypedModel, @NonNull AbstractEnforceableRelationDomain2CoreMapping> whenTypedModel2relationDomain2coreMapping = new HashMap<>();
/**
* The per-typed model where invocation conversions.
*/
private @NonNull Map<@NonNull TypedModel, @NonNull AbstractEnforceableRelationDomain2CoreMapping> whereTypedModel2relationDomain2coreMapping = new HashMap<>();
public InvokedRelationToMappingForEnforcement(@NonNull QVTr2QVTc qvtr2qvtc, @NonNull Relation rRelation) {
super(qvtr2qvtc, rRelation);
assert !rRelation.isIsTopLevel();
}
private void addWhenRelationDomain2coreMapping(@NonNull AbstractEnforceableRelationDomain2CoreMapping relationDomain2coreMapping) {
RelationDomain rDomain = relationDomain2coreMapping.rEnforcedDomain;
TypedModel rTypedModel = QVTrelationUtil.getTypedModel(rDomain);
AbstractEnforceableRelationDomain2CoreMapping old = whenTypedModel2relationDomain2coreMapping.put(rTypedModel, relationDomain2coreMapping);
assert old == null;
}
private void addWhereRelationDomain2coreMapping(@NonNull AbstractEnforceableRelationDomain2CoreMapping relationDomain2coreMapping) {
RelationDomain rDomain = relationDomain2coreMapping.rEnforcedDomain;
TypedModel rTypedModel = QVTrelationUtil.getTypedModel(rDomain);
AbstractEnforceableRelationDomain2CoreMapping old = whereTypedModel2relationDomain2coreMapping.put(rTypedModel, relationDomain2coreMapping);
assert old == null;
}
/**
* Each invocation of each enforced domain is synthesized as a separate mapping.
*/
@Override
public void analyze() throws CompilerChainException {
boolean hasWhenInvocation = false;
boolean hasWhereInvocation = false;
for (@NonNull Relation rOverride : rAllOverrides) {
Iterable<@NonNull RelationCallExp> incomingWhenInvocations = qvtr2qvtc.getIncomingWhenInvocationsOf(rOverride);
if ((incomingWhenInvocations != null) && !Iterables.isEmpty(incomingWhenInvocations)) {
hasWhenInvocation = true;
}
Iterable<@NonNull RelationCallExp> incomingWhereInvocations = qvtr2qvtc.getIncomingWhereInvocationsOf(rOverride);
if ((incomingWhereInvocations != null) && !Iterables.isEmpty(incomingWhereInvocations)) {
hasWhereInvocation = true;
}
}
if (hasWhenInvocation) {
QVTr2QVTc.SYNTHESIS.println("invocation of when " + rRelation);
for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(rRelation)) {
if (rDomain.isIsEnforceable()) {
String coreMappingName = qvtr2qvtc.getNameGenerator().createWhenMappingClassName(rDomain);
addWhenRelationDomain2coreMapping(new WhenedEnforceableRelationDomain2CoreMapping(rDomain, coreMappingName));
}
}
}
if (hasWhereInvocation) {
QVTr2QVTc.SYNTHESIS.println("invocation of where " + rRelation);
for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(rRelation)) {
if (rDomain.isIsEnforceable()) {
String coreMappingName = qvtr2qvtc.getNameGenerator().createWhereMappingClassName(rDomain);
addWhereRelationDomain2coreMapping(new WheredEnforceableRelationDomain2CoreMapping(rDomain, coreMappingName));
}
}
}
}
@Override
public @NonNull AbstractEnforceableRelationDomain2CoreMapping getWhenRelationDomain2CoreMapping(@NonNull TypedModel rEnforcedTypedModel) {
return ClassUtil.nonNullState(whenTypedModel2relationDomain2coreMapping.get(rEnforcedTypedModel));
}
@Override
public @NonNull AbstractEnforceableRelationDomain2CoreMapping getWhereRelationDomain2CoreMapping(@NonNull TypedModel rEnforcedTypedModel) {
return ClassUtil.nonNullState(whereTypedModel2relationDomain2coreMapping.get(rEnforcedTypedModel));
}
@Override
public void synthesize() throws CompilerChainException {
for (@NonNull AbstractEnforceableRelationDomain2CoreMapping enforceableRelationDomain2coreMapping : whenTypedModel2relationDomain2coreMapping.values()) {
enforceableRelationDomain2coreMapping.synthesize();
enforceableRelationDomain2coreMapping.variablesAnalysis.check();
Relation rOverriddenRelation = QVTrelationUtil.basicGetOverridden(rRelation);
if (rOverriddenRelation != null) {
TypedModel rEnforcedTypedModel = enforceableRelationDomain2coreMapping.rEnforcedTypedModel;
Mapping coreOverridingMapping = enforceableRelationDomain2coreMapping.getCoreMapping();
AbstractQVTr2QVTcRelations overriddenRelation2Mappings = qvtr2qvtc.getRelation2Mappings(rOverriddenRelation);
AbstractEnforceableRelationDomain2CoreMapping overriddenRelationDomain2CoreMapping = overriddenRelation2Mappings.getWhenRelationDomain2CoreMapping(rEnforcedTypedModel);
Mapping coreOverriddenMapping = overriddenRelationDomain2CoreMapping.getCoreMapping();
coreOverridingMapping.setOverridden(coreOverriddenMapping);
}
}
for (@NonNull AbstractEnforceableRelationDomain2CoreMapping enforceableRelationDomain2coreMapping : whereTypedModel2relationDomain2coreMapping.values()) {
enforceableRelationDomain2coreMapping.synthesize();
enforceableRelationDomain2coreMapping.variablesAnalysis.check();
Relation rOverriddenRelation = QVTrelationUtil.basicGetOverridden(rRelation);
if (rOverriddenRelation != null) {
TypedModel rEnforcedTypedModel = enforceableRelationDomain2coreMapping.rEnforcedTypedModel;
Mapping coreOverridingMapping = enforceableRelationDomain2coreMapping.getCoreMapping();
AbstractQVTr2QVTcRelations overriddenRelation2Mappings = qvtr2qvtc.getRelation2Mappings(rOverriddenRelation);
AbstractEnforceableRelationDomain2CoreMapping overriddenRelationDomain2CoreMapping = overriddenRelation2Mappings.getWhereRelationDomain2CoreMapping(rEnforcedTypedModel);
Mapping coreOverriddenMapping = overriddenRelationDomain2CoreMapping.getCoreMapping();
coreOverridingMapping.setOverridden(coreOverriddenMapping);
}
}
}
protected final class WhenedEnforceableRelationDomain2CoreMapping extends InvokedEnforceableRelationDomain2CoreMapping
{
protected WhenedEnforceableRelationDomain2CoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName) throws CompilerChainException {
super(rEnforcedDomain, cMappingName);
}
@Override
protected @NonNull VariablesAnalysis createVariablesAnalysis(@NonNull RelationDomain rEnforcedDomain, @NonNull Type traceClass) throws CompilerChainException {
return new VariablesAnalysis.WhenedVariablesAnalysis(qvtr2qvtc, rEnforcedDomain, cEnforcedDomain, traceClass);
}
@Override
protected @NonNull AbstractEnforceableRelationDomain2CoreMapping mapOverrides(@NonNull AbstractQVTr2QVTcRelations relation2Mappings) {
return relation2Mappings.getWhenRelationDomain2CoreMapping(rEnforcedTypedModel);
}
}
protected final class WheredEnforceableRelationDomain2CoreMapping extends InvokedEnforceableRelationDomain2CoreMapping
{
protected WheredEnforceableRelationDomain2CoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName) throws CompilerChainException {
super(rEnforcedDomain, cMappingName);
}
@Override
protected @NonNull VariablesAnalysis createVariablesAnalysis(@NonNull RelationDomain rEnforcedDomain, @NonNull Type traceClass) throws CompilerChainException {
return new VariablesAnalysis.WheredVariablesAnalysis(qvtr2qvtc, rEnforcedDomain, cEnforcedDomain, traceClass);
}
@Override
protected @NonNull AbstractEnforceableRelationDomain2CoreMapping mapOverrides(@NonNull AbstractQVTr2QVTcRelations relation2Mappings) {
return relation2Mappings.getWhereRelationDomain2CoreMapping(rEnforcedTypedModel);
}
}
}