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