public IDiff <TType> MergeDiffs(IDiff <TType> left, IDiff <TType> right, IConflictContainer conflicts) { if (this.aMergeItemsDiffs == null) { this.aMergeItemsDiffs = this.aMergerImplementation.Partial.Algorithms.GetMergeDiffsAlgorithm <TItemType>(); } List <IDiffItem> ret = new List <IDiffItem>(); foreach (var(leftItems, rightItems) in new MergeJoin(new Chunker(left.Cast <IDiffOrderedCollectionItem>()), new Chunker(right.Cast <IDiffOrderedCollectionItem>()))) { if (leftItems == null) { ret.AddRange(rightItems); } else if (rightItems == null) { ret.AddRange(leftItems); } else { this.ProcessConflicts(ret, leftItems, rightItems, conflicts); } } return(new Diff <TType>(ret)); }
public IDiff <TType> MergeDiffs(IDiff <TType> left, IDiff <TType> right, IConflictContainer conflicts) { if (this.aIdAccessor == null) { if (this.aIdProperty == null) { ParameterExpression obj = Expression.Parameter(typeof(TItemType), "obj"); Expression <Func <TItemType, TIdType> > identityFunction = Expression.Lambda <Func <TItemType, TIdType> >( obj, obj ); this.aIdAccessor = identityFunction.Compile(); } else { this.aIdAccessor = IdHelpers.CreateIdAccessor <TItemType, TIdType>(this.aIdProperty); } this.aMergeItemsDiffs = this.aMergerImplementation.Partial.Algorithms.GetMergeDiffsAlgorithm <TItemType>(); } Dictionary <TIdType, IDiffUnorderedCollectionItem> rightIndex = new Dictionary <TIdType, IDiffUnorderedCollectionItem>(right.Count); foreach (IDiffItem item in right) { rightIndex[this.GetID(item)] = (IDiffUnorderedCollectionItem)item; } List <IDiffItem> ret = new List <IDiffItem>(left.Count + right.Count); foreach (var leftItem in left.Cast <IDiffUnorderedCollectionItem>()) { IDiffUnorderedCollectionItem rightItem; TIdType id = this.GetID(leftItem); if (rightIndex.TryGetValue(id, out rightItem)) { rightIndex.Remove(id); this.ProcessConflict(id, leftItem, rightItem, ret, conflicts); } else { ret.Add(leftItem); } } ret.AddRange(rightIndex.Values); return(new Diff <TType>(ret)); }
private void ProcessConflict(IDiffValue leftItem, IDiffValue rightItem, List <IDiffItem> ret, IConflictContainer conflicts) { if (leftItem is IDiffItemReplaced && rightItem is IDiffItemReplaced && leftItem.IsSame(rightItem)) { ret.Add(leftItem); } else if (leftItem is IDiffItemChanged leftChanged && rightItem is IDiffItemChanged rightChanged) { Type itemType = leftItem.ValueType; IMergeDiffsAlgorithm mergeItemsDiffs = this.aMergerImplementation.Partial.Algorithms.GetMergeDiffsAlgorithm(itemType, this.aRules); IDiff diffLeft = leftChanged.ValueDiff; IDiff diffRight = rightChanged.ValueDiff; IDiff result = mergeItemsDiffs.MergeDiffs(diffLeft, diffRight, conflicts); ret.Add(new DiffValueChanged <TType>(itemType, (IDiff <TType>)result)); }
public IDiff <TType> MergeDiffs(IDiff <TType> left, IDiff <TType> right, IConflictContainer conflicts) { if (this.aMergeItemsDiffs == null) { this.aMergeItemsDiffs = this.aMergerImplementation.Partial.Algorithms.GetMergeDiffsAlgorithm <TItemType>(); } Dictionary <TKeyType, IDiffKeyValueCollectionItem <TKeyType> > rightIndex = new Dictionary <TKeyType, IDiffKeyValueCollectionItem <TKeyType> >(right.Count); foreach (IDiffItem item in right) { rightIndex[((IDiffKeyValueCollectionItem <TKeyType>)item).Key] = (IDiffKeyValueCollectionItem <TKeyType>)item; } List <IDiffItem> ret = new List <IDiffItem>(left.Count + right.Count); foreach (var leftItem in left.Cast <IDiffKeyValueCollectionItem <TKeyType> >()) { IDiffKeyValueCollectionItem <TKeyType> rightItem; if (rightIndex.TryGetValue(leftItem.Key, out rightItem)) { rightIndex.Remove(leftItem.Key); this.ProcessConflict(leftItem.Key, leftItem, rightItem, ret, conflicts); } else { ret.Add(leftItem); } } ret.AddRange(rightIndex.Values); return(new Diff <TType>(ret)); }
private Expression CompileCheckConflicts(Property property, Expression leftCurrent, Expression rightCurrent, Expression conflicts, Expression ret) { /* PSEUDO CODE FOR THIS: * if (leftCurrent is Unchanged) * { * add(rightCurrent) * } * else if (rightCurrent is Unchanged) * { * add(leftCurrent) * } * else if (leftCurrent is Replace || rightCurrent is Replace) * { * if (leftCurrent == rightCurrent) * add(leftCurrent) * else * { * conflict = Conflict(leftCurrent, rightCurrent) * add(conflict) * conflicts.register(conflict) * } * } * else if (leftCurrent is Changed && rightCurrent is Changed) * { * add(algorithm.Merge(leftCurrent.ValueDiff, rightCurrent.ValueDiff, conflicts)) * } * else * throw */ IMergeDiffsAlgorithm algorithm = this.aMergerImplementation.Partial.Algorithms.GetMergeDiffsAlgorithm(property.Type); Type itemReplacedType = typeof(IDiffItemReplaced <>).MakeGenericType(property.Type); ParameterExpression conflict = Expression.Parameter(typeof(IDiffItemConflicted), "conflict"); return(Expression.IfThenElse( Expression.TypeIs(leftCurrent, typeof(IDiffItemUnchanged)), Expression.Call( ret, ListMembers.Add(typeof(IDiffItem)), rightCurrent ), Expression.IfThenElse( Expression.TypeIs(rightCurrent, typeof(IDiffItemUnchanged)), Expression.Call( ret, ListMembers.Add(typeof(IDiffItem)), leftCurrent ), Expression.IfThenElse( Expression.OrElse( Expression.TypeIs(leftCurrent, itemReplacedType), Expression.TypeIs(rightCurrent, itemReplacedType) ), Expression.IfThenElse( Expression.Call( null, ObjectMembers.Equals(), leftCurrent, rightCurrent ), Expression.Call( ret, ListMembers.Add(typeof(IDiffItem)), leftCurrent ), Expression.Block( new[] { conflict }, Expression.Assign( conflict, Expression.New( DiffItemsMembers.NewConflict(), leftCurrent, rightCurrent ) ), Expression.Call( ret, ListMembers.Add(typeof(IDiffItem)), conflict ), Expression.Call( conflicts, ConflictContainerMembers.RegisterConflict(), conflict ) ) ), Expression.IfThenElse( Expression.AndAlso( Expression.TypeIs(leftCurrent, typeof(IDiffItemChanged)), Expression.TypeIs(rightCurrent, typeof(IDiffItemChanged)) ), Expression.Call( ret, ListMembers.Add(typeof(IDiffItem)), Expression.New( DiffItemsMembers.NewClassChanged(property.Type), Expression.Constant(property), Expression.Call( Expression.Constant(algorithm, typeof(IMergeDiffsAlgorithm <>).MakeGenericType(property.Type)), MergeDiffsAlgorithmMembers.MergeDiffs(property.Type), Expression.Property( Expression.Convert(leftCurrent, typeof(IDiffItemChanged <>).MakeGenericType(property.Type)), DiffItemsMembers.ChangedDiff(property.Type) ), Expression.Property( Expression.Convert(rightCurrent, typeof(IDiffItemChanged <>).MakeGenericType(property.Type)), DiffItemsMembers.ChangedDiff(property.Type) ), conflicts ) ) ), Expression.Throw( Expression.New(typeof(Exception)) ) ) ) ) )); }
public MergeOrderedCollectionDiffs(MergerImplementation mergerImplementation) { this.aMergerImplementation = mergerImplementation; this.aMergeItemsDiffs = null; }
public IDiff <TType> MergeDiffs <TType>(IDiff <TType> left, IDiff <TType> right, IConflictContainer conflicts) { IMergeDiffsAlgorithm <TType> algorithm = this.Algorithms.GetMergeDiffsAlgorithm <TType>(); return(algorithm.MergeDiffs(left, right, conflicts)); }