package jetbrains.mps.lang.migration.util;
/*Generated by MPS */
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import java.util.LinkedList;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.lang.migration.behavior.IMigrationUnit__BehaviorDescriptor;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import java.util.Map;
import java.util.Collection;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.smodel.Language;
import java.util.Collections;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.internal.collections.runtime.CollectionSequence;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import java.util.ArrayList;
public class MigrationsCheckUtil {
private static <T> boolean hasCycles(final _FunctionTypes._return_P1_E0<? extends Iterable<T>, ? super T> neighbours, T startPoint, final List<T> parents, final List<T> visited) {
if (ListSequence.fromList(visited).contains(startPoint)) {
return false;
}
if (ListSequence.fromList(parents).contains(startPoint)) {
return true;
}
ListSequence.fromList(parents).insertElement(0, startPoint);
if (Sequence.fromIterable(neighbours.invoke(startPoint)).any(new IWhereFilter<T>() {
public boolean accept(T it) {
return hasCycles(neighbours, it, parents, visited);
}
})) {
return true;
}
ListSequence.fromList(parents).removeElementAt(0);
ListSequence.fromList(visited).addElement(startPoint);
return false;
}
private static <T> boolean hasCycles(_FunctionTypes._return_P1_E0<? extends Iterable<T>, ? super T> neighbours, T startPoint) {
return hasCycles(neighbours, startPoint, ListSequence.fromList(new LinkedList<T>()), ListSequence.fromList(new LinkedList<T>()));
}
public static boolean hasCycles(SNode migrationScript) {
return hasCycles(new _FunctionTypes._return_P1_E0<Iterable<SNode>, SNode>() {
public Iterable<SNode> invoke(SNode migrationScript) {
return allScriptDependencies(migrationScript);
}
}, migrationScript);
}
public static boolean hasIncludeCycles(SNode migrationScript) {
return hasCycles(new _FunctionTypes._return_P1_E0<Iterable<SNode>, SNode>() {
public Iterable<SNode> invoke(SNode pureMigrationScript) {
return SNodeOperations.ofConcept(SLinkOperations.collect(SNodeOperations.ofConcept(SLinkOperations.getChildren(pureMigrationScript, MetaAdapterFactory.getContainmentLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x67236d4a5836cabbL, 0x67236d4a5836d7f3L, "part")), MetaAdapterFactory.getConcept(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x267418e6b5c2b903L, "jetbrains.mps.lang.migration.structure.IncludeMigrationPart")), MetaAdapterFactory.getReferenceLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x267418e6b5c2b903L, 0x267418e6b5c2b960L, "target")), MetaAdapterFactory.getConcept(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x67236d4a5836cabbL, "jetbrains.mps.lang.migration.structure.PureMigrationScript"));
}
}, migrationScript);
}
private static Iterable<SNode> allScriptDependencies(final SNode script) {
Iterable<SNode> result = Sequence.fromIterable(SLinkOperations.collect(IMigrationUnit__BehaviorDescriptor.getRequiredData_id7s$_UJMVosT.invoke(script), MetaAdapterFactory.getReferenceLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x44b28148e401c891L, 0x4f6b4ac0cd6d4af5L, "script"))).concat(Sequence.fromIterable(SLinkOperations.collect(IMigrationUnit__BehaviorDescriptor.getExecuteAfter_id2bWK$jI6RRp.invoke(script), MetaAdapterFactory.getReferenceLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x398343344f099b7aL, 0x398343344f099b7bL, "script"))));
result = Sequence.fromIterable(result).concat(ListSequence.fromList(SModelOperations.roots(SNodeOperations.getModel(script), MetaAdapterFactory.getInterfaceConcept(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x47bb811da2acc4d6L, "jetbrains.mps.lang.migration.structure.IMigrationUnit"))).where(new IWhereFilter<SNode>() {
public boolean accept(SNode it) {
return (int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it) < (int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(script);
}
}));
return result;
}
public static Map<SNode, Collection<String>> checkMigrationsVersions(SModule module) {
// check whether scripts are really migrations for some language
if (!(module instanceof Language)) {
return Collections.emptyMap();
}
SModel migModel = SModuleOperations.getAspect(module, "migration");
if (migModel == null) {
return Collections.emptyMap();
}
if (!(migModel.isLoaded())) {
return Collections.emptyMap();
}
List<SNode> allScripts = SModelOperations.roots(migModel, MetaAdapterFactory.getInterfaceConcept(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x47bb811da2acc4d6L, "jetbrains.mps.lang.migration.structure.IMigrationUnit"));
// scripts with no versions set
final Map<SNode, Collection<String>> result = MapSequence.fromMap(new HashMap<SNode, Collection<String>>());
Iterable<SNode> noVersionScripts = ListSequence.fromList(allScripts).where(new IWhereFilter<SNode>() {
public boolean accept(SNode it) {
return !((boolean) IMigrationUnit__BehaviorDescriptor.isVersionSet_id4uVwhQyFpOe.invoke(it));
}
});
Sequence.fromIterable(noVersionScripts).visitAll(new IVisitor<SNode>() {
public void visit(SNode it) {
MigrationsCheckUtil.ensureInitialized(result, it);
CollectionSequence.fromCollection(MapSequence.fromMap(result).get(it)).addElement("Script does not have version");
}
});
// no scripts with versions?
if (Sequence.fromIterable(noVersionScripts).count() == ListSequence.fromList(allScripts).count()) {
return result;
}
Iterable<SNode> scriptsWithVersions = ListSequence.fromList(allScripts).where(new IWhereFilter<SNode>() {
public boolean accept(SNode it) {
return (boolean) IMigrationUnit__BehaviorDescriptor.isVersionSet_id4uVwhQyFpOe.invoke(it);
}
});
final Map<Integer, Integer> versions = MapSequence.fromMap(new HashMap<Integer, Integer>());
Sequence.fromIterable(scriptsWithVersions).visitAll(new IVisitor<SNode>() {
public void visit(SNode it) {
if (MapSequence.fromMap(versions).get((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it)) == null) {
MapSequence.fromMap(versions).put((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it), 0);
}
MapSequence.fromMap(versions).put((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it), MapSequence.fromMap(versions).get((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it)) + 1);
}
});
final int minVersion = SetSequence.fromSet(MapSequence.fromMap(versions).keySet()).sort(new ISelector<Integer, Integer>() {
public Integer select(Integer it) {
return it;
}
}, true).first();
final int maxVersion = SetSequence.fromSet(MapSequence.fromMap(versions).keySet()).sort(new ISelector<Integer, Integer>() {
public Integer select(Integer it) {
return it;
}
}, false).first();
final int langVersion = ((Language) module).getLanguageVersion();
// last version+1 == version of a language?
if (maxVersion != langVersion - 1) {
Sequence.fromIterable(scriptsWithVersions).where(new IWhereFilter<SNode>() {
public boolean accept(SNode it) {
return (int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it) == maxVersion;
}
}).visitAll(new IVisitor<SNode>() {
public void visit(SNode it) {
ensureInitialized(result, it);
CollectionSequence.fromCollection(MapSequence.fromMap(result).get(it)).addElement("Language version (" + langVersion + ") is greater than the target version of last migration script (" + maxVersion + ")");
}
});
}
Sequence.fromIterable(scriptsWithVersions).visitAll(new IVisitor<SNode>() {
public void visit(SNode it) {
// multiple scripts for one version?
if (MapSequence.fromMap(versions).get((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it)) > 1) {
ensureInitialized(result, it);
CollectionSequence.fromCollection(MapSequence.fromMap(result).get(it)).addElement("Multiple scripts for version " + (int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it) + " found");
}
// version with no scripts for it?
if ((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it) != minVersion && MapSequence.fromMap(versions).get((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it) - 1) == null) {
ensureInitialized(result, it);
CollectionSequence.fromCollection(MapSequence.fromMap(result).get(it)).addElement("Missing script for version " + ((int) IMigrationUnit__BehaviorDescriptor.fromVersion_id4uVwhQyFcnl.invoke(it) - 1));
}
}
});
return result;
}
private static void ensureInitialized(Map<SNode, Collection<String>> coll, SNode index) {
if (MapSequence.fromMap(coll).get(index) == null) {
MapSequence.fromMap(coll).put(index, CollectionSequence.fromCollection(new ArrayList<String>()));
}
}
}