blob: 3885443184e23334355ab9332933305d13a9dc43 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 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.qvts2qvts.partitioner;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.qvtd.compiler.internal.qvtm2qvts.RegionUtil;
import org.eclipse.qvtd.pivot.qvtschedule.Edge;
import org.eclipse.qvtd.pivot.qvtschedule.MicroMappingRegion;
import org.eclipse.qvtd.pivot.qvtschedule.Node;
import org.eclipse.qvtd.pivot.qvtschedule.Role;
import org.eclipse.qvtd.pivot.qvtschedule.StatusNode;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil;
/**
* The AssignmentPartition identifies the nodes and edges required by an assignment micro-mapping
* which creates the predicates and realization of a property assignment.
*/
class AssignmentPartition extends AbstractPartition
{
// protected final @NonNull Edge realizedEdge;
public AssignmentPartition(@NonNull MappingPartitioner partitioner, @NonNull Edge realizedEdge) {
super(partitioner);
// this.realizedEdge = realizedEdge;
//
// The realized middle (trace) nodes become predicated head nodes.
//
for (@NonNull Node traceNode : partitioner.getTraceNodes()) {
addNode(traceNode, Role.PREDICATED);
Node statusNode = partitioner.getStatusNode(traceNode);
if (statusNode != null) { // status property is not mandatory
addNode(statusNode, Role.PREDICATED);
}
}
//
// The ends of the realized edge are used as is except that REALIZED elsewhere nodes are PREDICATED here.
//
Node sourceNode = realizedEdge.getEdgeSource();
if (!hasNode(sourceNode)) { // never fails; source node is not a trace node
Role sourceNodeRole = RegionUtil.getNodeRole(sourceNode);
if (sourceNodeRole == Role.REALIZED) {
sourceNodeRole = QVTscheduleUtil.asPredicated(sourceNodeRole);
}
addNode(sourceNode, sourceNodeRole);
}
Node targetNode = realizedEdge.getEdgeTarget();
if (!hasNode(targetNode)) { // very unlikely to fail; can a REALIZED edge share source/target
Role targetNodeRole = RegionUtil.getNodeRole(targetNode);
if (targetNodeRole == Role.REALIZED) {
targetNodeRole = QVTscheduleUtil.asPredicated(targetNodeRole);
}
addNode(targetNode, targetNodeRole);
}
//
// Add all nodes required to reach the source/target nodes.
//
resolvePrecedingNodes();
//
// Ensure that re-used trace classes do not lead to ambiguous mappings.
//
resolveDisambiguations();
//
// Join up the edges.
//
resolveEdges();
}
@Override
protected @NonNull PartitioningVisitor createPartitioningVisitor(@NonNull MicroMappingRegion partialRegion) {
return new PartitioningVisitor(partialRegion, this)
{
@Override
public @Nullable Element visitStatusNode(@NonNull StatusNode node) {
Node partialNode = RegionUtil.createTrueNode(partialRegion);
addNode(node, partialNode);
return partialNode;
}
};
}
@Override
protected @Nullable Role resolveEdgeRole(@NonNull Role sourceNodeRole, @NonNull Edge edge, @NonNull Role targetNodeRole) {
Role edgeRole = RegionUtil.getEdgeRole(edge);
if (edgeRole == Role.REALIZED) {
AbstractPartition realizingPartition = partitioner.getRealizingPartition(edge);
if (realizingPartition instanceof AssignmentPartition) {
if (!isCorrolary(RegionUtil.getTargetNode(edge))) { // FIXME do corrolaries before assigns
return null;
}
}
if (realizingPartition != null) {
edgeRole = Role.PREDICATED;
}
}
return edgeRole;
}
}