Merge branch 'master' of git.labs.intellij.net:idea/community
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / diff / impl / processing / TextCompareProcessor.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.diff.impl.processing;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.diff.ex.DiffFragment;
20 import com.intellij.openapi.diff.impl.ComparisonPolicy;
21 import com.intellij.openapi.diff.impl.fragments.Fragment;
22 import com.intellij.openapi.diff.impl.fragments.LineFragment;
23 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
24 import com.intellij.openapi.diff.impl.highlighting.LineBlockDivider;
25 import com.intellij.openapi.diff.impl.highlighting.Util;
26
27 import java.util.ArrayList;
28
29 public class TextCompareProcessor {
30   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.Processor");
31   private final ComparisonPolicy myComparisonPolicy;
32
33   public TextCompareProcessor(ComparisonPolicy comparisonPolicy) {
34     myComparisonPolicy = comparisonPolicy;
35   }
36
37   public ArrayList<LineFragment> process(String text1, String text2) {
38     DiffFragment[] woFormattingBlocks = DiffPolicy.LINES_WO_FORMATTING.buildFragments(text1, text2);
39     DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).
40         correctAndNormalize(woFormattingBlocks);
41     ArrayList<LineFragment> lineBlocks = new DiffFragmentsProcessor().process(step1lineFragments);
42     for (LineFragment lineBlock : lineBlocks) {
43       if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
44       String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
45       String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
46       ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
47       lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
48     }
49     return lineBlocks;
50   }
51
52   private ArrayList<LineFragment> findSubFragments(String text1, String text2) {
53     DiffFragment[] fragments = new ByWord(myComparisonPolicy).buildFragments(text1, text2);
54     fragments = DiffCorrection.ConnectSingleSideToChange.INSTANCE.correct(fragments);
55     fragments = UniteSameType.INSTANCE.correct(fragments);
56     fragments = PreferWholeLines.INSTANCE.correct(fragments);
57     fragments = UniteSameType.INSTANCE.correct(fragments);
58     DiffFragment[][] lines = Util.splitByUnchangedLines(fragments);
59     lines = Util.uniteFormattingOnly(lines);
60
61     LineFragmentsCollector collector = new LineFragmentsCollector();
62     for (DiffFragment[] line : lines) {
63       DiffFragment[][] subLines = LineBlockDivider.SINGLE_SIDE.divide(line);
64       subLines = Util.uniteFormattingOnly(subLines);
65       for (DiffFragment[] subLineFragments : subLines) {
66         LineFragment subLine = collector.addDiffFragment(Util.concatenate(subLineFragments));
67         if (!subLine.isOneSide()) {
68           subLine.setChildren(processInlineFragments(subLineFragments));
69         }
70       }
71     }
72     return collector.getFragments();
73   }
74
75   private static ArrayList<Fragment> processInlineFragments(DiffFragment[] subLineFragments) {
76     LOG.assertTrue(subLineFragments.length > 0);
77     FragmentsCollector result = new FragmentsCollector();
78     for (DiffFragment fragment : subLineFragments) {
79       result.addDiffFragment(fragment);
80     }
81     return result.getFragments();
82   }
83 }