package jetbrains.mps.build.mps.util;
/*Generated by MPS */
import org.jetbrains.mps.openapi.model.SNode;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.make.dependencies.graph.Graph;
import java.util.Map;
import java.util.LinkedHashMap;
import jetbrains.mps.make.dependencies.graph.IVertex;
import jetbrains.mps.make.dependencies.graph.Graphs;
import jetbrains.mps.util.GraphUtil;
import java.util.ArrayList;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.Set;
import java.util.HashSet;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.internal.collections.runtime.ITranslator2;
import java.util.LinkedHashSet;
import jetbrains.mps.build.mps.behavior.BuildMps_DevKit__BehaviorDescriptor;
public class MPSModulesPartitioner {
private final SNode project;
private final List<SNode> modules;
private List<MPSModulesPartitioner.Chunk> chunks;
private boolean useMeta;
private Iterable<SNode> external;
public MPSModulesPartitioner(SNode project) {
this(project, ListSequence.fromList(Sequence.fromIterable(getModules(project)).sort(new ISelector<SNode, String>() {
public String select(SNode it) {
return SPropertyOperations.getString(it, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"));
}
}, true).toListSequence()).asUnmodifiable());
}
public MPSModulesPartitioner(SNode project, List<SNode> modules) {
this.project = project;
this.modules = modules;
}
public void buildChunks() {
Graph<MPSModulesPartitioner.Node> graph = new Graph<MPSModulesPartitioner.Node>();
final Map<SNode, MPSModulesPartitioner.Node> map = new LinkedHashMap<SNode, MPSModulesPartitioner.Node>();
for (SNode module : modules) {
MPSModulesPartitioner.Node decorator = new MPSModulesPartitioner.Node(module);
map.put(module, decorator);
graph.add(decorator);
}
for (MPSModulesPartitioner.Node node : graph.getData()) {
node.fill(map);
}
IVertex[] vertices = graph.getData().toArray(new IVertex[graph.getNVertexes()]);
useMeta = false;
int[][] greater_or_eq = Graphs.graphToIntInt(vertices, false, true);
useMeta = true;
int[][] strictly_greater = Graphs.graphToIntInt(vertices, true, true);
int[] partition = GraphUtil.partition(greater_or_eq, strictly_greater);
this.chunks = ListSequence.fromList(new ArrayList<MPSModulesPartitioner.Chunk>());
for (int i = 0; i < vertices.length; i++) {
SNode m = ((MPSModulesPartitioner.Node) vertices[i]).module;
int pindex = partition[i];
boolean conflicting = pindex < 0;
if (conflicting) {
pindex = -1 - pindex;
}
while (ListSequence.fromList(chunks).count() <= pindex) {
ListSequence.fromList(chunks).addElement(new MPSModulesPartitioner.Chunk());
}
SetSequence.fromSet(ListSequence.fromList(chunks).getElement(pindex).getModules()).addElement(m);
if (conflicting) {
ListSequence.fromList(chunks).getElement(pindex).setBootstrap(m, true);
}
}
for (MPSModulesPartitioner.Chunk c : chunks) {
Set<MPSModulesPartitioner.Node> chunkNodes = SetSequence.fromSetWithValues(new HashSet<MPSModulesPartitioner.Node>(), SetSequence.fromSet(c.getModules()).select(new ISelector<SNode, MPSModulesPartitioner.Node>() {
public MPSModulesPartitioner.Node select(SNode it) {
return map.get(it);
}
}));
for (SNode confl : ListSequence.fromListWithValues(new ArrayList<SNode>(), c.getConflicting())) {
if (SetSequence.fromSet(map.get(confl).metaDependencies).intersect(SetSequence.fromSet(chunkNodes)).isEmpty()) {
c.setBootstrap(confl, false);
}
}
}
}
public void buildExternalDependencies() {
// Though we don't care about RT dependencies to generate a module, we need runtimeClosure() here due to
// module compilation/reload Generate task does in addition to M2M, M2T transformations.
this.external = Sequence.fromIterable(new MPSModulesClosure(modules, new MPSModulesClosure.ModuleDependenciesOptions().trackDevkits()).generationDependenciesClosure().runtimeClosure().getAllModules()).where(new IWhereFilter<SNode>() {
public boolean accept(SNode it) {
// FIXME exclusion of generator modules here is due to the fact ModuleMiner (which eventually takes whatever we specify in <library file>)
// is not ready yet to read generator modules (it's JavaModuleFacet of Language-loaded Generator that discovers -generator.jar)
// However, the way forward is to be explicit about generator modules (need to produce META-INF/module.xml first, though)
return !(SNodeOperations.isInstanceOf(it, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4c6db07d2e56a8b4L, "jetbrains.mps.build.mps.structure.BuildMps_Generator"))) && SNodeOperations.getContainingRoot(it) != SNodeOperations.getContainingRoot(MPSModulesPartitioner.this.project);
}
});
}
public List<MPSModulesPartitioner.Chunk> getChunks() {
return chunks;
}
public Iterable<SNode> getExternal() {
return external;
}
public static Iterable<SNode> getModules(SNode project) {
return Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x668c6cfbafacf6f2L, "parts")), MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x14d3fb6fb843ebddL, "jetbrains.mps.build.mps.structure.BuildMps_Group"))).translate(new ITranslator2<SNode, SNode>() {
public Iterable<SNode> translate(SNode it) {
return SLinkOperations.getChildren(it, MetaAdapterFactory.getContainmentLink(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x14d3fb6fb843ebddL, 0x14d3fb6fb843ebdeL, "modules"));
}
}).concat(Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x668c6cfbafacf6f2L, "parts")), MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d333ebL, "jetbrains.mps.build.mps.structure.BuildMps_AbstractModule"))));
}
private class Node implements IVertex {
private SNode module;
private Set<MPSModulesPartitioner.Node> dependencyNodes = SetSequence.fromSet(new LinkedHashSet<MPSModulesPartitioner.Node>());
private Set<MPSModulesPartitioner.Node> metaDependencies = SetSequence.fromSet(new LinkedHashSet<MPSModulesPartitioner.Node>());
public Node(SNode module) {
this.module = module;
}
@Override
public Set<? extends IVertex> getNexts() {
return (useMeta ? metaDependencies : dependencyNodes);
}
public void fill(Map<SNode, MPSModulesPartitioner.Node> map) {
if (SNodeOperations.isInstanceOf(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x48e82d508331930cL, "jetbrains.mps.build.mps.structure.BuildMps_Module"))) {
MPSModulesClosure closure = new MPSModulesClosure(SNodeOperations.cast(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x48e82d508331930cL, "jetbrains.mps.build.mps.structure.BuildMps_Module")), new MPSModulesClosure.ModuleDependenciesOptions()).generationDependenciesClosure();
for (SNode q : Sequence.fromIterable(closure.getAllModules())) {
MPSModulesPartitioner.Node node = map.get(q);
if (node != null) {
SetSequence.fromSet(metaDependencies).addElement(node);
}
}
closure = new MPSModulesClosure(SNodeOperations.cast(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x48e82d508331930cL, "jetbrains.mps.build.mps.structure.BuildMps_Module")), new MPSModulesClosure.ModuleDependenciesOptions().trackDevkits()).closure();
for (SNode q : Sequence.fromIterable(closure.getAllModules())) {
MPSModulesPartitioner.Node node = map.get(q);
if (node != null) {
SetSequence.fromSet(dependencyNodes).addElement(node);
}
}
} else if (SNodeOperations.isInstanceOf(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2060eL, "jetbrains.mps.build.mps.structure.BuildMps_DevKit"))) {
SNode devkit = SNodeOperations.cast(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2060eL, "jetbrains.mps.build.mps.structure.BuildMps_DevKit"));
Iterable<SNode> extended = SLinkOperations.collect(SLinkOperations.getChildren(devkit, MetaAdapterFactory.getContainmentLink(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2060eL, 0x4780308f5d23142L, "extends")), MetaAdapterFactory.getReferenceLink(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2313aL, 0x4780308f5d2313bL, "devkit"));
for (SNode q : Sequence.fromIterable(BuildMps_DevKit__BehaviorDescriptor.getExportedModules_id6qlcPcvboVF.invoke(devkit)).concat(Sequence.fromIterable(extended))) {
MPSModulesPartitioner.Node node = map.get(q);
if (node != null) {
SetSequence.fromSet(dependencyNodes).addElement(node);
}
}
}
}
}
public static class Chunk {
private final Set<SNode> modules;
private final Set<SNode> conflicting;
public Chunk() {
this.modules = SetSequence.fromSet(new LinkedHashSet<SNode>());
this.conflicting = SetSequence.fromSet(new HashSet<SNode>());
}
public Set<SNode> getModules() {
return modules;
}
public Set<SNode> getConflicting() {
return conflicting;
}
public boolean isConflicting(SNode mod) {
return SetSequence.fromSet(conflicting).contains(mod);
}
public boolean isBootstrap() {
return SetSequence.fromSet(conflicting).isNotEmpty();
}
public void setBootstrap(SNode module, boolean flag) {
if (flag) {
SetSequence.fromSet(conflicting).addElement(module);
} else {
SetSequence.fromSet(conflicting).removeElement(module);
}
}
}
}