blob: 745c98759ab5c68e1342b766c7ffc11cb70a14ec [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.qvtm2qvts;
import java.util.ArrayList;
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.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CompleteClass;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.NullLiteralExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.ids.OperationId;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.Nameable;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.ClassDatumAnalysis;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
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.CorePattern;
import org.eclipse.qvtd.pivot.qvtcore.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcore.Mapping;
import org.eclipse.qvtd.pivot.qvtcore.NavigationAssignment;
import org.eclipse.qvtd.pivot.qvtcore.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcore.VariableAssignment;
import org.eclipse.qvtd.pivot.qvtcore.analysis.DomainUsage;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil;
import org.eclipse.qvtd.pivot.qvtschedule.ClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.Edge;
import org.eclipse.qvtd.pivot.qvtschedule.MappingRegion;
import org.eclipse.qvtd.pivot.qvtschedule.NavigableEdge;
import org.eclipse.qvtd.pivot.qvtschedule.Node;
import org.eclipse.qvtd.pivot.qvtschedule.QVTscheduleFactory;
import org.eclipse.qvtd.pivot.qvtschedule.ScheduleModel;
import org.eclipse.qvtd.pivot.qvtschedule.impl.BasicMappingRegionImpl;
/**
* A BasicMappingRegion provides the initial QVTs node-edge graph representation of a QVTm mapping.
*/
public class MappingAnalysis implements Nameable
{
public static @NonNull MappingAnalysis createMappingRegion(@NonNull ScheduleManager scheduleManager, @NonNull Mapping mapping) {
MappingAnalysis mappingAnalysis = new MappingAnalysis(scheduleManager.getScheduleModel(), mapping);
@SuppressWarnings("unused")String name = mappingAnalysis.getMappingRegion().getName();
mappingAnalysis.initialize();
return mappingAnalysis;
}
private final @NonNull BasicMappingRegionImpl mappingRegion;
/**
* Predicates that are too complex to analyze. i.e. more than a comparison of a bound variable wrt
* a property call chain on another bound variable.
*/
private final @NonNull Set<@NonNull Predicate> complexPredicates = new HashSet<>();
private final @NonNull ExpressionAnalyzer expressionAnalyzer;
/**
* All the guard patterns. (domain and mapping).
*/
private final @NonNull List<@NonNull GuardPattern> guardPatterns = new ArrayList<>();
/**
* All the bottom patterns. (domain and mapping).
*/
private final @NonNull List<@NonNull BottomPattern> bottomPatterns = new ArrayList<>();
/**
* The node for each navigable VariableDeclaration.
*/
private final @NonNull List<@NonNull NavigationAssignment> navigationAssignments = new ArrayList<>();
/**
* The variable initializers, simple predicate reference expression and variable assignment values that define a value for each variable.
* Variable initializers are populated lazily since not all LetVariables may even exist for an eager population.
*/
private @NonNull Map<@NonNull VariableDeclaration, @NonNull List<@NonNull OCLExpression>> variable2expressions = new HashMap<>();
/**
* The dependency heads to accommodate operation content.
*/
private /*@LazyNonNull*/ List<@NonNull Node> dependencyHeadNodes = null;
private MappingAnalysis(@NonNull ScheduleModel scheduleModel, @NonNull Mapping mapping) {
this.mappingRegion = (BasicMappingRegionImpl) QVTscheduleFactory.eINSTANCE.createBasicMappingRegion();
mappingRegion.setFixmeScheduleModel(scheduleModel);
scheduleModel.getOwnedOtherMappingRegions().add(mappingRegion);
mappingRegion.setReferredMapping(mapping);
this.expressionAnalyzer = new ExpressionAnalyzer(this);
//
GuardPattern guardPattern = QVTcoreUtil.getGuardPattern(mapping);
BottomPattern bottomPattern = QVTcoreUtil.getBottomPattern(mapping);
guardPatterns.add(guardPattern);
bottomPatterns.add(bottomPattern);
for (@NonNull Assignment assignment : QVTcoreUtil.getOwnedAssignments(bottomPattern)) {
if (assignment instanceof NavigationAssignment) {
navigationAssignments.add((NavigationAssignment)assignment);
}
else if (assignment instanceof VariableAssignment) {
VariableAssignment variableAssignment = (VariableAssignment)assignment;
addExpression(QVTcoreUtil.getTargetVariable(variableAssignment), QVTcoreUtil.getValue(variableAssignment));
}
}
for (@NonNull CoreDomain coreDomain : QVTcoreUtil.getOwnedDomains(mapping)) {
guardPattern = QVTcoreUtil.getGuardPattern(coreDomain);
bottomPattern = QVTcoreUtil.getBottomPattern(coreDomain);
guardPatterns.add(guardPattern);
bottomPatterns.add(bottomPattern);
for (@NonNull Assignment assignment : QVTcoreUtil.getOwnedAssignments(bottomPattern)) {
if (assignment instanceof NavigationAssignment) {
navigationAssignments.add((NavigationAssignment)assignment);
}
else if (assignment instanceof VariableAssignment) {
VariableAssignment variableAssignment = (VariableAssignment)assignment;
addExpression(QVTcoreUtil.getTargetVariable(variableAssignment), QVTcoreUtil.getValue(variableAssignment));
}
}
}
}
protected void addExpression(@NonNull VariableDeclaration variable, @NonNull OCLExpression expression) {
List<@NonNull OCLExpression> initializers = variable2expressions.get(variable);
if (initializers == null) {
initializers = new ArrayList<>();
variable2expressions.put(variable, initializers);
}
if (!initializers.contains(expression)) { // Shouldn't really happen but variable.ownedIInit is lazy
initializers.add(expression);
}
}
/**
* Create the BLUE/CYAN computations for the RHS of assignments.
*/
protected void analyzeAssignmentValues() {
AssignmentSorter assignmentSorter = new AssignmentSorter();
for (@NonNull BottomPattern bottomPattern : bottomPatterns) {
assignmentSorter.addAll(ClassUtil.nullFree(bottomPattern.getAssignment()));
}
for (@NonNull Assignment assignment : assignmentSorter.getSortedAssignments()) {
assignment.accept(expressionAnalyzer);
}
}
protected void analyzeComplexPredicates() {
/**
* Identify any assignments and hidden inputs.
*/
for (Predicate predicate : complexPredicates) {
OCLExpression conditionExpression = predicate.getConditionExpression();
/* if (conditionExpression instanceof OperationCallExp) {
OperationCallExp callExp = (OperationCallExp)conditionExpression;
OperationId operationId = callExp.getReferredOperation().getOperationId();
if (ScheduleModel.isSameOperation(operationId, getScheduleModel().getOclAnyEqualsId())) {
OCLExpression leftExpression = callExp.getOwnedSource();
OCLExpression rightExpression = callExp.getOwnedArguments().get(0);
Node leftNode = expressionAnalyzer.analyze(leftExpression);
Node rightNode = expressionAnalyzer.analyze(rightExpression);
if (leftNode != rightNode) {
if (leftNode.isKnown() && !(leftExpression instanceof NavigationCallExp)) {
RegionUtil.ARGUMENT.createEdge(this, leftNode, "=", rightNode);
}
else if (rightNode.isKnown() && !(rightExpression instanceof NavigationCallExp)) {
RegionUtil.ARGUMENT.createEdge(this, rightNode, "=", leftNode);
}
else if (leftNode.isKnown()) {
RegionUtil.ARGUMENT.createEdge(this, leftNode, "=", rightNode);
}
else if (rightNode.isKnown()) {
RegionUtil.ARGUMENT.createEdge(this, rightNode, "=", leftNode);
}
else {
RegionUtil.BINDING.createEdge(this, leftNode, null, rightNode); // FIXME
RegionUtil.BINDING.createEdge(this, rightNode, null, leftNode);
}
}
}
}
else { */
Node resultNode = conditionExpression.accept(expressionAnalyzer);
if ((resultNode != null) && !resultNode.isTrue()) {
Node trueNode = RegionUtil.createTrueNode(mappingRegion);
RegionUtil.createPredicateEdge(resultNode, null, trueNode);
}
// FIXME ?? do includes() here explicitly
}
}
protected void analyzeContainments() {
for (@NonNull Node node : mappingRegion.getNewNodes()) {
boolean isContained = false;
for (@NonNull NavigableEdge edge : node.getNavigationEdges()) {
Property property = edge.getProperty();
Property opposite = property.getOpposite();
if ((opposite != null) && opposite.isIsComposite() && !edge.getEdgeTarget().isExplicitNull()) {
isContained = true;
break;
}
}
if (isContained) {
node.setContained(true);
}
}
}
/**
* Create a BLUE/CYAN node for each guard variable.
*/
protected void analyzeGuardVariables() {
for (@NonNull GuardPattern guardPattern : guardPatterns) {
for (@NonNull Variable guardVariable : ClassUtil.nullFree(guardPattern.getVariable())) {
Node guardNode = mappingRegion.getNode(guardVariable);
assert guardNode == null;
guardNode = RegionUtil.createOldNode(mappingRegion, guardVariable);
assert guardNode == mappingRegion.getNode(guardVariable);
}
}
}
/**
* Analyze the predicates to partition the guard variables into the distinct inputs that are not mutually
* navigable as a consequence of predicate constraints.
* @param bottomPatterns
*/
protected void analyzePredicates(@NonNull List<@NonNull ? extends CorePattern> corePatterns) {
//
// Populate the targetVariable2sourceVariable2paths from the simple "a.b = c" style predicates,
// and cache those that are too hard to analyze as complex predicates.
//
for (@NonNull CorePattern corePattern : corePatterns) {
for (@NonNull Predicate predicate : ClassUtil.nullFree(corePattern.getPredicate())) {
OCLExpression conditionExpression = predicate.getConditionExpression();
if (conditionExpression != null) {
OCLExpression boundExpression = getPredicateComparisonBoundExpression(conditionExpression);
if (boundExpression instanceof VariableExp) {
OCLExpression referenceExpression = getPredicateComparisonReferenceExpression(conditionExpression);
assert referenceExpression != null;
VariableDeclaration referredVariable = QVTcoreUtil.getReferredVariable(((VariableExp)boundExpression));
if (referredVariable instanceof BottomVariable) {
addExpression(referredVariable, referenceExpression);
}
else {
analyzeSimplePredicate(referredVariable, referenceExpression);
}
}
else if (boundExpression instanceof NullLiteralExp) {
OCLExpression referenceExpression = getPredicateComparisonReferenceExpression(conditionExpression);
assert referenceExpression != null;
analyzeSimplePredicate(null, referenceExpression);
}
else {
complexPredicates.add(predicate);
}
}
}
}
return;
}
/**
* Create a GREEN node for each realized variable.
*/
protected void analyzeRealizedVariables() {
for (@NonNull BottomPattern bottomPattern : bottomPatterns) {
for (@NonNull RealizedVariable realizedVariable : ClassUtil.nullFree(bottomPattern.getRealizedVariable())) {
Node realizedNode = mappingRegion.getNode(realizedVariable);
assert realizedNode == null;
realizedNode = RegionUtil.createRealizedStepNode(mappingRegion, realizedVariable);
assert realizedNode == mappingRegion.getNode(realizedVariable);
}
}
}
//
// Install the targetVariable2sourceVariable2paths entries for a "boundVariable = referenceExpression" predicate,
// where the referenceExpression involves zero or more PropertyCallExps of a VariableExp. boundVariable may be null
// for a negative application condition.
//
// A reverse entry is also created if no PropertyCallExp is not to-one.
//
private void analyzeSimplePredicate(@Nullable VariableDeclaration boundVariable, @NonNull OCLExpression referenceExpression) {
for (@NonNull OCLExpression expression = referenceExpression; expression instanceof NavigationCallExp; ) {
NavigationCallExp navigationCallExp = (NavigationCallExp)expression;
Property referredProperty = PivotUtil.getReferredProperty(navigationCallExp);
assert referredProperty != null;
expression = ClassUtil.nonNullState(navigationCallExp.getOwnedSource());
if (expression instanceof VariableExp) {
VariableDeclaration sourceVariable = ((VariableExp)expression).getReferredVariable();
assert sourceVariable != null;
// assert guardVariables.contains(targetVariable);
// assert guardVariables.contains(sourceVariable);
Node sourceNode = getReferenceNode(sourceVariable);
Node targetNode = boundVariable != null ? getReferenceNode(boundVariable) : RegionUtil.createNullNode(mappingRegion, true, null);
// assert sourceNode.isGuard();
// assert (boundVariable == null) || targetNode.isGuard();
assert sourceNode.isClass();
if (!referredProperty.isIsMany()) {
Edge predicateEdge = sourceNode.getPredicateEdge(referredProperty);
if (predicateEdge == null) {
RegionUtil.createNavigationEdge(sourceNode, referredProperty, targetNode, false);
}
else {
assert predicateEdge.getEdgeTarget() == targetNode;
}
}
}
}
}
private @Nullable Node analyzeVariable(@NonNull Variable variable, @NonNull List<@NonNull OCLExpression> expressions) {
//
// Use something hard to compute as the initializer that creates an initNode in the hope that other
// initializers might be easier and optimized as simple navigation edges.
//
OCLExpression bestInitExpression = null;
for (@NonNull OCLExpression initExpression : expressions) {
if (initExpression instanceof OperationCallExp ) {
OperationCallExp operationCallExp = (OperationCallExp)initExpression;
OperationId operationId = operationCallExp.getReferredOperation().getOperationId();
if (!PivotUtil.isSameOperation(operationId, OperationId.OCLANY_EQUALS) && !PivotUtil.isSameOperation(operationId, OperationId.OCLANY_NOT_EQUALS)) {
bestInitExpression = initExpression;
break;
}
}
}
if (bestInitExpression == null) {
bestInitExpression = (expressions.size() > 0) ? expressions.get(0) : null;
}
if (bestInitExpression == null) {
return null;
}
Node bestInitNode = bestInitExpression.accept(expressionAnalyzer);
assert bestInitNode != null;
/* if ((ownedInit instanceof OperationCallExp) && initNode.isOperation()) {
if (QVTbaseUtil.isIdentification(((OperationCallExp)ownedInit).getReferredOperation())) {
Node stepNode = RegionUtil.createRealizedStepNode(mappingRegion, variable);
RegionUtil.createEqualsEdge(initNode, stepNode);
initNode = stepNode;
}
// else if (variable.getType() instanceof CollectionType) {
// Node stepNode = RegionUtil.ATTRIBUTE.createNode(this, variable, (OperationCallExp)ownedInit);
// RegionUtil.RESULT.createEdge(this, initNode, null, stepNode);
// initNode = stepNode;
// }
else {
// Node stepNode = RegionUtil.STEP.createNode(this, variable.getName(), (OperationCallExp)ownedInit, initNode);
Node stepNode = RegionUtil.createLoadedStepNode(mappingRegion, variable);
RegionUtil.createEqualsEdge(initNode, stepNode);
initNode = stepNode;
}
} */
CompleteClass initCompleteClass = bestInitNode.getCompleteClass();
ScheduleManager scheduleManager = getScheduleManager();
ClassDatum variableClassDatum = scheduleManager.getClassDatum(variable);
CompleteClass variableCompleteClass = RegionUtil.getCompleteClass(variableClassDatum);
if (!initCompleteClass.conformsTo(variableCompleteClass)) {
Node castNode = RegionUtil.createOldNode(mappingRegion, variable);
Property castProperty = scheduleManager.getCastProperty(PivotUtil.getType(variable));
expressionAnalyzer.createCastEdge(bestInitNode, castProperty, castNode);
bestInitNode = castNode;
}
bestInitNode.addTypedElement(variable);
mappingRegion.addVariableNode(variable, bestInitNode);
for (@NonNull OCLExpression initExpression : expressions) {
if (initExpression != bestInitExpression) {
// FIXME if the extra init is a navigation we can add a navigation to the bestInitNode
Node initNode = bestInitExpression.accept(expressionAnalyzer);
assert initNode != null;
RegionUtil.createEqualsEdge(bestInitNode, initNode);
}
}
return bestInitNode;
}
public @NonNull Node createDependencyHead(@NonNull ClassDatumAnalysis classDatumAnalysis) {
if (dependencyHeadNodes == null) {
dependencyHeadNodes = new ArrayList<>();
}
Node dependencyHeadNode = RegionUtil.createDependencyNode(mappingRegion, "«extra-" + (dependencyHeadNodes.size()+1) + "»", classDatumAnalysis);
dependencyHeadNode.setHead();
dependencyHeadNodes.add(dependencyHeadNode);
return dependencyHeadNode;
}
public @Nullable Node getDependencyHead(@NonNull ClassDatumAnalysis classDatumAnalysis) {
if (dependencyHeadNodes != null) {
for (@NonNull Node dependencyHeadNode : dependencyHeadNodes) {
if (RegionUtil.getClassDatumAnalysis(dependencyHeadNode) == classDatumAnalysis) {
return dependencyHeadNode;
}
}
}
return null;
}
public @NonNull MappingRegion getMappingRegion() {
return mappingRegion;
}
@Override
public @NonNull String getName() {
return RegionUtil.getName(mappingRegion);
}
/**
* Return the boundExpression if conditionExpression is of the form
* <br>"variable = referenceExpression" => VariableExp(variable)
* <br>"referenceExpression = variable" => VariableExp(variable)
* <br>"null = referenceExpression" => NullLiteralExp(null)
* <br>"referenceExpression = null" => NullLiteralExp(null)
* <br>"constant-expression = referenceExpression" => OCLExpression(constant)
* <br>"referenceExpression = constant-expression" => OCLExpression(constant)
*
* <br>Returns null otherwise.
*/
private @Nullable OCLExpression getPredicateComparisonBoundExpression(@NonNull OCLExpression conditionExpression) {
if (conditionExpression instanceof OperationCallExp) {
OperationCallExp callExp = (OperationCallExp)conditionExpression;
OperationId operationId = callExp.getReferredOperation().getOperationId();
if (PivotUtil.isSameOperation(operationId, RegionUtil.getScheduleManager(mappingRegion).getStandardLibraryHelper().getOclAnyEqualsId())) {
OCLExpression leftExp = callExp.getOwnedSource();
if (leftExp instanceof VariableExp) {
return leftExp;
}
OCLExpression rightExp = callExp.getOwnedArguments().get(0);
if (rightExp instanceof VariableExp) {
return rightExp;
}
IsConstantExpressionVisitor isConstantExpressionVisitor = new IsConstantExpressionVisitor(null);
if (isConstantExpressionVisitor.isConstant(leftExp)) {
return leftExp;
}
if (isConstantExpressionVisitor.isConstant(rightExp)) {
return rightExp;
}
}
}
return null;
}
/**
* Return the referenceExpression if conditionExpression is of the form "boundVariable = referenceExpression" or
* "referenceExpression = boundVariable". Returns null otherwise.
*/
private @Nullable OCLExpression getPredicateComparisonReferenceExpression(@NonNull OCLExpression conditionExpression) {
if (conditionExpression instanceof OperationCallExp) {
OperationCallExp callExp = (OperationCallExp)conditionExpression;
OperationId operationId = callExp.getReferredOperation().getOperationId();
if (PivotUtil.isSameOperation(operationId, RegionUtil.getScheduleManager(mappingRegion).getStandardLibraryHelper().getOclAnyEqualsId())) {
OCLExpression leftExp = callExp.getOwnedSource();
OCLExpression rightExp = callExp.getOwnedArguments().get(0);
if (leftExp instanceof VariableExp) {
return rightExp;
}
else if (rightExp instanceof VariableExp) {
return leftExp;
}
IsConstantExpressionVisitor isConstantExpressionVisitor = new IsConstantExpressionVisitor(null);
if (isConstantExpressionVisitor.isConstant(leftExp)) {
return rightExp;
}
if (isConstantExpressionVisitor.isConstant(rightExp)) {
return leftExp;
}
}
}
return null;
}
public @NonNull Node getReferenceNode(@NonNull VariableDeclaration variableDeclaration) {
Node node = mappingRegion.getNode(variableDeclaration);
if (node == null) {
if (variableDeclaration instanceof Variable) {
Variable variable = (Variable)variableDeclaration;
OCLExpression ownedInit = variable.getOwnedInit();
if (ownedInit != null) {
addExpression(variable, ownedInit);
}
List<@NonNull OCLExpression> expressions = variable2expressions.get(variable);
if (expressions != null) {
node = analyzeVariable(variable, expressions);
}
else if (variable.eContainer() instanceof BottomPattern) {
DomainUsage domainUsage = RegionUtil.getScheduleManager(mappingRegion).getDomainUsage(variable);
boolean isEnforceable = domainUsage.isOutput() || domainUsage.isMiddle();
if (isEnforceable) {
node = RegionUtil.createRealizedStepNode(mappingRegion, variable);
}
else {
node = RegionUtil.createLoadedStepNode(mappingRegion, variable); // FIXME Predicated ??
}
}
}
}
assert node != null : "No variable2simpleNode entry for " + variableDeclaration;
return node;
/* if (variable instanceof RealizedVariable) {
return RegionUtil.REALIZED_VARIABLE.createNode(this, (RealizedVariable)variable);
}
else if (variable.eContainer() instanceof BottomPattern) {
return RegionUtil.UNREALIZED_VARIABLE.createNode(this, variable);
}
else {
return new GuardVariableNode(this, variable);
} */
}
protected @NonNull ScheduleManager getScheduleManager() {
return expressionAnalyzer.scheduleManager;
}
public @NonNull Node getUnknownNode(@NonNull TypedElement typedElement) {
assert !(typedElement instanceof Property); // Property entries should be AttributeNodes
Node node = mappingRegion.getNode(typedElement);
if (node == null) {
node = RegionUtil.createUnknownNode(mappingRegion, ClassUtil.nonNullState(typedElement.getType().toString()), typedElement);
// node2node.put(typedElement, node);
}
return node;
}
public void initialize() {
//
// Create the BLUE/CYAN guard nodes.
//
analyzeGuardVariables();
//
// Create the GREEN realized nodes.
//
analyzeRealizedVariables(); // FIXME bottom variables too
//
// Create the predicate/computation nodes and edges
//
analyzePredicates(guardPatterns);
analyzePredicates(bottomPatterns);
analyzeAssignmentValues();
analyzeComplexPredicates();
analyzeContainments();
//
RegionHelper regionHelper = new RegionHelper(mappingRegion);
List<@NonNull Node> headNodes = regionHelper.initHeadNodes();
regionHelper.computeUtilities(headNodes);
}
/**
* Return true if the navigation from sourceNode using source2targetProperty corresponds to a PropertyAssigmment,
*/
public boolean isPropertyAssignment(@NonNull Node sourceNode, @NonNull Property source2targetProperty) {
if (sourceNode.isRealized()) {
for (@NonNull NavigationAssignment navigationAssignment : navigationAssignments) {
Property navigationProperty = QVTcoreUtil.getTargetProperty(navigationAssignment);
if (source2targetProperty == navigationProperty) { // ??? opposites ??? do they even exist ???
Node slotNode = expressionAnalyzer.analyze(navigationAssignment.getSlotExpression());
if (slotNode == sourceNode) {
return true;
}
}
}
}
return false;
}
public void registerConsumptionsAndProductions(@NonNull QVTm2QVTs qvtm2qts) {
for (@NonNull Node newNode : mappingRegion.getNewNodes()) {
ClassDatumAnalysis classDatumAnalysis = RegionUtil.getClassDatumAnalysis(newNode);
classDatumAnalysis.addProduction(mappingRegion, newNode);
for (@NonNull Mapping consumingMapping : classDatumAnalysis.getRequiredBy()) {
MappingRegion consumingRegion = qvtm2qts.getMappingRegion(consumingMapping);
for (@NonNull Node consumingNode : consumingRegion.getOldNodes()) {
if (consumingNode.getCompleteClass() == classDatumAnalysis.getClassDatum().getCompleteClass()) { // FIXME inheritance
classDatumAnalysis.addConsumption(consumingRegion, consumingNode);
}
}
}
}
for (@NonNull Node predicatedNode : mappingRegion.getOldNodes()) {
ClassDatumAnalysis classDatumAnalysis = RegionUtil.getClassDatumAnalysis(predicatedNode);
classDatumAnalysis.addConsumption(mappingRegion, predicatedNode);
for (@NonNull Mapping producingMapping : classDatumAnalysis.getProducedBy()) {
MappingRegion producingRegion = qvtm2qts.getMappingRegion(producingMapping);
assert producingRegion != null;
for (@NonNull Node newNode : producingRegion.getNewNodes()) {
if (newNode.getCompleteClass() == classDatumAnalysis.getClassDatum().getCompleteClass()) { // FIXME inheritance
classDatumAnalysis.addProduction(producingRegion, newNode);
}
}
}
}
}
}