org.conqat.lib.commons.diff.RegionDiffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teamscale-lib-commons Show documentation
Show all versions of teamscale-lib-commons Show documentation
Provides common utility functions
/*
* Copyright (c) CQSE GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conqat.lib.commons.diff;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.conqat.lib.commons.region.Region;
import org.conqat.lib.commons.string.LineOffsetConverter;
/**
* Class for calculating diff based on given regions.
*/
public class RegionDiffer extends DifferBase {
/**
* Pattern used to parse region. See {@link #RegionDiffer(String)} for details.
*/
private static final Pattern REGION_PATTERN = Pattern.compile("(\\d+)-(\\d+):(\\d+)-(\\d+)");
/** The region in the left element. */
private final Region leftRegion;
/** The region in the right element. */
private final Region rightRegion;
/**
* Constructor.
*
* @param regionDescription
* description of the regions as a string, formatted as
* "leftStart-leftEnd:rightStart-rightEnd", where all are one-based inclusive line
* numbers.
* @throws IllegalArgumentException
* if the regionDescription does not follow the required format.
*/
public RegionDiffer(String regionDescription) throws IllegalArgumentException {
Matcher matcher = REGION_PATTERN.matcher(regionDescription);
if (!matcher.matches()) {
throw new IllegalArgumentException("Invalid region description: " + regionDescription);
}
try {
leftRegion = new Region(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)));
rightRegion = new Region(Integer.parseInt(matcher.group(3)), Integer.parseInt(matcher.group(4)));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid region description: " + regionDescription);
}
}
/** {@inheritDoc} */
@Override
protected String getElementText(String element) {
return element;
}
/** {@inheritDoc} */
@Override
protected String getDiffName() {
return "region-based";
}
/**
* This method return only three chunks. One for the text before the given region, the given region,
* and the text after. The comparison text is chosen such that the diff will be in the given region.
*/
@Override
protected List getChunks(String elementText, boolean isLeft) {
Region region = leftRegion;
if (!isLeft) {
region = rightRegion;
}
LineOffsetConverter converter = new LineOffsetConverter(elementText);
List result = new ArrayList<>();
// both pre-regions get the same comparison text, hence are mapped to
// each other
result.add(new TextChunk(0, converter.getOffset(region.getStart()), 1, region.getStart(), "pre"));
// both main regions get different comparison text, hence are detected
// as change
result.add(new TextChunk(converter.getOffset(region.getStart()), converter.getOffset(region.getEnd() + 1),
region.getStart(), region.getEnd() + 1, "content" + isLeft));
// both post-regions get the same comparison text, hence are mapped to
// each other
result.add(new TextChunk(converter.getOffset(region.getEnd() + 1), elementText.length(), region.getEnd() + 1,
converter.getLine(elementText.length()) + 1, "post"));
return result;
}
}