private void CommitCopy()
 {
     if (pendingCopy != null)
     {
         patchOperations.Add(pendingCopy);
         pendingCopy = null;
     } // if
 }
        /// <summary>
        /// Commits pending patch operations.
        /// </summary>
        /// <remarks>
        /// Note that addition patch operation is committed first, followed by an
        /// deletion patch operation.
        /// </remarks>
        private void CommitPendingPatchOperations()
        {
            if (pendingAddition != null)
            {
                patchOperations.Add(pendingAddition);
                pendingAddition = null;
            } // if

            if (pendingDeletion != null)
            {
                patchOperations.Add(pendingDeletion);
                pendingDeletion = null;
            } // if
        }
        /// <summary>
        /// Invoked for elements matching in <see cref="sourceDataProvider"/> and
        /// <see cref="targetDataProvider"/>.
        /// </summary>
        /// <param name="sourceIndex"></param>
        /// <param name="targetIndex"></param>
        private void Match(int sourceIndex, int targetIndex)
        {
            if (pendingCopy == null)
            {
                pendingCopy = PatchOperation.CreateCopy(sourceIndex, sourceIndex);
            } // if
            else
            {
                pendingCopy.Copy =
                    new Range <int>(Math.Min(pendingCopy.Copy.Start, sourceIndex),
                                    Math.Max(pendingCopy.Copy.Start, sourceIndex));
            } // else

            CommitPendingPatchOperations();
        }
        /// <summary>
        /// Invoked for elements in <see cref="targetDataProvider"/> and not in
        /// <see cref="sourceDataProvider"/>.
        /// </summary>
        /// <param name="sourceIndex"></param>
        /// <param name="targetIndex"></param>
        private void InTargetNotInSource(int sourceIndex, int targetIndex)
        {
            CommitCopy();

            if (pendingAddition == null)
            {
                pendingAddition =
                    PatchOperation.CreateAddition(new Range <int>(targetIndex, targetIndex));
            } // if
            else
            {
                pendingAddition.Addition =
                    new Range <int>(Math.Min(pendingAddition.Addition.Start, targetIndex),
                                    Math.Max(pendingAddition.Addition.Start, targetIndex));
            } // else
        }
        /// <summary>
        /// Invoked for elements in <see cref="sourceDataProvider"/> and not in
        /// <see cref="targetDataProvider"/>.
        /// </summary>
        /// <param name="sourceIndex"></param>
        /// <param name="targetIndex"></param>
        private void SourceNotInTarget(int sourceIndex, int targetIndex)
        {
            CommitCopy();

            if (pendingDeletion == null)
            {
                pendingDeletion =
                    PatchOperation.CreateDeletion(new Range <int>(sourceIndex, sourceIndex));
            } // if
            else
            {
                pendingDeletion.Deletion =
                    new Range <int>(Math.Min(pendingDeletion.Deletion.Start, sourceIndex),
                                    Math.Max(pendingDeletion.Deletion.Start, sourceIndex));
            } // else
        }
        /// <summary>
        /// Determines whether the specified <see cref="object"/> is equal to the
        /// current object.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>
        /// <see langword="true" /> if the specified object is equal to the current Object;
        /// otherwise, <see langword="false" />.</returns>
        public override bool Equals(object obj)
        {
            if (this == obj)
            {
                return(true);
            }

            PatchOperation difference = obj as PatchOperation;

            if (difference == null)
            {
                return(false);
            }

            if (!Equals(Type, difference.Type))
            {
                return(false);
            }

            if (Type == PatchOperationType.Addition)
            {
                return(Equals(Addition, difference.Addition));
            }

            if (Type == PatchOperationType.Deletion)
            {
                return(Equals(Deletion, difference.Deletion));
            }

            if (Type == PatchOperationType.Copy)
            {
                return(Equals(Copy, difference.Copy));
            }

            return(false);
        }