diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/filemove/MatchesByScore.java b/server/sonar-server/src/main/java/org/sonar/server/computation/filemove/MatchesByScore.java index 35852ac9ee85..69cde753d2a9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/filemove/MatchesByScore.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/filemove/MatchesByScore.java @@ -21,56 +21,81 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; import java.util.List; import static org.sonar.server.computation.filemove.FileMoveDetectionStep.MIN_REQUIRED_SCORE; -class MatchesByScore implements ScoreMatrix.ScoreMatrixVisitor, Iterable> { - private final ScoreMatrix scoreMatrix; - private final List[] matches; - private int totalMatches = 0; - - private MatchesByScore(ScoreMatrix scoreMatrix) { - this.scoreMatrix = scoreMatrix; - this.matches = new List[Math.max(MIN_REQUIRED_SCORE, scoreMatrix.getMaxScore()) - MIN_REQUIRED_SCORE]; - } +abstract class MatchesByScore implements Iterable> { public static MatchesByScore create(ScoreMatrix scoreMatrix) { - MatchesByScore res = new MatchesByScore(scoreMatrix); + if (scoreMatrix.getMaxScore() < MIN_REQUIRED_SCORE) { + return EmptyMatchesByScore.INSTANCE; + } + MatchesByScoreImpl res = new MatchesByScoreImpl(scoreMatrix); res.populate(); return res; } - private void populate() { - scoreMatrix.accept(this); - } + public abstract int getSize(); + + private static final class MatchesByScoreImpl extends MatchesByScore implements ScoreMatrix.ScoreMatrixVisitor { + private final ScoreMatrix scoreMatrix; + private final List[] matches; + private int totalMatches = 0; - @Override - public void visit(String dbFileKey, String reportFileKey, int score) { - if (!isAcceptableScore(score)) { - return; + private MatchesByScoreImpl(ScoreMatrix scoreMatrix) { + this.scoreMatrix = scoreMatrix; + this.matches = new List[scoreMatrix.getMaxScore() - MIN_REQUIRED_SCORE + 1]; } - int index = score - MIN_REQUIRED_SCORE - 1; - if (matches[index] == null) { - matches[index] = new ArrayList<>(1); + private void populate() { + scoreMatrix.accept(this); + } + + @Override + public void visit(String dbFileKey, String reportFileKey, int score) { + if (!isAcceptableScore(score)) { + return; + } + + int index = score - MIN_REQUIRED_SCORE; + if (matches[index] == null) { + matches[index] = new ArrayList<>(1); + } + Match match = new Match(dbFileKey, reportFileKey); + matches[index].add(match); + totalMatches++; } - Match match = new Match(dbFileKey, reportFileKey); - matches[index].add(match); - totalMatches++; - } - private static boolean isAcceptableScore(int score) { - return score >= MIN_REQUIRED_SCORE; - } - public int getSize() { - return totalMatches; + private static boolean isAcceptableScore(int score) { + return score >= MIN_REQUIRED_SCORE; + } + + @Override + public int getSize() { + return totalMatches; + } + + @Override + public Iterator> iterator() { + return Arrays.asList(matches).iterator(); + } } - @Override - public Iterator> iterator() { - return Arrays.asList(matches).iterator(); + private static class EmptyMatchesByScore extends MatchesByScore { + private static final EmptyMatchesByScore INSTANCE = new EmptyMatchesByScore(); + + @Override + public int getSize() { + return 0; + } + + @Override + public Iterator> iterator() { + return Collections.>emptyList().iterator(); + } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/filemove/MatchesByScoreTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/filemove/MatchesByScoreTest.java new file mode 100644 index 000000000000..415bdb971882 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/filemove/MatchesByScoreTest.java @@ -0,0 +1,83 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.server.computation.filemove; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.junit.Test; + +import static com.google.common.collect.ImmutableSet.of; +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.computation.filemove.FileMoveDetectionStep.MIN_REQUIRED_SCORE; + +public class MatchesByScoreTest { + + private static final List NO_MATCH = null; + + @Test + public void creates_returns_always_the_same_instance_of_maxScore_is_less_than_min_required_score() { + Set doesNotMatterDbFileKeys = Collections.emptySet(); + Map doesNotMatterReportFiles = Collections.emptyMap(); + int[][] doesNotMatterScores = new int[0][0]; + + ScoreMatrix scoreMatrix1 = new ScoreMatrix(doesNotMatterDbFileKeys, doesNotMatterReportFiles, doesNotMatterScores, MIN_REQUIRED_SCORE - 1); + MatchesByScore matchesByScore = MatchesByScore.create(scoreMatrix1); + + assertThat(matchesByScore.getSize()).isEqualTo(0); + assertThat(matchesByScore).isEmpty(); + + ScoreMatrix scoreMatrix2 = new ScoreMatrix(doesNotMatterDbFileKeys, doesNotMatterReportFiles, doesNotMatterScores, MIN_REQUIRED_SCORE - 5); + assertThat(MatchesByScore.create(scoreMatrix2)).isSameAs(matchesByScore); + } + + @Test + public void creates_supports_score_with_same_value_as_min_required_score() { + int maxScore = 92; + int[][] scores = { + {maxScore}, + {8}, + {85}, + }; + MatchesByScore matchesByScore = MatchesByScore.create(new ScoreMatrix( + of("A", "B", "C"), ImmutableMap.of("1", fileOf("1")), scores, maxScore)); + + assertThat(matchesByScore.getSize()).isEqualTo(2); + assertThat(Lists.newArrayList(matchesByScore)).isEqualTo(Arrays.asList( + ImmutableList.of(new Match("C", "1")), // 85 + NO_MATCH, + NO_MATCH, + NO_MATCH, + NO_MATCH, + NO_MATCH, + NO_MATCH, + ImmutableList.of(new Match("A", "1")) // 92 + )); + } + + private static FileSimilarity.File fileOf(String key) { + return new FileSimilarity.File("path of " + key, null, null); + } +}