blob: 7a111b9a07e19e39b0c1c30afa277e2a208f4156 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018, 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.compiler.internal.qvtb2qvts;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.BooleanLiteralExp;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionLiteralPart;
import org.eclipse.ocl.pivot.CollectionRange;
import org.eclipse.ocl.pivot.DataType;
import org.eclipse.ocl.pivot.EnumLiteralExp;
import org.eclipse.ocl.pivot.EnumerationLiteral;
import org.eclipse.ocl.pivot.IfExp;
import org.eclipse.ocl.pivot.MapLiteralExp;
import org.eclipse.ocl.pivot.MapLiteralPart;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.NullLiteralExp;
import org.eclipse.ocl.pivot.NumericLiteralExp;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.Parameter;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.ShadowExp;
import org.eclipse.ocl.pivot.ShadowPart;
import org.eclipse.ocl.pivot.StringLiteralExp;
import org.eclipse.ocl.pivot.TupleLiteralExp;
import org.eclipse.ocl.pivot.TupleLiteralPart;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.internal.prettyprint.PrettyPrinter;
import org.eclipse.ocl.pivot.utilities.Nameable;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtcore.NavigationAssignment;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil;
import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil;
import org.eclipse.qvtd.pivot.qvtschedule.BasicPartition;
import org.eclipse.qvtd.pivot.qvtschedule.BooleanLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.CastEdge;
import org.eclipse.qvtd.pivot.qvtschedule.ClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.CollectionLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.CollectionPartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.CollectionRangeNode;
import org.eclipse.qvtd.pivot.qvtschedule.CyclicPartition;
import org.eclipse.qvtd.pivot.qvtschedule.DependencyEdge;
import org.eclipse.qvtd.pivot.qvtschedule.DependencyNode;
import org.eclipse.qvtd.pivot.qvtschedule.Edge;
import org.eclipse.qvtd.pivot.qvtschedule.EnumLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.ErrorNode;
import org.eclipse.qvtd.pivot.qvtschedule.ExpressionEdge;
import org.eclipse.qvtd.pivot.qvtschedule.IfNode;
import org.eclipse.qvtd.pivot.qvtschedule.InputNode;
import org.eclipse.qvtd.pivot.qvtschedule.IteratedEdge;
import org.eclipse.qvtd.pivot.qvtschedule.IteratorNode;
import org.eclipse.qvtd.pivot.qvtschedule.KeyPartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.KeyedValueNode;
import org.eclipse.qvtd.pivot.qvtschedule.LoadingPartition;
import org.eclipse.qvtd.pivot.qvtschedule.LoadingRegion;
import org.eclipse.qvtd.pivot.qvtschedule.MapLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.MapPartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.MapPartNode;
import org.eclipse.qvtd.pivot.qvtschedule.MappingRegion;
import org.eclipse.qvtd.pivot.qvtschedule.MergedPartition;
import org.eclipse.qvtd.pivot.qvtschedule.NavigableEdge;
import org.eclipse.qvtd.pivot.qvtschedule.NavigationEdge;
import org.eclipse.qvtd.pivot.qvtschedule.Node;
import org.eclipse.qvtd.pivot.qvtschedule.NonPartition;
import org.eclipse.qvtd.pivot.qvtschedule.NullLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.NumericLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.OperationCallNode;
import org.eclipse.qvtd.pivot.qvtschedule.OperationParameterEdge;
import org.eclipse.qvtd.pivot.qvtschedule.OperationSelfEdge;
import org.eclipse.qvtd.pivot.qvtschedule.PatternTypedNode;
import org.eclipse.qvtd.pivot.qvtschedule.PatternVariableNode;
import org.eclipse.qvtd.pivot.qvtschedule.PredicateEdge;
import org.eclipse.qvtd.pivot.qvtschedule.PropertyDatum;
import org.eclipse.qvtd.pivot.qvtschedule.QVTscheduleFactory;
import org.eclipse.qvtd.pivot.qvtschedule.Region;
import org.eclipse.qvtd.pivot.qvtschedule.Role;
import org.eclipse.qvtd.pivot.qvtschedule.RootPartition;
import org.eclipse.qvtd.pivot.qvtschedule.ShadowNode;
import org.eclipse.qvtd.pivot.qvtschedule.ShadowPartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.StringLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.SuccessEdge;
import org.eclipse.qvtd.pivot.qvtschedule.SuccessNode;
import org.eclipse.qvtd.pivot.qvtschedule.TupleLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.TuplePartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.TypeLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.UnknownNode;
import org.eclipse.qvtd.pivot.qvtschedule.VariableNode;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.DomainUsage;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil;
import org.eclipse.qvtd.runtime.utilities.QVTruntimeUtil;
import com.google.common.collect.Iterables;
/**
* A RegionHelper provides stateless utility methods, mostly construction, for use within a Region
* supervised by a ScheduleManager.
*/
public class RegionHelper<R extends Region> extends QVTscheduleUtil implements Nameable
{
public static final @NonNull String EQUALS_NAME = "«equals»";
public static final @NonNull String INCLUDES_NAME = "«includes»";
public static final @NonNull String LOOP_ITERATOR_NAME = "«iterator»";
protected final @NonNull ScheduleManager scheduleManager;
protected final @NonNull R region;
public RegionHelper(@NonNull ScheduleManager scheduleManager, @NonNull R region) {
this.scheduleManager = scheduleManager;
this.region = region;
}
public @NonNull BasicPartition createBasicPartition(@NonNull String name, @NonNull Iterable<@NonNull Node> headNodes) {
BasicPartition basicPartition = QVTscheduleFactory.eINSTANCE.createBasicPartition();
basicPartition.setName(name);
// basicPartition.setRegion(region);
((MappingRegion)region).getMappingPartitions().add(basicPartition);
Iterables.addAll(QVTscheduleUtil.Internal.getHeadNodesList(basicPartition), headNodes);
return basicPartition;
}
public @NonNull BooleanLiteralNode createBooleanLiteralNode(boolean isTrue) {
ClassDatum classDatum = scheduleManager.getBooleanClassDatum();
BooleanLiteralNode booleanLiteralNode = QVTscheduleFactory.eINSTANCE.createBooleanLiteralNode();
booleanLiteralNode.initialize(Role.CONSTANT, region, Boolean.toString(isTrue), classDatum);
booleanLiteralNode.setMatched(true);
booleanLiteralNode.setBooleanValue(isTrue);
return booleanLiteralNode;
}
public @NonNull BooleanLiteralNode createBooleanLiteralNode(boolean isMatched, boolean booleanValue, @NonNull BooleanLiteralExp booleanLiteralExp) {
Role nodeRole = getOperationNodePhase(region, booleanLiteralExp);
BooleanLiteralNode booleanLiteralNode = QVTscheduleFactory.eINSTANCE.createBooleanLiteralNode();
booleanLiteralNode.initialize(nodeRole, region, Boolean.toString(booleanValue), scheduleManager.getClassDatum(booleanLiteralExp));
booleanLiteralNode.setMatched(isMatched);
booleanLiteralNode.setBooleanValue(booleanValue);
booleanLiteralNode.setOriginatingElement(booleanLiteralExp);
return booleanLiteralNode;
}
public @NonNull CastEdge createCastEdge(@NonNull Node sourceNode, @NonNull ClassDatum classDatum, @NonNull Node targetNode) {
Role phase = mergeToLessKnownPhase(getNodeRole(sourceNode), getNodeRole(targetNode));
Role edgeRole = phase;
CastEdge castEdge = QVTscheduleFactory.eINSTANCE.createCastEdge();
castEdge.initialize(edgeRole, sourceNode, classDatum, targetNode);
return castEdge;
}
public @NonNull CollectionLiteralNode createCollectionLiteralNode(boolean isMatched, @NonNull String name, @NonNull CollectionLiteralExp collectionLiteralExp, @NonNull Node @NonNull [] partNodes) {
Role nodeRole = getOperationNodePhase(region, collectionLiteralExp, partNodes);
CollectionLiteralNode node = QVTscheduleFactory.eINSTANCE.createCollectionLiteralNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(collectionLiteralExp));
node.setMatched(isMatched);
node.setOriginatingElement(collectionLiteralExp);
return node;
}
public @NonNull Edge createCollectionPartEdge(@NonNull Node sourceNode, @NonNull CollectionLiteralPart collectionPart, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
CollectionPartEdge edge = QVTscheduleFactory.eINSTANCE.createCollectionPartEdge();
edge.setReferredPart(collectionPart);
String partName = collectionPart.getName(); // Always null
String label = partName != null ? "«" + partName + "»" : "«part»";
edge.initialize(edgeRole, sourceNode, label, targetNode);
return edge;
}
public @NonNull CollectionRangeNode createCollectionRangeNode(boolean isMatched, @NonNull String name, @NonNull CollectionRange collectionRange, @NonNull Node @NonNull [] argNodes) {
Role nodeRole = getOperationNodePhase(region, collectionRange, argNodes);
CollectionRangeNode node = QVTscheduleFactory.eINSTANCE.createCollectionRangeNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(collectionRange));
node.setMatched(isMatched);
node.setOriginatingElement(collectionRange);
return node;
}
/** FIXME make non-static */
public static @NonNull CyclicPartition createCyclicPartition(@NonNull String name, @NonNull Object scheduleManager) {
CyclicPartition cyclicPartition = QVTscheduleFactory.eINSTANCE.createCyclicPartition();
cyclicPartition.setName(name);
// cyclicPartition.setRegion(region);
// Iterables.addAll(cyclicPartition.getHeadNodes(), headNodes);
return cyclicPartition;
}
public @NonNull Node createDataTypeNode(@NonNull String name, @NonNull Node sourceNode, @NonNull NavigationCallExp navigationCallExp) {
Property property = PivotUtil.getReferredProperty(navigationCallExp);
boolean isMatched = sourceNode.isMatched() && isMatched(property);
Role nodeRole = getPatternNodeRole(sourceNode, property);
assert sourceNode.isClass() || (property.getOpposite() != null); // FIXME review is this relevant?
// String name = property.getName();
// assert name != null;
PatternTypedNode node = QVTscheduleFactory.eINSTANCE.createPatternTypedNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(navigationCallExp));
node.setMatched(isMatched);
node.setOriginatingElement(navigationCallExp);
return node;
}
public @NonNull Node createDataTypeNode(@NonNull Node targetNode, @NonNull NavigationAssignment navigationAssignment) {
Role nodeRole = getNodeRole(targetNode);
Property property = QVTcoreUtil.getTargetProperty(navigationAssignment);
// PatternNodeRole nodeRole = PatternNodeRole.getDataTypeNodeRole(targetNode, property);
// assert sourceNode.isClass(); // FIXME review is this relevant?
String name = property.getName();
assert name != null;
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)property.getType();
assert type != null;
TypedModel typedModel = getTypedModel(targetNode);
ClassDatum classDatum = scheduleManager.getClassDatum(typedModel, type);
PatternTypedNode node = QVTscheduleFactory.eINSTANCE.createPatternTypedNode();
node.initialize(nodeRole, region, name, classDatum);
node.setMatched(true);
node.setOriginatingElement(property);
return node;
}
public @NonNull Node createDataTypeNode(@NonNull Node sourceNode, @NonNull Property property) {
Role nodeRole = getPatternNodeRole(sourceNode, property);
return createPatternNode(nodeRole, sourceNode, property, sourceNode.isMatched() && isMatched(property));
}
public @NonNull Node createDependencyClassNode(@NonNull Node parentNode, @NonNull NavigationAssignment navigationAssignment) {
assert parentNode.isClass();
Property property = QVTcoreUtil.getTargetProperty(navigationAssignment);
assert property != null;
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)property.getType();
assert type != null;
TypedModel typedModel = getTypedModel(parentNode);
ClassDatum classDatum = scheduleManager.getClassDatum(typedModel, type);
// DomainUsage domainUsage = parentNode.getClassDatumAnalysis().getDomainUsage();
String name = property.getName();
assert name != null;
return createDependencyNode(name, classDatum);
}
public @NonNull Edge createDependencyEdge(@NonNull Node sourceNode, @NonNull String name, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
DependencyEdge edge = QVTscheduleFactory.eINSTANCE.createDependencyEdge();
edge.initialize(edgeRole, sourceNode, name, targetNode);
return edge;
}
public @NonNull Node createDependencyNode(@NonNull String name, @NonNull ClassDatum classDatum) {
Role nodeRole = Role.PREDICATED;
DependencyNode node = QVTscheduleFactory.eINSTANCE.createDependencyNode();
node.initialize(nodeRole, region, name, classDatum);
return node;
}
/**
* Create, install and return the edgeRole edge for source2targetProperty from sourceNode to targetNode. If
* source2targetProperty has an opposite, the opposite edge is also created and installed.
*
public @NonNull NavigableEdge createEdge(@NonNull Role edgeRole,
@NonNull Node sourceNode, @NonNull Property source2targetProperty, @NonNull Node targetNode) {
CastEdge castEdge = QVTscheduleFactory.eINSTANCE.createCastEdge();
castEdge.initialize(edgeRole, sourceNode, source2targetProperty.getName(), targetNode);
castEdge.initializeProperty(source2targetProperty);
return castEdge;
} */
public @NonNull EnumLiteralNode createEnumLiteralNode(boolean isMatched, @NonNull EnumerationLiteral enumValue, @NonNull EnumLiteralExp enumLiteralExp) {
ClassDatum classDatum = scheduleManager.getClassDatum(enumLiteralExp);
String typeName = PrettyPrinter.printType(enumValue);
Role nodeRole = getOperationNodePhase(region, enumLiteralExp);
EnumLiteralNode enumLiteralNode = QVTscheduleFactory.eINSTANCE.createEnumLiteralNode();
enumLiteralNode.initialize(nodeRole, region, typeName, classDatum);
enumLiteralNode.setMatched(isMatched);
enumLiteralNode.setEnumValue(enumValue);
enumLiteralNode.setOriginatingElement(enumLiteralExp);
return enumLiteralNode;
}
//
// equals edges seem to be a legacy relic. They are used to equate two nodes that have been carelessly created as distinct. The difficulties
// of ensuring that downstream code accommodates the duality far outweight the difficulties of creating a single node in the first place.
//
// This method is not used by any tests, but one anticipated usage arises if a variable has multiple initializers,
// and/or multiple predicates, in which case a hard initializer such as an operation call is preferred,
// and then other initializers are checked as predicates using equals edges.
//
public @NonNull Edge createEqualsEdge(@NonNull Node sourceNode, @NonNull Node targetNode) {
if (!region.isOperationRegion()) {
QVTruntimeUtil.errPrintln("Unexpected " + EQUALS_NAME + " edge in " + region + " from " + sourceNode + " to " + targetNode);
}
// Role edgeRole = getNodeRole(sourceNode);
// ExpressionEdge edge = QVTscheduleFactory.eINSTANCE.createEqualsEdge();
// edge.initialize(edgeRole, sourceNode, QVTscheduleConstants.EQUALS_NAME, targetNode);
// return edge;
return createPredicateEdge(sourceNode, EQUALS_NAME, targetNode);
}
public @NonNull Node createErrorNode(@NonNull String name, @NonNull ClassDatum classDatum) {
Role nodeRole = Role.OTHER;
ErrorNode node = QVTscheduleFactory.eINSTANCE.createErrorNode();
node.initialize(nodeRole, region, name, classDatum);
return node;
}
public @NonNull IfNode createIfNode(boolean isMatched, @NonNull String name, @NonNull IfExp ifExp, @NonNull Node @NonNull [] argNodes) {
Role nodeRole = getOperationNodePhase(region, ifExp, argNodes);
IfNode node = QVTscheduleFactory.eINSTANCE.createIfNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(ifExp));
node.setMatched(isMatched);
node.setOriginatingElement(ifExp);
return node;
}
public @NonNull IfNode createIfNode2(boolean isMatched, @NonNull String name, @NonNull ClassDatum classDatum, @NonNull Node @NonNull [] argNodes) {
Role nodeRole = getOperationNodePhase(region, null, argNodes);
IfNode node = QVTscheduleFactory.eINSTANCE.createIfNode();
node.initialize(nodeRole, region, name, classDatum);
node.setMatched(isMatched);
return node;
}
public @NonNull Node createInputNode(@NonNull Role nodeRole, @NonNull String name, @NonNull ClassDatum classDatum) {
InputNode node = QVTscheduleFactory.eINSTANCE.createInputNode();
node.initialize(nodeRole, region, name, classDatum);
return node;
}
public @NonNull Edge createIteratedEdge(@NonNull Node sourceNode, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
IteratedEdge edge = QVTscheduleFactory.eINSTANCE.createIteratedEdge();
edge.initialize(edgeRole, sourceNode, LOOP_ITERATOR_NAME, targetNode);
return edge;
}
public @NonNull VariableNode createIteratorNode(@NonNull VariableDeclaration iterator, @NonNull Node sourceNode) {
Role nodeRole = getNodeRole(sourceNode);
IteratorNode node = QVTscheduleFactory.eINSTANCE.createIteratorNode();
node.initialize(nodeRole, region, getName(iterator), scheduleManager.getClassDatum(iterator));
node.initializeVariable(region, iterator);
return node;
}
public @NonNull Edge createKeyPartEdge(@NonNull Node sourceNode, @NonNull PropertyDatum propertyDatum, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
KeyPartEdge edge = QVTscheduleFactory.eINSTANCE.createKeyPartEdge();
edge.setReferredPart(propertyDatum);
Property referredProperty = QVTscheduleUtil.getReferredProperty(propertyDatum);
String name = "«" + QVTrelationUtil.getName(referredProperty) + "»";
edge.initialize(edgeRole, sourceNode, name, targetNode);
return edge;
}
public @NonNull Node createKeyedNode(boolean isMatched, @NonNull String name, @NonNull VariableDeclaration templateVariable) {
ClassDatum classDatum = scheduleManager.getClassDatum(templateVariable);
KeyedValueNode node = QVTscheduleFactory.eINSTANCE.createKeyedValueNode();
node.setClassDatumValue(classDatum);
node.initialize(Role.REALIZED, region, name, classDatum);
region.addVariableNode(templateVariable, node);
node.setMatched(isMatched);
// node.addTypedElement(templateVariable);
return node;
}
public @NonNull VariableNode createLetVariableNode(@NonNull VariableDeclaration letVariable, @NonNull Node inNode) {
Role nodeRole = getNodeRole(inNode);
PatternVariableNode node = QVTscheduleFactory.eINSTANCE.createPatternVariableNode();
node.initialize(nodeRole, region, getName(letVariable), scheduleManager.getClassDatum(letVariable));
node.initializeVariable(region, letVariable);
node.setMatched(inNode.isMatched());
return node;
}
public @NonNull VariableNode createLoadedStepNode(@NonNull VariableDeclaration stepVariable) {
Role nodeRole = Role.LOADED;
PatternVariableNode node = QVTscheduleFactory.eINSTANCE.createPatternVariableNode();
node.initialize(nodeRole, region, getName(stepVariable), scheduleManager.getClassDatum(stepVariable));
node.initializeVariable(region, stepVariable);
node.setMatched(true);
return node;
}
public @NonNull LoadingPartition createLoadingPartition() {
LoadingPartition loadingPartition = QVTscheduleFactory.eINSTANCE.createLoadingPartition();
loadingPartition.setName(region.getName());
// loadingPartition.setRegion(region);
((LoadingRegion)region).setLoadingPartition(loadingPartition);
// Iterables.addAll(loadingPartition.getHeadNodes(), headNodes);
return loadingPartition;
}
public @NonNull MapLiteralNode createMapLiteralNode(boolean isMatched, @NonNull String name, @NonNull MapLiteralExp mapLiteralExp, @NonNull Node @NonNull [] partNodes) {
Role nodeRole = getOperationNodePhase(region, mapLiteralExp, partNodes);
MapLiteralNode node = QVTscheduleFactory.eINSTANCE.createMapLiteralNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(mapLiteralExp));
node.setMatched(isMatched);
node.setOriginatingElement(mapLiteralExp);
return node;
}
public @NonNull Edge createMapPartEdge(@NonNull Node sourceNode, @NonNull MapLiteralPart mapPart, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
MapPartEdge edge = QVTscheduleFactory.eINSTANCE.createMapPartEdge();
edge.setReferredPart(mapPart);
String label = "«" + mapPart.toString() + "»";
edge.initialize(edgeRole, sourceNode, label, targetNode);
return edge;
}
public @NonNull Node createMapPartNode(boolean isMatched, @NonNull String name, @NonNull MapLiteralPart mapLiteralPart, @NonNull Node @NonNull [] argNodes) {
TypedElement typedElement = QVTbaseUtil.getOwnedValue(mapLiteralPart); // FIXME delete this
Role nodeRole = getOperationNodePhase(region, typedElement, argNodes);
MapPartNode node = QVTscheduleFactory.eINSTANCE.createMapPartNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(typedElement));
node.setMatched(isMatched);
node.setOriginatingElement(mapLiteralPart);
return node;
}
public @NonNull MergedPartition createMergedPartition(@NonNull String name, @NonNull Iterable<@NonNull Node> headNodes) {
MergedPartition mergedPartition = QVTscheduleFactory.eINSTANCE.createMergedPartition();
mergedPartition.setName(name);
// basicPartition.setRegion(region);
((MappingRegion)region).getMappingPartitions().add(mergedPartition);
Iterables.addAll(QVTscheduleUtil.Internal.getHeadNodesList(mergedPartition), headNodes);
return mergedPartition;
}
public @NonNull NavigableEdge createNavigationEdge(@NonNull Node sourceNode, @NonNull Property source2targetProperty, @NonNull Node targetNode, boolean isPartial) {
Role phase = mergeToLessKnownPhase(getNodeRole(sourceNode), getNodeRole(targetNode));
return createNavigationEdge(phase, sourceNode, source2targetProperty, targetNode, isPartial);
}
public @NonNull NavigableEdge createNavigationEdge(@NonNull Role edgeRole, @NonNull Node sourceNode, @NonNull Property source2targetProperty, @NonNull Node targetNode, boolean isPartial) {
NavigationEdge edge = QVTscheduleFactory.eINSTANCE.createNavigationEdge();
edge.initialize(edgeRole, sourceNode, source2targetProperty.getName(), targetNode);
edge.initializeProperty(source2targetProperty, isPartial);
return edge;
}
public @NonNull NonPartition createNonPartition(@NonNull String name) {
NonPartition nonPartition = QVTscheduleFactory.eINSTANCE.createNonPartition();
nonPartition.setName(name);
// nonPartition.setRegion(region);
((MappingRegion)region).getMappingPartitions().add(nonPartition);
// Iterables.addAll(nonPartition.getHeadNodes(), headNodes);
return nonPartition;
}
public @NonNull Node createNullLiteralNode(boolean isMatched, @Nullable NullLiteralExp nullLiteralExp) {
Role nodeRole = Role.CONSTANT;
ClassDatum classDatum;
if (nullLiteralExp != null) {
classDatum = scheduleManager.getClassDatum(nullLiteralExp);
}
else {
classDatum = scheduleManager.getOclVoidClassDatum();
}
NullLiteralNode node = QVTscheduleFactory.eINSTANCE.createNullLiteralNode();
node.initialize(nodeRole, region, "«null»", classDatum);
node.setMatched(isMatched);
if (nullLiteralExp != null) {
node.setOriginatingElement(nullLiteralExp);
}
return node;
}
public @NonNull NumericLiteralNode createNumericLiteralNode(boolean isMatched, @NonNull Number numericValue, @NonNull NumericLiteralExp numericLiteralExp) {
Role nodeRole = getOperationNodePhase(region, numericLiteralExp);
NumericLiteralNode node = QVTscheduleFactory.eINSTANCE.createNumericLiteralNode();
node.initialize(nodeRole, region, numericValue.toString(), scheduleManager.getClassDatum(numericLiteralExp));
node.setMatched(isMatched);
node.setNumericValue(numericValue);
node.setOriginatingElement(numericLiteralExp);
return node;
}
public @NonNull VariableNode createOldNode(@NonNull VariableDeclaration variable) {
DomainUsage domainUsage = scheduleManager.getDomainUsage(variable);
boolean isEnforceable = domainUsage.isOutput() || domainUsage.isMiddle();
Role phase = isEnforceable ? Role.PREDICATED : Role.LOADED;
Role nodeRole = phase;
PatternVariableNode node = QVTscheduleFactory.eINSTANCE.createPatternVariableNode();
node.initialize(nodeRole, region, getName(variable), scheduleManager.getClassDatum(variable));
node.initializeVariable(region, variable);
node.setMatched(variable.isIsRequired());
return node;
}
public @NonNull OperationCallNode createOperationCallNode(boolean isMatched, @Nullable String nameHint, @NonNull Operation operation, @NonNull TypedElement callExpOrCollectionTemplateExp, @NonNull Node ... argNodes) {
String name = nameHint;
if (name == null) {
name = QVTbaseUtil.getName(operation);
}
Role nodeRole = getOperationNodePhase(region, callExpOrCollectionTemplateExp, argNodes);
OperationCallNode node = QVTscheduleFactory.eINSTANCE.createOperationCallNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(callExpOrCollectionTemplateExp));
node.setMatched(isMatched);
node.setOriginatingElement(callExpOrCollectionTemplateExp);
node.setReferredOperation(operation);
return node;
}
public @NonNull OperationCallNode createOperationCallNode2(@NonNull Role nodeRole, boolean isMatched, @Nullable String nameHint, @NonNull Operation operation, @NonNull ClassDatum classDatum, @NonNull Node ... argNodes) {
String name = nameHint;
if (name == null) {
name = QVTbaseUtil.getName(operation);
}
assert nodeRole != null;
OperationCallNode node = QVTscheduleFactory.eINSTANCE.createOperationCallNode();
node.initialize(nodeRole, region, name, classDatum);
node.setMatched(isMatched);
node.setReferredOperation(operation);
return node;
}
public @NonNull Edge createOperationParameterEdge(@NonNull Node sourceNode, @NonNull Parameter parameter, int parameterIndex, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
String name;
OperationParameterEdge edge = QVTscheduleFactory.eINSTANCE.createOperationParameterEdge();
edge.setReferredParameter(parameter);
if (parameterIndex >= 0) {
// assert parameter.isIsMany();
edge.setParameterIndex(parameterIndex);
name = "«" + parameter.getName() + "-" + parameterIndex + "»";
}
else {
// assert !parameter.isIsMany();
name = "«" + parameter.getName() + "»";
}
// edge.setReferredObject(typeOrParameter); // FIXME redundant
edge.initialize(edgeRole, sourceNode, name, targetNode);
return edge;
}
public @NonNull Edge createOperationSelfEdge(@NonNull Node sourceNode, @NonNull Type type, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
OperationSelfEdge edge = QVTscheduleFactory.eINSTANCE.createOperationSelfEdge();
edge.setReferredType(type);
String name = "«" + PivotConstants.SELF_NAME + "»";
// edge.setReferredObject(typeOrParameter); // FIXME redundant
edge.initialize(edgeRole, sourceNode, name, targetNode);
return edge;
}
public @NonNull Node createPatternNode(@NonNull Role nodeRole, @NonNull Node sourceNode, @NonNull Property source2targetProperty, boolean isMatched) {
assert sourceNode.isClass();
org.eclipse.ocl.pivot.Class type = (org.eclipse.ocl.pivot.Class)source2targetProperty.getType();
assert type != null;
Type elementType = PivotUtil.getElementalType(type);
TypedModel typedModel = elementType instanceof DataType ? scheduleManager.getDomainUsageAnalysis().getPrimitiveTypeModel() : sourceNode.getClassDatum().getReferredTypedModel();
assert typedModel != null;
ClassDatum classDatum = scheduleManager.getClassDatum(typedModel, type);
String name = source2targetProperty.getName();
assert name != null;
PatternTypedNode node = QVTscheduleFactory.eINSTANCE.createPatternTypedNode();
node.initialize(nodeRole, region, name, classDatum);
node.setMatched(isMatched);
return node;
}
public @NonNull Edge createPredicateEdge(@NonNull Node sourceNode, @Nullable String name, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
PredicateEdge edge = QVTscheduleFactory.eINSTANCE.createPredicateEdge();
edge.initialize(edgeRole, sourceNode, name, targetNode);
return edge;
}
/* public @NonNull NavigableEdge createPredicatedNavigationEdge(@NonNull Node sourceNode, @NonNull Property source2targetProperty, @NonNull Node targetNode, @Nullable Boolean isPartial) {
Role edgeRole = Role.PREDICATED;
NavigationEdge forwardEdge = QVTscheduleFactory.eINSTANCE.createNavigationEdge();
forwardEdge.initialize(edgeRole, sourceNode, source2targetProperty.getName(), targetNode);
boolean isPartial2 = QVTscheduleUtil.computeIsPartial(QVTscheduleUtil.getClassDatum(QVTscheduleUtil.getTargetNode(forwardEdge)), source2targetProperty, isPartial);
forwardEdge.initializeProperty(source2targetProperty, isPartial2);
return forwardEdge;
} */
public @NonNull Node createPredicatedNode(@NonNull String name, @NonNull ClassDatum classDatum, boolean isMatched) {
PatternTypedNode node = QVTscheduleFactory.eINSTANCE.createPatternTypedNode();
node.initialize(Role.PREDICATED, region, name, classDatum);
node.setMatched(isMatched);
return node;
}
public @NonNull Node createPredicatedStepNode(@NonNull Node typedNode, boolean isMatched) {
String name = getName(typedNode);
ClassDatum classDatum = getClassDatum(typedNode);
return createPredicatedNode(name, classDatum, isMatched);
}
/**
* Create a predicated source2targetProperty success edge from sourceNode to a true/false BooleanValueNode.
*/
public @NonNull SuccessEdge createPredicatedSuccess(@NonNull Node sourceNode, @NonNull Property source2targetProperty, boolean isSuccess) {
BooleanLiteralNode successNode = createBooleanLiteralNode(isSuccess);
SuccessEdge edge = QVTscheduleFactory.eINSTANCE.createSuccessEdge();
edge.initialize(Role.PREDICATED, sourceNode, source2targetProperty.getName(), successNode);
edge.initializeProperty(source2targetProperty, false);
return edge;
}
public @NonNull Node createRealizedDataTypeNode(@NonNull Node sourceNode, @NonNull Property source2targetProperty) {
Role nodeRole = Role.REALIZED;
return createPatternNode(nodeRole, sourceNode, source2targetProperty, sourceNode.isMatched());
}
public @NonNull Edge createRealizedIncludesEdge(@NonNull Node sourceNode, @NonNull Node targetNode) {
Role edgeRole = Role.REALIZED;
ExpressionEdge edge = QVTscheduleFactory.eINSTANCE.createIncludesEdge();
edge.initialize(edgeRole, sourceNode, INCLUDES_NAME, targetNode);
return edge;
}
public @NonNull NavigableEdge createRealizedNavigationEdge(@NonNull Node sourceNode, @NonNull Property source2targetProperty, @NonNull Node targetNode, boolean isPartial) {
Role edgeRole = Role.REALIZED;
NavigationEdge forwardEdge = QVTscheduleFactory.eINSTANCE.createNavigationEdge();
forwardEdge.initialize(edgeRole, sourceNode, source2targetProperty.getName(), targetNode);
forwardEdge.initializeProperty(source2targetProperty, isPartial);
return forwardEdge;
}
public @NonNull VariableNode createRealizedNode(@NonNull String name, @NonNull ClassDatum classDatum, boolean isMatched) {
PatternVariableNode node = QVTscheduleFactory.eINSTANCE.createPatternVariableNode();
node.initialize(Role.REALIZED, region, name, classDatum);
node.setMatched(isMatched);
return node;
}
public @NonNull VariableNode createRealizedStepNode(@NonNull VariableDeclaration stepVariable) {
VariableNode node = createRealizedNode(getName(stepVariable), scheduleManager.getClassDatum(stepVariable), true);
node.initializeVariable(region, stepVariable);
return node;
}
/**
* Create a realized source2targetProperty success edge from sourceNode to a true/false BooleanValueNode if isSuccesss is non-null,
* else to a SuccessNode.
*/
public @NonNull SuccessEdge createRealizedSuccess(@NonNull Node sourceNode, @NonNull Property source2targetProperty, @Nullable Boolean isSuccess) {
ClassDatum classDatum = scheduleManager.getBooleanClassDatum();
Node node;
if (isSuccess != null) {
node = createBooleanLiteralNode(isSuccess);
}
else {
SuccessNode successNode = QVTscheduleFactory.eINSTANCE.createSuccessNode();
successNode.initialize(Role.REALIZED, region, "«success»", classDatum);
node = successNode;
}
SuccessEdge edge = QVTscheduleFactory.eINSTANCE.createSuccessEdge();
edge.initialize(Role.REALIZED, sourceNode, source2targetProperty.getName(), node);
edge.initializeProperty(source2targetProperty, false);
return edge;
}
/** FIXME make non-static */
public static @NonNull RootPartition createRootPartition(@NonNull String name, @NonNull Object scheduleManager) {
RootPartition rootPartition = QVTscheduleFactory.eINSTANCE.createRootPartition();
rootPartition.setName(name);
// rootPartition.setRegion(region);
// Iterables.addAll(rootPartition.getHeadNodes(), headNodes);
return rootPartition;
}
/* public @NonNull Edge createRecursionEdge(@NonNull Node sourceNode, @NonNull Node targetNode, boolean isPrimary) {
Role edgeRole = Role.OTHER;
RecursionEdge edge = QVTscheduleFactory.eINSTANCE.createRecursionEdge();
edge.initialize(edgeRole, sourceNode, null, targetNode);
edge.setPrimary(isPrimary);
return edge;
} */
public @NonNull ShadowNode createShadowNode(boolean isMatched, @NonNull String name, @NonNull ShadowExp shadowExp, @NonNull Node @NonNull [] partNodes) {
Role nodeRole = getOperationNodePhase(region, shadowExp, partNodes);
ShadowNode node = QVTscheduleFactory.eINSTANCE.createShadowNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(shadowExp));
node.setMatched(isMatched);
node.setOriginatingElement(shadowExp);
return node;
}
public @NonNull Edge createShadowPartEdge(@NonNull Node sourceNode, @NonNull ShadowPart shadowPart, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
ShadowPartEdge edge = QVTscheduleFactory.eINSTANCE.createShadowPartEdge();
edge.setReferredPart(shadowPart);
String label = "«" + shadowPart.getName() + "»";
edge.initialize(edgeRole, sourceNode, label, targetNode);
return edge;
}
public @NonNull Node createStepNode(@NonNull String name, @NonNull CallExp callExp, @NonNull Node sourceNode, boolean isMatched) {
DomainUsage domainUsage = scheduleManager.getDomainUsage(callExp);
boolean isMiddleOrOutput = domainUsage.isOutput() || domainUsage.isMiddle();
boolean isDirty = false;
if (callExp instanceof NavigationCallExp) {
Property referredProperty = PivotUtil.getReferredProperty((NavigationCallExp)callExp);
isDirty = scheduleManager.isDirty(referredProperty);
}
Role phase = /*sourceNode.isPredicated() ||*/ isMiddleOrOutput || isDirty ? Role.PREDICATED : Role.LOADED;
Role stepNodeRole = phase;
PatternTypedNode node = QVTscheduleFactory.eINSTANCE.createPatternTypedNode();
node.initialize(stepNodeRole, region, name, scheduleManager.getClassDatum(callExp));
node.setMatched(isMatched);
node.setOriginatingElement(callExp);
return node;
}
/* public @NonNull Edge createRecursionEdge(@NonNull Node sourceNode, @NonNull Node targetNode, boolean isPrimary) {
Role edgeRole = Role.OTHER;
RecursionEdge edge = QVTscheduleFactory.eINSTANCE.createRecursionEdge();
edge.initialize(edgeRole, sourceNode, null, targetNode);
edge.setPrimary(isPrimary);
return edge;
} */
public @NonNull StringLiteralNode createStringLiteralNode(boolean isMatched, @NonNull String stringValue, @NonNull StringLiteralExp stringLiteralExp) {
Role nodeRole = getOperationNodePhase(region, stringLiteralExp);
StringLiteralNode node = QVTscheduleFactory.eINSTANCE.createStringLiteralNode();
node.initialize(nodeRole, region, stringValue, scheduleManager.getClassDatum(stringLiteralExp));
node.setMatched(isMatched);
node.setStringValue(stringValue);
node.setOriginatingElement(stringLiteralExp);
return node;
}
public @NonNull TupleLiteralNode createTupleLiteralNode(boolean isMatched, @NonNull String name, @NonNull TupleLiteralExp tupleLiteralExp, @NonNull Node @NonNull [] partNodes) {
Role nodeRole = getOperationNodePhase(region, tupleLiteralExp, partNodes);
TupleLiteralNode node = QVTscheduleFactory.eINSTANCE.createTupleLiteralNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(tupleLiteralExp));
node.setMatched(isMatched);
node.setOriginatingElement(tupleLiteralExp);
return node;
}
public @NonNull Edge createTuplePartEdge(@NonNull Node sourceNode, @NonNull TupleLiteralPart tuplePart, @NonNull Node targetNode) {
Role edgeRole = getNodeRole(sourceNode);
TuplePartEdge edge = QVTscheduleFactory.eINSTANCE.createTuplePartEdge();
edge.setReferredPart(tuplePart);
String label = "«" + tuplePart.getName() + "»";
edge.initialize(edgeRole, sourceNode, label, targetNode);
return edge;
}
public @NonNull TypeLiteralNode createTypeLiteralNode(boolean isMatched, @NonNull Type typeValue, @NonNull TypeExp typeExp) {
ClassDatum classDatum = scheduleManager.getClassDatum(typeExp);
// String typeName = PrettyPrinter.printType(QVTscheduleUtil.getCompleteClass(classDatum));
Role nodeRole = getOperationNodePhase(region, typeExp);
TypeLiteralNode typeLiteralNode = QVTscheduleFactory.eINSTANCE.createTypeLiteralNode();
typeLiteralNode.initialize(nodeRole, region, String.valueOf(typeValue), classDatum);
typeLiteralNode.setMatched(isMatched);
typeLiteralNode.setTypeValue(typeValue);
typeLiteralNode.setOriginatingElement(typeExp);
return typeLiteralNode;
}
public @NonNull Node createUnknownNode(@NonNull String name, @NonNull TypedElement typedElement) {
Role nodeRole = Role.OTHER;
UnknownNode node = QVTscheduleFactory.eINSTANCE.createUnknownNode();
node.initialize(nodeRole, region, name, scheduleManager.getClassDatum(typedElement));
return node;
}
@Override
public @NonNull String getName() {
return QVTscheduleUtil.getName(region);
}
protected @NonNull Role getPatternNodeRole(@NonNull Node sourceNode, @NonNull Property property) {
Role phase;
switch (getNodeRole(sourceNode)) {
case REALIZED: phase = Role.REALIZED; break;
case PREDICATED: phase = Role.PREDICATED; break;
case LOADED: {
boolean isDirty = scheduleManager.isDirty(property);
phase = isDirty ? Role.PREDICATED : Role.LOADED; break;
}
case CONSTANT_SUCCESS_FALSE: /* fall through */
case CONSTANT_SUCCESS_TRUE: /* fall through */
case CONSTANT: phase = Role.CONSTANT; break;
default: throw new UnsupportedOperationException();
}
return phase;
}
public @NonNull R getRegion() {
return region;
}
public @NonNull ScheduleManager getScheduleManager() {
return scheduleManager;
}
}