{"action":"created","comment":{"url":"https://api.github.com/repos/SonarSource/sonarqube/pulls/comments/53597733","id":53597733,"diff_hunk":"@@ -31,97 +33,135 @@\n import org.sonar.batch.protocol.output.BatchReport;\n import org.sonar.batch.protocol.output.BatchReportWriter;\n import org.sonar.batch.scan.measure.MeasureCache;\n+import org.sonar.core.metric.BatchMetrics;\n+\n+import static com.google.common.collect.Iterables.filter;\n+import static com.google.common.collect.Iterables.transform;\n+import static com.google.common.collect.Sets.newHashSet;\n \n public class MeasuresPublisher implements ReportPublisherStep {\n \n-  private final BatchComponentCache resourceCache;\n-  private final MeasureCache measureCache;\n+  private static final class MeasureToReportMeasure implements Function<Measure, BatchReport.Measure> {\n+    private final BatchComponent resource;\n+    private final BatchReport.Measure.Builder builder = BatchReport.Measure.newBuilder();\n \n-  public MeasuresPublisher(BatchComponentCache resourceCache, MeasureCache measureCache) {\n-    this.resourceCache = resourceCache;\n-    this.measureCache = measureCache;\n-  }\n+    private MeasureToReportMeasure(BatchComponent resource) {\n+      this.resource = resource;\n+    }\n \n-  @Override\n-  public void publish(BatchReportWriter writer) {\n-    for (final BatchComponent resource : resourceCache.all()) {\n-      Iterable<Measure> batchMeasures = measureCache.byResource(resource.resource());\n-      Iterable<org.sonar.batch.protocol.output.BatchReport.Measure> reportMeasures = Iterables.transform(batchMeasures, new Function<Measure, BatchReport.Measure>() {\n-        private final BatchReport.Measure.Builder builder = BatchReport.Measure.newBuilder();\n-\n-        @Override\n-        public BatchReport.Measure apply(@Nonnull Measure input) {\n-          validateMeasure(input, resource.key());\n-          return toReportMeasure(builder, input);\n-        }\n-      });\n-      writer.writeComponentMeasures(resource.batchId(), reportMeasures);\n+    @Override\n+    public BatchReport.Measure apply(@Nonnull Measure input) {\n+      validateMeasure(input, resource.key());\n+      return toReportMeasure(builder, input);\n+    }\n+\n+    private static void validateMeasure(Measure measure, String componentKey) {\n+      if (measure.getValue() == null && measure.getData() == null) {\n+        throw new IllegalArgumentException(String.format(\"Measure on metric '%s' and component '%s' has no value, but it's not allowed\", measure.getMetricKey(), componentKey));\n+      }\n+    }\n+\n+    private BatchReport.Measure toReportMeasure(BatchReport.Measure.Builder builder, Measure measure) {\n+      builder.clear();\n+\n+      builder.setValueType(getMeasureValueType(measure.getMetric().getType()));\n+      setValueAccordingToType(builder, measure);\n+      // Because some numeric measures also have a data (like Sqale rating)\n+      String data = measure.getData();\n+      if (data != null) {\n+        builder.setStringValue(data);\n+      }\n+      builder.setMetricKey(measure.getMetricKey());\n+      return builder.build();\n     }\n-  }\n \n-  private static void validateMeasure(Measure measure, String componentKey) {\n-    if (measure.getValue() == null && measure.getData() == null) {\n-      throw new IllegalArgumentException(String.format(\"Measure on metric '%s' and component '%s' has no value, but it's not allowed\", measure.getMetricKey(), componentKey));\n+    private void setValueAccordingToType(BatchReport.Measure.Builder builder, Measure measure) {\n+      Serializable value = measure.value();\n+      switch (builder.getValueType()) {\n+        case BOOLEAN:\n+          builder.setBooleanValue((Boolean) value);\n+          break;\n+        case DOUBLE:\n+          builder.setDoubleValue(((Number) value).doubleValue());\n+          break;\n+        case INT:\n+          builder.setIntValue(((Number) value).intValue());\n+          break;\n+        case LONG:\n+          builder.setLongValue(((Number) value).longValue());\n+          break;\n+        case STRING:\n+          builder.setStringValue((String) value);\n+          break;\n+        default:\n+          throw new IllegalStateException(\"Unknown value type: \" + builder.getValueType());\n+      }\n     }\n+\n+    private MeasureValueType getMeasureValueType(ValueType type) {\n+      switch (type) {\n+        case INT:\n+        case RATING:\n+          return MeasureValueType.INT;\n+        case FLOAT:\n+        case PERCENT:\n+          return MeasureValueType.DOUBLE;\n+        case BOOL:\n+          return MeasureValueType.BOOLEAN;\n+        case STRING:\n+        case DATA:\n+        case LEVEL:\n+        case DISTRIB:\n+          return MeasureValueType.STRING;\n+        case WORK_DUR:\n+        case MILLISEC:\n+          return MeasureValueType.LONG;\n+        default:\n+          throw new IllegalStateException(\"Unknown value type: \" + type);\n+      }\n+    }\n+\n   }\n \n-  private BatchReport.Measure toReportMeasure(BatchReport.Measure.Builder builder, Measure measure) {\n-    builder.clear();\n+  private final class IsMetricAllowed implements Predicate<Measure> {","path":"sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java","position":133,"original_position":133,"commit_id":"71032ad8578ed47da526dca5b0f31302b62d2dab","original_commit_id":"71032ad8578ed47da526dca5b0f31302b62d2dab","user":{"login":"SonarTech","id":1842438,"avatar_url":"https://avatars.githubusercontent.com/u/1842438?v=3","gravatar_id":"","url":"https://api.github.com/users/SonarTech","html_url":"https://github.com/SonarTech","followers_url":"https://api.github.com/users/SonarTech/followers","following_url":"https://api.github.com/users/SonarTech/following{/other_user}","gists_url":"https://api.github.com/users/SonarTech/gists{/gist_id}","starred_url":"https://api.github.com/users/SonarTech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SonarTech/subscriptions","organizations_url":"https://api.github.com/users/SonarTech/orgs","repos_url":"https://api.github.com/users/SonarTech/repos","events_url":"https://api.github.com/users/SonarTech/events{/privacy}","received_events_url":"https://api.github.com/users/SonarTech/received_events","type":"User","site_admin":false},"body":"![MAJOR](https://raw.githubusercontent.com/SonarCommunity/sonar-github/master/images/severity-major.png) Make this a \"static\" inner class. [![rule](https://raw.githubusercontent.com/SonarCommunity/sonar-github/master/images/rule.png)](https://dory.sonarsource.com/coding_rules#rule_key=squid%3AS2694)\n","created_at":"2016-02-22T08:45:44Z","updated_at":"2016-02-22T08:45:44Z","html_url":"https://github.com/SonarSource/sonarqube/pull/785#discussion_r53597733","pull_request_url":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785","_links":{"self":{"href":"https://api.github.com/repos/SonarSource/sonarqube/pulls/comments/53597733"},"html":{"href":"https://github.com/SonarSource/sonarqube/pull/785#discussion_r53597733"},"pull_request":{"href":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785"}}},"pull_request":{"url":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785","id":59945009,"html_url":"https://github.com/SonarSource/sonarqube/pull/785","diff_url":"https://github.com/SonarSource/sonarqube/pull/785.diff","patch_url":"https://github.com/SonarSource/sonarqube/pull/785.patch","issue_url":"https://api.github.com/repos/SonarSource/sonarqube/issues/785","number":785,"state":"open","locked":false,"title":"Zero coverage","user":{"login":"henryju","id":281596,"avatar_url":"https://avatars.githubusercontent.com/u/281596?v=3","gravatar_id":"","url":"https://api.github.com/users/henryju","html_url":"https://github.com/henryju","followers_url":"https://api.github.com/users/henryju/followers","following_url":"https://api.github.com/users/henryju/following{/other_user}","gists_url":"https://api.github.com/users/henryju/gists{/gist_id}","starred_url":"https://api.github.com/users/henryju/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/henryju/subscriptions","organizations_url":"https://api.github.com/users/henryju/orgs","repos_url":"https://api.github.com/users/henryju/repos","events_url":"https://api.github.com/users/henryju/events{/privacy}","received_events_url":"https://api.github.com/users/henryju/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-02-19T12:48:53Z","updated_at":"2016-02-22T08:45:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a6c63e4d02a1187518acd1bc510c555f2b031c47","assignee":{"login":"dbmeneses","id":12492673,"avatar_url":"https://avatars.githubusercontent.com/u/12492673?v=3","gravatar_id":"","url":"https://api.github.com/users/dbmeneses","html_url":"https://github.com/dbmeneses","followers_url":"https://api.github.com/users/dbmeneses/followers","following_url":"https://api.github.com/users/dbmeneses/following{/other_user}","gists_url":"https://api.github.com/users/dbmeneses/gists{/gist_id}","starred_url":"https://api.github.com/users/dbmeneses/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dbmeneses/subscriptions","organizations_url":"https://api.github.com/users/dbmeneses/orgs","repos_url":"https://api.github.com/users/dbmeneses/repos","events_url":"https://api.github.com/users/dbmeneses/events{/privacy}","received_events_url":"https://api.github.com/users/dbmeneses/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785/commits","review_comments_url":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785/comments","review_comment_url":"https://api.github.com/repos/SonarSource/sonarqube/pulls/comments{/number}","comments_url":"https://api.github.com/repos/SonarSource/sonarqube/issues/785/comments","statuses_url":"https://api.github.com/repos/SonarSource/sonarqube/statuses/71032ad8578ed47da526dca5b0f31302b62d2dab","head":{"label":"SonarSource:zero_coverage","ref":"zero_coverage","sha":"71032ad8578ed47da526dca5b0f31302b62d2dab","user":{"login":"SonarSource","id":545988,"avatar_url":"https://avatars.githubusercontent.com/u/545988?v=3","gravatar_id":"","url":"https://api.github.com/users/SonarSource","html_url":"https://github.com/SonarSource","followers_url":"https://api.github.com/users/SonarSource/followers","following_url":"https://api.github.com/users/SonarSource/following{/other_user}","gists_url":"https://api.github.com/users/SonarSource/gists{/gist_id}","starred_url":"https://api.github.com/users/SonarSource/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SonarSource/subscriptions","organizations_url":"https://api.github.com/users/SonarSource/orgs","repos_url":"https://api.github.com/users/SonarSource/repos","events_url":"https://api.github.com/users/SonarSource/events{/privacy}","received_events_url":"https://api.github.com/users/SonarSource/received_events","type":"Organization","site_admin":false},"repo":{"id":1222504,"name":"sonarqube","full_name":"SonarSource/sonarqube","owner":{"login":"SonarSource","id":545988,"avatar_url":"https://avatars.githubusercontent.com/u/545988?v=3","gravatar_id":"","url":"https://api.github.com/users/SonarSource","html_url":"https://github.com/SonarSource","followers_url":"https://api.github.com/users/SonarSource/followers","following_url":"https://api.github.com/users/SonarSource/following{/other_user}","gists_url":"https://api.github.com/users/SonarSource/gists{/gist_id}","starred_url":"https://api.github.com/users/SonarSource/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SonarSource/subscriptions","organizations_url":"https://api.github.com/users/SonarSource/orgs","repos_url":"https://api.github.com/users/SonarSource/repos","events_url":"https://api.github.com/users/SonarSource/events{/privacy}","received_events_url":"https://api.github.com/users/SonarSource/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SonarSource/sonarqube","description":"Put your technical debt under control","fork":false,"url":"https://api.github.com/repos/SonarSource/sonarqube","forks_url":"https://api.github.com/repos/SonarSource/sonarqube/forks","keys_url":"https://api.github.com/repos/SonarSource/sonarqube/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SonarSource/sonarqube/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SonarSource/sonarqube/teams","hooks_url":"https://api.github.com/repos/SonarSource/sonarqube/hooks","issue_events_url":"https://api.github.com/repos/SonarSource/sonarqube/issues/events{/number}","events_url":"https://api.github.com/repos/SonarSource/sonarqube/events","assignees_url":"https://api.github.com/repos/SonarSource/sonarqube/assignees{/user}","branches_url":"https://api.github.com/repos/SonarSource/sonarqube/branches{/branch}","tags_url":"https://api.github.com/repos/SonarSource/sonarqube/tags","blobs_url":"https://api.github.com/repos/SonarSource/sonarqube/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SonarSource/sonarqube/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SonarSource/sonarqube/git/refs{/sha}","trees_url":"https://api.github.com/repos/SonarSource/sonarqube/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SonarSource/sonarqube/statuses/{sha}","languages_url":"https://api.github.com/repos/SonarSource/sonarqube/languages","stargazers_url":"https://api.github.com/repos/SonarSource/sonarqube/stargazers","contributors_url":"https://api.github.com/repos/SonarSource/sonarqube/contributors","subscribers_url":"https://api.github.com/repos/SonarSource/sonarqube/subscribers","subscription_url":"https://api.github.com/repos/SonarSource/sonarqube/subscription","commits_url":"https://api.github.com/repos/SonarSource/sonarqube/commits{/sha}","git_commits_url":"https://api.github.com/repos/SonarSource/sonarqube/git/commits{/sha}","comments_url":"https://api.github.com/repos/SonarSource/sonarqube/comments{/number}","issue_comment_url":"https://api.github.com/repos/SonarSource/sonarqube/issues/comments{/number}","contents_url":"https://api.github.com/repos/SonarSource/sonarqube/contents/{+path}","compare_url":"https://api.github.com/repos/SonarSource/sonarqube/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SonarSource/sonarqube/merges","archive_url":"https://api.github.com/repos/SonarSource/sonarqube/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SonarSource/sonarqube/downloads","issues_url":"https://api.github.com/repos/SonarSource/sonarqube/issues{/number}","pulls_url":"https://api.github.com/repos/SonarSource/sonarqube/pulls{/number}","milestones_url":"https://api.github.com/repos/SonarSource/sonarqube/milestones{/number}","notifications_url":"https://api.github.com/repos/SonarSource/sonarqube/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SonarSource/sonarqube/labels{/name}","releases_url":"https://api.github.com/repos/SonarSource/sonarqube/releases{/id}","deployments_url":"https://api.github.com/repos/SonarSource/sonarqube/deployments","created_at":"2011-01-05T11:05:17Z","updated_at":"2016-02-21T12:54:20Z","pushed_at":"2016-02-22T08:31:00Z","git_url":"git://github.com/SonarSource/sonarqube.git","ssh_url":"git@github.com:SonarSource/sonarqube.git","clone_url":"https://github.com/SonarSource/sonarqube.git","svn_url":"https://github.com/SonarSource/sonarqube","homepage":"http://www.sonarqube.org","size":132800,"stargazers_count":946,"watchers_count":946,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":437,"mirror_url":null,"open_issues_count":8,"forks":437,"open_issues":8,"watchers":946,"default_branch":"master"}},"base":{"label":"SonarSource:master","ref":"master","sha":"cc00abdb06af7466b4aedbaa7159d0844f465e96","user":{"login":"SonarSource","id":545988,"avatar_url":"https://avatars.githubusercontent.com/u/545988?v=3","gravatar_id":"","url":"https://api.github.com/users/SonarSource","html_url":"https://github.com/SonarSource","followers_url":"https://api.github.com/users/SonarSource/followers","following_url":"https://api.github.com/users/SonarSource/following{/other_user}","gists_url":"https://api.github.com/users/SonarSource/gists{/gist_id}","starred_url":"https://api.github.com/users/SonarSource/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SonarSource/subscriptions","organizations_url":"https://api.github.com/users/SonarSource/orgs","repos_url":"https://api.github.com/users/SonarSource/repos","events_url":"https://api.github.com/users/SonarSource/events{/privacy}","received_events_url":"https://api.github.com/users/SonarSource/received_events","type":"Organization","site_admin":false},"repo":{"id":1222504,"name":"sonarqube","full_name":"SonarSource/sonarqube","owner":{"login":"SonarSource","id":545988,"avatar_url":"https://avatars.githubusercontent.com/u/545988?v=3","gravatar_id":"","url":"https://api.github.com/users/SonarSource","html_url":"https://github.com/SonarSource","followers_url":"https://api.github.com/users/SonarSource/followers","following_url":"https://api.github.com/users/SonarSource/following{/other_user}","gists_url":"https://api.github.com/users/SonarSource/gists{/gist_id}","starred_url":"https://api.github.com/users/SonarSource/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SonarSource/subscriptions","organizations_url":"https://api.github.com/users/SonarSource/orgs","repos_url":"https://api.github.com/users/SonarSource/repos","events_url":"https://api.github.com/users/SonarSource/events{/privacy}","received_events_url":"https://api.github.com/users/SonarSource/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SonarSource/sonarqube","description":"Put your technical debt under control","fork":false,"url":"https://api.github.com/repos/SonarSource/sonarqube","forks_url":"https://api.github.com/repos/SonarSource/sonarqube/forks","keys_url":"https://api.github.com/repos/SonarSource/sonarqube/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SonarSource/sonarqube/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SonarSource/sonarqube/teams","hooks_url":"https://api.github.com/repos/SonarSource/sonarqube/hooks","issue_events_url":"https://api.github.com/repos/SonarSource/sonarqube/issues/events{/number}","events_url":"https://api.github.com/repos/SonarSource/sonarqube/events","assignees_url":"https://api.github.com/repos/SonarSource/sonarqube/assignees{/user}","branches_url":"https://api.github.com/repos/SonarSource/sonarqube/branches{/branch}","tags_url":"https://api.github.com/repos/SonarSource/sonarqube/tags","blobs_url":"https://api.github.com/repos/SonarSource/sonarqube/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SonarSource/sonarqube/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SonarSource/sonarqube/git/refs{/sha}","trees_url":"https://api.github.com/repos/SonarSource/sonarqube/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SonarSource/sonarqube/statuses/{sha}","languages_url":"https://api.github.com/repos/SonarSource/sonarqube/languages","stargazers_url":"https://api.github.com/repos/SonarSource/sonarqube/stargazers","contributors_url":"https://api.github.com/repos/SonarSource/sonarqube/contributors","subscribers_url":"https://api.github.com/repos/SonarSource/sonarqube/subscribers","subscription_url":"https://api.github.com/repos/SonarSource/sonarqube/subscription","commits_url":"https://api.github.com/repos/SonarSource/sonarqube/commits{/sha}","git_commits_url":"https://api.github.com/repos/SonarSource/sonarqube/git/commits{/sha}","comments_url":"https://api.github.com/repos/SonarSource/sonarqube/comments{/number}","issue_comment_url":"https://api.github.com/repos/SonarSource/sonarqube/issues/comments{/number}","contents_url":"https://api.github.com/repos/SonarSource/sonarqube/contents/{+path}","compare_url":"https://api.github.com/repos/SonarSource/sonarqube/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SonarSource/sonarqube/merges","archive_url":"https://api.github.com/repos/SonarSource/sonarqube/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SonarSource/sonarqube/downloads","issues_url":"https://api.github.com/repos/SonarSource/sonarqube/issues{/number}","pulls_url":"https://api.github.com/repos/SonarSource/sonarqube/pulls{/number}","milestones_url":"https://api.github.com/repos/SonarSource/sonarqube/milestones{/number}","notifications_url":"https://api.github.com/repos/SonarSource/sonarqube/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SonarSource/sonarqube/labels{/name}","releases_url":"https://api.github.com/repos/SonarSource/sonarqube/releases{/id}","deployments_url":"https://api.github.com/repos/SonarSource/sonarqube/deployments","created_at":"2011-01-05T11:05:17Z","updated_at":"2016-02-21T12:54:20Z","pushed_at":"2016-02-22T08:31:00Z","git_url":"git://github.com/SonarSource/sonarqube.git","ssh_url":"git@github.com:SonarSource/sonarqube.git","clone_url":"https://github.com/SonarSource/sonarqube.git","svn_url":"https://github.com/SonarSource/sonarqube","homepage":"http://www.sonarqube.org","size":132800,"stargazers_count":946,"watchers_count":946,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":437,"mirror_url":null,"open_issues_count":8,"forks":437,"open_issues":8,"watchers":946,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785"},"html":{"href":"https://github.com/SonarSource/sonarqube/pull/785"},"issue":{"href":"https://api.github.com/repos/SonarSource/sonarqube/issues/785"},"comments":{"href":"https://api.github.com/repos/SonarSource/sonarqube/issues/785/comments"},"review_comments":{"href":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785/comments"},"review_comment":{"href":"https://api.github.com/repos/SonarSource/sonarqube/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/SonarSource/sonarqube/pulls/785/commits"},"statuses":{"href":"https://api.github.com/repos/SonarSource/sonarqube/statuses/71032ad8578ed47da526dca5b0f31302b62d2dab"}}}}