package jetbrains.mps.build.workflow.generator.util; /*Generated by MPS */ import java.util.List; import org.jetbrains.mps.openapi.model.SNode; import java.util.Map; import java.util.HashMap; import jetbrains.mps.generator.template.TemplateQueryContext; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.util.GraphUtil; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import java.util.Set; import java.util.HashSet; import java.util.Arrays; public class SubTaskOrderHelper { private final List<SNode> list; private final Map<SNode, SubTaskOrderHelper.SubTask> map = new HashMap<SNode, SubTaskOrderHelper.SubTask>(); private final TemplateQueryContext genContext; public SubTaskOrderHelper(List<SNode> list, TemplateQueryContext genContext) { this.list = list; this.genContext = genContext; } public void sort() { int count = 0; SubTaskOrderHelper.SubTask[] subtasks = new SubTaskOrderHelper.SubTask[ListSequence.fromList(list).count()]; for (SNode st : list) { SubTaskOrderHelper.SubTask wrapper = new SubTaskOrderHelper.SubTask(st, count); map.put(st, wrapper); subtasks[count++] = wrapper; } for (SubTaskOrderHelper.SubTask st : subtasks) { for (SNode dep : SLinkOperations.getChildren(st.getTask(), MetaAdapterFactory.getContainmentLink(0x698a8d22a10447a0L, 0xba8d10e3ec237f13L, 0x2670d5989d5a6275L, 0x2670d5989d5b4a01L, "after"))) { SubTaskOrderHelper.SubTask afterTask = map.get(SLinkOperations.getTarget(dep, MetaAdapterFactory.getReferenceLink(0x698a8d22a10447a0L, 0xba8d10e3ec237f13L, 0x2670d5989d5b49b8L, 0x2670d5989d5b49b9L, "target"))); if (afterTask == null) { genContext.showErrorMessage(dep, "dependency on non-existing subtask"); continue; } st.targets.add(afterTask.getIndex()); } for (SNode dep : SLinkOperations.getChildren(st.getTask(), MetaAdapterFactory.getContainmentLink(0x698a8d22a10447a0L, 0xba8d10e3ec237f13L, 0x2670d5989d5a6275L, 0x36fb0dc9fd36bb1bL, "before"))) { SubTaskOrderHelper.SubTask beforeTask = map.get(SLinkOperations.getTarget(dep, MetaAdapterFactory.getReferenceLink(0x698a8d22a10447a0L, 0xba8d10e3ec237f13L, 0x2670d5989d5b49b8L, 0x2670d5989d5b49b9L, "target"))); if (beforeTask == null) { genContext.showErrorMessage(dep, "dependency on non-existing subtask"); continue; } beforeTask.targets.add(st.getIndex()); } } int[][] graph = new int[count][]; for (SubTaskOrderHelper.SubTask st : subtasks) { graph[st.getIndex()] = st.getTargets(); } int[][] partitions = GraphUtil.tarjan(graph); ListSequence.fromList(list).clear(); for (int[] cycle : partitions) { if (cycle.length > 1) { StringBuilder sb = new StringBuilder(); sb.append("subtasks cycle detected: "); for (int i = 0; i < 5 && i < cycle.length; i++) { if (i > 0) { sb.append(", "); } sb.append(SPropertyOperations.getString(subtasks[cycle[i]].getTask(), MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"))); } if (cycle.length > 5) { sb.append(" ..."); } genContext.showErrorMessage(subtasks[cycle[0]].getTask(), sb.toString()); continue; } ListSequence.fromList(list).addElement(subtasks[cycle[0]].getTask()); } } private class SubTask { private final int index; private final SNode task; public final Set<Integer> targets = new HashSet<Integer>(); public SubTask(SNode task, int index) { this.task = task; this.index = index; } public int[] getTargets() { targets.remove(index); int[] arr = new int[targets.size()]; if (targets.isEmpty()) { return arr; } int i = 0; for (Integer val : targets) { arr[i++] = val; } assert i == targets.size(); if (arr.length > 1) { Arrays.sort(arr); } return arr; } public SNode getTask() { return task; } public int getIndex() { return index; } } }