Home | History | Annotate | Download | only in dumprendertree2
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      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 
     17 package com.android.dumprendertree2;
     18 
     19 import name.fraser.neil.plaintext.diff_match_patch;
     20 
     21 import java.util.LinkedList;
     22 
     23 /**
     24  * Helper methods fo TextResult.getDiffAsHtml()
     25  */
     26 public class VisualDiffUtils {
     27 
     28     private static final int DONT_PRINT_LINE_NUMBER = -1;
     29 
     30     /**
     31      * Preprocesses the list of diffs so that new line characters appear only at the end of
     32      * diff.text
     33      *
     34      * @param diffs
     35      * @return
     36      *      LinkedList of diffs where new line character appears only on the end of
     37      *      diff.text
     38      */
     39     public static LinkedList<diff_match_patch.Diff> splitDiffsOnNewline(
     40             LinkedList<diff_match_patch.Diff> diffs) {
     41         LinkedList<diff_match_patch.Diff> newDiffs = new LinkedList<diff_match_patch.Diff>();
     42 
     43         String[] parts;
     44         int lengthMinusOne;
     45         for (diff_match_patch.Diff diff : diffs) {
     46             parts = diff.text.split("\n", -1);
     47             if (parts.length == 1) {
     48                 newDiffs.add(diff);
     49                 continue;
     50             }
     51 
     52             lengthMinusOne = parts.length - 1;
     53             for (int i = 0; i < lengthMinusOne; i++) {
     54                 newDiffs.add(new diff_match_patch.Diff(diff.operation, parts[i] + "\n"));
     55             }
     56             if (!parts[lengthMinusOne].isEmpty()) {
     57                 newDiffs.add(new diff_match_patch.Diff(diff.operation, parts[lengthMinusOne]));
     58             }
     59         }
     60 
     61         return newDiffs;
     62     }
     63 
     64     public static void generateExpectedResultLines(LinkedList<diff_match_patch.Diff> diffs,
     65             LinkedList<Integer> lineNums, LinkedList<String> lines) {
     66         String delSpan = "<span class=\"del\">";
     67         String eqlSpan = "<span class=\"eql\">";
     68 
     69         String line = "";
     70         int i = 1;
     71         diff_match_patch.Diff diff;
     72         int size = diffs.size();
     73         boolean isLastDiff;
     74         for (int j = 0; j < size; j++) {
     75             diff = diffs.get(j);
     76             isLastDiff = j == size - 1;
     77             switch (diff.operation) {
     78                 case DELETE:
     79                     line = processDiff(diff, lineNums, lines, line, i, delSpan, isLastDiff);
     80                     if (line.equals("")) {
     81                         i++;
     82                     }
     83                     break;
     84 
     85                 case INSERT:
     86                     // If the line is currently empty and this insertion is the entire line, the
     87                     // expected line is absent, so it has no line number.
     88                     if (diff.text.endsWith("\n") || isLastDiff) {
     89                         lineNums.add(line.equals("") ? DONT_PRINT_LINE_NUMBER : i++);
     90                         lines.add(line);
     91                         line = "";
     92                     }
     93                     break;
     94 
     95                 case EQUAL:
     96                     line = processDiff(diff, lineNums, lines, line, i, eqlSpan, isLastDiff);
     97                     if (line.equals("")) {
     98                         i++;
     99                     }
    100                     break;
    101             }
    102         }
    103     }
    104 
    105     public static void generateActualResultLines(LinkedList<diff_match_patch.Diff> diffs,
    106             LinkedList<Integer> lineNums, LinkedList<String> lines) {
    107         String insSpan = "<span class=\"ins\">";
    108         String eqlSpan = "<span class=\"eql\">";
    109 
    110         String line = "";
    111         int i = 1;
    112         diff_match_patch.Diff diff;
    113         int size = diffs.size();
    114         boolean isLastDiff;
    115         for (int j = 0; j < size; j++) {
    116             diff = diffs.get(j);
    117             isLastDiff = j == size - 1;
    118             switch (diff.operation) {
    119                 case INSERT:
    120                     line = processDiff(diff, lineNums, lines, line, i, insSpan, isLastDiff);
    121                     if (line.equals("")) {
    122                         i++;
    123                     }
    124                     break;
    125 
    126                 case DELETE:
    127                     // If the line is currently empty and deletion is the entire line, the
    128                     // actual line is absent, so it has no line number.
    129                     if (diff.text.endsWith("\n") || isLastDiff) {
    130                         lineNums.add(line.equals("") ? DONT_PRINT_LINE_NUMBER : i++);
    131                         lines.add(line);
    132                         line = "";
    133                     }
    134                     break;
    135 
    136                 case EQUAL:
    137                     line = processDiff(diff, lineNums, lines, line, i, eqlSpan, isLastDiff);
    138                     if (line.equals("")) {
    139                         i++;
    140                     }
    141                     break;
    142             }
    143         }
    144     }
    145 
    146     /**
    147      * Generate or append a line for a given diff and add it to given collections if necessary.
    148      * It puts diffs in HTML spans.
    149      *
    150      * @param diff
    151      * @param lineNums
    152      * @param lines
    153      * @param line
    154      * @param i
    155      * @param begSpan
    156      * @param forceOutputLine Force the current line to be output
    157      * @return
    158      */
    159     public static String processDiff(diff_match_patch.Diff diff, LinkedList<Integer> lineNums,
    160             LinkedList<String> lines, String line, int i, String begSpan, boolean forceOutputLine) {
    161         String endSpan = "</span>";
    162         String br = "&nbsp;";
    163 
    164         if (diff.text.endsWith("\n") || forceOutputLine) {
    165             lineNums.add(i);
    166             /** TODO: Think of better way to replace stuff */
    167             line += begSpan + diff.text.replace("  ", "&nbsp;&nbsp;")
    168                     + endSpan + br;
    169             lines.add(line);
    170             line = "";
    171         } else {
    172             line += begSpan + diff.text.replace("  ", "&nbsp;&nbsp;") + endSpan;
    173         }
    174 
    175         return line;
    176     }
    177 
    178     public static String getHtml(LinkedList<Integer> lineNums1, LinkedList<String> lines1,
    179             LinkedList<Integer> lineNums2, LinkedList<String> lines2) {
    180         StringBuilder html = new StringBuilder();
    181         int lineNum;
    182         int size = lines1.size();
    183         for (int i = 0; i < size; i++) {
    184             html.append("<tr class=\"results\">");
    185 
    186             html.append("    <td class=\"line_count\">");
    187             lineNum = lineNums1.removeFirst();
    188             if (lineNum > 0) {
    189                 html.append(lineNum);
    190             }
    191             html.append("    </td>");
    192 
    193             html.append("    <td class=\"line\">");
    194             html.append(lines1.removeFirst());
    195             html.append("    </td>");
    196 
    197             html.append("    <td class=\"space\"></td>");
    198 
    199             html.append("    <td class=\"line_count\">");
    200             lineNum = lineNums2.removeFirst();
    201             if (lineNum > 0) {
    202                 html.append(lineNum);
    203             }
    204             html.append("    </td>");
    205 
    206             html.append("    <td class=\"line\">");
    207             html.append(lines2.removeFirst());
    208             html.append("    </td>");
    209 
    210             html.append("</tr>");
    211         }
    212         return html.toString();
    213     }
    214 }
    215