package jetbrains.mps.vcs.diff.changes;
/*Generated by MPS */
import java.util.Map;
import org.jetbrains.mps.openapi.model.SNodeId;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.smodel.CopyUtil;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.smodel.references.UnregisteredNodes;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.smodel.SNodeUtil;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.internal.collections.runtime.IMapping;
public class NodeCopier {
private Map<SNodeId, SNodeId> myIdReplacementCache = MapSequence.fromMap(new HashMap<SNodeId, SNodeId>());
private SModel myModel;
public NodeCopier(SModel model) {
myModel = model;
}
public SNodeId getReplacementId(SNodeId originalId) {
return MapSequence.fromMap(myIdReplacementCache).get(originalId);
}
public SNode copyNode(SNode sourceNode) {
SNode copy = CopyUtil.copyAndPreserveId(sourceNode);
for (SNode node : ListSequence.fromList(SNodeOperations.getNodeDescendants(copy, null, true, new SAbstractConcept[]{}))) {
SNodeId nodeId = node.getNodeId();
if (myModel.getNode(nodeId) == null) {
continue;
}
SNodeId replacedId;
do {
replacedId = jetbrains.mps.smodel.SModel.generateUniqueId();
} while (myModel.getNode(replacedId) != null);
((jetbrains.mps.smodel.SNode) node).setId(replacedId);
if (!(MapSequence.fromMap(myIdReplacementCache).containsKey(nodeId))) {
MapSequence.fromMap(myIdReplacementCache).put(nodeId, replacedId);
}
}
return copy;
}
public void restoreIds(boolean affectOthers) {
UnregisteredNodes.WarningLevel oldWarningLevel = UnregisteredNodes.instance().setWarningLevel(UnregisteredNodes.WarningLevel.WARNING);
try {
softRestoreIds();
if (affectOthers) {
evictOtherDuplicates();
softRestoreIds();
assert Sequence.fromIterable(MapSequence.fromMap(myIdReplacementCache).values()).all(new IWhereFilter<SNodeId>() {
public boolean accept(SNodeId id) {
return id == null;
}
});
}
} finally {
UnregisteredNodes.instance().setWarningLevel(oldWarningLevel);
}
}
private void setId(SNode node, SNodeId id) {
SModel model = SNodeOperations.getModel(node);
if (SNodeOperations.getParent(node) == null) {
SNodeOperations.deleteNode(node);
((jetbrains.mps.smodel.SNode) node).setId(id);
SModelOperations.addRootNode(model, node);
} else {
SNode stubNode = new jetbrains.mps.smodel.SNode(SNodeUtil.concept_BaseConcept);
SNodeOperations.replaceWithAnother(node, stubNode);
((jetbrains.mps.smodel.SNode) node).setId(id);
SNodeOperations.replaceWithAnother(stubNode, node);
}
}
private void softRestoreIds() {
for (SNodeId id : SetSequence.fromSet(MapSequence.fromMap(myIdReplacementCache).keySet())) {
if (MapSequence.fromMap(myIdReplacementCache).get(id) != null && myModel.getNode(id) == null) {
// node id is free now!
setId(myModel.getNode(MapSequence.fromMap(myIdReplacementCache).get(id)), id);
MapSequence.fromMap(myIdReplacementCache).put(id, null);
}
}
}
private void evictOtherDuplicates() {
for (SNodeId id : SetSequence.fromSet(MapSequence.fromMap(myIdReplacementCache).keySet())) {
SNode toBeEvicted = myModel.getNode(id);
assert toBeEvicted != null;
setId(toBeEvicted, jetbrains.mps.smodel.SModel.generateUniqueId());
}
}
public Map<SNodeId, SNodeId> getState() {
final Map<SNodeId, SNodeId> state = MapSequence.fromMap(new HashMap<SNodeId, SNodeId>(MapSequence.fromMap(myIdReplacementCache).count()));
MapSequence.fromMap(myIdReplacementCache).visitAll(new IVisitor<IMapping<SNodeId, SNodeId>>() {
public void visit(IMapping<SNodeId, SNodeId> m) {
MapSequence.fromMap(state).put(m.key(), m.value());
}
});
return state;
}
public void setState(Map<SNodeId, SNodeId> state, SModel model) {
myIdReplacementCache = state;
myModel = model;
}
public boolean hasIdsToRestore() {
return Sequence.fromIterable(MapSequence.fromMap(myIdReplacementCache).values()).any(new IWhereFilter<SNodeId>() {
public boolean accept(SNodeId id) {
return id != null;
}
});
}
}