001/*-----------------------------------------------------------------------+ 002 | com.teamscale.ui 003 | | 004 $Id$ 005 | | 006 | Copyright (c) 2009-2013 CQSE GmbH | 007 +-----------------------------------------------------------------------*/ 008package org.conqat.lib.commons.diff; 009 010import java.util.ArrayList; 011import java.util.List; 012 013import org.conqat.lib.commons.string.StringUtils; 014 015/** 016 * Class for calculating a line-based diff. 017 */ 018public class LineBasedDiffer extends DifferBase<String> { 019 020 /** Whether to ignore whitespace in each line. */ 021 private final boolean ignoreWhitespace; 022 023 /** Constructor. */ 024 public LineBasedDiffer(boolean ignoreWhitespace) { 025 this.ignoreWhitespace = ignoreWhitespace; 026 } 027 028 /** {@inheritDoc} */ 029 @Override 030 protected String getElementText(String element) { 031 return element; 032 } 033 034 /** {@inheritDoc} */ 035 @Override 036 protected String getDiffName() { 037 String diffName = "line-based"; 038 if (ignoreWhitespace) { 039 diffName += " (ignore whitespace)"; 040 } 041 return diffName; 042 } 043 044 /** {@inheritDoc} */ 045 @Override 046 protected List<TextChunk> getChunks(String elementText, boolean isLeft) { 047 List<String> lines = StringUtils.splitLinesAsList(elementText); 048 049 List<TextChunk> result = new ArrayList<TextChunk>(); 050 int offset = 0; 051 int lineNumber = 1; 052 for (String line : lines) { 053 result.add(createChunkForLine(offset, lineNumber, line)); 054 offset += line.length() + 1; 055 lineNumber += 1; 056 } 057 return result; 058 } 059 060 /** Creates a chunk for a single line of the element. */ 061 private TextChunk createChunkForLine(int offset, int lineNumber, String line) { 062 int startOffset = offset; 063 int endOffset = startOffset + line.length(); 064 String comparisonText = line; 065 066 if (ignoreWhitespace) { 067 comparisonText = line.replaceFirst("^\\s+", StringUtils.EMPTY_STRING); 068 int removed = endOffset - startOffset - comparisonText.length(); 069 070 startOffset += removed; 071 072 comparisonText = line.replaceFirst("\\s+$", StringUtils.EMPTY_STRING); 073 removed = endOffset - startOffset - comparisonText.length(); 074 endOffset -= removed; 075 076 comparisonText = comparisonText.replaceAll("\\s+", StringUtils.EMPTY_STRING); 077 } 078 079 return new TextChunk(startOffset, endOffset, lineNumber, lineNumber + 1, comparisonText); 080 } 081}