예제 #1
0
        /// <summary>
        /// Finds all the common elements in all the loaded collections and returns a list. Might want to override if the
        /// diff produces diff elements of a different type
        /// </summary>
        /// <returns>The collection of common elements</returns>
        public virtual IDiffObjectsCollection FindCommonElements()
        {
            int n = _collections.Count;

            IDiffObjectsCollection commonElements = _collections[0];

            for (int i = 1; i < n; i++)
            {
                //disable merges for this diff

                bool allowMerges = _properties.AllowMerges;
                _properties.AllowMerges = false;

                DoDiff(commonElements, _collections[i]);

                _properties.AllowMerges = allowMerges;

                //replace the current collection with the common elements collection
                //at the next iteration the next element in the collection will be compared against the common elements
                commonElements = _collections[i].CommonElements;

                if (commonElements.Count == 0)
                {
                    return(commonElements);                    //return an empty collection, there are no common elements
                }

                //sort the elements by position
                commonElements.SortByPosition();
            }

            return(commonElements);            //the last element will hold all the common elements
        }
 public void PushRange(IDiffObjectsCollection collection)
 {
     if (collection != null)
     {
         Items.InsertRange(0, collection.Items);
     }
 }
예제 #3
0
        /// <summary>
        /// Executes the diff operation between the specified indexes of the collections list
        /// </summary>
        /// <param name="indexOfFirst">The index of the first element to diff</param>
        /// <param name="indexOfSecond">The index of the second element to diff</param>
        public double DoDiff(int indexOfFirst, int indexOfSecond)
        {
            IDiffObjectsCollection first  = _collections[indexOfFirst];
            IDiffObjectsCollection second = _collections[indexOfSecond];

            return(DoDiff(first, second));
        }
예제 #4
0
        /// <summary>
        /// Check if the values match and outputs a set of granular differences
        /// </summary>
        /// <param name="diffObject"></param>
        /// <param name="diffsForSelf"></param>
        /// <param name="diffsForArgument"></param>
        /// <returns></returns>
        public bool ValueMatches(IDiffObject diffObject,
                                 out IDiffObjectsCollection diffsForSelf,
                                 out IDiffObjectsCollection diffsForArgument,
                                 out IDiffObjectsCollection commonElements)
        {
            HeaderDiffObject otherObject = diffObject as HeaderDiffObject;

            diffsForSelf     = null;
            diffsForArgument = null;
            commonElements   = null;

            bool matches = false;

            if (otherObject != null)
            {
                matches = _headerLineHash == otherObject.HeaderLineHash;
                //if the values are different but the headers are the same
                if (!matches && String.Compare(_name, otherObject.Name, true) == 0)
                {
                    WordsDiffer valuesDiffer = new WordsDiffer();
                    valuesDiffer.AddTask(_values);
                    valuesDiffer.AddTask(otherObject.Values);
                    valuesDiffer.Properties.Sorted = true;
                    valuesDiffer.Properties.CaseInSensitiveSort = true;
                    double diffRatio = valuesDiffer.DoDiff(0, 1);

                    diffsForSelf     = valuesDiffer.GetResultingDifferences(0);
                    diffsForArgument = valuesDiffer.GetResultingDifferences(1);
                    commonElements   = valuesDiffer.GetResultingCommonElements(0);
                    matches          = diffRatio >= _valuesMinSimilarity;
                }
            }
            return(matches);
        }
예제 #5
0
        public void WordsDiff()
        {
            string text1 = "first second;third1";
            string text2 = "second;first fourth-third";

            WordsDiffer differ = new WordsDiffer();

            DiffResult             result      = differ.DoDiff(text1, text2);
            IDiffObjectsCollection firstDiffs  = result.DifferencesForFirst;
            IDiffObjectsCollection secondDiffs = result.DifferencesForSecond;

            Assert.IsTrue(firstDiffs[0].ValueEquals(new WordDiffObject(0, 0, "first ")));
            Assert.IsTrue(firstDiffs[1].ValueEquals(new LetterDiffObject(0, 0, "1")));
            Assert.IsTrue(secondDiffs[0].ValueEquals(new WordDiffObject(0, 0, "first ")));
            Assert.IsTrue(secondDiffs[1].ValueEquals(new WordDiffObject(0, 0, "fourth-")));

            //test a sorted diff
            differ.Properties.Sorted = true;
            result = differ.DoDiff(text1, text2);

            firstDiffs  = result.DifferencesForFirst;
            secondDiffs = result.DifferencesForSecond;

            Assert.IsTrue(firstDiffs[0].ValueEquals(new LetterDiffObject(0, 0, "1")));
            Assert.IsTrue(secondDiffs[0].ValueEquals(new WordDiffObject(0, 0, "fourth-")));
        }
예제 #6
0
        public void LinesDiff()
        {
            string text1 = "LineLine1.1\r\n" +
                           "eniLLine1.3\r\n" +
                           "ABC1.4";
            string text2 = "LineLine2.1\r\n" +
                           "XYZ2.4\r\n" +
                           "eniLLine2.3";

            LinesDiffer differ = new LinesDiffer();

            DiffResult             result      = differ.DoDiff(text1, text2);
            IDiffObjectsCollection firstDiffs  = result.DifferencesForFirst;
            IDiffObjectsCollection secondDiffs = result.DifferencesForSecond;

            firstDiffs.SortByPosition();
            secondDiffs.SortByPosition();

            Assert.IsTrue(firstDiffs[0].ValueEquals(new LetterDiffObject(0, 0, "1")));
            Assert.IsTrue(secondDiffs[0].ValueEquals(new LetterDiffObject(0, 0, "2")));
            Assert.IsTrue(firstDiffs[1].ValueEquals(new LetterDiffObject(0, 0, "1")));
            Assert.IsTrue(secondDiffs[1].ValueEquals(new LineDiffObject(0, 0, "XYZ2.4")));
            Assert.IsTrue(firstDiffs[2].ValueEquals(new LineDiffObject(0, 0, "ABC1.4")));
            Assert.IsTrue(secondDiffs[2].ValueEquals(new LetterDiffObject(0, 0, "2")));
        }
 public void AddRange(IDiffObjectsCollection collection)
 {
     if (collection != null)
     {
         Items.AddRange(collection.Items);
     }
 }
예제 #8
0
        private string PrintTextDifferences(IDiffObjectsCollection diff)
        {
            StringBuilder result = new StringBuilder();

            for (int i = 0; i < diff.Count; i++)
            {
                result.Append((diff[i] as BaseTextDiffObject).Value);
                result.Append(" ");
            }

            return(result.ToString());
        }
예제 #9
0
        private string GetRtf(string text, IDiffObjectsCollection differences)
        {
            int i, n = differences.Count;

            RtfHighlight[] diffHighlights = new RtfHighlight[n];

            for (i = 0; i < n; i++)
            {
                diffHighlights[i]       = new RtfHighlight(differences[i]);
                diffHighlights[i].Color = TVColorConverter.GetColorFromString(TrafficViewerOptions.Instance.ColorDiffText);
            }

            return(_builder.Convert(text, diffHighlights));
        }
예제 #10
0
        public void LettersDiff()
        {
            string text1 = "abcdefg;1";
            string text2 = "xabcdfg1!";

            LettersDiffer differ = new LettersDiffer();

            DiffResult             result      = differ.DoDiff(text1, text2);
            IDiffObjectsCollection firstDiffs  = result.DifferencesForFirst;
            IDiffObjectsCollection secondDiffs = result.DifferencesForSecond;

            Assert.IsTrue(firstDiffs[0].ValueEquals(new LetterDiffObject(0, 0, "e")));
            Assert.IsTrue(firstDiffs[1].ValueEquals(new LetterDiffObject(0, 0, ";")));
            Assert.IsTrue(secondDiffs[0].ValueEquals(new LetterDiffObject(0, 0, "x")));
            Assert.IsTrue(secondDiffs[1].ValueEquals(new LetterDiffObject(0, 0, "!")));
        }
예제 #11
0
        /// <summary>
        /// Diffs the two collections using the ValueEquals function of their elements and stores differences in the
        /// arguments collection
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        public double Diff(ref IDiffObjectsCollection first, ref IDiffObjectsCollection second)
        {
            double similarity = 0.0;

            if ((first == null || first.Count == 0) && second != null)
            {
                second.Differences = second;
            }
            else if ((second == null || second.Count == 0) && first != null)
            {
                first.Differences = first;
            }
            else
            {
                //use the LCS algorith to compute the longest common subsequence and populate the Differences in first and second
                similarity = LCS(ref first, ref second);
            }
            return(similarity);
        }
예제 #12
0
        protected double DoDiff(IDiffObjectsCollection first, IDiffObjectsCollection second)
        {
            first.InitDiffs();
            second.InitDiffs();
            first.InitCommonElements();
            second.InitCommonElements();

            if (_properties.Sorted)
            {
                first.SortByValues(_properties.CaseInSensitiveSort);
                second.SortByValues(_properties.CaseInSensitiveSort);
                //replace the default LCS algorithm with a simple algorithm for sorted collections
                _algorithm = new SortedCollectionsDiffAlgorithm();
            }

            first.AllowMerges  = _properties.AllowMerges;
            second.AllowMerges = _properties.AllowMerges;

            return(_algorithm.Diff(ref first, ref second));
        }
예제 #13
0
        /// <summary>
        /// Checks is the value is equal. If not where applicable a collection of granular differences is outputed
        /// </summary>
        /// <param name="diffObject"></param>
        /// <param name="diffsForSelf"></param>
        /// <param name="diffsForArgument"></param>
        /// <param name="commonElements"></param>
        /// <returns></returns>
        public bool ValueMatches(IDiffObject diffObject, out IDiffObjectsCollection diffsForSelf, out IDiffObjectsCollection diffsForArgument, out IDiffObjectsCollection commonElements)
        {
            BaseTextDiffObject otherObject = diffObject as BaseTextDiffObject;

            diffsForSelf     = null;
            diffsForArgument = null;
            commonElements   = null;
            bool matches = false;

            if (otherObject != null)
            {
                matches = this.ValueHash == otherObject.ValueHash;

                if (!matches)
                {
                    double simFactor = ASESimilarityAlgorithm.CalculateSimilarity(this.Value, otherObject.Value);

                    LettersDiffer granularDiffer = InitGranularDiffer();

                    if (simFactor > 0 && granularDiffer != null)
                    {
                        //calculate granular differences
                        granularDiffer.AddTask(Value, Position);                         //imports the current word into a letters collection starting from the position of the current element
                        granularDiffer.AddTask(otherObject.Value, otherObject.Position);

                        double diffRatio = granularDiffer.DoDiff(0, 1);

                        diffsForSelf     = granularDiffer.GetResultingDifferences(0);
                        diffsForArgument = granularDiffer.GetResultingDifferences(1);
                        commonElements   = granularDiffer.GetResultingCommonElements(0);

                        matches = diffRatio >= this.SimilarityFactor;
                    }
                }
            }

            return(matches);
        }
예제 #14
0
        private void DiffWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _progress.Visible = false;
            _timer.Stop();

            RequestsDifferResult result = e.Result as RequestsDifferResult;

            if (result != null)
            {
                _labelSimilarity.Text = String.Format(Properties.Resources.SimilarityText,
                                                      result.BodyAproximateSimilarity * 100);

                _firstDiffs  = result.DiffsForFirst;
                _secondDiffs = result.DiffsForSecond;

                _boxFirst.Rtf  = GetRtf(result.FirstText, result.DiffsForFirst);
                _boxSecond.Rtf = GetRtf(result.SecondText, result.DiffsForSecond);
            }

            //re-enable the diff buttons
            DiffButtonsSwitch(true);

            _diffInProgress = false;
        }
예제 #15
0
        /// <summary>
        /// Computes the longest common subsequence matrix between the two collections
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        private double LCS(ref IDiffObjectsCollection first, ref IDiffObjectsCollection second)
        {
            int start = 0;
            int firstEnd = first.Count;
            int secondEnd = second.Count;
            int i, j, n, m;

            IDiffObjectsCollection granularDiffsForFirst = null;
            IDiffObjectsCollection granularDiffsForSecond = null;
            IDiffObjectsCollection granularCommonElements = null;

            IDiffObjectsCollection currCommonElements = first.CommonElements;

            second.CommonElements = currCommonElements;

            //trim the matching items at the beggining
            while (start < firstEnd && start < secondEnd && first[start].ValueMatches(second[start], out granularDiffsForFirst, out granularDiffsForSecond, out granularCommonElements))
            {
                //if the collections were slightly different add the small differences
                first.Differences.AddRange(granularDiffsForFirst);
                second.Differences.AddRange(granularDiffsForSecond);
                if (granularDiffsForFirst == null && granularDiffsForSecond == null)
                {
                    currCommonElements.Add(first[start]);
                }
                else
                {
                    currCommonElements.AddRange(granularCommonElements);
                }

                start++;
            }

            //trim the matching items at the end
            while (firstEnd > start && secondEnd > start && first[firstEnd - 1].ValueMatches(second[secondEnd - 1], out granularDiffsForFirst, out granularDiffsForSecond, out granularCommonElements))
            {
                firstEnd--;
                secondEnd--;

                if (granularDiffsForFirst == null && granularDiffsForSecond == null)
                {
                    currCommonElements.Add(first[firstEnd]);
                }
                else
                {
                    currCommonElements.AddRange(granularCommonElements);
                }
                //if the collections were slightly different insert the small differences
                first.Differences.PushRange(granularDiffsForFirst);
                second.Differences.PushRange(granularDiffsForSecond);
            }

            m = firstEnd - start + 1;
            n = secondEnd - start + 1;

            //truncate the matrix to prevent OOM
            m = Math.Min(m, MAX_MATRIX_LENGTH);
            n = Math.Min(n, MAX_MATRIX_LENGTH);
            //create the matrix for LCS

            ushort[,] C = new ushort[m, n];


            for (i = 1; i < m; i++)
            {
                for (j = 1; j < n; j++)
                {
                    if (first[start + i - 1].ValueMatches(second[start + j - 1]))
                    {
                        C[i, j] = (ushort)(C[i - 1, j - 1] + 1);
                    }
                    else
                    {
                        C[i, j] = Math.Max(C[i, j - 1], C[i - 1, j]);
                    }
                }
            }

            //populate the differences
            return(ExtractDiffs(C, first, second, start, m, n));
        }
예제 #16
0
 /// <summary>
 /// Adds a task to be compared
 /// </summary>
 /// <param name="task"></param>
 /// <returns>Index of the added task</returns>
 public int AddTask(IDiffObjectsCollection task)
 {
     _collections.Add(task);
     return(_collections.Count - 1);
 }
예제 #17
0
        private double ExtractDiffs(
            ushort[, ] C, IDiffObjectsCollection first, IDiffObjectsCollection second, int start, int m, int n)
        {
            int i = m - 1, j = n - 1;

            double diffCount1 = 0;
            double diffCount2 = 0;

            IDiffObjectsCollection currFirstDiffs     = first.Differences;
            IDiffObjectsCollection currSecondDiffs    = second.Differences;
            IDiffObjectsCollection currCommonElements = first.CommonElements;

            second.CommonElements = currCommonElements;

            do
            {
                int         iIndex     = start + i - 1;
                int         jIndex     = start + j - 1;
                IDiffObject currFirst  = null;
                IDiffObject currSecond = null;


                IDiffObjectsCollection granularDiffsForFirst  = null;
                IDiffObjectsCollection granularDiffsForSecond = null;
                IDiffObjectsCollection granularCommonElements = null;


                if (iIndex >= 0 && iIndex < first.Count)
                {
                    currFirst = first[iIndex];
                }

                if (jIndex >= 0 && jIndex < second.Count)
                {
                    currSecond = second[jIndex];
                }


                if (currFirst != null &&
                    currFirst.ValueMatches(currSecond, out granularDiffsForFirst, out granularDiffsForSecond, out granularCommonElements))
                {
                    //ValuesMatch can return true if the objects are very similar
                    //In that case we need to capture granular differences
                    currFirstDiffs.PushRange(granularDiffsForFirst);
                    currSecondDiffs.PushRange(granularDiffsForSecond);


                    if (granularDiffsForFirst == null && granularDiffsForSecond == null)
                    {
                        currCommonElements.Add(currFirst);
                    }
                    else
                    {
                        currCommonElements.AddRange(granularCommonElements);
                    }

                    i--; j--;
                }
                else if (j > 0 && (i <= 0 || C[i, j - 1] >= C[i - 1, j]))
                {
                    currSecondDiffs.Push(currSecond);
                    diffCount2++;
                    j--;
                }
                else if (i > 0 && (j <= 0 || C[i, j - 1] < C[i - 1, j]))
                {
                    currFirstDiffs.Push(currFirst);
                    diffCount1++;
                    i--;
                }
            }while (i > 0 || j > 0);

            //calculate diff ratio, or similarity factor
            double ratio1 = 0;

            if (first.Count > 0)
            {
                ratio1 = 1 - diffCount1 / first.Count;
            }

            double ratio2 = 0;

            if (second.Count > 0)
            {
                ratio2 = 1 - diffCount2 / second.Count;
            }

            return(Math.Min(ratio1, ratio2));
        }
예제 #18
0
        public double Diff(ref IDiffObjectsCollection first, ref IDiffObjectsCollection second)
        {
            int i = 0, j = 0, m = first.Count, n = second.Count;

            double diffCount1 = 0;
            double diffCount2 = 0;

            IDiffObjectsCollection granularDiffs1 = null;
            IDiffObjectsCollection granularDiffs2 = null;
            IDiffObjectsCollection granularCommon = null;

            IDiffObjectsCollection currCommonElements = first.CommonElements;

            second.CommonElements = currCommonElements;

            while (i < m || j < n)
            {
                if (j < n && i < m && first[i].ValueMatches(second[j], out granularDiffs1, out granularDiffs2, out granularCommon))
                {
                    first.Differences.AddRange(granularDiffs1);
                    second.Differences.AddRange(granularDiffs2);
                    if (granularDiffs1 == null && granularDiffs2 == null)
                    {
                        currCommonElements.Add(first[i]);
                    }
                    else
                    {
                        currCommonElements.AddRange(granularCommon);
                    }
                    i++;
                    j++;
                }
                else if (i < m && (j >= n || first[i].CompareValues(second[j], _ignoreCase) == CompareResult.Lower))
                {
                    first.Differences.Add(first[i]);
                    diffCount1++;
                    i++;
                }
                else if (j < n && (i >= m || first[i].CompareValues(second[j], _ignoreCase) == CompareResult.Greater))
                {
                    second.Differences.Add(second[j]);
                    diffCount2++;
                    j++;
                }
            }

            //calculate diff ratio, or similarity factor
            double ratio1 = 0;

            if (first.Count > 0)
            {
                ratio1 = 1 - diffCount1 / first.Count;
            }

            double ratio2 = 0;

            if (second.Count > 0)
            {
                ratio2 = 1 - diffCount2 / second.Count;
            }

            return(Math.Min(ratio1, ratio2));
        }