/*******************************************************************************
 * 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) {
		if (thisCompleteClass.conformsTo(thatCompleteClass)) {
			return true;
		}
		org.eclipse.ocl.pivot.Class behavioralClass = thatCompleteClass.getBehavioralClass();
		if (behavioralClass == null) {
			return false;
		}
		// See Bug 577546 (and Bug 574431) This is a dodgy downcast case.
		return thisCompleteClass.conformsTo(behavioralClass);
	}

	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);
	}
}