blob: 6447df8a35cc1445fae0a71fff82b3aafa9fbc9a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvts2qvti;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.qvtd.compiler.internal.qvtm2qvts.RegionUtil;
import org.eclipse.qvtd.pivot.qvtschedule.Edge;
import org.eclipse.qvtd.pivot.qvtschedule.NavigableEdge;
import org.eclipse.qvtd.pivot.qvtschedule.Node;
import com.google.common.collect.Lists;
/**
* NavigationEdgeSorter supports ordering of a list of NavigationEdges into least-dependent first order thereby ensuring
* that unrealized variables are created and initualized for accessed realized attribute nodes before they are used.
*/
public class NavigationEdgeSorter
{
public class SourceNodeSizeComparator implements Comparator<@NonNull NavigableEdge>
{
@Override
public int compare(@NonNull NavigableEdge o1, @NonNull NavigableEdge o2) {
Set<@NonNull Node> s1 = edge2sourceNodes.get(o1);
Set<@NonNull Node> s2 = edge2sourceNodes.get(o2);
int i1 = s1 != null ? s1.size() : 0;
int i2 = s2 != null ? s2.size() : 0;
if (i1 != i2) {
return i1 - i2;
}
String n1 = o1.toString();
String n2 = o2.toString();
return ClassUtil.safeCompareTo(n1, n2);
}
}
public static Iterable<@NonNull NavigableEdge> getSortedAssignments(@NonNull Iterable<@NonNull NavigableEdge> realizedNavigationEdges) {
NavigationEdgeSorter assignmentSorter = new NavigationEdgeSorter();
for (@NonNull NavigableEdge edge : realizedNavigationEdges) {
if (!edge.isSecondary()) {
assignmentSorter.add(edge);
}
}
return assignmentSorter.getSortedAssignments();
}
/**
* Map from each edge to the computational source nodes of the edge's target.
*/
protected final @NonNull Map<@NonNull NavigableEdge, @Nullable Set<@NonNull Node>> edge2sourceNodes = new HashMap<>();
/**
* Add all navigationEdges to the Map of analyzed edges.
*/
public void add(@NonNull NavigableEdge navigationEdge) {
Set<@NonNull Node> sourceNodes = null;
if (navigationEdge.isRealized()) {
Node targetNode = navigationEdge.getEdgeTarget();
if (targetNode.isDataType()) {
sourceNodes = gatherSourceNodes(new HashSet<@NonNull Node>(), targetNode);
}
}
edge2sourceNodes.put(navigationEdge, sourceNodes);
}
private @NonNull Set<@NonNull Node> gatherSourceNodes(@NonNull Set<@NonNull Node> sourceNodes, @NonNull Node node) {
if (sourceNodes.add(node)) {
for (@NonNull Edge edge : RegionUtil.getIncomingEdges(node)) {
if (edge.isComputation()) {
gatherSourceNodes(sourceNodes, edge.getEdgeSource());
}
}
}
return sourceNodes;
}
/**
* Return the edges in fewest dependencies first order.
*/
public @NonNull Iterable<@NonNull NavigableEdge> getSortedAssignments() {
List<@NonNull NavigableEdge> sortedEdges = Lists.newArrayList(edge2sourceNodes.keySet());
Collections.sort(sortedEdges, new SourceNodeSizeComparator());
return sortedEdges;
}
}