blob: 153137ee4b5c85f0a0589d432a8a00b509366825 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2020 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.pivot.qvtschedule.utilities;
import java.util.Collections;
import java.util.List;
import java.util.function.BinaryOperator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CompleteClass;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.EnumerationLiteral;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.ShadowPart;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.Nameable;
import org.eclipse.qvtd.pivot.qvtbase.Rule;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtschedule.RuleRegion;
import org.eclipse.qvtd.pivot.qvtschedule.BasicPartition;
import org.eclipse.qvtd.pivot.qvtschedule.ClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.CollectionClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.CompositePartition;
import org.eclipse.qvtd.pivot.qvtschedule.Connection;
import org.eclipse.qvtd.pivot.qvtschedule.ConnectionEnd;
import org.eclipse.qvtd.pivot.qvtschedule.Edge;
import org.eclipse.qvtd.pivot.qvtschedule.EdgeConnection;
import org.eclipse.qvtd.pivot.qvtschedule.EnumLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.KeyPartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.LoadingPartition;
import org.eclipse.qvtd.pivot.qvtschedule.LoadingRegion;
import org.eclipse.qvtd.pivot.qvtschedule.MappingPartition;
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.NodeConnection;
import org.eclipse.qvtd.pivot.qvtschedule.OperationCallNode;
import org.eclipse.qvtd.pivot.qvtschedule.OperationRegion;
import org.eclipse.qvtd.pivot.qvtschedule.Partition;
import org.eclipse.qvtd.pivot.qvtschedule.PropertyDatum;
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.ScheduleModel;
import org.eclipse.qvtd.pivot.qvtschedule.ShadowPartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.RootRegion;
public class QVTscheduleUtil extends QVTscheduleConstants
{
public static class Internal
{
public static @NonNull List<@NonNull Region> getActiveRegionsList(@NonNull RootRegion rootRegion) {
return ClassUtil.nullFree(rootRegion.getActiveRegions());
}
public static @NonNull List<@NonNull Node> getHeadNodesList(@NonNull BasicPartition basicPartition) {
return ClassUtil.nullFree(basicPartition.getHeadNodes());
}
public static @NonNull List<@NonNull Node> getHeadNodesList(@NonNull Region region) {
return ClassUtil.nullFree(region.getHeadNodes());
}
public static List<@NonNull RootRegion> getOwnedRootRegionsList(@NonNull ScheduleModel scheduleModel) {
return ClassUtil.nullFree(scheduleModel.getOwnedRootRegions());
}
public static @NonNull List<@NonNull ClassDatum> getSuperClassDatumsList(@NonNull ClassDatum classDatum) {
return ClassUtil.nullFree(classDatum.getSuperClassDatums());
}
}
public static @NonNull Role asPhase(@NonNull Role nodeRole, @NonNull Role phase) {
return phase;
}
public static @NonNull Role asPredicated(@NonNull Role nodeRole) {
return asPhase(nodeRole, Role.PREDICATED);
}
public static @NonNull Role asSpeculated(@NonNull Role nodeRole) {
return asPhase(nodeRole, Role.SPECULATED);
}
public static @NonNull Role asSpeculation(@NonNull Role nodeRole) {
return asPhase(nodeRole, Role.SPECULATION);
}
public static @Nullable ScheduleModel basicGetContainingScheduleModel(@NonNull Element element) {
for (EObject eObject = element; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof ScheduleModel) {
return (ScheduleModel)eObject;
}
}
return null;
}
public static @Nullable NavigationEdge basicGetOutgoingNavigationEdge(@NonNull Node traceNode, @NonNull Property property) {
for (@NonNull Edge edge : QVTscheduleUtil.getOutgoingEdges(traceNode)) {
if (edge instanceof NavigationEdge) {
NavigationEdge navigationEdge = (NavigationEdge)edge;
if (QVTscheduleUtil.getReferredProperty(navigationEdge) == property) {
return navigationEdge;
}
}
}
return null;
}
/**
* Return true if there may be a dynamic type conforming to both the firstType and secondType static types.
*/
public static boolean conformantWith(@NonNull ClassDatum thisClassDatum, @NonNull ClassDatum thatClassDatum) {
// if (conformsTo(thisClassDatum, thatClassDatum)) {
// return true;
// }
// if (conformsTo(thatClassDatum, thisClassDatum)) {
// return true;
// }
if (conformsToClassOrBehavioralClass(thisClassDatum, thatClassDatum)) {
return true;
}
if (conformsToClassOrBehavioralClass(thatClassDatum, thisClassDatum)) {
return true;
}
return false;
}
/**
* Return true if thisClassDatum conforms to, i.e can be used as, thatClassDatum.
*
* If the ClassDatum is a multi-CompleteClass there must be a CompleteClass, not necessarily the same CompleteClass, of thisClassDatum's CompleteClasses
* that conforms to each of thatClassDatum's CompleteClasses.
*/
public static boolean conformsTo(@NonNull ClassDatum thisClassDatum, @NonNull ClassDatum thatClassDatum) {
if (thisClassDatum == thatClassDatum) {
return true;
}
List<@NonNull CompleteClass> thoseCompleteClasses = thatClassDatum.basicGetCompleteClasses();
if (thoseCompleteClasses == null) {
return false;
}
for (CompleteClass thatCompleteClass : thoseCompleteClasses) {
if (!conformsTo(thisClassDatum, thatCompleteClass)) {
return false;
}
}
return true;
}
/**
* Return true if thisClassDatum conforms to, i.e can be used as, thatCompleteClass.
*
* If the ClassDatum is a multi-CompleteClass it is sufficient that any one of thisClassDatum's CompleteClasses conforms to thatCompleteClass.
*/
public static boolean conformsTo(@NonNull ClassDatum thisClassDatum, @NonNull CompleteClass thatCompleteClass) {
List<@NonNull CompleteClass> theseCompleteClasses = thisClassDatum.basicGetCompleteClasses();
if (theseCompleteClasses == null) {
return false;
}
for (@NonNull CompleteClass thisCompleteClass : theseCompleteClasses) {
if (thisCompleteClass.conformsTo(thatCompleteClass)) {
return true;
}
}
return false;
}
public static boolean conformsTo(@NonNull CompleteClass thisCompleteClass, @NonNull ClassDatum thatClassDatum) {
List<@NonNull CompleteClass> thoseCompleteClasses = thatClassDatum.basicGetCompleteClasses();
if (thoseCompleteClasses == null) {
return false;
}
for (@NonNull CompleteClass thatCompleteClass : thoseCompleteClasses) {
if (!thisCompleteClass.conformsTo(thatCompleteClass)) {
return false;
}
}
return true;
}
public static boolean conformsToClassOrBehavioralClass(@NonNull CompleteClass thisCompleteClass, @NonNull CompleteClass thatCompleteClass) {
return thisCompleteClass.conformsTo(thatCompleteClass) || thisCompleteClass.conformsTo(thatCompleteClass.getBehavioralClass());
}
public static boolean conformsToClassOrBehavioralClass(@NonNull ClassDatum thisClassDatum, @NonNull CompleteClass thatCompleteClass) {
List<@NonNull CompleteClass> theseCompleteClasses = thisClassDatum.basicGetCompleteClasses();
if (theseCompleteClasses == null) {
return false;
}
for (@NonNull CompleteClass thisCompleteClass : theseCompleteClasses) {
if (conformsToClassOrBehavioralClass(thisCompleteClass, thatCompleteClass)) {
return true;
}
}
return false;
}
public static boolean conformsToClassOrBehavioralClass(@NonNull ClassDatum thisClassDatum, @NonNull ClassDatum thatClassDatum) {
List<@NonNull CompleteClass> thoseCompleteClasses = thatClassDatum.basicGetCompleteClasses();
if (thoseCompleteClasses == null) {
return false;
}
for (@NonNull CompleteClass thatCompleteClass : thoseCompleteClasses) {
if (!conformsToClassOrBehavioralClass(thisClassDatum, thatCompleteClass)) {
return false;
}
}
return true;
}
public static boolean containsNone(@NonNull Iterable<@NonNull Node> firstNodes, @NonNull Iterable<@NonNull Node> secondNodes) {
for (@NonNull Node firstNode : firstNodes) {
for (@NonNull Node secondNode : secondNodes) {
if (firstNode == secondNode) {
return false;
}
}
}
return true;
}
public static @NonNull Iterable<@NonNull Region> getActiveRegions(@NonNull RootRegion rootRegion) {
return ClassUtil.nullFree(rootRegion.getActiveRegions());
}
public static @NonNull ClassDatum getClassDatum(@NonNull Node node) {
return ClassUtil.nonNullState(node.getClassDatum());
}
public static @NonNull ClassDatum getClassDatum(@NonNull NodeConnection connection) {
return ClassUtil.nonNullState(connection.getClassDatum());
}
public static @NonNull String getColor(@NonNull Role role) {
switch (role) {
case CONSTANT: return QVTscheduleConstants.CONSTANT_COLOR;
case CONSTANT_SUCCESS_FALSE: return QVTscheduleConstants.CONSTANT_COLOR;
case CONSTANT_SUCCESS_TRUE: return QVTscheduleConstants.CONSTANT_COLOR;
case LOADED: return QVTscheduleConstants.LOADED_COLOR;
case PREDICATED: return QVTscheduleConstants.PREDICATED_COLOR;
case REALIZED: return QVTscheduleConstants.REALIZED_COLOR;
case SPECULATION: return QVTscheduleConstants.SPECULATION_COLOR;
case SPECULATED: return QVTscheduleConstants.SPECULATED_COLOR;
default: return QVTscheduleConstants.OTHER_COLOR;
}
}
public static @NonNull List<@NonNull CompleteClass> getCompleteClasses(@NonNull ClassDatum classDatum) {
return ClassUtil.nullFree(classDatum.getCompleteClasses());
}
/* public static @NonNull Map<@NonNull CompleteClass, @NonNull List<@NonNull Node>> getCompleteClass2Nodes(@NonNull Region region) {
Map<@NonNull CompleteClass, @NonNull List<@NonNull Node>> completeClass2nodes = new HashMap<>();
for (@NonNull Node node : getOwnedNodes(region)) {
CompleteClass completeClass = node.getCompleteClass();
List<@NonNull Node> mergedNodes = completeClass2nodes.get(completeClass);
if (mergedNodes == null) {
mergedNodes = new ArrayList<>();
completeClass2nodes.put(completeClass, mergedNodes);
}
if (!mergedNodes.contains(node)) {
mergedNodes.add(node);
}
}
return completeClass2nodes;
} */
public static @NonNull RootRegion getContainingRootRegion(@NonNull Region region) {
return ClassUtil.nonNullState(region.getContainingRootRegion());
}
public static @NonNull Iterable<@NonNull Node> getDependencyNodes(@NonNull OperationRegion operationRegion) {
return ClassUtil.nullFree(operationRegion.getDependencyNodes());
}
public static @NonNull Role getEdgeRole(@NonNull Edge edge) {
return ClassUtil.nonNullState(edge.getEdgeRole());
}
public static @NonNull ClassDatum getElementalClassDatum(@NonNull CollectionClassDatum collectionClassDatum) {
return ClassUtil.nonNullState(collectionClassDatum.getElementalClassDatum());
}
public static @NonNull EnumerationLiteral getEnumValue(@NonNull EnumLiteralNode node) {
return ClassUtil.nonNullState(node.getEnumValue());
}
public static @NonNull Iterable<? extends @NonNull Partition> getExplicitPredecessors(@NonNull BasicPartition partition) {
return ClassUtil.nullFree(partition.getExplicitPredecessors());
}
public static @NonNull String getFillColor(@NonNull Role nodeRole) {
switch (nodeRole) {
case CONSTANT: return LIGHT_CONSTANT_COLOR;
case LOADED: return LIGHT_LOADED_COLOR;
case PREDICATED: return LIGHT_PREDICATED_COLOR;
case REALIZED: return LIGHT_REALIZED_COLOR;
case SPECULATION: return LIGHT_SPECULATION_COLOR;
case SPECULATED: return LIGHT_SPECULATED_COLOR;
default: return LIGHT_OTHER_COLOR;
}
}
public static @NonNull Iterable<@NonNull Node> getHeadNodes(@NonNull Partition partition) {
return ClassUtil.nullFree(partition.getHeadNodes());
}
public static @NonNull Iterable<@NonNull Node> getHeadNodes(@NonNull Region region) {
return ClassUtil.nullFree(region.getHeadNodes());
}
public static @NonNull Iterable<@NonNull Edge> getIncomingEdges(@NonNull Node node) {
return ClassUtil.nullFree(node.getIncomingEdges());
}
public static @NonNull List<@NonNull NodeConnection> getIntermediateConnections(@NonNull Partition partition) {
return ClassUtil.nullFree(partition.getIntermediateConnections());
}
public static @NonNull List<@NonNull Partition> getIntermediatePartitions(@NonNull NodeConnection connection) {
return ClassUtil.nullFree(connection.getIntermediatePartitions());
}
public static @NonNull LoadingPartition getLoadingPartition(@NonNull LoadingRegion loadingRegion) {
return ClassUtil.nonNullState(loadingRegion.getLoadingPartition());
}
public static @NonNull Iterable<@NonNull MappingPartition> getMappingPartitions(@NonNull MappingRegion mappingRegion) {
return ClassUtil.nullFree(mappingRegion.getMappingPartitions());
}
/**
* Return the merged partition that replaces this or this if not merged.
*/
public static @Nullable Partition getMergedPartition(@NonNull Partition partition) {
if (partition instanceof BasicPartition) {
for (MergedPartition mergedPartition; (mergedPartition = ((BasicPartition)partition).getOwningMergedPartition()) != null; ) {
partition = mergedPartition;
}
}
return partition;
}
public static @NonNull String getName(@NonNull Nameable nameable) {
return ClassUtil.nonNullState(nameable.getName());
}
public static @NonNull Role getNodeRole(@NonNull Node node) {
return ClassUtil.nonNullState(node.getNodeRole());
}
public static @NonNull Role getOperationNodePhase(@NonNull Region region, @Nullable TypedElement typedElement, @NonNull Node... argNodes) {
boolean isLoaded = false;
boolean isPredicated = false;
boolean isRealized = false;
if (argNodes != null) {
for (Node argNode : argNodes) {
if (argNode.isRealized()) {
isRealized = true;
}
else if (argNode.isPredicated()) {
isPredicated = true;
}
else if (argNode.isLoaded()) {
isLoaded = true;
}
}
}
if (typedElement instanceof OperationCallExp) {
Operation asOperation = ((OperationCallExp)typedElement).getReferredOperation();
if (QVTbaseUtil.isIdentification(asOperation)) {
// DomainUsage usage = getScheduleManager(region).getDomainUsage(typedElement);
// if (!usage.isInput()) {
isRealized = true;
// }
}
}
if (isRealized) {
return Role.REALIZED;
}
else if (isPredicated) {
return Role.PREDICATED;
}
else if (isLoaded) {
return Role.LOADED;
}
else {
return Role.CONSTANT;
}
}
public static @NonNull PropertyDatum getOpposite(@NonNull PropertyDatum propertyDatum) {
return ClassUtil.nonNullState(propertyDatum.getOpposite());
}
public static @NonNull NavigationEdge getOppositeEdge(@NonNull NavigationEdge navigationEdge) {
return ClassUtil.nonNullState(navigationEdge.getOppositeEdge());
}
public static @NonNull Iterable<@NonNull EdgeConnection> getOutgoingConnections(@NonNull NavigableEdge navigableEdge) {
return ClassUtil.nullFree(navigableEdge.getOutgoingConnections());
}
public static @NonNull Iterable<@NonNull NodeConnection> getOutgoingConnections(@NonNull Node node) {
return ClassUtil.nullFree(node.getOutgoingConnections());
}
public static @NonNull Iterable<@NonNull Edge> getOutgoingEdges(@NonNull Node node) {
return ClassUtil.nullFree(node.getOutgoingEdges());
}
public static @NonNull Iterable<@NonNull ClassDatum> getOwnedClassDatums(@NonNull ScheduleModel scheduleModel) {
return ClassUtil.nullFree(scheduleModel.getOwnedClassDatums());
}
public static @NonNull Iterable<@NonNull Connection> getOwnedConnections(@NonNull RootRegion rootRegion) {
return ClassUtil.nullFree(rootRegion.getOwnedConnections());
}
public static @NonNull Iterable<@NonNull Edge> getOwnedEdges(@NonNull Region region) {
return ClassUtil.nullFree(region.getOwnedEdges());
}
public static @NonNull LoadingRegion getOwnedLoadingRegion(@NonNull RootRegion rootRegion) {
return ClassUtil.nonNullState(rootRegion.getOwnedLoadingRegion());
}
public static @NonNull Iterable<@NonNull MappingPartition> getOwnedMappingPartitions(@NonNull CompositePartition composedPartition) {
return ClassUtil.nullFree(composedPartition.getOwnedMappingPartitions());
}
public static @NonNull Iterable<@NonNull Node> getOwnedNodes(@NonNull Region region) {
return ClassUtil.nullFree(region.getOwnedNodes());
}
public static @NonNull Iterable<@NonNull PropertyDatum> getOwnedPropertyDatums(@NonNull ClassDatum classDatum) {
return ClassUtil.nullFree(classDatum.getOwnedPropertyDatums());
}
public static @NonNull Iterable<@NonNull MappingRegion> getOwnedMappingRegions(@NonNull ScheduleModel scheduleModel) {
return ClassUtil.nullFree(scheduleModel.getOwnedMappingRegions());
}
public static @NonNull Iterable<@NonNull OperationRegion> getOwnedOperationRegions(@NonNull ScheduleModel scheduleModel) {
return ClassUtil.nullFree(scheduleModel.getOwnedOperationRegions());
}
public static @NonNull Iterable<@NonNull RootRegion> getOwnedRootRegions(@NonNull ScheduleModel scheduleModel) {
return ClassUtil.nullFree(scheduleModel.getOwnedRootRegions());
}
public static @NonNull ClassDatum getOwningClassDatum(@NonNull PropertyDatum propertyDatum) {
return ClassUtil.nonNullState(propertyDatum.getOwningClassDatum());
}
public static @NonNull Region getOwningRegion(@NonNull ConnectionEnd connectionEnd) {
return ClassUtil.nonNullState(connectionEnd.getOwningRegion());
}
public static @NonNull Region getOwningRegion(@NonNull Node node) {
return ClassUtil.nonNullState(node.getOwningRegion());
}
public static RootRegion getOwningRootRegion(@NonNull RootPartition rootPartition) {
return ClassUtil.nonNullState(rootPartition.getOwningRootRegion());
}
public static @NonNull ScheduleModel getOwningScheduleModel(@NonNull RootRegion rootRegion) {
return ClassUtil.nonNullState(rootRegion.getOwningScheduleModel());
}
public static @NonNull Iterable<@NonNull Integer> getPasses(@NonNull Partition partition) {
return ClassUtil.nullFree(partition.getPasses());
}
public static @NonNull NavigationEdge getPrimaryEdge(@NonNull NavigationEdge navigationEdge) {
return navigationEdge.isSecondary() ? getOppositeEdge(navigationEdge) : navigationEdge;
}
/**
* Return the forward/reverse variant of property that is more easily navigable and therefore
* to be preferred. When both variants are equally navigable a deterministic name-based choice is made.
*/
public static @NonNull Property getPrimaryProperty(@NonNull Property property) {
Property oppositeProperty = property.getOpposite();
if (oppositeProperty == null) { // No opposite - no choice to make
return property;
}
if (oppositeProperty.isIsComposite()) { // Container preferred
assert !property.isIsMany();
return property;
}
if (property.isIsComposite()) { // Container preferred
assert !oppositeProperty.isIsMany();
return oppositeProperty;
}
if (property.isIsImplicit()) { // Non-implicit preferred
return oppositeProperty;
}
if (oppositeProperty.isIsImplicit()) { // Non-implicit preferred
return property;
}
if (property.isIsDerived() && !oppositeProperty.isIsDerived()) { // choose non-derived
return oppositeProperty;
}
if (!property.isIsDerived() && oppositeProperty.isIsDerived()) { // choose non-derived
return property;
}
if (property.isIsTransient() && !oppositeProperty.isIsTransient()) { // choose non-transient
return oppositeProperty;
}
if (!property.isIsTransient() && oppositeProperty.isIsTransient()) { // choose non-transient
return property;
}
if (property.isIsVolatile() && !oppositeProperty.isIsVolatile()) { // choose non-volatile
return oppositeProperty;
}
if (!property.isIsVolatile() && oppositeProperty.isIsVolatile()) { // choose non-volatile
return property;
}
if (property.isIsMany() && !oppositeProperty.isIsMany()) { // 1:N - choose N:1
return oppositeProperty;
}
if (!property.isIsMany() && oppositeProperty.isIsMany()) { // N:1 - choose N:1
return property;
}
// use name hierarchy
EObject e1 = property;
EObject e2 = oppositeProperty;
while ((e1 != null) && (e2 != null)) {
String n1 = e1 instanceof Nameable ? ((Nameable)e1).getName() : null;
String n2 = e2 instanceof Nameable ? ((Nameable)e2).getName() : null;
if ((n1 != null) || (n2 != null)) {
if (n1 == null) {
return oppositeProperty;
}
if (n2 == null) {
return property;
}
int diff = n1.compareTo(n2);
if (diff != 0) {
return diff > 0 ? property : oppositeProperty;
}
}
e1 = e1.eContainer();
e2 = e2.eContainer();
}
if ((e1 != null) || (e2 != null)) {
if (e1 == null) {
return oppositeProperty;
}
if (e2 == null) {
return property;
}
}
// last resort - never happens - use hash codes
int diff = System.identityHashCode(property) - System.identityHashCode(oppositeProperty);
return diff >= 0 ? property : oppositeProperty;
}
//
// Commented out since getCompleteClass() is usually more appropriate.
//
// public static org.eclipse.ocl.pivot.@NonNull Class getReferredClass(@NonNull ClassDatum classDatum) {
// return ClassUtil.nonNullState(classDatum.getReferredClass());
// }
public static @NonNull Operation getReferredOperation(@NonNull OperationCallNode operationCallNode) {
return ClassUtil.nonNullState(operationCallNode.getReferredOperation()); // FIXME should be declared as [1..1]
}
public static @NonNull PropertyDatum getReferredPart(@NonNull KeyPartEdge keyPartEdge) {
return ClassUtil.nonNullState(keyPartEdge.getReferredPart());
}
public static @NonNull ShadowPart getReferredPart(@NonNull ShadowPartEdge shadowPartEdge) {
return ClassUtil.nonNullState(shadowPartEdge.getReferredPart());
}
public static @NonNull Property getReferredProperty(@NonNull PropertyDatum propertyDatum) {
return ClassUtil.nonNullState(propertyDatum.getReferredProperty());
}
public static @NonNull Rule getReferredRule(@NonNull RuleRegion ruleRegion) {
return ClassUtil.nonNullState(ruleRegion.getReferredRule());
}
public static @NonNull Transformation getReferredTransformation(@NonNull RootRegion rootRegion) {
return ClassUtil.nonNullState(rootRegion.getReferredTransformation());
}
public static @NonNull TypedModel getReferredTypedModel(@NonNull ClassDatum classDatum) {
return ClassUtil.nonNullState(classDatum.getReferredTypedModel());
}
public static @NonNull Region getRegion(@NonNull Partition partition) {
return ClassUtil.nonNullState(partition.getRegion());
}
public static @NonNull Property getReferredProperty(@NonNull NavigationEdge navigationEdge) {
return ClassUtil.nonNullState(navigationEdge.getReferredProperty());
}
public static @NonNull Iterable<@NonNull MappingPartition> getRegionPartitions(@NonNull Region region) {
Iterable<@NonNull MappingPartition> sourceRegionPartitions;
if (region instanceof LoadingRegion) {
sourceRegionPartitions = Collections.singletonList(getLoadingPartition((LoadingRegion)region));
}
else if (region instanceof MappingRegion) {
sourceRegionPartitions = getMappingPartitions((MappingRegion)region);
}
else {
throw new UnsupportedOperationException();
}
return sourceRegionPartitions;
}
public static @Nullable Role getRole(@NonNull Partition partition, @NonNull ConnectionEnd connectionEnd) {
return connectionEnd instanceof Node ? partition.getRole((Node)connectionEnd) : connectionEnd instanceof Edge ? partition.getRole((Edge)connectionEnd) : null;
}
public static @NonNull List<@NonNull NodeConnection> getRootConnections(@NonNull Partition partition) {
return ClassUtil.nullFree(partition.getRootConnections());
}
public static @NonNull RootRegion getRootRegion(@NonNull Region region) {
return ClassUtil.nonNullState(region.getRootRegion());
}
public static @NonNull ScheduleModel getScheduleModel(@NonNull Region region) {
for (EObject eObject = region; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof ScheduleModel) {
return (ScheduleModel)eObject;
}
}
return ClassUtil.nonNullState(null);
}
public static @NonNull List<@NonNull ConnectionEnd> getSourceEnds(@NonNull Connection connection) {
return ClassUtil.nullFree(connection.getSourceEnds());
}
@SuppressWarnings("unchecked")
public static @NonNull List<@NonNull NavigableEdge> getSourceEnds(@NonNull EdgeConnection connection) {
return (List<@NonNull NavigableEdge>)(Object)ClassUtil.nullFree(connection.getSourceEnds());
}
@SuppressWarnings("unchecked")
public static @NonNull List<@NonNull Node> getSourceEnds(@NonNull NodeConnection connection) {
return (List<@NonNull Node>)(Object)ClassUtil.nullFree(connection.getSourceEnds());
}
public static @NonNull Node getSourceNode(@NonNull Edge edge) {
return ClassUtil.nonNullState(edge.getSourceNode());
}
public static @NonNull Iterable<@NonNull ClassDatum> getSuperClassDatums(@NonNull ClassDatum classDatum) {
return ClassUtil.nullFree(classDatum.getSuperClassDatums());
}
@Deprecated /* @deprecated no longer used - cache too flaky, all candidates ssessed at consumption point */
public static @NonNull Iterable<@NonNull PropertyDatum> getSuperPropertyDatums(@NonNull PropertyDatum propertyDatum) {
return ClassUtil.nullFree(propertyDatum.getSuperPropertyDatums());
}
public static @NonNull Node getTargetNode(@NonNull Edge edge) {
return ClassUtil.nonNullState(edge.getTargetNode());
}
public static @NonNull TypedModel getTypedModel(@NonNull ClassDatum classDatum) {
return ClassUtil.nonNullState(classDatum.getReferredTypedModel());
}
public static @NonNull TypedModel getTypedModel(@NonNull Node node) {
return getTypedModel(getClassDatum(node));
}
//
// FIXME this is a legacy compatiility supporting the obsolescence of TrueNode.
//
@Deprecated
public static boolean hasPredicates(@NonNull Region mappingRegion) {
for (@NonNull Node node : QVTscheduleUtil.getOwnedNodes(mappingRegion)) {
if (node.isConstant()) {
for (@NonNull Edge incomingEdge : QVTscheduleUtil.getIncomingEdges(node)) {
if (incomingEdge.isOld()) {
return true;
}
}
}
}
return false;
}
/* public static boolean isRealizedIncludes(@NonNull Edge edge) { // FIXME includes should be a pseudo-navigation edge
if (!edge.isRealized()) {
return false;
}
if (!edge.isComputation()) {
return false;
}
return "«includes»".equals(edge.getName()) || "«includesAll»".equals(edge.getName());
} */
public static @NonNull Role mergeToLessKnownPhase(Role firstRole, Role secondRole) {
if (firstRole == Role.REALIZED) {
return firstRole;
}
else if (secondRole == Role.REALIZED) {
return secondRole;
}
else if (firstRole == Role.PREDICATED){
return firstRole;
}
else if (secondRole == Role.PREDICATED){
return secondRole;
}
else if (firstRole == Role.SPECULATED){
return Role.PREDICATED;
}
else if (secondRole == Role.SPECULATED){
return Role.PREDICATED;
}
else if (firstRole == Role.LOADED) {
return firstRole;
}
else if (secondRole == Role.LOADED) {
return secondRole;
}
else if (firstRole == Role.CONSTANT) {
return firstRole;
}
else if (secondRole == Role.CONSTANT) {
return secondRole;
}
throw new UnsupportedOperationException();
}
public static @NonNull Role mergeToMoreKnownPhase(@NonNull Role firstRole, @NonNull Role secondRole) {
if (firstRole == Role.CONSTANT) {
return firstRole;
}
else if (secondRole == Role.CONSTANT) {
return secondRole;
}
else if (firstRole == Role.LOADED) {
return firstRole;
}
else if (secondRole == Role.LOADED) {
return secondRole;
}
else if (firstRole == Role.REALIZED) {
return firstRole;
}
else if (secondRole == Role.REALIZED) {
return secondRole;
}
else if (firstRole == Role.SPECULATED) {
return firstRole;
}
else if (secondRole == Role.SPECULATED) {
return secondRole;
}
else if (firstRole == Role.SPECULATION) {
return firstRole;
}
else if (secondRole == Role.SPECULATION) {
return secondRole;
}
else if (firstRole == Role.PREDICATED) {
return firstRole;
}
else if (secondRole == Role.PREDICATED) {
return secondRole;
}
throw new UnsupportedOperationException();
}
/* public static Node.@NonNull Utility mergeToStrongerUtility(Node.@NonNull Utility nodeUtility1, Node.@NonNull Utility nodeUtility2) {
if (nodeUtility1 == Node.Utility.DISPATCH) {
assert (nodeUtility2 == Node.Utility.DISPATCH);
return Node.Utility.DISPATCH;
}
else if (nodeUtility1 == Node.Utility.TRACE) {
assert (nodeUtility2 == Node.Utility.TRACE);
return Node.Utility.TRACE;
}
else if ((nodeUtility1 == Node.Utility.STRONGLY_MATCHED) || (nodeUtility2 == Node.Utility.STRONGLY_MATCHED)) {
return Node.Utility.STRONGLY_MATCHED;
}
else if ((nodeUtility1 == Node.Utility.WEAKLY_MATCHED) || (nodeUtility2 == Node.Utility.WEAKLY_MATCHED)) {
return Node.Utility.WEAKLY_MATCHED;
}
else if ((nodeUtility1 == Node.Utility.CONDITIONAL) || (nodeUtility2 == Node.Utility.CONDITIONAL)) {
return Node.Utility.CONDITIONAL;
}
else if ((nodeUtility1 == Node.Utility.DEPENDENCY) || (nodeUtility2 == Node.Utility.DEPENDENCY)) {
return Node.Utility.DEPENDENCY;
}
else {
return Node.Utility.DEAD;
}
} */
public static @NonNull BinaryOperator<@NonNull String> stringJoin(@NonNull String delimiter) {
return (a, b) -> String.valueOf(a) + delimiter + String.valueOf(b);
}
}