All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fitnesse.testsystems.slim.HtmlDiffUtil Maven / Gradle / Ivy

There is a newer version: 20250223
Show newest version
package fitnesse.testsystems.slim;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import difflib.Chunk;
import difflib.Delta;
import difflib.DiffUtils;
import difflib.Patch;
import fitnesse.html.HtmlUtil;

public class HtmlDiffUtil {

  public abstract static class Builder {
    protected List text;
    protected final Patch patch;
    protected final StringBuilder stringBuilder = new StringBuilder();
    protected boolean isInDiffArea = false;
    protected String openingTag = "";
    protected String closingTag = "";

    protected Builder(final String actual, final String expected) {
      this.patch = DiffUtils.diff(stringToCharacterList(actual),
          stringToCharacterList(expected));
    }

    public Builder setOpeningTag(final String openingTag) {
      this.openingTag = openingTag;
      return this;
    }

    public Builder setClosingTag(final String closingTag) {
      this.closingTag = closingTag;
      return this;
    }

    public String build() {
      for (int i = 0; i < getText().size(); i++) {
        addElementToStringBuilder(i);
      }
      return stringBuilder.toString();
    }

    protected abstract Chunk getChunk(Delta d);

    private void addElementToStringBuilder(final int i) {
      Delta delta = getDeltaByIndex(i, patch);
      addOpeningTagIfDeltaAtFirstElement(i, delta);
      addTagIfDeltaSwitching(delta);
      addCharacterFromDeltaOrText(i, delta);
      addClosingTagIfDeltaAtLastElement(i, delta);
    }

    private void addCharacterFromDeltaOrText(final int i,
        final Delta delta) {
      if (delta == null) {
        stringBuilder.append(HtmlUtil.escapeHTML(getText().get(i).toString()));
      } else {
        stringBuilder.append(HtmlUtil
            .escapeHTML(getFromChunkByIndex(getChunk(delta), i).toString()));
      }
    }

    private void addTagIfDeltaSwitching(final Delta delta) {
      if (delta == null) {
        if (isInDiffArea) {
          addClosingTag();
        }
      } else {
        if (!isInDiffArea) {
          addOpeningTag();
        }
      }
    }

    private void addClosingTagIfDeltaAtLastElement(final int i,
        final Delta delta) {
      if (delta != null && isLastElement(i)) {
        addClosingTag();
      }
    }

    private void addClosingTag() {
      isInDiffArea = false;
      stringBuilder.append(closingTag);
    }

    private void addOpeningTagIfDeltaAtFirstElement(final int i,
        final Delta delta) {
      if (delta != null && isFirstElement(i)) {
        addOpeningTag();
      }
    }

    private void addOpeningTag() {
      isInDiffArea = true;
      stringBuilder.append(openingTag);
    }

    private Delta getDeltaByIndex(final int i,
        final Patch patch) {
      for (Delta delta : patch.getDeltas()) {
        if (isInChunk(getChunk(delta), i)) {
          return delta;
        }
      }
      return null;
    }

    private boolean isInChunk(final Chunk chunk, final int i) {
      return i >= chunk.getPosition() && i < chunk.getPosition() + chunk.size();
    }

    private Character getFromChunkByIndex(final Chunk chunk,
        final int i) {
      int j = i - chunk.getPosition();
      return chunk.getLines().get(j);
    }

    private List getText() {
      return text;
    }

    private boolean isFirstElement(final int i) {
      return i == 0;
    }

    private boolean isLastElement(final int i) {
      return i == getText().size() - 1;
    }

    protected List stringToCharacterList(final String s) {
      if (s == null || s.isEmpty()) {
        return Collections. emptyList();
      }
      List characterList = new ArrayList<>(s.length());
      for (char c : s.toCharArray()) {
        characterList.add(c);
      }
      return characterList;
    }

  }

  public static class ActualBuilder extends Builder {

    public ActualBuilder(final String actual, final String expected) {
      super(actual, expected);
      text = stringToCharacterList(actual);
    }

    @Override
    protected Chunk getChunk(final Delta d) {
      return d.getOriginal();
    }

  }

  public static class ExpectedBuilder extends Builder {

    public ExpectedBuilder(final String actual, final String expected) {
      super(actual, expected);
      text = stringToCharacterList(expected);
    }

    @Override
    protected Chunk getChunk(final Delta d) {
      return d.getRevised();
    }

  }

  /**
   * Conveniencemethod.
   *
   * @param actual
   * @param expected
   * @return
   */
  public static String buildActual(final String actual, final String expected) {
    return new ActualBuilder(actual, expected).build();
  }

  /**
   * Conveniencemethod.
   *
   * @param actual
   * @param expected
   * @return
   */
  public static String buildExpected(final String actual,
      final String expected) {
    return new ExpectedBuilder(actual, expected).build();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy