Ejemplo n.º 1
0
 private IEnumerable <DocumentChange <T> > GetForwardChanges(DocumentVersion <T> other)
 {
     // Return changes from this(inclusive) to other(exclusive).
     for (DocumentVersion <T> node = this; node != other; node = node.next)
     {
         foreach (DocumentChange <T> change in node.changes)
         {
             yield return(change);
         }
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Compares the age of this checkpoint to the other checkpoint.
        /// </summary>
        /// <remarks>This method is thread-safe.</remarks>
        /// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this version.</exception>
        /// <returns>-1 if this version is older than <paramref name="other"/>.
        /// 0 if <c>this</c> version instance represents the same version as <paramref name="other"/>.
        /// 1 if this version is newer than <paramref name="other"/>.</returns>
        public int CompareAge(DocumentVersion <T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            DocumentVersion <T> o = other as DocumentVersion <T>;

            if (o == null || provider != o.provider)
            {
                throw new ArgumentException("Versions do not belong to the same document");
            }
            // We will allow overflows, but assume that the maximum distance between checkpoints is 2^31-1.
            // This is guaranteed on x86 because so many checkpoints don't fit into memory.
            return(Math.Sign(unchecked (this.id - o.id)));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Gets the changes from this checkpoint to the other checkpoint.
        /// If 'other' is older than this checkpoint, an exception is thrown.
        /// </summary>
        /// <remarks>This method is thread-safe.</remarks>
        /// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint, or 'other' is older than this checkpoint.</exception>
        public IEnumerable <DocumentChange <T> > GetChangesTo(DocumentVersion <T> other)
        {
            int result = CompareAge(other);

            if (result < 0)
            {
                return(GetForwardChanges(other));
            }
            else if (result > 0)
            {
                return(other.GetForwardChanges(this).Reverse().Select(change => change.Invert()));
            }
            else
            {
                return(NO_CHANGES);
            }
        }
Ejemplo n.º 4
0
 public DocumentChangedEvent(DocumentVersion <T> before, DocumentVersion <T> after)
 {
     DocumentVersionBefore = before;
     DocumentVersionAfter  = after;
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets whether this checkpoint belongs to the same document as the other checkpoint.
        /// </summary>
        /// <remarks>
        /// Returns false when given <c>null</c>.
        /// </remarks>
        public bool BelongsToSameDocumentAs(DocumentVersion <T> other)
        {
            DocumentVersion <T> o = other as DocumentVersion <T>;

            return(o != null && provider == o.provider);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// New version of an existing document
 /// </summary>
 internal DocumentVersion(DocumentVersion <T> prev)
 {
     this.provider = prev.provider;
     this.id       = unchecked (prev.id + 1);
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Get changes between older version v1 and more recent version v2 :
        /// - with redundant changes applied on the same line merged in one single change
        /// - with line indexes translated to be valid in the v2 document
        /// - with changes sorted in the order of the line indexes in the v2 document
        /// </summary>
        public IList <DocumentChange <T> > GetReducedAndOrderedChangesInNewerVersion(DocumentVersion <T> other)
        {
            // Ensure the version received as parameter is more recent than teh current version
            int result = CompareAge(other);

            if (result >= 0)
            {
                throw new InvalidOperationException("other version must be more recent than this version");
            }

            // Merge the redundant changes and translate the line indexes to the last version
            List <DocumentChange <T> > reducedDocumentChanges = new List <DocumentChange <T> >();

            foreach (DocumentChange <T> documentChange in GetChangesTo(other))
            {
                switch (documentChange.Type)
                {
                case DocumentChangeType.DocumentCleared:
                    // Ignore all previous document changes : they are meaningless now that the document was completely cleared
                    reducedDocumentChanges.Clear();
                    // Add the clear event
                    reducedDocumentChanges.Add(documentChange);
                    break;

                case DocumentChangeType.LineInserted:
                    // Recompute the line indexes of all the changes prevously applied
                    foreach (DocumentChange <T> documentChangeToAdjust in reducedDocumentChanges)
                    {
                        if (documentChangeToAdjust.LineIndex >= documentChange.LineIndex)
                        {
                            documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex + 1;
                        }
                    }
                    // Add the insert change
                    reducedDocumentChanges.Add(documentChange);
                    break;

                case DocumentChangeType.LineUpdated:
                    // Check to see if this change can be merged with a previous one
                    bool changeAlreadyApplied = false;
                    foreach (DocumentChange <T> documentChangeToAdjust in reducedDocumentChanges)
                    {
                        if (documentChangeToAdjust.LineIndex == documentChange.LineIndex)
                        {
                            changeAlreadyApplied = true;
                            break;
                        }
                    }
                    if (!changeAlreadyApplied)
                    {
                        // Add the update change
                        reducedDocumentChanges.Add(documentChange);
                    }
                    break;

                case DocumentChangeType.LineRemoved:
                    // Recompute the line indexes of all the changes prevously applied
                    DocumentChange <T> documentChangeToRemove = null;
                    foreach (DocumentChange <T> documentChangeToAdjust in reducedDocumentChanges)
                    {
                        if (documentChangeToAdjust.LineIndex > documentChange.LineIndex)
                        {
                            documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex - 1;
                        }
                        else if (documentChangeToAdjust.LineIndex == documentChange.LineIndex)
                        {
                            documentChangeToRemove = documentChangeToAdjust;
                        }
                    }
                    // Ignore all previous changes applied to a line now removed
                    if (documentChangeToRemove != null)
                    {
                        reducedDocumentChanges.Remove(documentChangeToRemove);
                    }
                    break;
                }
            }

            // Sort all changes by line index
            reducedDocumentChanges.Sort((documentChange1, documentChange2) => documentChange1.LineIndex - documentChange2.LineIndex);
            return(reducedDocumentChanges);
        }