[490172] CollationManager experiment
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java
index a171d46..fbeeaf2 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java
@@ -51,6 +51,7 @@
 import org.eclipse.qvtd.compiler.internal.qvtb2qvts.trace.NameGenerator;
 import org.eclipse.qvtd.compiler.internal.qvtc2qvtu.QVTuConfiguration;
 import org.eclipse.qvtd.compiler.internal.qvtm2qvts.QVTm2QVTs;
+import org.eclipse.qvtd.compiler.internal.qvts2qvts.CollationManager;
 import org.eclipse.qvtd.compiler.internal.qvts2qvts.ConnectionManager;
 import org.eclipse.qvtd.compiler.internal.qvts2qvts.RegionAnalysis;
 import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.RootPartitionAnalysis;
@@ -196,6 +197,7 @@
 	private final boolean doDotGraphs;
 	private final boolean doYedGraphs;
 
+	private @Nullable CollationManager collationManager = null;
 	private @Nullable ConnectionManager connectionManager = null;
 
 	//	private final @NonNull Map<@NonNull TransformationAnalysis, @NonNull TransformationAnalysis2TracePackage> transformationAnalysis2transformationAnalysis2tracePackage = new HashMap<>();
@@ -344,6 +346,11 @@
 	}
 
 	@Override
+	public @Nullable CollationManager basicGetCollationManager() {
+		return collationManager;
+	}
+
+	@Override
 	public @Nullable ConnectionManager basicGetConnectionManager() {
 		return connectionManager;
 	}
@@ -405,6 +412,12 @@
 	}
 
 	@Override
+	public @NonNull CollationManager createCollationManager(@NonNull ProblemHandler problemHandler, @NonNull LoadingRegionAnalysis loadingRegionAnalysis) {
+		this.collationManager  = new CollationManager(problemHandler, this, loadingRegionAnalysis);
+		return collationManager;
+	}
+
+	@Override
 	public @NonNull ConnectionManager createConnectionManager(@NonNull ProblemHandler problemHandler, @NonNull LoadingRegionAnalysis loadingRegionAnalysis) {
 		this.connectionManager  = new ConnectionManager(problemHandler, this, loadingRegionAnalysis);
 		return connectionManager;
@@ -636,6 +649,11 @@
 	} */
 
 	@Override
+	public @NonNull CollationManager getCollationManager() {
+		return ClassUtil.nonNullState(collationManager);
+	}
+
+	@Override
 	public @NonNull ConnectionManager getConnectionManager() {
 		return ClassUtil.nonNullState(connectionManager);
 	}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/OriginalContentsAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/OriginalContentsAnalysis.java
index b58b88f..14d1575 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/OriginalContentsAnalysis.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/OriginalContentsAnalysis.java
@@ -236,6 +236,11 @@
 		return s.toString();
 	}
 
+
+	public @NonNull Map<@NonNull PropertyDatum, @NonNull List<@NonNull NavigableEdge>> getBasePropertyDatum2newEdges() {
+		return basePropertyDatum2newEdges;
+	}
+
 	/**
 	 * Return all Realized NavigationEdges corresponding to predicatedEdge that navigate an isComposite property in either direction.
 	 * Returns null in the very unusual event that there are none.
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java
index 924da56..c5a7616 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java
@@ -28,6 +28,7 @@
 import org.eclipse.qvtd.compiler.internal.qvtb2qvts.trace.NameGenerator;
 import org.eclipse.qvtd.compiler.internal.qvtb2qvts.trace.Rule2TraceGroup;
 import org.eclipse.qvtd.compiler.internal.qvtb2qvts.trace.Transformation2TracePackage;
+import org.eclipse.qvtd.compiler.internal.qvts2qvts.CollationManager;
 import org.eclipse.qvtd.compiler.internal.qvts2qvts.ConnectionManager;
 import org.eclipse.qvtd.compiler.internal.qvts2qvts.RegionAnalysis;
 import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.RootPartitionAnalysis;
@@ -80,6 +81,7 @@
 	 */
 	@NonNull Map<@NonNull RootRegion, @NonNull Iterable<@NonNull RuleRegion>> analyzeTransformations();
 
+	@Nullable CollationManager basicGetCollationManager();
 	@Nullable ConnectionManager basicGetConnectionManager();
 	//	@Nullable Property basicGetGlobalSuccessProperty(@NonNull Node node);
 	//	@Nullable Property basicGetLocalSuccessProperty(@NonNull Node node);
@@ -90,6 +92,7 @@
 	 * FIXME Many calls to this are lazy; cannot possibly be partial.
 	 */
 	boolean computeIsPartial(@NonNull Node targetNode, @NonNull Property property);
+	@NonNull CollationManager createCollationManager(@NonNull ProblemHandler problemHandler, @NonNull LoadingRegionAnalysis loadingRegionAnalysis);
 	@NonNull ConnectionManager createConnectionManager(@NonNull ProblemHandler problemHandler, @NonNull LoadingRegionAnalysis loadingRegionAnalysis);
 	@NonNull ExpressionSynthesizer createExpressionSynthesizer(@NonNull RuleAnalysis ruleAnalysis);
 	@NonNull RuleAnalysis createRuleAnalysis(@NonNull AbstractTransformationAnalysis transformationAnalysis, @NonNull Rule asRule);
@@ -104,6 +107,7 @@
 	@NonNull ClassDatum getClassDatum(@NonNull TypedModel typedModel, @NonNull CompleteClass completeClass);
 	@NonNull ClassDatum getClassDatum(@NonNull TypedModel typedModel, @NonNull Iterable<@NonNull CompleteClass> completeClasses);
 	@NonNull Iterable<@NonNull ClassDatum> getClassDatums();
+	@NonNull CollationManager getCollationManager();
 	@NonNull ConnectionManager getConnectionManager();
 	@NonNull ScheduleManager getDirectedScheduleManager(@NonNull RootRegion rootRegion);
 	@NonNull RootDomainUsageAnalysis getDomainUsageAnalysis();
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/CollationManager.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/CollationManager.java
new file mode 100644
index 0000000..f43d1dc
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/CollationManager.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 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.qvts2qvts;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.CollectionType;
+import org.eclipse.ocl.pivot.Property;
+import org.eclipse.ocl.pivot.Type;
+import org.eclipse.qvtd.compiler.ProblemHandler;
+import org.eclipse.qvtd.compiler.internal.qvtb2qvts.LoadingRegionAnalysis;
+import org.eclipse.qvtd.compiler.internal.qvtb2qvts.OriginalContentsAnalysis;
+import org.eclipse.qvtd.compiler.internal.qvtb2qvts.ScheduleManager;
+import org.eclipse.qvtd.pivot.qvtschedule.NavigableEdge;
+import org.eclipse.qvtd.pivot.qvtschedule.PropertyDatum;
+import org.eclipse.qvtd.pivot.qvtschedule.Region;
+import org.eclipse.qvtd.pivot.qvtschedule.RootRegion;
+
+/**
+ * CollationManager supervises the collation of elements in ordered slots.
+ */
+public class CollationManager
+{
+	protected final @NonNull ScheduleManager scheduleManager;
+	protected final @NonNull OriginalContentsAnalysis originalContentsAnalysis;
+
+	public CollationManager(@NonNull ProblemHandler problemHandler, @NonNull ScheduleManager scheduleManager, @NonNull LoadingRegionAnalysis loadingRegionAnalysis) {
+		//	super(qvtm2qvts.getEnvironmentFactory());
+		this.scheduleManager = scheduleManager;
+		//		this.loadingRegionAnalysis = loadingRegionAnalysis;
+		this.originalContentsAnalysis = scheduleManager.getOriginalContentsAnalysis();
+	}
+
+	public void createCollations(StringBuilder s, @NonNull RootRegion rootRegion, @NonNull Region region) {
+		List<@NonNull PropertyDatum> collations = new ArrayList<>();
+		Map<@NonNull PropertyDatum, @NonNull List<@NonNull NavigableEdge>> basePropertyDatum2newEdges = originalContentsAnalysis.getBasePropertyDatum2newEdges();
+		for (@NonNull PropertyDatum basePropertyDatum : basePropertyDatum2newEdges.keySet()) {
+			Property baseProperty = basePropertyDatum.getReferredProperty();
+			Property oppositeProperty = baseProperty.getOpposite();
+			if (oppositeProperty != null) {
+				Type type = oppositeProperty.getType();
+				if (type instanceof CollectionType) {
+					CollectionType collectionType = (CollectionType) type;
+					if (collectionType.isOrdered()) {
+						List<@NonNull NavigableEdge> newEdges = basePropertyDatum2newEdges.get(basePropertyDatum);
+						assert newEdges != null;
+						for (@NonNull NavigableEdge navigableEdge : newEdges) {
+							if (navigableEdge.isPartial()) {
+								collations.add(basePropertyDatum);
+								break;
+							}
+						}
+					}
+				}
+			}
+		}
+		System.out.println("Collations: " + collations);
+	}
+}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/QVTs2QVTs.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/QVTs2QVTs.java
index 24fcc99..d606b02 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/QVTs2QVTs.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/QVTs2QVTs.java
@@ -89,6 +89,7 @@
 		this.rootName = rootName;
 		this.loadingRegionAnalysis = new LoadingRegionAnalysis(directedScheduleManager, createLoadingRegion());		// FIXME Should treat LoadingRegion uniformly
 		this.completeModel = environmentFactory.getCompleteModel();
+		directedScheduleManager.createCollationManager(problemHandler, loadingRegionAnalysis);
 		directedScheduleManager.createConnectionManager(problemHandler, loadingRegionAnalysis);
 	}
 
@@ -601,6 +602,7 @@
 	}
 
 	public @NonNull Iterable<@NonNull RootRegion> transform(@NonNull Map<@NonNull RootRegion, Iterable<@NonNull MappingRegion>> rootRegion2activeRegions) throws CompilerChainException {
+		CollationManager collationManager = directedScheduleManager.getCollationManager();
 		ConnectionManager connectionManager = directedScheduleManager.getConnectionManager();
 		LoadingRegion loadingRegion = loadingRegionAnalysis.getRegion();
 		Iterable<@NonNull RootRegion> rootRegions = rootRegion2activeRegions.keySet();
@@ -623,6 +625,7 @@
 			for (@NonNull Region region : activeRegions2) {
 				if (!(region instanceof LoadingRegion)) {
 					connectionManager.createIncomingConnections(s, rootRegion, region);
+					collationManager.createCollations(s, rootRegion, region);
 				}
 			}
 			if (s != null) {