/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.duplications.detector; import java.util.Comparator; import org.sonar.duplications.index.ClonePart; import org.sonar.duplications.utils.FastStringComparator; /** * Allows to determine if ClonePart includes another ClonePart. * Inclusion is the partial order, so in fact this class violates contracts of {@link Comparator}, * however it allows to use {@link org.sonar.duplications.utils.SortedListsUtils} for efficient filtering. */ public final class ContainsInComparator implements Comparator<ClonePart> { /** * Defines order by resourceId. */ public static final Comparator<ClonePart> RESOURCE_ID_COMPARATOR = new Comparator<ClonePart>() { @Override public int compare(ClonePart o1, ClonePart o2) { return FastStringComparator.INSTANCE.compare(o1.getResourceId(), o2.getResourceId()); } }; /** * Defines order by resourceId and by unitStart. */ public static final Comparator<ClonePart> CLONEPART_COMPARATOR = new Comparator<ClonePart>() { @Override public int compare(ClonePart o1, ClonePart o2) { int c = RESOURCE_ID_COMPARATOR.compare(o1, o2); if (c == 0) { return o1.getUnitStart() - o2.getUnitStart(); } return c; } }; private final int l1; private final int l2; /** * Constructs new comparator for two parts with lengths {@code l1} and {@code l2} respectively. */ public ContainsInComparator(int l1, int l2) { this.l1 = l1; this.l2 = l2; } /** * Compares two parts on inclusion. * part1 includes part2 if {@code (part1.resourceId == part2.resourceId) && (part1.unitStart <= part2.unitStart) && (part2.unitEnd <= part1.unitEnd)}. * * @return 0 if part1 includes part2, * 1 if resourceId of part1 is greater than resourceId of part2 or if unitStart of part1 is greater than unitStart of part2, * -1 in all other cases */ @Override public int compare(ClonePart part1, ClonePart part2) { int c = RESOURCE_ID_COMPARATOR.compare(part1, part2); if (c == 0) { if (part1.getUnitStart() <= part2.getUnitStart()) { if (part2.getUnitStart() + l2 <= part1.getUnitStart() + l1) { // part1 contains part2 return 0; } else { // SortedListsUtils#contains should continue search return -1; } } else { // unitStart of part1 is less than unitStart of part2 - SortedListsUtils#contains should stop search return 1; } } else { return c; } } }