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; } }); } }