Esempio n. 1
0
 /**
  * Convert a Difference list into a pretty HTML report.
  *
  * @param diffs List of Difference objects
  * @return HTML representation
  */
 public String prettyHtml(List<Difference> diffs) {
   StringBuilder buf = new StringBuilder();
   for (int x = 0; x < diffs.size(); x++) {
     Difference diff = diffs.get(x);
     EditType editType = diff.getEditType(); // Mode (delete, equal,
     // insert)
     String text = diff.getText(); // Text of change.
     // TODO(DMS): Do replacements
     // text = text.replace(/&/g, "&amp;");
     // text = text.replace(/</g, "&lt;");
     // text = text.replace(/>/g, "&gt;");
     // text = text.replace(/\n/g, "&para;<BR>");
     if (EditType.DELETE.equals(editType)) {
       buf.append("<del style=\"background:#FFE6E6;\">");
       buf.append(text);
       buf.append("</del>");
     } else if (EditType.INSERT.equals(editType)) {
       buf.append("<ins style=\"background:#E6FFE6;\">");
       buf.append(text);
       buf.append("</ins>");
     } else {
       buf.append("<span>");
       buf.append(text);
       buf.append("</span>");
     }
   }
   return buf.toString();
 }
Esempio n. 2
0
  /**
   * loc is a location in source, compute and return the equivalent location in target. e.g. "The
   * cat" vs "The big cat", 1->1, 5->8
   *
   * @param diffs List of Difference objects
   * @param loc Location within source
   * @return Location within target
   */
  public int xIndex(final List<Difference> diffs, final int loc) {
    int chars1 = 0;
    int chars2 = 0;
    int lastChars1 = 0;
    int lastChars2 = 0;
    Difference lastDiff = null;
    for (Difference diff : diffs) {
      EditType editType = diff.getEditType();

      // Equality or deletion?
      if (!EditType.INSERT.equals(editType)) {
        chars1 += diff.getText().length();
      }

      // Equality or insertion?
      if (!EditType.DELETE.equals(editType)) {
        chars2 += diff.getText().length();
      }

      // Overshot the location?
      if (chars1 > loc) {
        lastDiff = diff;
        break;
      }
      lastChars1 = chars1;
      lastChars2 = chars2;
    }

    // Was the location was deleted?
    if (lastDiff != null && EditType.DELETE.equals(lastDiff.getEditType())) {
      return lastChars2;
    }

    // Add the remaining character length.
    return lastChars2 + (loc - lastChars1);
  }
Esempio n. 3
0
  /**
   * Find the differences between two texts.
   *
   * @return List of Difference objects
   */
  private List<Difference> compute() {
    List<Difference> diffs = new ArrayList<Difference>();

    if ("".equals(source)) {
      // Just add some text (speedup)
      diffs.add(new Difference(EditType.INSERT, target));
      return diffs;
    }

    if ("".equals(target)) {
      // Just delete some text (speedup)
      diffs.add(new Difference(EditType.DELETE, source));
      return diffs;
    }

    String longText = source.length() > target.length() ? source : target;
    String shortText = source.length() > target.length() ? target : source;
    int i = longText.indexOf(shortText);
    if (i != -1) {
      // Shorter text is inside the longer text (speedup)
      EditType editType = (source.length() > target.length()) ? EditType.DELETE : EditType.INSERT;
      diffs.add(new Difference(editType, longText.substring(0, i)));
      diffs.add(new Difference(EditType.EQUAL, shortText));
      diffs.add(new Difference(editType, longText.substring(i + shortText.length())));
      return diffs;
    }

    // Check to see if the problem can be split in two.
    CommonMiddle middleMatch = Commonality.halfMatch(source, target);
    if (middleMatch != null) {
      // A half-match was found, sort out the return data.
      // Send both pairs off for separate processing.
      Diff startDiff =
          new Diff(middleMatch.getSourcePrefix(), middleMatch.getTargetPrefix(), checkLines);
      Diff endDiff =
          new Diff(middleMatch.getSourceSuffix(), middleMatch.getTargetSuffix(), checkLines);
      // Merge the results.
      diffs = startDiff.compare();
      diffs.add(new Difference(EditType.EQUAL, middleMatch.getCommonality()));
      diffs.addAll(endDiff.compare());
      return diffs;
    }

    // Perform a real diff.
    if (checkLines && source.length() + target.length() < 250) {
      checkLines = false; // Too trivial for the overhead.
    }

    LineMap lineMap = null;
    if (checkLines) {
      // Scan the text on a line-by-line basis first.
      lineMap = new LineMap(source, target);
      source = lineMap.getSourceMap();
      target = lineMap.getTargetMap();
    }

    diffs = new DifferenceEngine(source, target).generate();

    if (diffs == null) {
      // No acceptable result.
      diffs = new ArrayList<Difference>();
      diffs.add(new Difference(EditType.DELETE, source));
      diffs.add(new Difference(EditType.INSERT, target));
    }

    if (checkLines && lineMap != null) {
      // Convert the diff back to original text.
      lineMap.restore(diffs);
      // Eliminate freak matches (e.g. blank lines)
      DiffCleanup.cleanupSemantic(diffs);

      // Rediff any replacement blocks, this time character-by-character.
      // Add a dummy entry at the end.
      diffs.add(new Difference(EditType.EQUAL, ""));
      int countDeletes = 0;
      int countInserts = 0;
      StringBuilder textDelete = new StringBuilder();
      StringBuilder textInsert = new StringBuilder();
      ListIterator<Difference> pointer = diffs.listIterator();
      Difference curDiff = pointer.next();
      while (curDiff != null) {
        EditType editType = curDiff.getEditType();
        if (EditType.INSERT.equals(editType)) {
          countInserts++;
          textInsert.append(curDiff.getText());
        } else if (EditType.DELETE.equals(editType)) {
          countDeletes++;
          textDelete.append(curDiff.getText());
        } else {
          // Upon reaching an equality, check for prior redundancies.
          if (countDeletes >= 1 && countInserts >= 1) {
            // Delete the offending records and add the merged ones.
            pointer.previous();
            for (int j = 0; j < countDeletes + countInserts; j++) {
              pointer.previous();
              pointer.remove();
            }
            Diff newDiff = new Diff(textDelete.toString(), textInsert.toString(), false);
            for (Difference diff : newDiff.compare()) {
              pointer.add(diff);
            }
          }
          countInserts = 0;
          countDeletes = 0;
          textDelete.delete(0, textDelete.length());
          textInsert.delete(0, textInsert.length());
        }
        curDiff = pointer.hasNext() ? pointer.next() : null;
      }
      diffs.remove(diffs.size() - 1); // Remove the dummy entry at the
      // end.
    }
    return diffs;
  }