]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3755 move and delete some classes related to issues
authorSimon Brandhof <simon.brandhof@gmail.com>
Mon, 27 May 2013 20:01:34 +0000 (22:01 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Mon, 27 May 2013 20:17:38 +0000 (22:17 +0200)
49 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/HashedSequence.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/HashedSequenceComparator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingHashSequence.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingHashSequenceComparator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/Sequence.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/SequenceComparator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/SourceChecksum.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/StringText.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/StringTextComparator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/ViolationTrackingBlocksRecognizer.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/package-info.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/SourceChecksum.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationTrackingBlocksRecognizer.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/HashedSequence.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/HashedSequenceComparator.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequence.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequenceComparator.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/Sequence.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/SequenceComparator.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/StringText.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/StringTextComparator.java [deleted file]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/package-info.java [deleted file]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/RollingHashSequenceTest.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/SourceChecksumTest.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/StringTextComparatorTest.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/StringTextTest.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/ViolationTrackingBlocksRecognizerTest.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/SourceChecksumTest.java [deleted file]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/ViolationTrackingBlocksRecognizerTest.java [deleted file]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequenceTest.java [deleted file]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/StringTextComparatorTest.java [deleted file]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/StringTextTest.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
sonar-batch/src/main/java/org/sonar/batch/report/SonarReport.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/test/java/org/sonar/batch/report/SonarReportTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/review/ReviewDto.java [deleted file]
sonar-core/src/main/java/org/sonar/core/workflow/ImmutableReview.java [deleted file]
sonar-core/src/main/java/org/sonar/core/workflow/ReviewStore.java [deleted file]
sonar-core/src/main/java/org/sonar/core/workflow/WorkflowEngine.java [deleted file]
sonar-core/src/main/java/org/sonar/core/workflow/package-info.java [deleted file]
sonar-core/src/test/java/org/sonar/core/workflow/WorkflowEngineTest.java [deleted file]
sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java [deleted file]
sonar-server/src/main/java/org/sonar/server/platform/Platform.java
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java [deleted file]

index 1a02b7fe8005b2830c4e5f4c370748726e5cbd2f..a95d97136065fd1017c4be1aeecb58bfb5724a71 100644 (file)
@@ -33,9 +33,9 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.batch.scan.LastSnapshots;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.issue.db.IssueDto;
-import org.sonar.plugins.core.timemachine.SourceChecksum;
-import org.sonar.plugins.core.timemachine.ViolationTrackingBlocksRecognizer;
-import org.sonar.plugins.core.timemachine.tracking.*;
+import org.sonar.plugins.core.issue.tracking.*;
+import org.sonar.plugins.core.issue.tracking.SourceChecksum;
+import org.sonar.plugins.core.issue.tracking.ViolationTrackingBlocksRecognizer;
 
 import javax.annotation.Nullable;
 import java.util.*;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/HashedSequence.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/HashedSequence.java
new file mode 100644 (file)
index 0000000..4edb4a8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Wraps a {@link Sequence} to assign hash codes to elements.
+ */
+public final class HashedSequence<S extends Sequence> implements Sequence {
+
+  final S base;
+  final int[] hashes;
+
+  public static <S extends Sequence> HashedSequence<S> wrap(S base, SequenceComparator<S> cmp) {
+    int size = base.length();
+    int[] hashes = new int[size];
+    for (int i = 0; i < size; i++) {
+      hashes[i] = cmp.hash(base, i);
+    }
+    return new HashedSequence<S>(base, hashes);
+  }
+
+  private HashedSequence(S base, int[] hashes) {
+    this.base = base;
+    this.hashes = hashes;
+  }
+
+  public int length() {
+    return base.length();
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/HashedSequenceComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/HashedSequenceComparator.java
new file mode 100644 (file)
index 0000000..9a8ec34
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Wrap another {@link SequenceComparator} for use with {@link HashedSequence}.
+ */
+public class HashedSequenceComparator<S extends Sequence> implements SequenceComparator<HashedSequence<S>> {
+
+  private final SequenceComparator<? super S> cmp;
+
+  public HashedSequenceComparator(SequenceComparator<? super S> cmp) {
+    this.cmp = cmp;
+  }
+
+  public boolean equals(HashedSequence<S> a, int ai, HashedSequence<S> b, int bi) {
+    if (a.hashes[ai] == b.hashes[bi]) {
+      return cmp.equals(a.base, ai, b.base, bi);
+    }
+    return false;
+  }
+
+  public int hash(HashedSequence<S> seq, int i) {
+    return seq.hashes[i];
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingHashSequence.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingHashSequence.java
new file mode 100644 (file)
index 0000000..f82830d
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Wraps a {@link Sequence} to assign hash codes to elements.
+ */
+public class RollingHashSequence<S extends Sequence> implements Sequence {
+
+  final S base;
+  final int[] hashes;
+
+  public static <S extends Sequence> RollingHashSequence<S> wrap(S base, SequenceComparator<S> cmp, int lines) {
+    int size = base.length();
+    int[] hashes = new int[size];
+
+    RollingHashCalculator hashCalulator = new RollingHashCalculator(lines * 2 + 1);
+    for (int i = 0; i <= Math.min(size - 1, lines); i++) {
+      hashCalulator.add(cmp.hash(base, i));
+    }
+    for (int i = 0; i < size; i++) {
+      hashes[i] = hashCalulator.getHash();
+      if (i - lines >= 0) {
+        hashCalulator.remove(cmp.hash(base, i - lines));
+      }
+      if (i + lines + 1 < size) {
+        hashCalulator.add(cmp.hash(base, i + lines + 1));
+      } else {
+        hashCalulator.add(0);
+      }
+    }
+
+    return new RollingHashSequence<S>(base, hashes);
+  }
+
+  private RollingHashSequence(S base, int[] hashes) {
+    this.base = base;
+    this.hashes = hashes;
+  }
+
+  public int length() {
+    return base.length();
+  }
+
+  private static class RollingHashCalculator {
+
+    private static final int PRIME_BASE = 31;
+
+    private final int power;
+    private int hash;
+
+    public RollingHashCalculator(int size) {
+      int pow = 1;
+      for (int i = 0; i < size - 1; i++) {
+        pow = pow * PRIME_BASE;
+      }
+      this.power = pow;
+    }
+
+    public void add(int value) {
+      hash = hash * PRIME_BASE + value;
+    }
+
+    public void remove(int value) {
+      hash = hash - power * value;
+    }
+
+    public int getHash() {
+      return hash;
+    }
+
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingHashSequenceComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingHashSequenceComparator.java
new file mode 100644 (file)
index 0000000..89d551e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Wrap another {@link SequenceComparator} for use with {@link RollingHashSequence}.
+ */
+public class RollingHashSequenceComparator<S extends Sequence> implements SequenceComparator<RollingHashSequence<S>> {
+
+  private final SequenceComparator<? super S> cmp;
+
+  public RollingHashSequenceComparator(SequenceComparator<? super S> cmp) {
+    this.cmp = cmp;
+  }
+
+  public boolean equals(RollingHashSequence<S> a, int ai, RollingHashSequence<S> b, int bi) {
+    if (a.hashes[ai] == b.hashes[bi]) {
+      return cmp.equals(a.base, ai, b.base, bi);
+    }
+    return false;
+  }
+
+  public int hash(RollingHashSequence<S> seq, int i) {
+    return seq.hashes[i];
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/Sequence.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/Sequence.java
new file mode 100644 (file)
index 0000000..9b506ab
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Arbitrary sequence of elements.
+ */
+public interface Sequence {
+
+  /**
+   * @return total number of items in the sequence
+   */
+  int length();
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/SequenceComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/SequenceComparator.java
new file mode 100644 (file)
index 0000000..d08ff4b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Equivalence function for a {@link Sequence}.
+ */
+public interface SequenceComparator<S extends Sequence> {
+
+  /**
+   * Compare two items to determine if they are equivalent.
+   */
+  boolean equals(S a, int ai, S b, int bi);
+
+  /**
+   * Get a hash value for an item in a sequence.
+   *
+   * If two items are equal according to this comparator's
+   * {@link #equals(Sequence, int, Sequence, int)} method,
+   * then this hash method must produce the same integer result for both items.
+   * However not required to have different hash values for different items.
+   */
+  int hash(S seq, int i);
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/SourceChecksum.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/SourceChecksum.java
new file mode 100644 (file)
index 0000000..b797bf4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.List;
+
+public final class SourceChecksum {
+
+  private static final String SPACE_CHARS = "\t\n\r ";
+
+  private SourceChecksum() {
+    // only static methods
+  }
+
+  /**
+   * @param line line number (first line has number 1)
+   * @return checksum or null if checksum not exists for line
+   */
+  public static String getChecksumForLine(List<String> checksums, Integer line) {
+    if (line == null || line < 1 || line > checksums.size()) {
+      return null;
+    }
+    return checksums.get(line - 1);
+  }
+
+  public static List<String> lineChecksumsOfFile(String file) {
+    List<String> result = Lists.newArrayList();
+    if (file != null) {
+      String[] lines = file.split("\r?\n|\r", -1);
+      for (String line : lines) {
+        result.add(lineChecksum(line));
+      }
+    }
+    return result;
+  }
+
+  public static String lineChecksum(String line) {
+    String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");
+    return DigestUtils.md5Hex(reducedLine);
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/StringText.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/StringText.java
new file mode 100644 (file)
index 0000000..ea59d21
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+/**
+ * Text is a {@link Sequence} of lines.
+ */
+public class StringText implements Sequence {
+
+  final String content;
+
+  /**
+   * Map of line number to starting position within {@link #content}.
+   */
+  final List<Integer> lines;
+
+  public StringText(String str) {
+    this.content = str;
+    this.lines = lineMap(content, 0, content.length());
+  }
+
+  public int length() {
+    return lines.size() - 2;
+  }
+
+  private static List<Integer> lineMap(String buf, int ptr, int end) {
+    List<Integer> lines = Lists.newArrayList();
+    lines.add(Integer.MIN_VALUE);
+    for (; ptr < end; ptr = nextLF(buf, ptr)) {
+      lines.add(ptr);
+    }
+    lines.add(end);
+    return lines;
+  }
+
+  private static int nextLF(String b, int ptr) {
+    return next(b, ptr, '\n');
+  }
+
+  private static int next(final String b, int ptr, final char chrA) {
+    final int sz = b.length();
+    while (ptr < sz) {
+      if (b.charAt(ptr++) == chrA) {
+        return ptr;
+      }
+    }
+    return ptr;
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/StringTextComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/StringTextComparator.java
new file mode 100644 (file)
index 0000000..e39488b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+/**
+ * Equivalence function for {@link StringText}.
+ */
+public abstract class StringTextComparator implements SequenceComparator<StringText> {
+
+  /**
+   * Ignores all whitespace.
+   */
+  public static final StringTextComparator IGNORE_WHITESPACE = new StringTextComparator() {
+
+    public boolean equals(StringText a, int ai, StringText b, int bi) {
+      ai++;
+      bi++;
+      int as = a.lines.get(ai);
+      int bs = b.lines.get(bi);
+      int ae = a.lines.get(ai + 1);
+      int be = b.lines.get(bi + 1);
+      ae = trimTrailingWhitespace(a.content, as, ae);
+      be = trimTrailingWhitespace(b.content, bs, be);
+      while ((as < ae) && (bs < be)) {
+        char ac = a.content.charAt(as);
+        char bc = b.content.charAt(bs);
+        while ((as < ae - 1) && (Character.isWhitespace(ac))) {
+          as++;
+          ac = a.content.charAt(as);
+        }
+        while ((bs < be - 1) && (Character.isWhitespace(bc))) {
+          bs++;
+          bc = b.content.charAt(bs);
+        }
+        if (ac != bc) {
+          return false;
+        }
+        as++;
+        bs++;
+      }
+      return (as == ae) && (bs == be);
+    }
+
+    @Override
+    protected int hashRegion(String content, int start, int end) {
+      int hash = 5381;
+      for (; start < end; start++) {
+        char c = content.charAt(start);
+        if (!Character.isWhitespace(c)) {
+          hash = ((hash << 5) + hash) + (c & 0xff);
+        }
+      }
+      return hash;
+    }
+
+  };
+
+  public int hash(StringText seq, int line) {
+    final int begin = seq.lines.get(line + 1);
+    final int end = seq.lines.get(line + 2);
+    return hashRegion(seq.content, begin, end);
+  }
+
+  protected abstract int hashRegion(String content, int start, int end);
+
+  public static int trimTrailingWhitespace(String content, int start, int end) {
+    end--;
+    while (start <= end && Character.isWhitespace(content.charAt(end))) {
+      end--;
+    }
+    return end + 1;
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/ViolationTrackingBlocksRecognizer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/ViolationTrackingBlocksRecognizer.java
new file mode 100644 (file)
index 0000000..b196588
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.sonar.plugins.core.issue.tracking.HashedSequence;
+import org.sonar.plugins.core.issue.tracking.HashedSequenceComparator;
+import org.sonar.plugins.core.issue.tracking.StringText;
+import org.sonar.plugins.core.issue.tracking.StringTextComparator;
+
+public class ViolationTrackingBlocksRecognizer {
+
+  private final HashedSequence<StringText> a;
+  private final HashedSequence<StringText> b;
+  private final HashedSequenceComparator<StringText> cmp;
+
+  @VisibleForTesting
+  public ViolationTrackingBlocksRecognizer(String referenceSource, String source) {
+    this.a = HashedSequence.wrap(new StringText(referenceSource), StringTextComparator.IGNORE_WHITESPACE);
+    this.b = HashedSequence.wrap(new StringText(source), StringTextComparator.IGNORE_WHITESPACE);
+    this.cmp = new HashedSequenceComparator<StringText>(StringTextComparator.IGNORE_WHITESPACE);
+  }
+
+  public ViolationTrackingBlocksRecognizer(HashedSequence<StringText> a, HashedSequence<StringText> b, HashedSequenceComparator<StringText> cmp) {
+    this.a = a;
+    this.b = b;
+    this.cmp = cmp;
+  }
+
+  public boolean isValidLineInReference(Integer line) {
+    return (line != null) && (0 <= line - 1) && (line - 1 < a.length());
+  }
+
+  public boolean isValidLineInSource(Integer line) {
+    return (line != null) && (0 <= line - 1) && (line - 1 < b.length());
+  }
+
+  /**
+   * @param startA number of line from first version of text (numbering starts from 0)
+   * @param startB number of line from second version of text (numbering starts from 0)
+   */
+  public int computeLengthOfMaximalBlock(int startA, int startB) {
+    if (!cmp.equals(a, startA, b, startB)) {
+      return 0;
+    }
+    int length = 0;
+    int ai = startA;
+    int bi = startB;
+    while (ai < a.length() && bi < b.length() && cmp.equals(a, ai, b, bi)) {
+      ai++;
+      bi++;
+      length++;
+    }
+    ai = startA;
+    bi = startB;
+    while (ai >= 0 && bi >= 0 && cmp.equals(a, ai, b, bi)) {
+      ai--;
+      bi--;
+      length++;
+    }
+    // Note that position (startA, startB) was counted twice
+    return length - 1;
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/package-info.java
new file mode 100644 (file)
index 0000000..3c9eb3d
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.plugins.core.issue.tracking;
+
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/SourceChecksum.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/SourceChecksum.java
deleted file mode 100644 (file)
index 6f4106f..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.lang.StringUtils;
-
-import java.util.List;
-
-public final class SourceChecksum {
-
-  private static final String SPACE_CHARS = "\t\n\r ";
-
-  private SourceChecksum() {
-    // only static methods
-  }
-
-  /**
-   * @param line line number (first line has number 1)
-   * @return checksum or null if checksum not exists for line
-   */
-  public static String getChecksumForLine(List<String> checksums, Integer line) {
-    if (line == null || line < 1 || line > checksums.size()) {
-      return null;
-    }
-    return checksums.get(line - 1);
-  }
-
-  public static List<String> lineChecksumsOfFile(String file) {
-    List<String> result = Lists.newArrayList();
-    if (file != null) {
-      String[] lines = file.split("\r?\n|\r", -1);
-      for (String line : lines) {
-        result.add(lineChecksum(line));
-      }
-    }
-    return result;
-  }
-
-  public static String lineChecksum(String line) {
-    String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");
-    return DigestUtils.md5Hex(reducedLine);
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationTrackingBlocksRecognizer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationTrackingBlocksRecognizer.java
deleted file mode 100644 (file)
index 9490cd5..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.sonar.plugins.core.timemachine.tracking.HashedSequence;
-import org.sonar.plugins.core.timemachine.tracking.HashedSequenceComparator;
-import org.sonar.plugins.core.timemachine.tracking.StringText;
-import org.sonar.plugins.core.timemachine.tracking.StringTextComparator;
-
-public class ViolationTrackingBlocksRecognizer {
-
-  private final HashedSequence<StringText> a;
-  private final HashedSequence<StringText> b;
-  private final HashedSequenceComparator<StringText> cmp;
-
-  @VisibleForTesting
-  public ViolationTrackingBlocksRecognizer(String referenceSource, String source) {
-    this.a = HashedSequence.wrap(new StringText(referenceSource), StringTextComparator.IGNORE_WHITESPACE);
-    this.b = HashedSequence.wrap(new StringText(source), StringTextComparator.IGNORE_WHITESPACE);
-    this.cmp = new HashedSequenceComparator<StringText>(StringTextComparator.IGNORE_WHITESPACE);
-  }
-
-  public ViolationTrackingBlocksRecognizer(HashedSequence<StringText> a, HashedSequence<StringText> b, HashedSequenceComparator<StringText> cmp) {
-    this.a = a;
-    this.b = b;
-    this.cmp = cmp;
-  }
-
-  public boolean isValidLineInReference(Integer line) {
-    return (line != null) && (0 <= line - 1) && (line - 1 < a.length());
-  }
-
-  public boolean isValidLineInSource(Integer line) {
-    return (line != null) && (0 <= line - 1) && (line - 1 < b.length());
-  }
-
-  /**
-   * @param startA number of line from first version of text (numbering starts from 0)
-   * @param startB number of line from second version of text (numbering starts from 0)
-   */
-  public int computeLengthOfMaximalBlock(int startA, int startB) {
-    if (!cmp.equals(a, startA, b, startB)) {
-      return 0;
-    }
-    int length = 0;
-    int ai = startA;
-    int bi = startB;
-    while (ai < a.length() && bi < b.length() && cmp.equals(a, ai, b, bi)) {
-      ai++;
-      bi++;
-      length++;
-    }
-    ai = startA;
-    bi = startB;
-    while (ai >= 0 && bi >= 0 && cmp.equals(a, ai, b, bi)) {
-      ai--;
-      bi--;
-      length++;
-    }
-    // Note that position (startA, startB) was counted twice
-    return length - 1;
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/HashedSequence.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/HashedSequence.java
deleted file mode 100644 (file)
index ea670b2..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Wraps a {@link Sequence} to assign hash codes to elements.
- */
-public final class HashedSequence<S extends Sequence> implements Sequence {
-
-  final S base;
-  final int[] hashes;
-
-  public static <S extends Sequence> HashedSequence<S> wrap(S base, SequenceComparator<S> cmp) {
-    int size = base.length();
-    int[] hashes = new int[size];
-    for (int i = 0; i < size; i++) {
-      hashes[i] = cmp.hash(base, i);
-    }
-    return new HashedSequence<S>(base, hashes);
-  }
-
-  private HashedSequence(S base, int[] hashes) {
-    this.base = base;
-    this.hashes = hashes;
-  }
-
-  public int length() {
-    return base.length();
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/HashedSequenceComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/HashedSequenceComparator.java
deleted file mode 100644 (file)
index e4d5f83..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Wrap another {@link SequenceComparator} for use with {@link HashedSequence}.
- */
-public class HashedSequenceComparator<S extends Sequence> implements SequenceComparator<HashedSequence<S>> {
-
-  private final SequenceComparator<? super S> cmp;
-
-  public HashedSequenceComparator(SequenceComparator<? super S> cmp) {
-    this.cmp = cmp;
-  }
-
-  public boolean equals(HashedSequence<S> a, int ai, HashedSequence<S> b, int bi) {
-    if (a.hashes[ai] == b.hashes[bi]) {
-      return cmp.equals(a.base, ai, b.base, bi);
-    }
-    return false;
-  }
-
-  public int hash(HashedSequence<S> seq, int i) {
-    return seq.hashes[i];
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequence.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequence.java
deleted file mode 100644 (file)
index 6e08774..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Wraps a {@link Sequence} to assign hash codes to elements.
- */
-public class RollingHashSequence<S extends Sequence> implements Sequence {
-
-  final S base;
-  final int[] hashes;
-
-  public static <S extends Sequence> RollingHashSequence<S> wrap(S base, SequenceComparator<S> cmp, int lines) {
-    int size = base.length();
-    int[] hashes = new int[size];
-
-    RollingHashCalculator hashCalulator = new RollingHashCalculator(lines * 2 + 1);
-    for (int i = 0; i <= Math.min(size - 1, lines); i++) {
-      hashCalulator.add(cmp.hash(base, i));
-    }
-    for (int i = 0; i < size; i++) {
-      hashes[i] = hashCalulator.getHash();
-      if (i - lines >= 0) {
-        hashCalulator.remove(cmp.hash(base, i - lines));
-      }
-      if (i + lines + 1 < size) {
-        hashCalulator.add(cmp.hash(base, i + lines + 1));
-      } else {
-        hashCalulator.add(0);
-      }
-    }
-
-    return new RollingHashSequence<S>(base, hashes);
-  }
-
-  private RollingHashSequence(S base, int[] hashes) {
-    this.base = base;
-    this.hashes = hashes;
-  }
-
-  public int length() {
-    return base.length();
-  }
-
-  private static class RollingHashCalculator {
-
-    private static final int PRIME_BASE = 31;
-
-    private final int power;
-    private int hash;
-
-    public RollingHashCalculator(int size) {
-      int pow = 1;
-      for (int i = 0; i < size - 1; i++) {
-        pow = pow * PRIME_BASE;
-      }
-      this.power = pow;
-    }
-
-    public void add(int value) {
-      hash = hash * PRIME_BASE + value;
-    }
-
-    public void remove(int value) {
-      hash = hash - power * value;
-    }
-
-    public int getHash() {
-      return hash;
-    }
-
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequenceComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequenceComparator.java
deleted file mode 100644 (file)
index ee44d0b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Wrap another {@link SequenceComparator} for use with {@link RollingHashSequence}.
- */
-public class RollingHashSequenceComparator<S extends Sequence> implements SequenceComparator<RollingHashSequence<S>> {
-
-  private final SequenceComparator<? super S> cmp;
-
-  public RollingHashSequenceComparator(SequenceComparator<? super S> cmp) {
-    this.cmp = cmp;
-  }
-
-  public boolean equals(RollingHashSequence<S> a, int ai, RollingHashSequence<S> b, int bi) {
-    if (a.hashes[ai] == b.hashes[bi]) {
-      return cmp.equals(a.base, ai, b.base, bi);
-    }
-    return false;
-  }
-
-  public int hash(RollingHashSequence<S> seq, int i) {
-    return seq.hashes[i];
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/Sequence.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/Sequence.java
deleted file mode 100644 (file)
index e3c4a39..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Arbitrary sequence of elements.
- */
-public interface Sequence {
-
-  /**
-   * @return total number of items in the sequence
-   */
-  int length();
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/SequenceComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/SequenceComparator.java
deleted file mode 100644 (file)
index 533cfe6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Equivalence function for a {@link Sequence}.
- */
-public interface SequenceComparator<S extends Sequence> {
-
-  /**
-   * Compare two items to determine if they are equivalent.
-   */
-  boolean equals(S a, int ai, S b, int bi);
-
-  /**
-   * Get a hash value for an item in a sequence.
-   *
-   * If two items are equal according to this comparator's
-   * {@link #equals(Sequence, int, Sequence, int)} method,
-   * then this hash method must produce the same integer result for both items.
-   * However not required to have different hash values for different items.
-   */
-  int hash(S seq, int i);
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/StringText.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/StringText.java
deleted file mode 100644 (file)
index 99808b0..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-import com.google.common.collect.Lists;
-
-import java.util.List;
-
-/**
- * Text is a {@link Sequence} of lines.
- */
-public class StringText implements Sequence {
-
-  final String content;
-
-  /**
-   * Map of line number to starting position within {@link #content}.
-   */
-  final List<Integer> lines;
-
-  public StringText(String str) {
-    this.content = str;
-    this.lines = lineMap(content, 0, content.length());
-  }
-
-  public int length() {
-    return lines.size() - 2;
-  }
-
-  private static List<Integer> lineMap(String buf, int ptr, int end) {
-    List<Integer> lines = Lists.newArrayList();
-    lines.add(Integer.MIN_VALUE);
-    for (; ptr < end; ptr = nextLF(buf, ptr)) {
-      lines.add(ptr);
-    }
-    lines.add(end);
-    return lines;
-  }
-
-  private static int nextLF(String b, int ptr) {
-    return next(b, ptr, '\n');
-  }
-
-  private static int next(final String b, int ptr, final char chrA) {
-    final int sz = b.length();
-    while (ptr < sz) {
-      if (b.charAt(ptr++) == chrA) {
-        return ptr;
-      }
-    }
-    return ptr;
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/StringTextComparator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/StringTextComparator.java
deleted file mode 100644 (file)
index 5613e8d..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-/**
- * Equivalence function for {@link StringText}.
- */
-public abstract class StringTextComparator implements SequenceComparator<StringText> {
-
-  /**
-   * Ignores all whitespace.
-   */
-  public static final StringTextComparator IGNORE_WHITESPACE = new StringTextComparator() {
-
-    public boolean equals(StringText a, int ai, StringText b, int bi) {
-      ai++;
-      bi++;
-      int as = a.lines.get(ai);
-      int bs = b.lines.get(bi);
-      int ae = a.lines.get(ai + 1);
-      int be = b.lines.get(bi + 1);
-      ae = trimTrailingWhitespace(a.content, as, ae);
-      be = trimTrailingWhitespace(b.content, bs, be);
-      while ((as < ae) && (bs < be)) {
-        char ac = a.content.charAt(as);
-        char bc = b.content.charAt(bs);
-        while ((as < ae - 1) && (Character.isWhitespace(ac))) {
-          as++;
-          ac = a.content.charAt(as);
-        }
-        while ((bs < be - 1) && (Character.isWhitespace(bc))) {
-          bs++;
-          bc = b.content.charAt(bs);
-        }
-        if (ac != bc) {
-          return false;
-        }
-        as++;
-        bs++;
-      }
-      return (as == ae) && (bs == be);
-    }
-
-    @Override
-    protected int hashRegion(String content, int start, int end) {
-      int hash = 5381;
-      for (; start < end; start++) {
-        char c = content.charAt(start);
-        if (!Character.isWhitespace(c)) {
-          hash = ((hash << 5) + hash) + (c & 0xff);
-        }
-      }
-      return hash;
-    }
-
-  };
-
-  public int hash(StringText seq, int line) {
-    final int begin = seq.lines.get(line + 1);
-    final int end = seq.lines.get(line + 2);
-    return hashRegion(seq.content, begin, end);
-  }
-
-  protected abstract int hashRegion(String content, int start, int end);
-
-  public static int trimTrailingWhitespace(String content, int start, int end) {
-    end--;
-    while (start <= end && Character.isWhitespace(content.charAt(end))) {
-      end--;
-    }
-    return end + 1;
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/tracking/package-info.java
deleted file mode 100644 (file)
index 2cbd7c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.
- */
-
-@javax.annotation.ParametersAreNonnullByDefault
-package org.sonar.plugins.core.timemachine.tracking;
-
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/RollingHashSequenceTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/RollingHashSequenceTest.java
new file mode 100644 (file)
index 0000000..0445d2b
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import org.junit.Test;
+import org.sonar.plugins.core.issue.tracking.RollingHashSequence;
+import org.sonar.plugins.core.issue.tracking.RollingHashSequenceComparator;
+import org.sonar.plugins.core.issue.tracking.StringText;
+import org.sonar.plugins.core.issue.tracking.StringTextComparator;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class RollingHashSequenceTest {
+
+  @Test
+  public void test_hash() {
+    StringText seq = new StringText("line0 \n line1 \n line2");
+    StringTextComparator cmp = StringTextComparator.IGNORE_WHITESPACE;
+    RollingHashSequence<StringText> seq2 = RollingHashSequence.wrap(seq, cmp, 1);
+    RollingHashSequenceComparator<StringText> cmp2 = new RollingHashSequenceComparator<StringText>(cmp);
+
+    assertThat(seq2.length()).isEqualTo(3);
+    assertThat(cmp2.hash(seq2, 0)).isEqualTo(cmp.hash(seq, 0) * 31 + cmp.hash(seq, 1));
+    assertThat(cmp2.hash(seq2, 1)).isEqualTo((cmp.hash(seq, 0) * 31 + cmp.hash(seq, 1)) * 31 + cmp.hash(seq, 2));
+    assertThat(cmp2.hash(seq2, 2)).isEqualTo((cmp.hash(seq, 1) * 31 + cmp.hash(seq, 2)) * 31);
+  }
+
+  @Test
+  public void test_equals() {
+    StringTextComparator baseCmp = StringTextComparator.IGNORE_WHITESPACE;
+    RollingHashSequence<StringText> a = RollingHashSequence.wrap(new StringText("line0 \n line1 \n line2"), baseCmp, 1);
+    RollingHashSequence<StringText> b = RollingHashSequence.wrap(new StringText("line0 \n line1 \n line2 \n line3"), baseCmp, 1);
+    RollingHashSequenceComparator<StringText> cmp = new RollingHashSequenceComparator<StringText>(baseCmp);
+
+    assertThat(cmp.equals(a, 0, b, 0)).isTrue();
+    assertThat(cmp.equals(a, 1, b, 1)).isTrue();
+    assertThat(cmp.equals(a, 2, b, 2)).isFalse();
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/SourceChecksumTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/SourceChecksumTest.java
new file mode 100644 (file)
index 0000000..11996d3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import org.junit.Test;
+import org.sonar.plugins.core.issue.tracking.SourceChecksum;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class SourceChecksumTest {
+  @Test
+  public void shouldGetChecksumForLine() {
+    List<String> checksums = SourceChecksum.lineChecksumsOfFile("line");
+    assertThat(SourceChecksum.getChecksumForLine(checksums, null)).isNull();
+    assertThat(SourceChecksum.getChecksumForLine(checksums, 0)).isNull();
+    assertThat(SourceChecksum.getChecksumForLine(checksums, 1)).isNotNull();
+    assertThat(SourceChecksum.getChecksumForLine(checksums, 2)).isNull();
+  }
+
+  /**
+   * See http://jira.codehaus.org/browse/SONAR-2358
+   */
+  @Test
+  public void shouldGenerateCorrectChecksums() {
+    List<String> encoding = SourceChecksum.lineChecksumsOfFile("Привет ÐœÐ¸Ñ€");
+    assertThat(encoding).hasSize(1);
+    assertThat(encoding.get(0)).isEqualTo("5ba3a45e1299ede07f56e5531351be52");
+  }
+
+  @Test
+  public void shouldSplitLinesAndIgnoreSpaces() {
+    List<String> crlf = SourceChecksum.lineChecksumsOfFile("Hello\r\nWorld");
+    List<String> lf = SourceChecksum.lineChecksumsOfFile("Hello\nWorld");
+    List<String> cr = SourceChecksum.lineChecksumsOfFile("Hello\rWorld");
+    assertThat(crlf).hasSize(2);
+    assertThat(crlf.get(0)).isNotEqualTo(crlf.get(1));
+    assertThat(lf).isEqualTo(crlf);
+    assertThat(cr).isEqualTo(crlf);
+
+    assertThat(SourceChecksum.lineChecksum("\tvoid  method()  {\n")).isEqualTo(SourceChecksum.lineChecksum("  void method() {"));
+  }
+}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/StringTextComparatorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/StringTextComparatorTest.java
new file mode 100644 (file)
index 0000000..6d8e6eb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import org.junit.Test;
+import org.sonar.plugins.core.issue.tracking.StringText;
+import org.sonar.plugins.core.issue.tracking.StringTextComparator;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+
+public class StringTextComparatorTest {
+
+  @Test
+  public void testEquals() {
+    StringTextComparator cmp = StringTextComparator.IGNORE_WHITESPACE;
+
+    StringText a = new StringText("abc\nabc\na bc");
+    StringText b = new StringText("abc\nabc d\nab c");
+
+    assertThat(cmp.equals(a, 0, b, 0)).as("abc == abc").isTrue();
+    assertThat(cmp.equals(a, 1, b, 1)).as("abc != abc d").isFalse();
+    assertThat(cmp.equals(a, 2, b, 2)).as("a bc == ab c").isTrue();
+    assertThat(cmp.hash(a, 0)).isEqualTo(cmp.hash(b, 0));
+    assertThat(cmp.hash(a, 2)).isEqualTo(cmp.hash(b, 2));
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/StringTextTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/StringTextTest.java
new file mode 100644 (file)
index 0000000..cd55387
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import org.junit.Test;
+import org.sonar.plugins.core.issue.tracking.StringText;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class StringTextTest {
+
+  @Test
+  public void testEmpty() {
+    StringText r = new StringText("");
+    assertThat(r.length()).isEqualTo(0);
+  }
+
+  @Test
+  public void testTwoLines() {
+    StringText r = new StringText("a\nb");
+    assertThat(r.length()).isEqualTo(2);
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/ViolationTrackingBlocksRecognizerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/ViolationTrackingBlocksRecognizerTest.java
new file mode 100644 (file)
index 0000000..194ee7d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.plugins.core.issue.tracking;
+
+import org.junit.Test;
+import org.sonar.plugins.core.issue.tracking.ViolationTrackingBlocksRecognizer;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ViolationTrackingBlocksRecognizerTest {
+
+  @Test
+  public void test() {
+    assertThat(compute(t("abcde"), t("abcde"), 3, 3)).isEqualTo(5);
+    assertThat(compute(t("abcde"), t("abcd"), 3, 3)).isEqualTo(4);
+    assertThat(compute(t("bcde"), t("abcde"), 3, 3)).isEqualTo(0);
+    assertThat(compute(t("bcde"), t("abcde"), 2, 3)).isEqualTo(4);
+  }
+
+  private static int compute(String a, String b, int ai, int bi) {
+    ViolationTrackingBlocksRecognizer rec = new ViolationTrackingBlocksRecognizer(a, b);
+    return rec.computeLengthOfMaximalBlock(ai, bi);
+  }
+
+  private static String t(String text) {
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < text.length(); i++) {
+      sb.append(text.charAt(i)).append('\n');
+    }
+    return sb.toString();
+  }
+
+}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/SourceChecksumTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/SourceChecksumTest.java
deleted file mode 100644 (file)
index 2de003b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine;
-
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class SourceChecksumTest {
-  @Test
-  public void shouldGetChecksumForLine() {
-    List<String> checksums = SourceChecksum.lineChecksumsOfFile("line");
-    assertThat(SourceChecksum.getChecksumForLine(checksums, null)).isNull();
-    assertThat(SourceChecksum.getChecksumForLine(checksums, 0)).isNull();
-    assertThat(SourceChecksum.getChecksumForLine(checksums, 1)).isNotNull();
-    assertThat(SourceChecksum.getChecksumForLine(checksums, 2)).isNull();
-  }
-
-  /**
-   * See http://jira.codehaus.org/browse/SONAR-2358
-   */
-  @Test
-  public void shouldGenerateCorrectChecksums() {
-    List<String> encoding = SourceChecksum.lineChecksumsOfFile("Привет ÐœÐ¸Ñ€");
-    assertThat(encoding).hasSize(1);
-    assertThat(encoding.get(0)).isEqualTo("5ba3a45e1299ede07f56e5531351be52");
-  }
-
-  @Test
-  public void shouldSplitLinesAndIgnoreSpaces() {
-    List<String> crlf = SourceChecksum.lineChecksumsOfFile("Hello\r\nWorld");
-    List<String> lf = SourceChecksum.lineChecksumsOfFile("Hello\nWorld");
-    List<String> cr = SourceChecksum.lineChecksumsOfFile("Hello\rWorld");
-    assertThat(crlf).hasSize(2);
-    assertThat(crlf.get(0)).isNotEqualTo(crlf.get(1));
-    assertThat(lf).isEqualTo(crlf);
-    assertThat(cr).isEqualTo(crlf);
-
-    assertThat(SourceChecksum.lineChecksum("\tvoid  method()  {\n")).isEqualTo(SourceChecksum.lineChecksum("  void method() {"));
-  }
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/ViolationTrackingBlocksRecognizerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/ViolationTrackingBlocksRecognizerTest.java
deleted file mode 100644 (file)
index 93227aa..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class ViolationTrackingBlocksRecognizerTest {
-
-  @Test
-  public void test() {
-    assertThat(compute(t("abcde"), t("abcde"), 3, 3)).isEqualTo(5);
-    assertThat(compute(t("abcde"), t("abcd"), 3, 3)).isEqualTo(4);
-    assertThat(compute(t("bcde"), t("abcde"), 3, 3)).isEqualTo(0);
-    assertThat(compute(t("bcde"), t("abcde"), 2, 3)).isEqualTo(4);
-  }
-
-  private static int compute(String a, String b, int ai, int bi) {
-    ViolationTrackingBlocksRecognizer rec = new ViolationTrackingBlocksRecognizer(a, b);
-    return rec.computeLengthOfMaximalBlock(ai, bi);
-  }
-
-  private static String t(String text) {
-    StringBuilder sb = new StringBuilder();
-    for (int i = 0; i < text.length(); i++) {
-      sb.append(text.charAt(i)).append('\n');
-    }
-    return sb.toString();
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequenceTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/RollingHashSequenceTest.java
deleted file mode 100644 (file)
index 015d51a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class RollingHashSequenceTest {
-
-  @Test
-  public void test_hash() {
-    StringText seq = new StringText("line0 \n line1 \n line2");
-    StringTextComparator cmp = StringTextComparator.IGNORE_WHITESPACE;
-    RollingHashSequence<StringText> seq2 = RollingHashSequence.wrap(seq, cmp, 1);
-    RollingHashSequenceComparator<StringText> cmp2 = new RollingHashSequenceComparator<StringText>(cmp);
-
-    assertThat(seq2.length()).isEqualTo(3);
-    assertThat(cmp2.hash(seq2, 0)).isEqualTo(cmp.hash(seq, 0) * 31 + cmp.hash(seq, 1));
-    assertThat(cmp2.hash(seq2, 1)).isEqualTo((cmp.hash(seq, 0) * 31 + cmp.hash(seq, 1)) * 31 + cmp.hash(seq, 2));
-    assertThat(cmp2.hash(seq2, 2)).isEqualTo((cmp.hash(seq, 1) * 31 + cmp.hash(seq, 2)) * 31);
-  }
-
-  @Test
-  public void test_equals() {
-    StringTextComparator baseCmp = StringTextComparator.IGNORE_WHITESPACE;
-    RollingHashSequence<StringText> a = RollingHashSequence.wrap(new StringText("line0 \n line1 \n line2"), baseCmp, 1);
-    RollingHashSequence<StringText> b = RollingHashSequence.wrap(new StringText("line0 \n line1 \n line2 \n line3"), baseCmp, 1);
-    RollingHashSequenceComparator<StringText> cmp = new RollingHashSequenceComparator<StringText>(baseCmp);
-
-    assertThat(cmp.equals(a, 0, b, 0)).isTrue();
-    assertThat(cmp.equals(a, 1, b, 1)).isTrue();
-    assertThat(cmp.equals(a, 2, b, 2)).isFalse();
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/StringTextComparatorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/StringTextComparatorTest.java
deleted file mode 100644 (file)
index 7187111..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-
-public class StringTextComparatorTest {
-
-  @Test
-  public void testEquals() {
-    StringTextComparator cmp = StringTextComparator.IGNORE_WHITESPACE;
-
-    StringText a = new StringText("abc\nabc\na bc");
-    StringText b = new StringText("abc\nabc d\nab c");
-
-    assertThat(cmp.equals(a, 0, b, 0)).as("abc == abc").isTrue();
-    assertThat(cmp.equals(a, 1, b, 1)).as("abc != abc d").isFalse();
-    assertThat(cmp.equals(a, 2, b, 2)).as("a bc == ab c").isTrue();
-    assertThat(cmp.hash(a, 0)).isEqualTo(cmp.hash(b, 0));
-    assertThat(cmp.hash(a, 2)).isEqualTo(cmp.hash(b, 2));
-  }
-
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/StringTextTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/tracking/StringTextTest.java
deleted file mode 100644 (file)
index f7424af..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.plugins.core.timemachine.tracking;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class StringTextTest {
-
-  @Test
-  public void testEmpty() {
-    StringText r = new StringText("");
-    assertThat(r.length()).isEqualTo(0);
-  }
-
-  @Test
-  public void testTwoLines() {
-    StringText r = new StringText("a\nb");
-    assertThat(r.length()).isEqualTo(2);
-  }
-
-}
index 3a85c4c42bbb0ad8b0c61d20a29ca2a763c685be..b690f19d43e4bc82dce39fcbe793be4135068c68 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.batch.events.EventBus;
 import org.sonar.batch.index.DefaultIndex;
 import org.sonar.batch.index.PersistenceManager;
 import org.sonar.batch.index.ScanPersister;
-import org.sonar.batch.report.SonarReport;
+import org.sonar.batch.scan.JsonReport;
 import org.sonar.batch.scan.filesystem.FileSystemLogger;
 import org.sonar.batch.scan.maven.MavenPhaseExecutor;
 import org.sonar.batch.scan.maven.MavenPluginsConfigurator;
@@ -60,14 +60,14 @@ public final class PhaseExecutor {
   private ProjectInitializer pi;
   private ScanPersister[] persisters;
   private FileSystemLogger fsLogger;
-  private final SonarReport sonarReport;
+  private final JsonReport jsonReport;
 
   public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
                        MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
                        PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
                        PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
                        EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi,
-                       ScanPersister[] persisters, FileSystemLogger fsLogger, SonarReport sonarReport) {
+                       ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport) {
     this.phases = phases;
     this.decoratorsExecutor = decoratorsExecutor;
     this.mavenPhaseExecutor = mavenPhaseExecutor;
@@ -83,16 +83,16 @@ public final class PhaseExecutor {
     this.pi = pi;
     this.persisters = persisters;
     this.fsLogger = fsLogger;
-    this.sonarReport = sonarReport;
+    this.jsonReport = jsonReport;
   }
 
   public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
                        MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
                        PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
                        PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
-                       EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, SonarReport sonarReport) {
+                       EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport) {
     this(phases, decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor,
-      sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, sonarReport);
+      sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport);
   }
 
   /**
@@ -121,7 +121,7 @@ public final class PhaseExecutor {
     persistenceManager.setDelayedMode(false);
 
     if (module.isRoot()) {
-      sonarReport.execute();
+      jsonReport.execute();
 
       LOGGER.info("Store results in database");
       for (ScanPersister persister : persisters) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/SonarReport.java b/sonar-batch/src/main/java/org/sonar/batch/report/SonarReport.java
deleted file mode 100644 (file)
index d6e24c7..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.batch.report;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.io.Closeables;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.Server;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.issue.IssueCache;
-import org.sonar.batch.issue.ScanIssues;
-import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.core.issue.DefaultIssue;
-
-import java.io.*;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Set;
-
-import static com.google.common.collect.Sets.newHashSet;
-
-/**
- * @since 3.6
- */
-
-public class SonarReport implements BatchComponent {
-
-  private static final Logger LOG = LoggerFactory.getLogger(SonarReport.class);
-  private final Settings settings;
-  private final ModuleFileSystem fileSystem;
-  private final Server server;
-  private final RuleI18nManager ruleI18nManager;
-  private final IssueCache issueCache;
-
-  public SonarReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache) {
-    this.settings = settings;
-    this.fileSystem = fileSystem;
-    this.server = server;
-    this.ruleI18nManager = ruleI18nManager;
-    this.issueCache = issueCache;
-  }
-
-  public void execute() {
-    if (settings.getBoolean(CoreProperties.DRY_RUN)) {
-      exportResults();
-    }
-  }
-
-  private void exportResults() {
-    File exportFile = new File(fileSystem.workingDir(), settings.getString("sonar.report.export.path"));
-
-    LOG.info("Exporting report results to " + exportFile.getAbsolutePath());
-    Writer output = null;
-    try {
-      output = new BufferedWriter(new FileWriter(exportFile));
-      createJson().writeJSONString(output);
-    } catch (IOException e) {
-      throw new SonarException("Unable to write report results in file " + exportFile.getAbsolutePath(), e);
-    } finally {
-      Closeables.closeQuietly(output);
-    }
-  }
-
-  @VisibleForTesting
-  JSONObject createJson(){
-    Set<RuleKey> ruleKeyList = newHashSet();
-    Set<String> componentKeyList = newHashSet();
-
-    JSONObject json = new JSONObject();
-    put(json, "version", server.getVersion());
-
-    addIssues(json, ruleKeyList, componentKeyList);
-    addComponents(json, componentKeyList);
-    addRules(json, ruleKeyList);
-    return json;
-  }
-
-  private void addIssues(JSONObject root, Collection<RuleKey> ruleKeyList, Collection<String> componentKeyList) {
-    JSONArray json = new JSONArray();
-    for (DefaultIssue issue : getIssues()) {
-      JSONObject jsonIssue = new JSONObject();
-      put(jsonIssue, "key", issue.key());
-      put(jsonIssue, "component", issue.componentKey());
-      put(jsonIssue, "line", issue.line());
-      put(jsonIssue, "message", issue.message());
-      put(jsonIssue, "severity", issue.severity());
-      put(jsonIssue, "rule", issue.ruleKey());
-      put(jsonIssue, "status", issue.status());
-      put(jsonIssue, "resolution", issue.resolution());
-      put(jsonIssue, "isNew", issue.isNew());
-      put(jsonIssue, "reporter", issue.reporter());
-      put(jsonIssue, "assignee", issue.assignee());
-      put(jsonIssue, "effortToFix", issue.effortToFix());
-      put(jsonIssue, "creationDate", issue.creationDate());
-      put(jsonIssue, "updateDate", issue.updateDate());
-      put(jsonIssue, "closeDate", issue.closeDate());
-      json.add(jsonIssue);
-
-      componentKeyList.add(issue.componentKey());
-      ruleKeyList.add(issue.ruleKey());
-    }
-    root.put("issues", json);
-  }
-
-  private void addComponents(JSONObject root, Collection<String> componentKeyList) {
-    JSONArray json = new JSONArray();
-    for (String componentKey : componentKeyList) {
-      JSONObject jsonComponent = new JSONObject();
-      // TODO add module key
-      put(jsonComponent, "key", componentKey);
-      json.add(jsonComponent);
-    }
-    root.put("components", json);
-  }
-
-  private void addRules(JSONObject root, Collection<RuleKey> ruleKeyList) {
-    JSONArray json = new JSONArray();
-    for (RuleKey ruleKey : ruleKeyList) {
-      JSONObject jsonRuleKey = new JSONObject();
-      put(jsonRuleKey, "key", ruleKey);
-      put(jsonRuleKey, "rule", ruleKey.rule());
-      put(jsonRuleKey, "repository", ruleKey.repository());
-      put(jsonRuleKey, "name", getRuleName(ruleKey));
-      json.add(jsonRuleKey);
-    }
-    root.put("rules", json);
-  }
-
-  private void put(JSONObject json, String key, Object value) {
-    if (value != null) {
-      json.put(key, value);
-    }
-  }
-
-  private void put(JSONObject json, String key, RuleKey ruleKey) {
-    if (ruleKey != null) {
-      json.put(key, ruleKey.toString());
-    }
-  }
-
-  private void put(JSONObject json, String key, Date date) {
-    if (date != null) {
-      json.put(key, DateUtils.formatDateTime(date));
-    }
-  }
-
-  private String getRuleName(RuleKey ruleKey) {
-    return ruleI18nManager.getName(ruleKey.repository(), ruleKey.rule(), Locale.getDefault());
-  }
-
-  @VisibleForTesting
-  Collection<DefaultIssue> getIssues() {
-    return issueCache.all();
-  }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java
new file mode 100644 (file)
index 0000000..89336f6
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.batch.scan;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.io.Closeables;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.issue.IssueCache;
+import org.sonar.core.i18n.RuleI18nManager;
+import org.sonar.core.issue.DefaultIssue;
+
+import java.io.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * @since 3.6
+ */
+
+public class JsonReport implements BatchComponent {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JsonReport.class);
+  private final Settings settings;
+  private final ModuleFileSystem fileSystem;
+  private final Server server;
+  private final RuleI18nManager ruleI18nManager;
+  private final IssueCache issueCache;
+
+  public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache) {
+    this.settings = settings;
+    this.fileSystem = fileSystem;
+    this.server = server;
+    this.ruleI18nManager = ruleI18nManager;
+    this.issueCache = issueCache;
+  }
+
+  public void execute() {
+    if (settings.getBoolean(CoreProperties.DRY_RUN)) {
+      exportResults();
+    }
+  }
+
+  private void exportResults() {
+    File exportFile = new File(fileSystem.workingDir(), settings.getString("sonar.report.export.path"));
+
+    LOG.info("Exporting report results to " + exportFile.getAbsolutePath());
+    Writer output = null;
+    try {
+      output = new BufferedWriter(new FileWriter(exportFile));
+      createJson().writeJSONString(output);
+    } catch (IOException e) {
+      throw new SonarException("Unable to write report results in file " + exportFile.getAbsolutePath(), e);
+    } finally {
+      Closeables.closeQuietly(output);
+    }
+  }
+
+  @VisibleForTesting
+  JSONObject createJson(){
+    Set<RuleKey> ruleKeyList = newHashSet();
+    Set<String> componentKeyList = newHashSet();
+
+    JSONObject json = new JSONObject();
+    put(json, "version", server.getVersion());
+
+    addIssues(json, ruleKeyList, componentKeyList);
+    addComponents(json, componentKeyList);
+    addRules(json, ruleKeyList);
+    return json;
+  }
+
+  private void addIssues(JSONObject root, Collection<RuleKey> ruleKeyList, Collection<String> componentKeyList) {
+    JSONArray json = new JSONArray();
+    for (DefaultIssue issue : getIssues()) {
+      JSONObject jsonIssue = new JSONObject();
+      put(jsonIssue, "key", issue.key());
+      put(jsonIssue, "component", issue.componentKey());
+      put(jsonIssue, "line", issue.line());
+      put(jsonIssue, "message", issue.message());
+      put(jsonIssue, "severity", issue.severity());
+      put(jsonIssue, "rule", issue.ruleKey());
+      put(jsonIssue, "status", issue.status());
+      put(jsonIssue, "resolution", issue.resolution());
+      put(jsonIssue, "isNew", issue.isNew());
+      put(jsonIssue, "reporter", issue.reporter());
+      put(jsonIssue, "assignee", issue.assignee());
+      put(jsonIssue, "effortToFix", issue.effortToFix());
+      put(jsonIssue, "creationDate", issue.creationDate());
+      put(jsonIssue, "updateDate", issue.updateDate());
+      put(jsonIssue, "closeDate", issue.closeDate());
+      json.add(jsonIssue);
+
+      componentKeyList.add(issue.componentKey());
+      ruleKeyList.add(issue.ruleKey());
+    }
+    root.put("issues", json);
+  }
+
+  private void addComponents(JSONObject root, Collection<String> componentKeyList) {
+    JSONArray json = new JSONArray();
+    for (String componentKey : componentKeyList) {
+      JSONObject jsonComponent = new JSONObject();
+      // TODO add module key
+      put(jsonComponent, "key", componentKey);
+      json.add(jsonComponent);
+    }
+    root.put("components", json);
+  }
+
+  private void addRules(JSONObject root, Collection<RuleKey> ruleKeyList) {
+    JSONArray json = new JSONArray();
+    for (RuleKey ruleKey : ruleKeyList) {
+      JSONObject jsonRuleKey = new JSONObject();
+      put(jsonRuleKey, "key", ruleKey);
+      put(jsonRuleKey, "rule", ruleKey.rule());
+      put(jsonRuleKey, "repository", ruleKey.repository());
+      put(jsonRuleKey, "name", getRuleName(ruleKey));
+      json.add(jsonRuleKey);
+    }
+    root.put("rules", json);
+  }
+
+  private void put(JSONObject json, String key, Object value) {
+    if (value != null) {
+      json.put(key, value);
+    }
+  }
+
+  private void put(JSONObject json, String key, RuleKey ruleKey) {
+    if (ruleKey != null) {
+      json.put(key, ruleKey.toString());
+    }
+  }
+
+  private void put(JSONObject json, String key, Date date) {
+    if (date != null) {
+      json.put(key, DateUtils.formatDateTime(date));
+    }
+  }
+
+  private String getRuleName(RuleKey ruleKey) {
+    return ruleI18nManager.getName(ruleKey.repository(), ruleKey.rule(), Locale.getDefault());
+  }
+
+  @VisibleForTesting
+  Collection<DefaultIssue> getIssues() {
+    return issueCache.all();
+  }
+}
index f7f5f5cc12ee50628ff8db65a7c9a618ea9744ee..bbc6b8da89777159dba5eced3dc989e0936af00d 100644 (file)
@@ -44,7 +44,6 @@ import org.sonar.batch.issue.ScanIssues;
 import org.sonar.batch.local.DryRunExporter;
 import org.sonar.batch.phases.PhaseExecutor;
 import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.report.SonarReport;
 import org.sonar.batch.scan.filesystem.*;
 import org.sonar.core.component.ScanPerspectives;
 
@@ -107,7 +106,7 @@ public class ModuleScanContainer extends ComponentContainer {
       ViolationFilters.class,
       ResourceFilters.class,
       DryRunExporter.class,
-      SonarReport.class,
+      JsonReport.class,
       new ProfileProvider(),
 
       // issues
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/SonarReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/SonarReportTest.java
deleted file mode 100644 (file)
index b0f3aed..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.batch.report;
-
-import com.google.common.collect.Lists;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.platform.Server;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.batch.issue.IssueCache;
-import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.core.issue.DefaultIssue;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Locale;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class SonarReportTest {
-
-  @org.junit.Rule
-  public TemporaryFolder temporaryFolder = new TemporaryFolder();
-  SonarReport sonarReport;
-  Resource resource = mock(Resource.class);
-  ModuleFileSystem fileSystem = mock(ModuleFileSystem.class);
-  Server server = mock(Server.class);
-  RuleI18nManager ruleI18nManager = mock(RuleI18nManager.class);
-  Settings settings;
-  IssueCache issueCache = mock(IssueCache.class);
-
-  @Before
-  public void before() {
-    when(resource.getEffectiveKey()).thenReturn("Action.java");
-    when(server.getVersion()).thenReturn("3.6");
-
-    settings = new Settings();
-    settings.setProperty(CoreProperties.DRY_RUN, true);
-    sonarReport = new SonarReport(settings, fileSystem, server, ruleI18nManager, issueCache);
-  }
-
-  @Test
-  public void should_export_json() {
-    DefaultIssue issue = new DefaultIssue()
-      .setKey("200")
-      .setComponentKey("Action.java")
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setNew(false);
-
-    when(sonarReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
-
-    JSONObject json = sonarReport.createJson();
-    assertThat(json.values()).hasSize(4);
-
-    assertThat(json.get("version")).isEqualTo("3.6");
-
-    assertThat(json.get("components")).isNotNull();
-    JSONArray components = (JSONArray) json.get("components");
-    assertThat(components).hasSize(1);
-
-    assertThat(json.get("issues")).isNotNull();
-    JSONArray issues = (JSONArray) json.get("issues");
-    assertThat(issues).hasSize(1);
-
-    assertThat(json.get("rules")).isNotNull();
-    JSONArray rules = (JSONArray) json.get("rules");
-    assertThat(rules).hasSize(1);
-  }
-
-  @Test
-  public void should_export_components() {
-    DefaultIssue issue = new DefaultIssue()
-      .setKey("200")
-      .setComponentKey("Action.java")
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setNew(false);
-
-    when(sonarReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
-
-    JSONObject json = sonarReport.createJson();
-    assertThat(json.get("version")).isEqualTo("3.6");
-
-    assertThat(json.get("components")).isNotNull();
-    JSONArray components = (JSONArray) json.get("components");
-    assertThat(components).hasSize(1);
-    JSONObject jsonComponent = (JSONObject) components.get(0);
-    assertThat(jsonComponent.values()).hasSize(1);
-    assertThat(jsonComponent.get("key")).isEqualTo("Action.java");
-  }
-
-  @Test
-  public void should_export_issues() {
-    DefaultIssue issue = new DefaultIssue()
-      .setKey("200")
-      .setComponentKey("Action.java")
-      .setMessage("SystemPrintln")
-      .setSeverity("MINOR")
-      .setStatus(Issue.STATUS_CLOSED)
-      .setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
-      .setLine(1)
-      .setEffortToFix(3.14)
-      .setReporter("julien")
-      .setAssignee("simon")
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
-      .setCreationDate(DateUtils.parseDate("2013-04-24"))
-      .setUpdateDate(DateUtils.parseDate("2013-04-25"))
-      .setCloseDate(DateUtils.parseDate("2013-04-26"))
-      .setNew(false);
-
-    when(sonarReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
-
-    JSONObject json = sonarReport.createJson();
-    assertThat(json.get("issues")).isNotNull();
-    JSONArray issues = (JSONArray) json.get("issues");
-    assertThat(issues).hasSize(1);
-    JSONObject jsonIssue = (JSONObject) issues.get(0);
-    assertThat(jsonIssue.values()).hasSize(15);
-
-    assertThat(jsonIssue.get("key")).isEqualTo("200");
-    assertThat(jsonIssue.get("component")).isEqualTo("Action.java");
-    assertThat(jsonIssue.get("line")).isEqualTo(1);
-    assertThat(jsonIssue.get("message")).isEqualTo("SystemPrintln");
-    assertThat(jsonIssue.get("severity")).isEqualTo("MINOR");
-    assertThat(jsonIssue.get("rule")).isEqualTo("squid:AvoidCycle");
-    assertThat(jsonIssue.get("status")).isEqualTo("CLOSED");
-    assertThat(jsonIssue.get("resolution")).isEqualTo("FALSE-POSITIVE");
-    assertThat(jsonIssue.get("assignee")).isEqualTo("simon");
-    assertThat(jsonIssue.get("effortToFix")).isEqualTo(3.14);
-    assertThat(jsonIssue.get("reporter")).isEqualTo("julien");
-    assertThat(jsonIssue.get("isNew")).isEqualTo(false);
-    assertThat((String) jsonIssue.get("creationDate")).contains("2013-04-24T00:00");
-    assertThat((String) jsonIssue.get("updateDate")).contains("2013-04-25T00:00");
-    assertThat((String) jsonIssue.get("closeDate")).contains("2013-04-26T00:00");
-  }
-
-  @Test
-  public void should_export_rules() {
-    DefaultIssue issue = new DefaultIssue()
-      .setKey("200")
-      .setComponentKey("Action.java")
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"));
-
-    when(ruleI18nManager.getName("squid", "AvoidCycle", Locale.getDefault())).thenReturn("Avoid Cycle");
-    when(sonarReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
-
-    JSONObject root = sonarReport.createJson();
-
-    assertThat(root.get("rules")).isNotNull();
-    JSONArray rules = (JSONArray) root.get("rules");
-    assertThat(rules).hasSize(1);
-    JSONObject json = (JSONObject) rules.get(0);
-    assertThat(json.values()).hasSize(4);
-
-    assertThat(json.get("key")).isEqualTo("squid:AvoidCycle");
-    assertThat(json.get("rule")).isEqualTo("AvoidCycle");
-    assertThat(json.get("repository")).isEqualTo("squid");
-    assertThat(json.get("name")).isEqualTo("Avoid Cycle");
-  }
-
-  @Test
-  public void should_export_issues_with_no_line() {
-    DefaultIssue issue = new DefaultIssue()
-      .setKey("200")
-      .setComponentKey("Action.java")
-      .setLine(null)
-      .setRuleKey(RuleKey.of("squid", "AvoidCycle"));
-
-    when(sonarReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
-
-    JSONObject json = sonarReport.createJson();
-    assertThat(json.get("issues")).isNotNull();
-
-    JSONArray issues = (JSONArray) json.get("issues");
-    JSONObject jsonIssue = (JSONObject) issues.get(0);
-    assertThat(jsonIssue.get("key")).isEqualTo("200");
-    assertThat(jsonIssue.containsKey("line")).isFalse();
-  }
-
-  @Test
-  public void should_ignore_resources_without_issue() {
-    when(sonarReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());
-
-    JSONObject json = sonarReport.createJson();
-    assertThat(json.get("version")).isEqualTo("3.6");
-
-    assertThat(json.get("components")).isNotNull();
-    JSONArray components = (JSONArray) json.get("components");
-    assertThat(components).isEmpty();
-
-    assertThat(json.get("issues")).isNotNull();
-    JSONArray issues = (JSONArray) json.get("issues");
-    assertThat(issues).isEmpty();
-  }
-
-  @Test
-  public void should_export_issues_to_file() throws IOException {
-    File sonarDirectory = temporaryFolder.newFolder("sonar");
-
-    Rule rule = Rule.create("squid", "AvoidCycle");
-    when(ruleI18nManager.getName(rule, Locale.getDefault())).thenReturn("Avoid Cycle");
-    when(sonarReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());
-
-    settings.setProperty("sonar.report.export.path", "output.json");
-    when(fileSystem.workingDir()).thenReturn(sonarDirectory);
-
-    sonarReport.execute();
-
-    assertThat(new File(sonarDirectory, "output.json")).exists();
-  }
-
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java
new file mode 100644 (file)
index 0000000..a517fa8
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.batch.scan;
+
+import com.google.common.collect.Lists;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.platform.Server;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.batch.issue.IssueCache;
+import org.sonar.batch.scan.JsonReport;
+import org.sonar.core.i18n.RuleI18nManager;
+import org.sonar.core.issue.DefaultIssue;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Locale;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class JsonReportTest {
+
+  @org.junit.Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  JsonReport jsonReport;
+  Resource resource = mock(Resource.class);
+  ModuleFileSystem fileSystem = mock(ModuleFileSystem.class);
+  Server server = mock(Server.class);
+  RuleI18nManager ruleI18nManager = mock(RuleI18nManager.class);
+  Settings settings;
+  IssueCache issueCache = mock(IssueCache.class);
+
+  @Before
+  public void before() {
+    when(resource.getEffectiveKey()).thenReturn("Action.java");
+    when(server.getVersion()).thenReturn("3.6");
+
+    settings = new Settings();
+    settings.setProperty(CoreProperties.DRY_RUN, true);
+    jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache);
+  }
+
+  @Test
+  public void should_export_json() {
+    DefaultIssue issue = new DefaultIssue()
+      .setKey("200")
+      .setComponentKey("Action.java")
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setNew(false);
+
+    when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+
+    JSONObject json = jsonReport.createJson();
+    assertThat(json.values()).hasSize(4);
+
+    assertThat(json.get("version")).isEqualTo("3.6");
+
+    assertThat(json.get("components")).isNotNull();
+    JSONArray components = (JSONArray) json.get("components");
+    assertThat(components).hasSize(1);
+
+    assertThat(json.get("issues")).isNotNull();
+    JSONArray issues = (JSONArray) json.get("issues");
+    assertThat(issues).hasSize(1);
+
+    assertThat(json.get("rules")).isNotNull();
+    JSONArray rules = (JSONArray) json.get("rules");
+    assertThat(rules).hasSize(1);
+  }
+
+  @Test
+  public void should_export_components() {
+    DefaultIssue issue = new DefaultIssue()
+      .setKey("200")
+      .setComponentKey("Action.java")
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setNew(false);
+
+    when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+
+    JSONObject json = jsonReport.createJson();
+    assertThat(json.get("version")).isEqualTo("3.6");
+
+    assertThat(json.get("components")).isNotNull();
+    JSONArray components = (JSONArray) json.get("components");
+    assertThat(components).hasSize(1);
+    JSONObject jsonComponent = (JSONObject) components.get(0);
+    assertThat(jsonComponent.values()).hasSize(1);
+    assertThat(jsonComponent.get("key")).isEqualTo("Action.java");
+  }
+
+  @Test
+  public void should_export_issues() {
+    DefaultIssue issue = new DefaultIssue()
+      .setKey("200")
+      .setComponentKey("Action.java")
+      .setMessage("SystemPrintln")
+      .setSeverity("MINOR")
+      .setStatus(Issue.STATUS_CLOSED)
+      .setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
+      .setLine(1)
+      .setEffortToFix(3.14)
+      .setReporter("julien")
+      .setAssignee("simon")
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"))
+      .setCreationDate(DateUtils.parseDate("2013-04-24"))
+      .setUpdateDate(DateUtils.parseDate("2013-04-25"))
+      .setCloseDate(DateUtils.parseDate("2013-04-26"))
+      .setNew(false);
+
+    when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+
+    JSONObject json = jsonReport.createJson();
+    assertThat(json.get("issues")).isNotNull();
+    JSONArray issues = (JSONArray) json.get("issues");
+    assertThat(issues).hasSize(1);
+    JSONObject jsonIssue = (JSONObject) issues.get(0);
+    assertThat(jsonIssue.values()).hasSize(15);
+
+    assertThat(jsonIssue.get("key")).isEqualTo("200");
+    assertThat(jsonIssue.get("component")).isEqualTo("Action.java");
+    assertThat(jsonIssue.get("line")).isEqualTo(1);
+    assertThat(jsonIssue.get("message")).isEqualTo("SystemPrintln");
+    assertThat(jsonIssue.get("severity")).isEqualTo("MINOR");
+    assertThat(jsonIssue.get("rule")).isEqualTo("squid:AvoidCycle");
+    assertThat(jsonIssue.get("status")).isEqualTo("CLOSED");
+    assertThat(jsonIssue.get("resolution")).isEqualTo("FALSE-POSITIVE");
+    assertThat(jsonIssue.get("assignee")).isEqualTo("simon");
+    assertThat(jsonIssue.get("effortToFix")).isEqualTo(3.14);
+    assertThat(jsonIssue.get("reporter")).isEqualTo("julien");
+    assertThat(jsonIssue.get("isNew")).isEqualTo(false);
+    assertThat((String) jsonIssue.get("creationDate")).contains("2013-04-24T00:00");
+    assertThat((String) jsonIssue.get("updateDate")).contains("2013-04-25T00:00");
+    assertThat((String) jsonIssue.get("closeDate")).contains("2013-04-26T00:00");
+  }
+
+  @Test
+  public void should_export_rules() {
+    DefaultIssue issue = new DefaultIssue()
+      .setKey("200")
+      .setComponentKey("Action.java")
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"));
+
+    when(ruleI18nManager.getName("squid", "AvoidCycle", Locale.getDefault())).thenReturn("Avoid Cycle");
+    when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+
+    JSONObject root = jsonReport.createJson();
+
+    assertThat(root.get("rules")).isNotNull();
+    JSONArray rules = (JSONArray) root.get("rules");
+    assertThat(rules).hasSize(1);
+    JSONObject json = (JSONObject) rules.get(0);
+    assertThat(json.values()).hasSize(4);
+
+    assertThat(json.get("key")).isEqualTo("squid:AvoidCycle");
+    assertThat(json.get("rule")).isEqualTo("AvoidCycle");
+    assertThat(json.get("repository")).isEqualTo("squid");
+    assertThat(json.get("name")).isEqualTo("Avoid Cycle");
+  }
+
+  @Test
+  public void should_export_issues_with_no_line() {
+    DefaultIssue issue = new DefaultIssue()
+      .setKey("200")
+      .setComponentKey("Action.java")
+      .setLine(null)
+      .setRuleKey(RuleKey.of("squid", "AvoidCycle"));
+
+    when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+
+    JSONObject json = jsonReport.createJson();
+    assertThat(json.get("issues")).isNotNull();
+
+    JSONArray issues = (JSONArray) json.get("issues");
+    JSONObject jsonIssue = (JSONObject) issues.get(0);
+    assertThat(jsonIssue.get("key")).isEqualTo("200");
+    assertThat(jsonIssue.containsKey("line")).isFalse();
+  }
+
+  @Test
+  public void should_ignore_resources_without_issue() {
+    when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());
+
+    JSONObject json = jsonReport.createJson();
+    assertThat(json.get("version")).isEqualTo("3.6");
+
+    assertThat(json.get("components")).isNotNull();
+    JSONArray components = (JSONArray) json.get("components");
+    assertThat(components).isEmpty();
+
+    assertThat(json.get("issues")).isNotNull();
+    JSONArray issues = (JSONArray) json.get("issues");
+    assertThat(issues).isEmpty();
+  }
+
+  @Test
+  public void should_export_issues_to_file() throws IOException {
+    File sonarDirectory = temporaryFolder.newFolder("sonar");
+
+    Rule rule = Rule.create("squid", "AvoidCycle");
+    when(ruleI18nManager.getName(rule, Locale.getDefault())).thenReturn("Avoid Cycle");
+    when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());
+
+    settings.setProperty("sonar.report.export.path", "output.json");
+    when(fileSystem.workingDir()).thenReturn(sonarDirectory);
+
+    jsonReport.execute();
+
+    assertThat(new File(sonarDirectory, "output.json")).exists();
+  }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/review/ReviewDto.java b/sonar-core/src/main/java/org/sonar/core/review/ReviewDto.java
deleted file mode 100644 (file)
index 3147226..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.review;
-
-import com.google.common.base.Preconditions;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-
-import javax.annotation.Nullable;
-import java.util.Date;
-
-/**
- * @since 2.13
- */
-public final class ReviewDto {
-
-  public static final String STATUS_OPEN = "OPEN";
-  public static final String STATUS_REOPENED = "REOPENED";
-  public static final String STATUS_RESOLVED = "RESOLVED";
-  public static final String STATUS_CLOSED = "CLOSED";
-
-  public static final String RESOLUTION_FALSE_POSITIVE = "FALSE-POSITIVE";
-  public static final String RESOLUTION_FIXED = "FIXED";
-
-  private Long id;
-  private Integer userId;
-  private Long assigneeId;
-  private String title;
-  private String status;
-  private String resolution;
-  private Integer violationPermanentId;
-  private Integer projectId;
-  private Integer resourceId;
-  private Integer line;
-  private Date createdAt;
-  private Date updatedAt;
-  private String severity;
-  private Integer ruleId;
-  private boolean manualViolation;
-  private boolean manualSeverity;
-  private Integer actionPlanId;
-  private String data;
-
-  public Long getId() {
-    return id;
-  }
-
-  public ReviewDto setId(Long id) {
-    this.id = id;
-    return this;
-  }
-
-  public Integer getUserId() {
-    return userId;
-  }
-
-  public ReviewDto setUserId(Integer userId) {
-    this.userId = userId;
-    return this;
-  }
-
-  public Long getAssigneeId() {
-    return assigneeId;
-  }
-
-  public ReviewDto setAssigneeId(@Nullable Long assigneeId) {
-    this.assigneeId = assigneeId;
-    return this;
-  }
-
-  public String getTitle() {
-    return title;
-  }
-
-  public ReviewDto setTitle(String title) {
-    this.title = title;
-    return this;
-  }
-
-  public String getStatus() {
-    return status;
-  }
-
-  public ReviewDto setStatus(@Nullable String status) {
-    this.status = status;
-    return this;
-  }
-
-  public String getResolution() {
-    return resolution;
-  }
-
-  public ReviewDto setResolution(@Nullable String resolution) {
-    this.resolution = resolution;
-    return this;
-  }
-
-  public Integer getViolationPermanentId() {
-    return violationPermanentId;
-  }
-
-  public ReviewDto setViolationPermanentId(Integer violationPermanentId) {
-    this.violationPermanentId = violationPermanentId;
-    return this;
-  }
-
-  public Integer getProjectId() {
-    return projectId;
-  }
-
-  public ReviewDto setProjectId(Integer projectId) {
-    this.projectId = projectId;
-    return this;
-  }
-
-  public Integer getResourceId() {
-    return resourceId;
-  }
-
-  public ReviewDto setResourceId(Integer resourceId) {
-    this.resourceId = resourceId;
-    return this;
-  }
-
-  public Integer getLine() {
-    return line;
-  }
-
-  public ReviewDto setLine(@Nullable Integer line) {
-    this.line = line;
-    return this;
-  }
-
-  public Date getCreatedAt() {
-    return createdAt;
-  }
-
-  public ReviewDto setCreatedAt(Date createdAt) {
-    this.createdAt = createdAt;
-    return this;
-  }
-
-  public Date getUpdatedAt() {
-    return updatedAt;
-  }
-
-  public ReviewDto setUpdatedAt(Date updatedAt) {
-    this.updatedAt = updatedAt;
-    return this;
-  }
-
-  public String getSeverity() {
-    return severity;
-  }
-
-  public ReviewDto setSeverity(@Nullable String severity) {
-    this.severity = severity;
-    return this;
-  }
-
-  public Integer getRuleId() {
-    return ruleId;
-  }
-
-  public ReviewDto setRuleId(Integer ruleId) {
-    this.ruleId = ruleId;
-    return this;
-  }
-
-  public boolean getManualViolation() {
-    return manualViolation;
-  }
-
-  public boolean isManualViolation() {
-    return manualViolation;
-  }
-
-  public ReviewDto setManualViolation(boolean b) {
-    this.manualViolation = b;
-    return this;
-  }
-
-  public boolean getManualSeverity() {
-    return manualSeverity;
-  }
-
-  public ReviewDto setManualSeverity(boolean b) {
-    this.manualSeverity = b;
-    return this;
-  }
-
-  public boolean isManualSeverity() {
-    return manualSeverity;
-  }
-
-  public Integer getActionPlanId() {
-    return actionPlanId;
-  }
-
-  public ReviewDto setActionPlanId(@Nullable Integer i) {
-    this.actionPlanId = i;
-    return this;
-  }
-
-  public String getData() {
-    return data;
-  }
-
-  public ReviewDto setData(String s) {
-    Preconditions.checkArgument(s == null || s.length() <= 4000,
-        "Review data must not exceed 4000 characters: " + s);
-    this.data = s;
-    return this;
-  }
-
-  @Override
-  public String toString() {
-    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    ReviewDto reviewDto = (ReviewDto) o;
-    return !(id != null ? !id.equals(reviewDto.id) : reviewDto.id != null);
-  }
-
-  @Override
-  public int hashCode() {
-    return id != null ? id.hashCode() : 0;
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/workflow/ImmutableReview.java b/sonar-core/src/main/java/org/sonar/core/workflow/ImmutableReview.java
deleted file mode 100644 (file)
index baa0822..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.workflow;
-
-import com.google.common.collect.ImmutableMap;
-import org.sonar.api.workflow.Review;
-import org.sonar.api.workflow.internal.DefaultReview;
-
-import java.util.Map;
-
-public final class ImmutableReview implements Review {
-  private final Long violationId;
-  private final Long reviewId;
-  private final String ruleRepositoryKey;
-  private final String ruleKey;
-  private final String ruleName;
-  private final Long line;
-  private final boolean switchedOff;
-  private final boolean manual;
-  private final String message;
-  private final String status;
-  private final String resolution;
-  private final String severity;
-  private final Map<String, String> properties;
-
-  /**
-   * Warning : implementation is still mutable.
-   */
-  public ImmutableReview(DefaultReview review) {
-    this.line = review.getLine();
-    this.manual = review.isManual();
-    this.message = review.getMessage();
-    this.properties = ImmutableMap.copyOf(review.getProperties());
-    this.resolution = review.getResolution();
-    this.reviewId = review.getReviewId();
-    this.ruleKey = review.getRuleKey();
-    this.ruleRepositoryKey = review.getRuleRepositoryKey();
-    this.ruleName = review.getRuleName();
-    this.severity = review.getSeverity();
-    this.status = review.getStatus();
-    this.switchedOff = review.isSwitchedOff();
-    this.violationId = review.getViolationId();
-  }
-
-  public Long getViolationId() {
-    return violationId;
-  }
-
-  public Long getReviewId() {
-    return reviewId;
-  }
-
-  public String getRuleName() {
-    return ruleName;
-  }
-
-  public String getRuleRepositoryKey() {
-    return ruleRepositoryKey;
-  }
-
-  public String getRuleKey() {
-    return ruleKey;
-  }
-
-  public Long getLine() {
-    return line;
-  }
-
-  public boolean isSwitchedOff() {
-    return switchedOff;
-  }
-
-  public boolean isManual() {
-    return manual;
-  }
-
-  public String getMessage() {
-    return message;
-  }
-
-  public String getStatus() {
-    return status;
-  }
-
-  public String getResolution() {
-    return resolution;
-  }
-
-  public String getSeverity() {
-    return severity;
-  }
-
-  public Map<String, String> getProperties() {
-    return properties;
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/workflow/ReviewStore.java b/sonar-core/src/main/java/org/sonar/core/workflow/ReviewStore.java
deleted file mode 100644 (file)
index 5001695..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.workflow;
-
-import org.sonar.api.config.Settings;
-import org.sonar.api.workflow.internal.DefaultReview;
-import java.util.List;
-
-public interface ReviewStore {
-  void store(DefaultReview review);
-
-  void completeProjectSettings(Long projectId, Settings settings, List<String> propertyKeys);
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/workflow/WorkflowEngine.java b/sonar-core/src/main/java/org/sonar/core/workflow/WorkflowEngine.java
deleted file mode 100644 (file)
index 6560eb8..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.workflow;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.config.Settings;
-import org.sonar.api.workflow.Review;
-import org.sonar.api.workflow.WorkflowContext;
-import org.sonar.api.workflow.condition.Condition;
-import org.sonar.api.workflow.function.Function;
-import org.sonar.api.workflow.internal.DefaultReview;
-import org.sonar.api.workflow.internal.DefaultWorkflow;
-import org.sonar.api.workflow.internal.DefaultWorkflowContext;
-import org.sonar.api.workflow.screen.Screen;
-
-import javax.annotation.Nullable;
-import java.util.List;
-import java.util.Map;
-
-public class WorkflowEngine implements ServerComponent {
-
-  private final DefaultWorkflow workflow;
-  private final ReviewStore store;
-  private final Settings settings;
-
-  public WorkflowEngine(DefaultWorkflow workflow, ReviewStore store, Settings settings) {
-    this.workflow = workflow;
-    this.store = store;
-    this.settings = settings;
-  }
-
-  /**
-   * @return non-null list of screens per review#violationId
-   */
-  public ListMultimap<Long, Screen> listAvailableScreens(DefaultReview[] reviews, DefaultWorkflowContext context, boolean verifyConditions) {
-    ListMultimap<Long, Screen> result = ArrayListMultimap.create();
-
-    completeProjectSettings(context);
-
-    for (Map.Entry<String, Screen> entry : workflow.getScreensByCommand().entrySet()) {
-      String commandKey = entry.getKey();
-      if (!verifyConditions || verifyConditionsQuietly(null, context, workflow.getContextConditions(commandKey))) {
-        for (DefaultReview review : reviews) {
-          if (!verifyConditions || verifyConditionsQuietly(review, context, workflow.getReviewConditions(commandKey))) {
-            result.put(review.getViolationId(), entry.getValue());
-          }
-        }
-      }
-    }
-    return result;
-  }
-
-  public List<Screen> listAvailableScreens(Review review, DefaultWorkflowContext context, boolean verifyConditions) {
-    List<Screen> result = Lists.newArrayList();
-    completeProjectSettings(context);
-    for (Map.Entry<String, Screen> entry : workflow.getScreensByCommand().entrySet()) {
-      String commandKey = entry.getKey();
-      if (!verifyConditions || verifyConditionsQuietly(review, context, workflow.getConditions(commandKey))) {
-        result.add(entry.getValue());
-
-      }
-    }
-    return result;
-  }
-
-  /**
-   * @return the optional (nullable) screen associated to the command
-   */
-  public Screen getScreen(String commandKey) {
-    return workflow.getScreen(commandKey);
-  }
-
-  public void execute(String commandKey, DefaultReview review, DefaultWorkflowContext context, Map<String, String> parameters) {
-    Preconditions.checkArgument(!Strings.isNullOrEmpty(commandKey), "Missing command");
-    Preconditions.checkArgument(workflow.hasCommand(commandKey), "Unknown command: " + commandKey);
-
-    completeProjectSettings(context);
-
-    verifyConditions(review, context, workflow.getConditions(commandKey));
-
-    Map<String, String> immutableParameters = ImmutableMap.copyOf(parameters);
-
-    // TODO execute functions are change state before functions that consume state (like "create-jira-issue")
-    Review initialReview = new ImmutableReview(review);
-    for (Function function : workflow.getFunctions(commandKey)) {
-      function.doExecute(review, initialReview, context, immutableParameters);
-    }
-
-    // should it be extracted to a core function ?
-    store.store(review);
-
-    // TODO notify listeners
-  }
-
-  private boolean verifyConditionsQuietly(@Nullable Review review, WorkflowContext context, List<Condition> conditions) {
-    for (Condition condition : conditions) {
-      if (!condition.doVerify(review, context)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  private void verifyConditions(@Nullable Review review, WorkflowContext context, List<Condition> conditions) {
-    for (Condition condition : conditions) {
-      if (!condition.doVerify(review, context)) {
-        throw new IllegalStateException("Condition is not respected: " + condition.toString());
-      }
-    }
-  }
-
-  private void completeProjectSettings(DefaultWorkflowContext context) {
-    Settings projectSettings = new Settings(settings);
-    List<String> propertyKeys = workflow.getProjectPropertyKeys();
-    store.completeProjectSettings(context.getProjectId(), projectSettings, propertyKeys);
-    context.setSettings(projectSettings);
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/workflow/package-info.java b/sonar-core/src/main/java/org/sonar/core/workflow/package-info.java
deleted file mode 100644 (file)
index 0a0eb1d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.core.workflow;
-
-import javax.annotation.ParametersAreNonnullByDefault;
\ No newline at end of file
diff --git a/sonar-core/src/test/java/org/sonar/core/workflow/WorkflowEngineTest.java b/sonar-core/src/test/java/org/sonar/core/workflow/WorkflowEngineTest.java
deleted file mode 100644 (file)
index c9f7f79..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.core.workflow;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Maps;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.Settings;
-import org.sonar.api.workflow.internal.DefaultWorkflow;
-import org.sonar.api.workflow.Review;
-import org.sonar.api.workflow.WorkflowContext;
-import org.sonar.api.workflow.condition.Condition;
-import org.sonar.api.workflow.condition.HasProjectPropertyCondition;
-import org.sonar.api.workflow.function.Function;
-import org.sonar.api.workflow.internal.DefaultReview;
-import org.sonar.api.workflow.internal.DefaultWorkflowContext;
-import org.sonar.api.workflow.screen.CommentScreen;
-import org.sonar.api.workflow.screen.Screen;
-import org.sonar.core.workflow.ImmutableReview;
-import org.sonar.core.workflow.ReviewStore;
-import org.sonar.core.workflow.WorkflowEngine;
-
-import java.util.List;
-import java.util.Map;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItem;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-public class WorkflowEngineTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Test
-  public void listAvailableScreensForReview_empty() {
-    WorkflowEngine engine = new WorkflowEngine(new DefaultWorkflow(), mock(ReviewStore.class), new Settings());
-    List<Screen> screens = engine.listAvailableScreens(new DefaultReview(), new DefaultWorkflowContext(), true);
-    assertThat(screens).isEmpty();
-  }
-
-  @Test
-  public void listAvailableScreensForReview() {
-    DefaultWorkflow workflow = new DefaultWorkflow();
-    workflow.addCommand("command-without-screen");
-    workflow.addCommand("resolve");
-    CommentScreen screen = new CommentScreen();
-    workflow.setScreen("resolve", screen);
-
-    WorkflowEngine engine = new WorkflowEngine(workflow, mock(ReviewStore.class), new Settings());
-    List<Screen> screens = engine.listAvailableScreens(new DefaultReview(), new DefaultWorkflowContext(), true);
-    assertThat(screens).containsExactly(screen);
-  }
-
-  @Test
-  public void listAvailableScreensForReview_verify_conditions() {
-    DefaultWorkflow workflow = new DefaultWorkflow();
-    workflow.addCommand("resolve");
-    Condition condition = mock(Condition.class);
-    when(condition.doVerify(any(Review.class), any(WorkflowContext.class))).thenReturn(false);
-    workflow.addCondition("resolve", condition);
-    workflow.setScreen("resolve", new CommentScreen());
-
-    WorkflowEngine engine = new WorkflowEngine(workflow, mock(ReviewStore.class), new Settings());
-    DefaultReview review = new DefaultReview();
-    DefaultWorkflowContext context = new DefaultWorkflowContext();
-    assertThat(engine.listAvailableScreens(review, context, true)).isEmpty();
-
-    verify(condition).doVerify(review, context);
-  }
-
-  @Test
-  public void listAvailableScreensForReviews_empty() {
-    WorkflowEngine engine = new WorkflowEngine(new DefaultWorkflow(), mock(ReviewStore.class), new Settings());
-    ListMultimap<Long, Screen> screens = engine.listAvailableScreens(
-        new DefaultReview[]{new DefaultReview().setViolationId(1000L), new DefaultReview().setViolationId(2000L)},
-        new DefaultWorkflowContext(), true);
-    assertThat(screens.size()).isEqualTo(0);
-  }
-
-  @Test
-  public void listAvailableScreensForReviews() {
-    DefaultWorkflow workflow = new DefaultWorkflow();
-    workflow.addCommand("command-without-screen");
-    workflow.addCommand("resolve");
-    CommentScreen screen = new CommentScreen();
-    workflow.setScreen("resolve", screen);
-    WorkflowEngine engine = new WorkflowEngine(workflow, mock(ReviewStore.class), new Settings());
-    ListMultimap<Long, Screen> screens = engine.listAvailableScreens(
-        new DefaultReview[]{new DefaultReview().setViolationId(1000L), new DefaultReview().setViolationId(2000L)},
-        new DefaultWorkflowContext(), true);
-    assertThat(screens.size()).isEqualTo(2);
-    assertThat(screens.get(1000L)).containsExactly(screen);
-    assertThat(screens.get(2000L)).containsExactly(screen);
-  }
-
-  @Test
-  public void listAvailableScreensForReviews_load_project_properties() {
-    DefaultWorkflow workflow = new DefaultWorkflow();
-    workflow.addCommand("resolve");
-    workflow.addCondition("resolve", new HasProjectPropertyCondition("foo"));
-
-    ReviewStore store = mock(ReviewStore.class);
-    WorkflowEngine engine = new WorkflowEngine(workflow, store, new Settings());
-
-    engine.listAvailableScreens(
-        new DefaultReview[]{new DefaultReview().setViolationId(1000L), new DefaultReview().setViolationId(2000L)},
-        new DefaultWorkflowContext().setProjectId(300L),
-        true);
-
-    verify(store).completeProjectSettings(eq(300L), any(Settings.class), (List<String>) argThat(hasItem("foo")));
-  }
-
-  @Test
-  public void execute_conditions_pass() {
-    DefaultWorkflow workflow = new DefaultWorkflow();
-    workflow.addCommand("resolve");
-    workflow.addCondition("resolve", new HasProjectPropertyCondition("foo"));
-    Function function = mock(Function.class);
-    workflow.addFunction("resolve", function);
-
-    ReviewStore store = mock(ReviewStore.class);
-    Settings settings = new Settings();
-    settings.setProperty("foo", "bar");
-    WorkflowEngine engine = new WorkflowEngine(workflow, store, settings);
-
-    DefaultReview review = new DefaultReview().setViolationId(1000L);
-    Map<String, String> parameters = Maps.newHashMap();
-    DefaultWorkflowContext context = new DefaultWorkflowContext().setProjectId(300L);
-
-    engine.execute("resolve", review, context, parameters);
-
-    verify(store).completeProjectSettings(eq(300L), any(Settings.class), (List<String>) argThat(hasItem("foo")));
-    verify(function).doExecute(eq(review), any(ImmutableReview.class), eq(context), eq(parameters));
-  }
-
-  @Test
-  public void execute_fail_if_conditions_dont_pass() {
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Condition is not respected: Property foo must be set");
-
-    DefaultWorkflow workflow = new DefaultWorkflow();
-    workflow.addCommand("resolve");
-    workflow.addCondition("resolve", new HasProjectPropertyCondition("foo"));
-    Function function = mock(Function.class);
-    workflow.addFunction("resolve", function);
-
-    ReviewStore store = mock(ReviewStore.class);
-    Settings settings = new Settings();// missing property 'foo'
-    WorkflowEngine engine = new WorkflowEngine(workflow, store, settings);
-
-    DefaultReview review = new DefaultReview().setViolationId(1000L);
-    Map<String, String> parameters = Maps.newHashMap();
-    DefaultWorkflowContext context = new DefaultWorkflowContext().setProjectId(300L);
-
-    engine.execute("resolve", review, context, parameters);
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java b/sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java
deleted file mode 100644 (file)
index 6d3defc..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.notifications.reviews;
-
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.notifications.Notification;
-import org.sonar.api.notifications.NotificationManager;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @since 2.10
- */
-public class ReviewsNotificationManager implements ServerComponent {
-
-  private NotificationManager notificationManager;
-
-  public ReviewsNotificationManager(NotificationManager notificationManager) {
-    this.notificationManager = notificationManager;
-  }
-
-  /**
-   * @param reviewId reviewId id of review, which was modified
-   * @param author author of change (username)
-   * @param oldValues map of old values
-   * @param newValues map of new values
-   */
-  public void notifyChanged(Long reviewId, String author, Map<String, String> oldValues, Map<String, String> newValues) {
-    Notification notification = new Notification("review-changed")
-        .setDefaultMessage("Review #" + reviewId + " has changed.")
-        .setFieldValue("reviewId", String.valueOf(reviewId))
-        .setFieldValue("project", newValues.get("project"))
-        .setFieldValue("projectId", newValues.get("projectId"))
-        .setFieldValue("resource", newValues.get("resource"))
-        .setFieldValue("title", newValues.get("title"))
-        .setFieldValue("author", author)
-        .setFieldValue("creator", newValues.get("creator"))
-        .setFieldValue("severity", newValues.get("severity"))
-        .setFieldValue("assignee", newValues.get("assignee"));
-    Set<String> fields = Sets.newHashSet();
-    fields.addAll(oldValues.keySet());
-    fields.addAll(newValues.keySet());
-    for (String field : fields) {
-      String oldValue = oldValues.get(field);
-      String newValue = newValues.get(field);
-      if (!StringUtils.equals(oldValue, newValue)) {
-        notification.setFieldValue("new." + field, newValue);
-        notification.setFieldValue("old." + field, oldValue);
-      }
-    }
-    notificationManager.scheduleForSending(notification);
-  }
-
-}
index 60c7474adc44149fac2f86c505aa06f4ccb1c2ec..fcf02b695f83b825879d1ea18b8d80813fd65613 100644 (file)
@@ -60,7 +60,6 @@ import org.sonar.core.test.TestablePerspectiveLoader;
 import org.sonar.core.timemachine.Periods;
 import org.sonar.core.user.DefaultUserFinder;
 import org.sonar.core.user.HibernateUserFinder;
-import org.sonar.core.workflow.WorkflowEngine;
 import org.sonar.jpa.dao.MeasuresDao;
 import org.sonar.jpa.dao.ProfilesDao;
 import org.sonar.jpa.dao.RulesDao;
@@ -75,7 +74,6 @@ import org.sonar.server.database.EmbeddedDatabaseFactory;
 import org.sonar.server.issue.*;
 import org.sonar.server.notifications.NotificationCenter;
 import org.sonar.server.notifications.NotificationService;
-import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
 import org.sonar.server.plugins.*;
 import org.sonar.server.qualitymodel.DefaultModelManager;
 import org.sonar.server.rule.RubyRuleService;
@@ -209,7 +207,6 @@ public final class Platform {
   private void startServiceComponents() {
     servicesContainer = coreContainer.createChild();
     servicesContainer.addSingleton(DefaultWorkflow.class);
-    servicesContainer.addSingleton(WorkflowEngine.class);
     servicesContainer.addSingleton(HttpDownloader.class);
     servicesContainer.addSingleton(UriReader.class);
     servicesContainer.addSingleton(UpdateCenterClient.class);
@@ -282,7 +279,6 @@ public final class Platform {
     servicesContainer.addSingleton(NotificationService.class);
     servicesContainer.addSingleton(NotificationCenter.class);
     servicesContainer.addSingleton(DefaultNotificationManager.class);
-    servicesContainer.addSingleton(ReviewsNotificationManager.class);
 
     // graphs and perspective related classes
     servicesContainer.addSingleton(TestablePerspectiveLoader.class);
index 09b78e1f42b14e7b76b55f70df3a0925219f1852..c4df84c368c18052b731f6a70b918c5c527b0b3b 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.server.ui;
 
-import com.google.common.collect.ListMultimap;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.config.License;
@@ -42,10 +41,6 @@ import org.sonar.api.test.TestPlan;
 import org.sonar.api.test.Testable;
 import org.sonar.api.utils.ValidationMessages;
 import org.sonar.api.web.*;
-import org.sonar.api.workflow.Review;
-import org.sonar.api.workflow.internal.DefaultReview;
-import org.sonar.api.workflow.internal.DefaultWorkflowContext;
-import org.sonar.api.workflow.screen.Screen;
 import org.sonar.core.component.SnapshotPerspectives;
 import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.core.measure.MeasureFilterEngine;
@@ -57,10 +52,8 @@ import org.sonar.core.purge.PurgeDao;
 import org.sonar.core.resource.ResourceIndexerDao;
 import org.sonar.core.resource.ResourceKeyUpdaterDao;
 import org.sonar.core.timemachine.Periods;
-import org.sonar.core.workflow.WorkflowEngine;
 import org.sonar.server.configuration.Backup;
 import org.sonar.server.configuration.ProfilesManager;
-import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
 import org.sonar.server.platform.*;
 import org.sonar.server.plugins.*;
 import org.sonar.server.rules.ProfilesConsole;
@@ -456,10 +449,6 @@ public final class JRubyFacade {
     return get(Settings.class).getString(CoreProperties.SONAR_HOME);
   }
 
-  public ReviewsNotificationManager getReviewsNotificationManager() {
-    return get(ReviewsNotificationManager.class);
-  }
-
   public ComponentContainer getContainer() {
     return Platform.getInstance().getContainer();
   }
diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java
deleted file mode 100644 (file)
index f00d622..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.notifications.reviews;
-
-import com.google.common.collect.Maps;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.notifications.Notification;
-import org.sonar.api.notifications.NotificationManager;
-
-import java.util.Map;
-
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-
-public class ReviewsNotificationManagerTest {
-
-  private Notification notification;
-  private ReviewsNotificationManager manager;
-
-  @Before
-  public void setUp() {
-    NotificationManager delegate = mock(NotificationManager.class);
-    doAnswer(new Answer() {
-      public Object answer(InvocationOnMock invocation) throws Throwable {
-        notification = (Notification) invocation.getArguments()[0];
-        return null;
-      }
-    }).when(delegate).scheduleForSending(any(Notification.class));
-    manager = new ReviewsNotificationManager(delegate);
-  }
-
-  @Test
-  public void shouldScheduleNotification() {
-    Map<String, String> oldValues = Maps.newHashMap();
-    Map<String, String> newValues = Maps.newHashMap();
-    newValues.put("project", "Sonar");
-    newValues.put("projectId", "42");
-    newValues.put("resource", "org.sonar.server.ui.DefaultPages");
-    newValues.put("title", "Utility classes should not have a public or default constructor.");
-    newValues.put("creator", "olivier");
-    newValues.put("assignee", "godin");
-    oldValues.put("assignee", "simon");
-    manager.notifyChanged(1L, "freddy", oldValues, newValues);
-    assertThat(notification, notNullValue());
-    assertThat(notification.getType(), is("review-changed"));
-    assertThat(notification.getDefaultMessage(), is("Review #1 has changed."));
-    assertThat(notification.getFieldValue("reviewId"), is("1"));
-    assertThat(notification.getFieldValue("author"), is("freddy"));
-    assertThat(notification.getFieldValue("project"), is("Sonar"));
-    assertThat(notification.getFieldValue("projectId"), is("42"));
-    assertThat(notification.getFieldValue("resource"), is("org.sonar.server.ui.DefaultPages"));
-    assertThat(notification.getFieldValue("title"), is("Utility classes should not have a public or default constructor."));
-    assertThat(notification.getFieldValue("creator"), is("olivier"));
-    assertThat(notification.getFieldValue("assignee"), is("godin"));
-    assertThat(notification.getFieldValue("old.assignee"), is("simon"));
-    assertThat(notification.getFieldValue("new.assignee"), is("godin"));
-  }
-
-}