package jetbrains.mps.vcs.diff; /*Generated by MPS */ import org.jetbrains.mps.openapi.model.SModel; import java.util.List; import jetbrains.mps.vcs.diff.changes.ModelChange; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.language.SProperty; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.smodel.PropertySupport; import jetbrains.mps.RuntimeFlags; import jetbrains.mps.util.EqualUtil; import jetbrains.mps.vcs.diff.changes.SetPropertyChange; import org.jetbrains.mps.openapi.model.SReference; import org.jetbrains.mps.openapi.language.SReferenceLink; import jetbrains.mps.internal.collections.runtime.ISelector; import org.jetbrains.mps.openapi.model.SNodeId; import jetbrains.mps.smodel.DynamicReference; import org.jetbrains.mps.openapi.model.SModelReference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.vcs.diff.changes.SetReferenceChange; import org.jetbrains.annotations.Nullable; import jetbrains.mps.vcs.diff.changes.AddRootChange; import jetbrains.mps.vcs.diff.changes.DeleteRootChange; import org.jetbrains.mps.openapi.language.SContainmentLink; import jetbrains.mps.util.IterableUtil; import jetbrains.mps.util.LongestCommonSubsequenceFinder; import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; import jetbrains.mps.vcs.diff.changes.NodeGroupChange; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import jetbrains.mps.extapi.model.SModelBase; import jetbrains.mps.vcs.diff.changes.DependencyChange; import jetbrains.mps.smodel.SModelOperations; import jetbrains.mps.vcs.diff.changes.ImportedModelChange; import jetbrains.mps.vcs.diff.changes.ModuleDependencyChange; import org.jetbrains.mps.openapi.module.SModuleReference; import java.util.Collection; import org.jetbrains.mps.openapi.language.SLanguage; import jetbrains.mps.vcs.diff.changes.UsedLanguageChange; import jetbrains.mps.vcs.diff.changes.EngagedLanguageChange; import jetbrains.mps.extapi.model.GeneratableSModel; import jetbrains.mps.vcs.diff.changes.DoNotGenerateOptionChange; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import java.util.Set; import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; public class ChangeSetBuilder { private SModel myOldModel; private SModel myNewModel; private ChangeSetImpl myChangeSet; private List<ModelChange> myNewChanges = ListSequence.fromList(new ArrayList<ModelChange>()); private ChangeSetBuilder(SModel oldModel, SModel newModel) { this(new ChangeSetImpl(oldModel, newModel)); } private ChangeSetBuilder(ChangeSetImpl changeSet) { myOldModel = changeSet.getOldModel(); myNewModel = changeSet.getNewModel(); myChangeSet = changeSet; } private void buildForProperties(SNode oldNode, SNode newNode) { Iterable<SProperty> oldProperties = oldNode.getProperties(); Iterable<SProperty> newProperties = newNode.getProperties(); for (SProperty p : Sequence.fromIterable(oldProperties).union(Sequence.fromIterable(newProperties))) { buildForProperty(oldNode, newNode, p); } } public void buildForProperty(SNode oldNode, SNode newNode, SProperty property) { PropertySupport propertySupport = new ChangeSetBuilder.DefaultPropertySupport(); if (!(RuntimeFlags.isMergeDriverMode())) { propertySupport = PropertySupport.getPropertySupport(property); } String oldPresentableValue = propertySupport.fromInternalValue(oldNode.getProperty(property)); String newPresentableValue = propertySupport.fromInternalValue(newNode.getProperty(property)); if (!(EqualUtil.equals(oldPresentableValue, newPresentableValue))) { ListSequence.fromList(myNewChanges).addElement(new SetPropertyChange(myChangeSet, oldNode.getNodeId(), property, newNode.getProperty(property))); } } private void buildForReferences(SNode oldNode, SNode newNode) { List<SReference> oldReferences = (List<SReference>) oldNode.getReferences(); List<SReference> newReferences = (List<SReference>) newNode.getReferences(); for (SReferenceLink role : ListSequence.fromList(oldReferences).concat(ListSequence.fromList(newReferences)).select(new ISelector<SReference, SReferenceLink>() { public SReferenceLink select(SReference r) { return r.getLink(); } }).distinct()) { buildForReference(oldNode, newNode, role); } } public void buildForReference(SNode oldNode, SNode newNode, SReferenceLink role) { SReference oldReference = oldNode.getReference(role); SReference newReference = newNode.getReference(role); SNodeId oldTargetId = (oldReference instanceof DynamicReference ? null : check_nbyrtw_a0a2a51(oldReference)); SNodeId newTargetId = (newReference instanceof DynamicReference ? null : check_nbyrtw_a0a3a51(newReference)); SModelReference oldTargetModel = check_nbyrtw_a0e0p(oldReference); if (SNodeOperations.getModel(oldNode).getReference().equals(oldTargetModel)) { oldTargetModel = null; } SModelReference newTargetModel = check_nbyrtw_a0g0p(newReference); if (SNodeOperations.getModel(newNode).getReference().equals(newTargetModel)) { newTargetModel = null; } if (eq_nbyrtw_a0a0i0p(oldTargetId, newTargetId) && eq_nbyrtw_a0a0i0p_0(oldTargetModel, newTargetModel) && eq_nbyrtw_a0a8a51(check_nbyrtw_a0a8a51(((jetbrains.mps.smodel.SReference) oldReference)), check_nbyrtw_a0a8a51_0(((jetbrains.mps.smodel.SReference) newReference)))) { // same references } else { SModelReference targetModel = check_nbyrtw_a0a0a8a51(newReference); ListSequence.fromList(myNewChanges).addElement(new SetReferenceChange(myChangeSet, oldNode.getNodeId(), role, targetModel, newTargetId, check_nbyrtw_f0a0a1a0i0p(((jetbrains.mps.smodel.SReference) newReference)))); } } public void buildForNode(@Nullable SNode oldNode, @Nullable SNode newNode) { assert oldNode != null || newNode != null; if (oldNode == null) { ListSequence.fromList(myNewChanges).addElement(new AddRootChange(myChangeSet, newNode.getNodeId())); } else if (newNode == null) { ListSequence.fromList(myNewChanges).addElement(new DeleteRootChange(myChangeSet, oldNode.getNodeId())); } else { buildForProperties(oldNode, newNode); buildForReferences(oldNode, newNode); for (SContainmentLink role : ListSequence.fromList(SNodeOperations.getChildren(oldNode)).concat(ListSequence.fromList(SNodeOperations.getChildren(newNode))).select(new ISelector<SNode, SContainmentLink>() { public SContainmentLink select(SNode ch) { return ch.getContainmentLink(); } }).distinct()) { buildForNodeRole(oldNode, newNode, role); } } } private void buildForNodeRole(SNode oldNode, SNode newNode, SContainmentLink role) { buildForNodeRole(IterableUtil.asList(oldNode.getChildren(role)), IterableUtil.asList(newNode.getChildren(role)), oldNode.getNodeId(), role); } public void buildForNodeRole(final List<? extends SNode> oldChildren, List<? extends SNode> newChildren, SNodeId parentId, SContainmentLink role) { List<SNodeId> oldIds = ListSequence.fromList(oldChildren).select(new ISelector<SNode, SNodeId>() { public SNodeId select(SNode n) { return n.getNodeId(); } }).toListSequence(); List<SNodeId> newIds = ListSequence.fromList(newChildren).select(new ISelector<SNode, SNodeId>() { public SNodeId select(SNode n) { return n.getNodeId(); } }).toListSequence(); LongestCommonSubsequenceFinder<SNodeId> finder = new LongestCommonSubsequenceFinder<SNodeId>(oldIds, newIds); // Finding insertings, deletings and replacings List<Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>>> differentIndices = finder.getDifferentIndices(); for (Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>> indices : ListSequence.fromList(differentIndices)) { Tuples._2<Integer, Integer> oldIndices = indices._0(); Tuples._2<Integer, Integer> newIndices = indices._1(); ListSequence.fromList(myNewChanges).addElement(new NodeGroupChange(myChangeSet, parentId, role, (int) oldIndices._0(), (int) oldIndices._1(), (int) newIndices._0(), (int) newIndices._1())); } // Finding changes for children List<Tuples._2<Integer, Integer>> commonIndices = finder.getCommonIndices(); ListSequence.fromList(commonIndices).select(new ISelector<Tuples._2<Integer, Integer>, SNode>() { public SNode select(Tuples._2<Integer, Integer> in) { return ListSequence.fromList(oldChildren).getElement((int) in._0()); } }).visitAll(new IVisitor<SNode>() { public void visit(SNode child) { buildForNode(child, myNewModel.getNode(child.getNodeId())); } }); } private <D> void buildAddedAndDeletedDependencies(_FunctionTypes._return_P1_E0<? extends Iterable<D>, ? super SModelBase> referencesExtractor, final _FunctionTypes._return_P2_E0<? extends DependencyChange, ? super D, ? super Boolean> changeCreator) { Iterable<D> added; Iterable<D> deleted; { Tuples._2<Iterable<D>, Iterable<D>> _tmp_nbyrtw_c0x = getAddedAndDeleted(referencesExtractor); added = _tmp_nbyrtw_c0x._0(); deleted = _tmp_nbyrtw_c0x._1(); } ListSequence.fromList(myNewChanges).addSequence(Sequence.fromIterable(added).select(new ISelector<D, DependencyChange>() { public DependencyChange select(D r) { return changeCreator.invoke(r, false); } })); ListSequence.fromList(myNewChanges).addSequence(Sequence.fromIterable(deleted).select(new ISelector<D, DependencyChange>() { public DependencyChange select(D r) { return changeCreator.invoke(r, true); } })); } private void buildForImports() { _FunctionTypes._return_P1_E0<? extends Iterable<SModelReference>, ? super SModelBase> importedModelsExtractor = new _FunctionTypes._return_P1_E0<List<SModelReference>, SModelBase>() { public List<SModelReference> invoke(SModelBase model) { return SModelOperations.getImportedModelUIDs(model); } }; _FunctionTypes._return_P2_E0<? extends ImportedModelChange, ? super SModelReference, ? super Boolean> changeCreator = new _FunctionTypes._return_P2_E0<ImportedModelChange, SModelReference, Boolean>() { public ImportedModelChange invoke(SModelReference mr, Boolean deleted) { return new ImportedModelChange(myChangeSet, mr, deleted); } }; buildAddedAndDeletedDependencies(importedModelsExtractor, changeCreator); } private void buildForDependencies(final ModuleDependencyChange.DependencyType dependencyType, _FunctionTypes._return_P1_E0<? extends Iterable<SModuleReference>, ? super SModelBase> referencesExtractor) { _FunctionTypes._return_P2_E0<? extends ModuleDependencyChange, ? super SModuleReference, ? super Boolean> changeCreator = new _FunctionTypes._return_P2_E0<ModuleDependencyChange, SModuleReference, Boolean>() { public ModuleDependencyChange invoke(SModuleReference mr, Boolean deleted) { return new ModuleDependencyChange(myChangeSet, mr, dependencyType, deleted); } }; buildAddedAndDeletedDependencies(referencesExtractor, changeCreator); } private void buildForUsedLanguages() { buildAddedAndDeletedDependencies(new _FunctionTypes._return_P1_E0<Collection<SLanguage>, SModelBase>() { public Collection<SLanguage> invoke(SModelBase m) { return m.importedLanguageIds(); } }, new _FunctionTypes._return_P2_E0<UsedLanguageChange, SLanguage, Boolean>() { public UsedLanguageChange invoke(SLanguage l, Boolean deleted) { return new UsedLanguageChange(myChangeSet, deleted, l); } }); } private void buildForLanguagesEngagedOnGeneration() { buildAddedAndDeletedDependencies(new _FunctionTypes._return_P1_E0<Collection<SLanguage>, SModelBase>() { public Collection<SLanguage> invoke(SModelBase m) { return m.getLanguagesEngagedOnGeneration(); } }, new _FunctionTypes._return_P2_E0<EngagedLanguageChange, SLanguage, Boolean>() { public EngagedLanguageChange invoke(SLanguage l, Boolean deleted) { return new EngagedLanguageChange(myChangeSet, deleted, l); } }); } private void buildForMetadata() { buildForImports(); buildForUsedLanguages(); buildForDependencies(ModuleDependencyChange.DependencyType.USED_DEVKIT, new _FunctionTypes._return_P1_E0<List<SModuleReference>, SModelBase>() { public List<SModuleReference> invoke(SModelBase model) { return model.importedDevkits(); } }); buildForLanguagesEngagedOnGeneration(); if (myNewModel instanceof GeneratableSModel && myOldModel instanceof GeneratableSModel) { if (((GeneratableSModel) myNewModel).isDoNotGenerate() != ((GeneratableSModel) myOldModel).isDoNotGenerate()) { ListSequence.fromList(myNewChanges).addElement(new DoNotGenerateOptionChange(myChangeSet)); } } } private void build(boolean withOpposite) { Iterable<SNodeId> allRootIds = ListSequence.fromList(jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations.roots(myOldModel, null)).concat(ListSequence.fromList(jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations.roots(myNewModel, null))).select(new ISelector<SNode, SNodeId>() { public SNodeId select(SNode n) { return n.getNodeId(); } }); for (SNodeId rootId : SetSequence.fromSetWithValues(new HashSet<SNodeId>(), allRootIds)) { buildForNode(myOldModel.getNode(rootId), myNewModel.getNode(rootId)); } buildForMetadata(); if (withOpposite) { myChangeSet.buildOppositeChangeSet(); } } public void commit() { ListSequence.fromList(myNewChanges).visitAll(new IVisitor<ModelChange>() { public void visit(ModelChange it) { myChangeSet.add(it); } }); ListSequence.fromList(myNewChanges).clear(); myChangeSet.fillRootToChange(); } public List<ModelChange> getNewChanges() { return myNewChanges; } private <D> Tuples._2<Iterable<D>, Iterable<D>> getAddedAndDeleted(Iterable<D> oldItems, Iterable<D> newItems) { Set<D> oldSet = SetSequence.fromSetWithValues(new HashSet<D>(), oldItems); Set<D> newSet = SetSequence.fromSetWithValues(new HashSet<D>(), newItems); return MultiTuple.<Iterable<D>,Iterable<D>>from(SetSequence.fromSet(newSet).subtract(SetSequence.fromSet(oldSet)), SetSequence.fromSet(oldSet).subtract(SetSequence.fromSet(newSet))); } private <D> Tuples._2<Iterable<D>, Iterable<D>> getAddedAndDeleted(_FunctionTypes._return_P1_E0<? extends Iterable<D>, ? super SModelBase> itemsExtractor) { return getAddedAndDeleted(itemsExtractor.invoke(as_nbyrtw_a0a0a0rb(myOldModel, SModelBase.class)), itemsExtractor.invoke(as_nbyrtw_a0b0a0rb(myNewModel, SModelBase.class))); } public static ModelChangeSet buildChangeSet(SModel oldModel, SModel newModel) { return buildChangeSet(oldModel, newModel, false); } public static ModelChangeSet buildChangeSet(SModel oldModel, SModel newModel, boolean withOpposite) { ChangeSetBuilder builder = new ChangeSetBuilder(oldModel, newModel); builder.build(withOpposite); builder.commit(); return builder.myChangeSet; } public static void rebuildChangeSet(ChangeSet changeSet) { ChangeSetImpl impl = (ChangeSetImpl) changeSet; impl.clear(); impl.clearOppositeChangeSet(); ChangeSetBuilder builder = new ChangeSetBuilder(impl); builder.build(true); builder.commit(); } public static ChangeSetBuilder createBuilder(ChangeSet changeSet) { return new ChangeSetBuilder((ChangeSetImpl) changeSet); } /*package*/ static class DefaultPropertySupport extends PropertySupport { /*package*/ DefaultPropertySupport() { } @Override protected boolean canSetValue(String string) { return true; } } private static SNodeId check_nbyrtw_a0a2a51(SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getTargetNodeId(); } return null; } private static SNodeId check_nbyrtw_a0a3a51(SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getTargetNodeId(); } return null; } private static SModelReference check_nbyrtw_a0e0p(SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getTargetSModelReference(); } return null; } private static SModelReference check_nbyrtw_a0g0p(SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getTargetSModelReference(); } return null; } private static boolean eq_nbyrtw_a0a0i0p(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } private static boolean eq_nbyrtw_a0a0i0p_0(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } private static boolean eq_nbyrtw_a0a8a51(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } private static String check_nbyrtw_a0a8a51(jetbrains.mps.smodel.SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getResolveInfo(); } return null; } private static String check_nbyrtw_a0a8a51_0(jetbrains.mps.smodel.SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getResolveInfo(); } return null; } private static SModelReference check_nbyrtw_a0a0a8a51(SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getTargetSModelReference(); } return null; } private static String check_nbyrtw_f0a0a1a0i0p(jetbrains.mps.smodel.SReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getResolveInfo(); } return null; } private static <T> T as_nbyrtw_a0a0a0rb(Object o, Class<T> type) { return (type.isInstance(o) ? (T) o : null); } private static <T> T as_nbyrtw_a0b0a0rb(Object o, Class<T> type) { return (type.isInstance(o) ? (T) o : null); } }